[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-7710":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":16,"stars7d":17,"stars30d":18,"stars90d":16,"forks30d":16,"starsTrendScore":16,"compositeScore":19,"rankGlobal":10,"rankLanguage":10,"license":10,"archived":20,"fork":20,"defaultBranch":21,"hasWiki":22,"hasPages":20,"topics":23,"createdAt":10,"pushedAt":10,"updatedAt":28,"readmeContent":29,"aiSummary":30,"trendingCount":16,"starSnapshotCount":16,"syncStatus":17,"lastSyncTime":31,"discoverSource":32},7710,"fast-ruby","fastruby\u002Ffast-ruby","fastruby",":dash: Writing Fast Ruby :heart_eyes: -- Collect Common Ruby idioms.","https:\u002F\u002Fgithub.com\u002Ffastruby\u002Ffast-ruby",null,"Ruby",5730,374,167,30,0,2,3,38.72,false,"main",true,[24,25,26,27],"benchmark-ips","hacktoberfest","performance-optimization","ruby","2026-06-12 02:01:43","Fast Ruby [![Benchmarks](https:\u002F\u002Fgithub.com\u002Ffastruby\u002Ffast-ruby\u002Factions\u002Fworkflows\u002Fbenchmarks.yml\u002Fbadge.svg)](https:\u002F\u002Fgithub.com\u002Ffastruby\u002Ffast-ruby\u002Factions\u002Fworkflows\u002Fbenchmarks.yml)\n=======================================================================================================================================================================\n\nIn [Erik Michaels-Ober](https:\u002F\u002Fgithub.com\u002Fsferik)'s great talk, 'Writing Fast Ruby': [Video @ Baruco 2014](https:\u002F\u002Fwww.youtube.com\u002Fwatch?v=fGFM_UrSp70), [Slide](https:\u002F\u002Fspeakerdeck.com\u002Fsferik\u002Fwriting-fast-ruby), he presented us with many idioms that lead to faster running Ruby code. He inspired me to document these to let more people know. I try to link to real commits so people can see that this can really have benefits in the real world. **This does not mean you can always blindly replace one with another. It depends on the context (e.g. `gsub` versus `tr`). Friendly reminder: Use with caution!**\n\nEach idiom has a corresponding code example that resides in [code](code).\n\nAll results listed in README.md are running with Ruby 4.0.0 on macOS 15.6.1. Machine information: MacBook Pro (14-inch, Nov 2024), Apple M4 Pro, 48 GB RAM. Your results may vary, but you get the idea. : )\n\nYou can checkout [the GitHub Actions build](https:\u002F\u002Fgithub.com\u002Ffastruby\u002Ffast-ruby\u002Factions) for these benchmark results ran against different Ruby implementations.\n\n**Let's write faster code, together! \u003C3**\n\nAnalyze your code\n-----------------\n\nCheckout the [fasterer](https:\u002F\u002Fgithub.com\u002FDamirSvrtan\u002Ffasterer) project - it's a static analysis that checks speed idioms written in this repo.\n\nMeasurement Tool\n-----------------\n\nUse [benchmark-ips](https:\u002F\u002Fgithub.com\u002Fevanphx\u002Fbenchmark-ips) (2.0+).\n\n### Template\n\n```ruby\nrequire \"benchmark\u002Fips\"\n\ndef fast\nend\n\ndef slow\nend\n\nBenchmark.ips do |x|\n  x.report(\"fast code description\") { fast }\n  x.report(\"slow code description\") { slow }\n  x.compare!\nend\n```\n\nIdioms\n------\n\n### Index\n\n- [General](#general)\n- [Array](#array)\n- [Date](#date)\n- [Enumerable](#enumerable)\n- [Hash](#hash)\n- [Proc & Block](#proc--block)\n- [String](#string)\n- [Time](#time)\n- [Range](#range)\n\n### General\n\n##### `attr_accessor` vs `getter and setter` [code](code\u002Fgeneral\u002Fattr-accessor-vs-getter-and-setter.rb)\n\n> https:\u002F\u002Fwww.omniref.com\u002Fruby\u002F2.2.0\u002Ffiles\u002Fmethod.h?#annotation=4081781&line=47\n\n```\n$ ruby -v code\u002Fgeneral\u002Fattr-accessor-vs-getter-and-setter.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n   getter_and_setter     1.122M i\u002F100ms\n       attr_accessor     1.303M i\u002F100ms\nCalculating -------------------------------------\n   getter_and_setter     10.999M (± 2.1%) i\u002Fs   (90.92 ns\u002Fi) -     56.083M in   5.101077s\n       attr_accessor     12.517M (± 1.5%) i\u002Fs   (79.89 ns\u002Fi) -     63.841M in   5.101477s\n\nComparison:\n       attr_accessor: 12517008.0 i\u002Fs\n   getter_and_setter: 10999275.5 i\u002Fs - 1.14x  slower\n```\n\n##### `begin...rescue` vs `respond_to?` for Control Flow [code](code\u002Fgeneral\u002Fbegin-rescue-vs-respond-to.rb)\n\n```\n$ ruby -v code\u002Fgeneral\u002Fbegin-rescue-vs-respond-to.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n      begin...rescue   230.601k i\u002F100ms\n         respond_to?     1.915M i\u002F100ms\nCalculating -------------------------------------\n      begin...rescue      2.390M (± 0.9%) i\u002Fs  (418.40 ns\u002Fi) -     11.991M in   5.017466s\n         respond_to?     18.745M (± 1.8%) i\u002Fs   (53.35 ns\u002Fi) -     93.843M in   5.007990s\n\nComparison:\n         respond_to?: 18744998.8 i\u002Fs\n      begin...rescue:  2390076.1 i\u002Fs - 7.84x  slower\n```\n\n##### `define_method` vs `module_eval` for Defining Methods [code](code\u002Fgeneral\u002Fdefine_method-vs-module-eval.rb)\n\n```\n$ ruby -v code\u002Fgeneral\u002Fdefine_method-vs-module-eval.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\nmodule_eval with string\n                       630.000 i\u002F100ms\n       define_method   685.000 i\u002F100ms\nCalculating -------------------------------------\nmodule_eval with string\n                          5.633k (±18.1%) i\u002Fs  (177.53 μs\u002Fi) -     27.090k in   5.009884s\n       define_method      7.239k (±17.6%) i\u002Fs  (138.14 μs\u002Fi) -     34.250k in   5.040522s\n\nComparison:\n       define_method:     7238.9 i\u002Fs\nmodule_eval with string:     5632.8 i\u002Fs - same-ish: difference falls within error\n```\n\n##### `String#constantize` vs a comparison for inflection [code](code\u002Fgeneral\u002Fconstantize-vs-comparison.rb)\n\nActiveSupport's [String#constantize](https:\u002F\u002Fguides.rubyonrails.org\u002Factive_support_core_extensions.html#constantize) \"resolves the constant reference expression in its receiver\".\n\n[Read the rationale here](https:\u002F\u002Fgithub.com\u002Ffastruby\u002Ffast-ruby\u002Fpull\u002F200)\n\n```\n$ ruby -v code\u002Fgeneral\u002Fconstantize-vs-comparison.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\nusing an if statement\n                         1.507M i\u002F100ms\n  String#constantize     1.048M i\u002F100ms\nCalculating -------------------------------------\nusing an if statement\n                         15.518M (± 1.2%) i\u002Fs   (64.44 ns\u002Fi) -     78.355M in   5.050041s\n  String#constantize     10.556M (± 1.0%) i\u002Fs   (94.73 ns\u002Fi) -     53.448M in   5.063570s\n\nComparison:\nusing an if statement: 15517955.2 i\u002Fs\n  String#constantize: 10556362.4 i\u002Fs - 1.47x  slower\n```\n\n##### `raise` vs `E2MM#Raise` for raising (and defining) exceptions  [code](code\u002Fgeneral\u002Fraise-vs-e2mmap.rb)\n\nRuby's [Exception2MessageMapper module](http:\u002F\u002Fruby-doc.org\u002Fstdlib-2.2.0\u002Flibdoc\u002Fe2mmap\u002Frdoc\u002Findex.html) allows one to define and raise exceptions with predefined messages.\n\n```\n$ ruby -v code\u002Fgeneral\u002Fraise-vs-e2mmap.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\nRuby exception: E2MM#Raise\n                         8.751k i\u002F100ms\nRuby exception: Kernel#raise\n                       254.268k i\u002F100ms\nCalculating -------------------------------------\nRuby exception: E2MM#Raise\n                         88.269k (± 0.5%) i\u002Fs   (11.33 μs\u002Fi) -    446.301k in   5.056287s\nRuby exception: Kernel#raise\n                          2.571M (± 1.0%) i\u002Fs  (389.01 ns\u002Fi) -     12.968M in   5.044976s\n\nComparison:\nRuby exception: Kernel#raise:  2570660.6 i\u002Fs\nRuby exception: E2MM#Raise:    88268.9 i\u002Fs - 29.12x  slower\n\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\nCustom exception: E2MM#Raise\n                         8.837k i\u002F100ms\nCustom exception: Kernel#raise\n                       263.896k i\u002F100ms\nCalculating -------------------------------------\nCustom exception: E2MM#Raise\n                         88.322k (± 0.6%) i\u002Fs   (11.32 μs\u002Fi) -    441.850k in   5.002885s\nCustom exception: Kernel#raise\n                          2.599M (± 2.1%) i\u002Fs  (384.78 ns\u002Fi) -     13.195M in   5.079300s\n\nComparison:\nCustom exception: Kernel#raise:  2598894.6 i\u002Fs\nCustom exception: E2MM#Raise:    88322.1 i\u002Fs - 29.43x  slower\n```\n\n##### `loop` vs `while true` [code](code\u002Fgeneral\u002Floop-vs-while-true.rb)\n\n```\n$ ruby -v code\u002Fgeneral\u002Floop-vs-while-true.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n          While Loop     1.000 i\u002F100ms\n         Kernel loop     1.000 i\u002F100ms\nCalculating -------------------------------------\n          While Loop      1.331 (± 0.0%) i\u002Fs  (751.41 ms\u002Fi) -      7.000 in   5.260296s\n         Kernel loop      0.528 (± 0.0%) i\u002Fs     (1.89 s\u002Fi) -      3.000 in   5.709880s\n\nComparison:\n          While Loop:        1.3 i\u002Fs\n         Kernel loop:        0.5 i\u002Fs - 2.52x  slower\n```\n\n##### `ancestors.include?` vs `\u003C=` [code](code\u002Fgeneral\u002Finheritance-check.rb)\n\n```\n$ ruby -v code\u002Fgeneral\u002Finheritance-check.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n  less than or equal     1.150M i\u002F100ms\n  ancestors.include?   179.611k i\u002F100ms\nCalculating -------------------------------------\n  less than or equal     11.426M (± 1.4%) i\u002Fs   (87.52 ns\u002Fi) -     57.493M in   5.032894s\n  ancestors.include?      1.880M (± 1.0%) i\u002Fs  (531.84 ns\u002Fi) -      9.519M in   5.063302s\n\nComparison:\n  less than or equal: 11425608.6 i\u002Fs\n  ancestors.include?:  1880262.8 i\u002Fs - 6.08x  slower\n```\n\n### Method Invocation\n\n##### `call` vs `send` vs `method_missing` [code](code\u002Fmethod\u002Fcall-vs-send-vs-method_missing.rb)\n\n```\n$ ruby -v code\u002Fmethod\u002Fcall-vs-send-vs-method_missing.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n                call     1.670M i\u002F100ms\n                send     1.182M i\u002F100ms\n      method_missing   837.965k i\u002F100ms\nCalculating -------------------------------------\n                call     16.799M (± 0.3%) i\u002Fs   (59.53 ns\u002Fi) -     85.150M in   5.068737s\n                send     11.845M (± 0.3%) i\u002Fs   (84.42 ns\u002Fi) -     60.281M in   5.089071s\n      method_missing      8.392M (± 0.3%) i\u002Fs  (119.17 ns\u002Fi) -     42.736M in   5.092719s\n\nComparison:\n                call: 16799285.6 i\u002Fs\n                send: 11845293.0 i\u002Fs - 1.42x  slower\n      method_missing:  8391692.6 i\u002Fs - 2.00x  slower\n```\n\n##### Normal way to apply method vs `&method(...)` [code](code\u002Fgeneral\u002Fblock-apply-method.rb)\n\n```\n$ ruby -v code\u002Fgeneral\u002Fblock-apply-method.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n              normal   698.536k i\u002F100ms\n             &method   322.901k i\u002F100ms\nCalculating -------------------------------------\n              normal      6.978M (± 0.9%) i\u002Fs  (143.31 ns\u002Fi) -     34.927M in   5.005888s\n             &method      3.214M (± 0.5%) i\u002Fs  (311.12 ns\u002Fi) -     16.145M in   5.023139s\n\nComparison:\n              normal:  6977718.6 i\u002Fs\n             &method:  3214214.6 i\u002Fs - 2.17x  slower\n```\n\n##### Function with single Array argument vs splat arguments [code](code\u002Fgeneral\u002Farray-argument-vs-splat-arguments.rb)\n\n```\n$ ruby -v code\u002Fgeneral\u002Farray-argument-vs-splat-arguments.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\nFunction with single Array argument\n                         1.910M i\u002F100ms\nFunction with splat arguments\n                        18.841k i\u002F100ms\nCalculating -------------------------------------\nFunction with single Array argument\n                         18.818M (± 1.2%) i\u002Fs   (53.14 ns\u002Fi) -     95.479M in   5.074468s\nFunction with splat arguments\n                        217.060k (±11.2%) i\u002Fs    (4.61 μs\u002Fi) -      1.093M in   5.099583s\n\nComparison:\nFunction with single Array argument: 18818207.9 i\u002Fs\nFunction with splat arguments:   217059.9 i\u002Fs - 86.70x  slower\n```\n\n##### Hash vs OpenStruct on access assuming you already have a Hash or an OpenStruct [code](code\u002Fgeneral\u002Fhash-vs-openstruct-on-access.rb)\n\n```\n$ ruby -v code\u002Fgeneral\u002Fhash-vs-openstruct-on-access.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n                Hash     2.028M i\u002F100ms\n          OpenStruct     1.478M i\u002F100ms\nCalculating -------------------------------------\n                Hash     20.290M (± 0.5%) i\u002Fs   (49.29 ns\u002Fi) -    103.430M in   5.097815s\n          OpenStruct     14.807M (± 0.6%) i\u002Fs   (67.54 ns\u002Fi) -     75.387M in   5.091599s\n\nComparison:\n                Hash: 20289714.4 i\u002Fs\n          OpenStruct: 14806564.8 i\u002Fs - 1.37x  slower\n```\n\n##### Hash vs OpenStruct (creation) [code](code\u002Fgeneral\u002Fhash-vs-openstruct.rb)\n\n```\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n                Hash     2.652M i\u002F100ms\n          OpenStruct    31.241k i\u002F100ms\nCalculating -------------------------------------\n                Hash     26.301M (± 1.0%) i\u002Fs   (38.02 ns\u002Fi) -    132.614M in   5.042769s\n          OpenStruct    313.539k (± 1.8%) i\u002Fs    (3.19 μs\u002Fi) -      1.593M in   5.083245s\n\nComparison:\n                Hash: 26300561.3 i\u002Fs\n          OpenStruct:   313538.7 i\u002Fs - 83.88x  slower\n```\n\n##### Kernel#format vs Float#round().to_s [code](code\u002Fgeneral\u002Fformat-vs-round-and-to-s.rb)\n\n```\n$ ruby -v code\u002Fgeneral\u002Fformat-vs-round-and-to-s.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n         Float#round   465.786k i\u002F100ms\n       Kernel#format   618.743k i\u002F100ms\n            String#%   562.895k i\u002F100ms\nCalculating -------------------------------------\n         Float#round      4.780M (± 0.6%) i\u002Fs  (209.21 ns\u002Fi) -     24.221M in   5.067359s\n       Kernel#format      6.200M (± 1.4%) i\u002Fs  (161.29 ns\u002Fi) -     31.556M in   5.090736s\n            String#%      5.642M (± 1.1%) i\u002Fs  (177.25 ns\u002Fi) -     28.708M in   5.088913s\n\nComparison:\n       Kernel#format:  6199975.0 i\u002Fs\n            String#%:  5641863.3 i\u002Fs - 1.10x  slower\n         Float#round:  4779984.9 i\u002Fs - 1.30x  slower\n```\n\n### Array\n\n##### `Array#bsearch` vs `Array#find` [code](code\u002Farray\u002Fbsearch-vs-find.rb)\n\n**WARNING:** `bsearch` ONLY works on *sorted array*. More details please see [#29](https:\u002F\u002Fgithub.com\u002Ffastruby\u002Ffast-ruby\u002Fissues\u002F29).\n\n```\n$ ruby -v code\u002Farray\u002Fbsearch-vs-find.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n                find     1.000 i\u002F100ms\n             bsearch   189.387k i\u002F100ms\nCalculating -------------------------------------\n                find      0.703 (± 0.0%) i\u002Fs     (1.42 s\u002Fi) -      4.000 in   5.692110s\n             bsearch      1.893M (± 1.6%) i\u002Fs  (528.21 ns\u002Fi) -      9.469M in   5.003152s\n\nComparison:\n             bsearch:  1893194.5 i\u002Fs\n                find:        0.7 i\u002Fs - 2691605.95x  slower\n```\n\n##### `Array#length` vs `Array#size` vs `Array#count` [code](code\u002Farray\u002Flength-vs-size-vs-count.rb)\n\nUse `#length` when you only want to know how many elements in the array, `#count` could also achieve this. However `#count` should be use for counting specific elements in array. [Note `#size` is an alias of `#length`](https:\u002F\u002Fgithub.com\u002Fruby\u002Fruby\u002Fblob\u002Ff8fb526ad9e9f31453bffbc908b6a986736e21a7\u002Farray.c#L5817-L5818).\n\n```\n$ ruby -v code\u002Farray\u002Flength-vs-size-vs-count.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n        Array#length     5.024M i\u002F100ms\n          Array#size     4.994M i\u002F100ms\n         Array#count     3.781M i\u002F100ms\nCalculating -------------------------------------\n        Array#length     50.668M (± 0.8%) i\u002Fs   (19.74 ns\u002Fi) -    256.237M in   5.057495s\n          Array#size     50.580M (± 0.7%) i\u002Fs   (19.77 ns\u002Fi) -    254.704M in   5.035880s\n         Array#count     38.202M (± 0.8%) i\u002Fs   (26.18 ns\u002Fi) -    192.843M in   5.048306s\n\nComparison:\n        Array#length: 50667869.8 i\u002Fs\n          Array#size: 50580088.8 i\u002Fs - same-ish: difference falls within error\n         Array#count: 38201768.5 i\u002Fs - 1.33x  slower\n```\n\n##### `Array#shuffle.first` vs `Array#sample` [code](code\u002Farray\u002Fshuffle-first-vs-sample.rb)\n\n> `Array#shuffle` allocates an extra array. \u003Cbr>\n> `Array#sample` indexes into the array without allocating an extra array. \u003Cbr>\n> This is the reason why Array#sample exists. \u003Cbr>\n> —— @sferik [rails\u002Frails#17245](https:\u002F\u002Fgithub.com\u002Frails\u002Frails\u002Fpull\u002F17245)\n\n```\n$ ruby -v code\u002Farray\u002Fshuffle-first-vs-sample.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n Array#shuffle.first    88.991k i\u002F100ms\n        Array#sample     2.503M i\u002F100ms\nCalculating -------------------------------------\n Array#shuffle.first    891.780k (± 0.5%) i\u002Fs    (1.12 μs\u002Fi) -      4.539M in   5.089459s\n        Array#sample     25.133M (± 0.6%) i\u002Fs   (39.79 ns\u002Fi) -    127.660M in   5.079516s\n\nComparison:\n        Array#sample: 25133099.8 i\u002Fs\n Array#shuffle.first:   891779.8 i\u002Fs - 28.18x  slower\n```\n\n##### `Array#[](0)` vs `Array#first` [code](code\u002Farray\u002Farray-first-vs-index.rb)\n\n```\n$ ruby -v code\u002Farray\u002Farray-first-vs-index.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n           Array#[0]     3.922M i\u002F100ms\n         Array#first     3.697M i\u002F100ms\nCalculating -------------------------------------\n           Array#[0]     39.347M (± 0.7%) i\u002Fs   (25.41 ns\u002Fi) -    200.006M in   5.083307s\n         Array#first     37.289M (± 1.1%) i\u002Fs   (26.82 ns\u002Fi) -    188.546M in   5.056917s\n\nComparison:\n           Array#[0]: 39347487.6 i\u002Fs\n         Array#first: 37288935.3 i\u002Fs - 1.06x  slower\n```\n\n##### `Array#[](-1)` vs `Array#last` [code](code\u002Farray\u002Farray-last-vs-index.rb)\n\n```\n$ ruby -v code\u002Farray\u002Farray-last-vs-index.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n          Array#[-1]     3.906M i\u002F100ms\n          Array#last     3.727M i\u002F100ms\nCalculating -------------------------------------\n          Array#[-1]     39.303M (± 0.7%) i\u002Fs   (25.44 ns\u002Fi) -    199.228M in   5.069210s\n          Array#last     37.280M (± 1.1%) i\u002Fs   (26.82 ns\u002Fi) -    190.075M in   5.099254s\n\nComparison:\n          Array#[-1]: 39303493.5 i\u002Fs\n          Array#last: 37279563.5 i\u002Fs - 1.05x  slower\n```\n\n##### `Array#insert` vs `Array#unshift` [code](code\u002Farray\u002Finsert-vs-unshift.rb)\n\n```\n$ ruby -v code\u002Farray\u002Finsert-vs-unshift.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n       Array#unshift    37.000 i\u002F100ms\n        Array#insert     1.000 i\u002F100ms\nCalculating -------------------------------------\n       Array#unshift    379.798 (± 1.1%) i\u002Fs    (2.63 ms\u002Fi) -      1.924k in   5.066300s\n        Array#insert      1.717 (± 0.0%) i\u002Fs  (582.49 ms\u002Fi) -      9.000 in   5.242429s\n\nComparison:\n       Array#unshift:      379.8 i\u002Fs\n        Array#insert:        1.7 i\u002Fs - 221.23x  slower\n```\n##### `Array#concat` vs `Array#+` [code](code\u002Farray\u002Farray-concat-vs-+.rb)\n`Array#+` returns a new array built by concatenating the two arrays together to\nproduce a third array. `Array#concat` appends the elements of the other array to self.\nThis means that the + operator will create a new array each time it is called\n(which is expensive), while concat only appends the new element.\n```\n$ ruby -v code\u002Farray\u002Farray-concat-vs-+.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n        Array#concat   126.000 i\u002F100ms\n             Array#+     1.000 i\u002F100ms\nCalculating -------------------------------------\n        Array#concat      1.259k (± 1.1%) i\u002Fs  (793.98 μs\u002Fi) -      6.300k in   5.002769s\n             Array#+      5.170 (± 0.0%) i\u002Fs  (193.42 ms\u002Fi) -     26.000 in   5.033770s\n\nComparison:\n        Array#concat:     1259.5 i\u002Fs\n             Array#+:        5.2 i\u002Fs - 243.60x  slower\n```\n\n##### `Array#new` vs `Fixnum#times + map` [code](code\u002Farray\u002Farray-new-vs-fixnum-times-map.rb)\n\nTypical slowdown is 40-60% depending on the size of the array. See the corresponding\n[pull request](https:\u002F\u002Fgithub.com\u002Ffastruby\u002Ffast-ruby\u002Fpull\u002F91\u002F) for performance characteristics.\n\n```\n$ ruby -v code\u002Farray\u002Farray-new-vs-fixnum-times-map.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n           Array#new   424.914k i\u002F100ms\n  Fixnum#times + map   187.997k i\u002F100ms\nCalculating -------------------------------------\n           Array#new      4.251M (± 0.4%) i\u002Fs  (235.25 ns\u002Fi) -     21.671M in   5.098122s\n  Fixnum#times + map      1.886M (± 0.4%) i\u002Fs  (530.31 ns\u002Fi) -      9.588M in   5.084632s\n\nComparison:\n           Array#new:  4250785.8 i\u002Fs\n  Fixnum#times + map:  1885679.9 i\u002Fs - 2.25x  slower\n```\n\n##### `Array#sort.reverse` vs `Array#sort_by` +  block [code](code\u002Farray\u002Fsort-reverse-vs-sort_by-with-block.rb)\n\n```\n$ ruby -v code\u002Farray\u002Fsort-reverse-vs-sort_by-with-block.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n  Array#sort.reverse    55.279k i\u002F100ms\n  Array#sort_by &:-@    22.773k i\u002F100ms\nCalculating -------------------------------------\n  Array#sort.reverse    560.570k (± 0.9%) i\u002Fs    (1.78 μs\u002Fi) -      2.819M in   5.029648s\n  Array#sort_by &:-@    229.324k (± 0.6%) i\u002Fs    (4.36 μs\u002Fi) -      1.161M in   5.064717s\n\nComparison:\n  Array#sort.reverse:   560570.1 i\u002Fs\n  Array#sort_by &:-@:   229323.6 i\u002Fs - 2.44x  slower\n```\n\n### Enumerable\n\n##### `Enumerable#each + push` vs `Enumerable#map` [code](code\u002Fenumerable\u002Feach-push-vs-map.rb)\n\n```\n$ ruby -v code\u002Fenumerable\u002Feach-push-vs-map.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n   Array#each + push    31.310k i\u002F100ms\n           Array#map    51.371k i\u002F100ms\nCalculating -------------------------------------\n   Array#each + push    320.334k (± 0.6%) i\u002Fs    (3.12 μs\u002Fi) -      1.628M in   5.082743s\n           Array#map    511.854k (± 1.3%) i\u002Fs    (1.95 μs\u002Fi) -      2.569M in   5.019061s\n\nComparison:\n           Array#map:   511854.5 i\u002Fs\n   Array#each + push:   320334.1 i\u002Fs - 1.60x  slower\n```\n\n##### `Enumerable#each` vs `for` loop [code](code\u002Fenumerable\u002Feach-vs-for-loop.rb)\n\n```\n$ ruby -v code\u002Fenumerable\u002Feach-vs-for-loop.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n            For loop    54.498k i\u002F100ms\n               #each    63.984k i\u002F100ms\nCalculating -------------------------------------\n            For loop    525.548k (± 8.8%) i\u002Fs    (1.90 μs\u002Fi) -      2.670M in   5.128917s\n               #each    641.789k (± 0.3%) i\u002Fs    (1.56 μs\u002Fi) -      3.263M in   5.084548s\n\nComparison:\n               #each:   641788.6 i\u002Fs\n            For loop:   525547.8 i\u002Fs - 1.22x  slower\n```\n\n##### `Enumerable#each_with_index` vs `while` loop [code](code\u002Fenumerable\u002Feach_with_index-vs-while-loop.rb)\n\n> [rails\u002Frails#12065](https:\u002F\u002Fgithub.com\u002Frails\u002Frails\u002Fpull\u002F12065)\n\n```\n$ ruby -v code\u002Fenumerable\u002Feach_with_index-vs-while-loop.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n          While Loop    49.050k i\u002F100ms\n     each_with_index    36.684k i\u002F100ms\nCalculating -------------------------------------\n          While Loop    501.430k (± 2.9%) i\u002Fs    (1.99 μs\u002Fi) -      2.551M in   5.091049s\n     each_with_index    369.364k (± 0.3%) i\u002Fs    (2.71 μs\u002Fi) -      1.871M in   5.065187s\n\nComparison:\n          While Loop:   501430.2 i\u002Fs\n     each_with_index:   369364.5 i\u002Fs - 1.36x  slower\n```\n\n##### `Enumerable#map`...`Array#flatten` vs `Enumerable#flat_map` [code](code\u002Fenumerable\u002Fmap-flatten-vs-flat_map.rb)\n\n> -- @sferik [rails\u002Frails@3413b88](https:\u002F\u002Fgithub.com\u002Frails\u002Frails\u002Fcommit\u002F3413b88), [Replace map.flatten with flat_map](https:\u002F\u002Fgithub.com\u002Frails\u002Frails\u002Fcommit\u002F817fe31196dd59ee31f71ef1740122b6759cf16d), [Replace map.flatten(1) with flat_map](https:\u002F\u002Fgithub.com\u002Frails\u002Frails\u002Fcommit\u002Fb11ebf1d80e4fb124f0ce0448cea30988256da59)\n\n```\n$ ruby -v code\u002Fenumerable\u002Fmap-flatten-vs-flat_map.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\nArray#map.flatten(1)    19.072k i\u002F100ms\n   Array#map.flatten     8.810k i\u002F100ms\n      Array#flat_map    21.362k i\u002F100ms\nCalculating -------------------------------------\nArray#map.flatten(1)    196.444k (± 1.2%) i\u002Fs    (5.09 μs\u002Fi) -    991.744k in   5.049225s\n   Array#map.flatten     89.917k (± 1.2%) i\u002Fs   (11.12 μs\u002Fi) -    458.120k in   5.095661s\n      Array#flat_map    215.149k (± 0.6%) i\u002Fs    (4.65 μs\u002Fi) -      1.089M in   5.063916s\n\nComparison:\n      Array#flat_map:   215149.2 i\u002Fs\nArray#map.flatten(1):   196443.8 i\u002Fs - 1.10x  slower\n   Array#map.flatten:    89916.9 i\u002Fs - 2.39x  slower\n```\n\n##### `Enumerable#reverse.each` vs `Enumerable#reverse_each` [code](code\u002Fenumerable\u002Freverse-each-vs-reverse_each.rb)\n\n> `Enumerable#reverse` allocates an extra array.  \u003Cbr>\n> `Enumerable#reverse_each` yields each value without allocating an extra array. \u003Cbr>\n> This is the reason why `Enumerable#reverse_each` exists. \u003Cbr>\n> -- @sferik [rails\u002Frails#17244](https:\u002F\u002Fgithub.com\u002Frails\u002Frails\u002Fpull\u002F17244)\n\n```\n$ ruby -v code\u002Fenumerable\u002Freverse-each-vs-reverse_each.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n  Array#reverse.each    58.610k i\u002F100ms\n  Array#reverse_each    63.669k i\u002F100ms\nCalculating -------------------------------------\n  Array#reverse.each    586.309k (± 0.7%) i\u002Fs    (1.71 μs\u002Fi) -      2.989M in   5.098469s\n  Array#reverse_each    635.904k (± 2.3%) i\u002Fs    (1.57 μs\u002Fi) -      3.183M in   5.009371s\n\nComparison:\n  Array#reverse_each:   635904.1 i\u002Fs\n  Array#reverse.each:   586309.0 i\u002Fs - 1.08x  slower\n```\n\n##### `Enumerable#sort_by.first` vs `Enumerable#min_by` [code](code\u002Fenumerable\u002Fsort_by-first-vs-min_by.rb)\n`Enumerable#sort_by` performs a sort of the enumerable and allocates a\nnew array the size of the enumerable.  `Enumerable#min_by` doesn't\nperform a sort or allocate an array the size of the enumerable.\nSimilar comparisons hold for `Enumerable#sort_by.last` vs\n`Enumerable#max_by`, `Enumerable#sort.first` vs `Enumerable#min`, and\n`Enumerable#sort.last` vs `Enumerable#max`.\n\n```\n$ ruby -v code\u002Fenumerable\u002Fsort_by-first-vs-min_by.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n   Enumerable#min_by    40.784k i\u002F100ms\nEnumerable#sort_by...first\n                        32.912k i\u002F100ms\nCalculating -------------------------------------\n   Enumerable#min_by    408.114k (± 0.3%) i\u002Fs    (2.45 μs\u002Fi) -      2.080M in   5.096613s\nEnumerable#sort_by...first\n                        334.401k (± 0.7%) i\u002Fs    (2.99 μs\u002Fi) -      1.679M in   5.019698s\n\nComparison:\n   Enumerable#min_by:   408113.9 i\u002Fs\nEnumerable#sort_by...first:   334400.9 i\u002Fs - 1.22x  slower\n```\n\n##### `Enumerable#detect` vs `Enumerable#select.first` [code](code\u002Fenumerable\u002Fselect-first-vs-detect.rb)\n\n```\n$ ruby -v code\u002Fenumerable\u002Fselect-first-vs-detect.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\nEnumerable#select.first\n                        37.402k i\u002F100ms\n   Enumerable#detect   247.638k i\u002F100ms\nCalculating -------------------------------------\nEnumerable#select.first\n                        373.115k (± 0.6%) i\u002Fs    (2.68 μs\u002Fi) -      7.480M in  20.049160s\n   Enumerable#detect      2.462M (± 0.8%) i\u002Fs  (406.12 ns\u002Fi) -     49.280M in  20.014730s\n\nComparison:\n   Enumerable#detect:  2462330.2 i\u002Fs\nEnumerable#select.first:   373115.1 i\u002Fs - 6.60x  slower\n```\n\n##### `Enumerable#select.last` vs `Enumerable#reverse.detect` [code](code\u002Fenumerable\u002Fselect-last-vs-reverse-detect.rb)\n\n```\n$ ruby -v code\u002Fenumerable\u002Fselect-last-vs-reverse-detect.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\nEnumerable#reverse.detect\n                        23.133k i\u002F100ms\nEnumerable#select.last\n                       562.000 i\u002F100ms\nCalculating -------------------------------------\nEnumerable#reverse.detect\n                        241.463k (± 5.5%) i\u002Fs    (4.14 μs\u002Fi) -      1.226M in   5.092374s\nEnumerable#select.last\n                          5.640k (± 0.9%) i\u002Fs  (177.30 μs\u002Fi) -     28.662k in   5.082075s\n\nComparison:\nEnumerable#reverse.detect:   241463.1 i\u002Fs\nEnumerable#select.last:     5640.3 i\u002Fs - 42.81x  slower\n```\n\n##### `Enumerable#sort` vs `Enumerable#sort_by` [code](code\u002Fenumerable\u002Fsort-vs-sort_by.rb)\n\n```\n$ ruby -v code\u002Fenumerable\u002Fsort-vs-sort_by.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\nEnumerable#sort_by (Symbol#to_proc)\n                        16.077k i\u002F100ms\n  Enumerable#sort_by    15.265k i\u002F100ms\n     Enumerable#sort     4.580k i\u002F100ms\nCalculating -------------------------------------\nEnumerable#sort_by (Symbol#to_proc)\n                        162.709k (± 0.9%) i\u002Fs    (6.15 μs\u002Fi) -    819.927k in   5.039602s\n  Enumerable#sort_by    152.611k (± 0.7%) i\u002Fs    (6.55 μs\u002Fi) -    763.250k in   5.001512s\n     Enumerable#sort     45.814k (± 1.4%) i\u002Fs   (21.83 μs\u002Fi) -    233.580k in   5.099352s\n\nComparison:\nEnumerable#sort_by (Symbol#to_proc):   162709.4 i\u002Fs\n  Enumerable#sort_by:   152611.3 i\u002Fs - 1.07x  slower\n     Enumerable#sort:    45814.3 i\u002Fs - 3.55x  slower\n```\n\n##### `Enumerable#inject Symbol` vs `Enumerable#inject Proc` [code](code\u002Fenumerable\u002Finject-symbol-vs-block.rb)\n\nOf note, `to_proc` for 1.8.7 is considerable slower than the block format\n\n```\n$ ruby -v code\u002Fenumerable\u002Finject-symbol-vs-block.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n       inject symbol   183.846k i\u002F100ms\n      inject to_proc     4.100k i\u002F100ms\n        inject block     3.882k i\u002F100ms\nCalculating -------------------------------------\n       inject symbol      1.841M (± 0.4%) i\u002Fs  (543.31 ns\u002Fi) -      9.376M in   5.094226s\n      inject to_proc     41.165k (± 0.3%) i\u002Fs   (24.29 μs\u002Fi) -    209.100k in   5.079636s\n        inject block     39.550k (± 0.6%) i\u002Fs   (25.28 μs\u002Fi) -    197.982k in   5.006073s\n\nComparison:\n       inject symbol:  1840578.1 i\u002Fs\n      inject to_proc:    41164.7 i\u002Fs - 44.71x  slower\n        inject block:    39550.0 i\u002Fs - 46.54x  slower\n```\n\n### Date\n\n##### `Date.iso8601` vs `Date.parse` [code](code\u002Fdate\u002Fiso8601-vs-parse.rb)\n\nWhen expecting well-formatted data from e.g. an API, `iso8601` is faster and will raise an `ArgumentError` on malformed input.\n\n```\n$ ruby -v code\u002Fdate\u002Fiso8601-vs-parse.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n        Date.iso8601   195.684k i\u002F100ms\n          Date.parse    62.633k i\u002F100ms\nCalculating -------------------------------------\n        Date.iso8601      2.008M (± 0.8%) i\u002Fs  (497.99 ns\u002Fi) -     10.176M in   5.067673s\n          Date.parse    627.349k (± 0.7%) i\u002Fs    (1.59 μs\u002Fi) -      3.194M in   5.092000s\n\nComparison:\n        Date.iso8601:  2008075.4 i\u002Fs\n          Date.parse:   627349.2 i\u002Fs - 3.20x  slower\n```\n\n### Hash\n\n##### `Hash#[]` vs `Hash#fetch` [code](code\u002Fhash\u002Fbracket-vs-fetch.rb)\n\nIf you use Ruby 2.2, `Symbol` could be more performant than `String` as `Hash` keys.\nRead more regarding this: [Symbol GC in Ruby 2.2](http:\u002F\u002Fwww.sitepoint.com\u002Fsymbol-gc-ruby-2-2\u002F) and [Unraveling String Key Performance in Ruby 2.2](http:\u002F\u002Fwww.sitepoint.com\u002Funraveling-string-key-performance-ruby-2-2\u002F).\n\n```\n$ ruby -v code\u002Fhash\u002Fbracket-vs-fetch.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n     Hash#[], symbol     3.471M i\u002F100ms\n  Hash#fetch, symbol     2.869M i\u002F100ms\n     Hash#[], string     1.969M i\u002F100ms\n  Hash#fetch, string     1.746M i\u002F100ms\nCalculating -------------------------------------\n     Hash#[], symbol     34.983M (± 0.8%) i\u002Fs   (28.59 ns\u002Fi) -    177.026M in   5.060743s\n  Hash#fetch, symbol     28.927M (± 1.1%) i\u002Fs   (34.57 ns\u002Fi) -    146.331M in   5.059120s\n     Hash#[], string     19.711M (± 1.7%) i\u002Fs   (50.73 ns\u002Fi) -    100.431M in   5.096713s\n  Hash#fetch, string     17.825M (± 1.4%) i\u002Fs   (56.10 ns\u002Fi) -     90.775M in   5.093555s\n\nComparison:\n     Hash#[], symbol: 34982573.5 i\u002Fs\n  Hash#fetch, symbol: 28927450.2 i\u002Fs - 1.21x  slower\n     Hash#[], string: 19710678.7 i\u002Fs - 1.77x  slower\n  Hash#fetch, string: 17825222.3 i\u002Fs - 1.96x  slower\n```\n\n##### `Hash#dig` vs `Hash#[]` vs `Hash#fetch` [code](code\u002Fhash\u002Fdig-vs-[]-vs-fetch.rb)\n\n[Ruby 2.3 introduced `Hash#dig`](http:\u002F\u002Fruby-doc.org\u002Fcore-2.3.0\u002FHash.html#method-i-dig) which is a readable\nand performant option for retrieval from a nested hash, returning `nil` if an extraction step fails.\nSee [#102 (comment)](https:\u002F\u002Fgithub.com\u002Ffastruby\u002Ffast-ruby\u002Fpull\u002F102#issuecomment-198827506) for more info.\n\n```\n$ ruby -v code\u002Fhash\u002Fdig-vs-[]-vs-fetch.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n            Hash#dig     1.939M i\u002F100ms\n             Hash#[]     1.903M i\u002F100ms\n          Hash#[] ||     1.787M i\u002F100ms\n          Hash#[] &&   725.944k i\u002F100ms\n          Hash#fetch     1.246M i\u002F100ms\n Hash#fetch fallback   803.269k i\u002F100ms\nCalculating -------------------------------------\n            Hash#dig     19.434M (± 0.8%) i\u002Fs   (51.46 ns\u002Fi) -     98.877M in   5.088095s\n             Hash#[]     19.005M (± 2.2%) i\u002Fs   (52.62 ns\u002Fi) -     95.141M in   5.008511s\n          Hash#[] ||     17.879M (± 0.7%) i\u002Fs   (55.93 ns\u002Fi) -     91.138M in   5.097648s\n          Hash#[] &&      7.303M (± 0.6%) i\u002Fs  (136.93 ns\u002Fi) -     37.023M in   5.069773s\n          Hash#fetch     12.634M (± 2.0%) i\u002Fs   (79.15 ns\u002Fi) -     63.570M in   5.033708s\n Hash#fetch fallback      8.117M (± 1.0%) i\u002Fs  (123.20 ns\u002Fi) -     40.967M in   5.047539s\n\nComparison:\n            Hash#dig: 19434078.6 i\u002Fs\n             Hash#[]: 19004999.7 i\u002Fs - same-ish: difference falls within error\n          Hash#[] ||: 17879337.5 i\u002Fs - 1.09x  slower\n          Hash#fetch: 12633982.2 i\u002Fs - 1.54x  slower\n Hash#fetch fallback:  8116930.3 i\u002Fs - 2.39x  slower\n          Hash#[] &&:  7302991.9 i\u002Fs - 2.66x  slower\n```\n\n##### `Hash[]` vs `Hash#dup` [code](code\u002Fhash\u002Fbracket-vs-dup.rb)\n\nSource: http:\u002F\u002Ftenderlovemaking.com\u002F2015\u002F02\u002F11\u002Fweird-stuff-with-hashes.html\n\n> Does this mean that you should switch to Hash[]?\n> Only if your benchmarks can prove that it’s a bottleneck.\n> Please please please don’t change all of your code because\n> this shows it’s faster. Make sure to measure your app performance first.\n\n```\n$ ruby -v code\u002Fhash\u002Fbracket-vs-dup.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n              Hash[]   684.060k i\u002F100ms\n            Hash#dup   612.214k i\u002F100ms\nCalculating -------------------------------------\n              Hash[]      7.555M (± 2.8%) i\u002Fs  (132.37 ns\u002Fi) -     38.307M in   5.074888s\n            Hash#dup      5.851M (± 2.1%) i\u002Fs  (170.90 ns\u002Fi) -     29.386M in   5.024310s\n\nComparison:\n              Hash[]:  7554758.4 i\u002Fs\n            Hash#dup:  5851408.7 i\u002Fs - 1.29x  slower\n```\n\n##### `Hash#fetch` with argument vs `Hash#fetch` + block [code](code\u002Fhash\u002Ffetch-vs-fetch-with-block.rb)\n\n> Note that the speedup in the block version comes from avoiding repeated \u003Cbr>\n> construction of the argument. If the argument is a constant, number symbol or \u003Cbr>\n> something of that sort the argument version is actually slightly faster \u003Cbr>\n> See also [#39 (comment)](https:\u002F\u002Fgithub.com\u002Ffastruby\u002Ffast-ruby\u002Fissues\u002F39#issuecomment-103989335)\n\n```\n$ ruby -v code\u002Fhash\u002Ffetch-vs-fetch-with-block.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n  Hash#fetch + const     3.136M i\u002F100ms\n  Hash#fetch + block     3.313M i\u002F100ms\n    Hash#fetch + arg     2.266M i\u002F100ms\nCalculating -------------------------------------\n  Hash#fetch + const     32.198M (± 1.0%) i\u002Fs   (31.06 ns\u002Fi) -    163.090M in   5.065722s\n  Hash#fetch + block     33.319M (± 1.1%) i\u002Fs   (30.01 ns\u002Fi) -    168.953M in   5.071324s\n    Hash#fetch + arg     22.838M (± 1.3%) i\u002Fs   (43.79 ns\u002Fi) -    115.561M in   5.060964s\n\nComparison:\n  Hash#fetch + block: 33319415.6 i\u002Fs\n  Hash#fetch + const: 32198246.2 i\u002Fs - 1.03x  slower\n    Hash#fetch + arg: 22837560.4 i\u002Fs - 1.46x  slower\n```\n\n##### `Hash#each_key` instead of `Hash#keys.each` [code](code\u002Fhash\u002Fkeys-each-vs-each_key.rb)\n\n> `Hash#keys.each` allocates an array of keys;  \u003Cbr>\n> `Hash#each_key` iterates through the keys without allocating a new array.  \u003Cbr>\n> This is the reason why `Hash#each_key` exists.  \u003Cbr>\n> —— @sferik [rails\u002Frails#17099](https:\u002F\u002Fgithub.com\u002Frails\u002Frails\u002Fpull\u002F17099)\n\n```\n$ ruby -v code\u002Fhash\u002Fkeys-each-vs-each_key.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n      Hash#keys.each   494.495k i\u002F100ms\n       Hash#each_key   510.269k i\u002F100ms\nCalculating -------------------------------------\n      Hash#keys.each      5.026M (± 0.5%) i\u002Fs  (198.95 ns\u002Fi) -     25.219M in   5.017574s\n       Hash#each_key      5.118M (± 1.2%) i\u002Fs  (195.39 ns\u002Fi) -     26.024M in   5.085610s\n\nComparison:\n       Hash#each_key:  5117890.6 i\u002Fs\n      Hash#keys.each:  5026302.4 i\u002Fs - 1.02x  slower\n```\n\n#### `Hash#key?` instead of `Hash#keys.include?` [code](code\u002Fhash\u002Fkeys-include-vs-key.rb)\n\n> `Hash#keys.include?` allocates an array of keys and performs an O(n) search; \u003Cbr>\n> `Hash#key?` performs an O(1) hash lookup without allocating a new array.\n\n```\n$ ruby -v code\u002Fhash\u002Fkeys-include-vs-key.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n  Hash#keys.include?     2.217k i\u002F100ms\n           Hash#key?     2.683M i\u002F100ms\nCalculating -------------------------------------\n  Hash#keys.include?     26.005k (± 5.6%) i\u002Fs   (38.45 μs\u002Fi) -    130.803k in   5.047937s\n           Hash#key?     26.686M (± 1.3%) i\u002Fs   (37.47 ns\u002Fi) -    134.156M in   5.028106s\n\nComparison:\n           Hash#key?: 26685586.3 i\u002Fs\n  Hash#keys.include?:    26005.2 i\u002Fs - 1026.16x  slower\n```\n\n##### `Hash#value?` instead of `Hash#values.include?` [code](code\u002Fhash\u002Fvalues-include-vs-value.rb)\n\n> `Hash#values.include?` allocates an array of values and performs an O(n) search; \u003Cbr>\n> `Hash#value?` performs an O(n) search without allocating a new array.\n\n```\n$ ruby -v code\u002Fhash\u002Fvalues-include-vs-value.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\nHash#values.include?     5.620k i\u002F100ms\n         Hash#value?     7.474k i\u002F100ms\nCalculating -------------------------------------\nHash#values.include?     62.053k (± 2.8%) i\u002Fs   (16.12 μs\u002Fi) -    314.720k in   5.076009s\n         Hash#value?     71.151k (± 4.4%) i\u002Fs   (14.05 μs\u002Fi) -    358.752k in   5.051774s\n\nComparison:\n         Hash#value?:    71150.8 i\u002Fs\nHash#values.include?:    62052.8 i\u002Fs - 1.15x  slower\n```\n\n##### `Hash#merge!` vs `Hash#[]=` [code](code\u002Fhash\u002Fmerge-bang-vs-\\[\\]=.rb)\n\n```\n$ ruby -v code\u002Fhash\u002Fmerge-bang-vs-[]=.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n         Hash#merge!     8.974k i\u002F100ms\n            Hash#[]=    20.052k i\u002F100ms\nCalculating -------------------------------------\n         Hash#merge!     91.391k (± 0.5%) i\u002Fs   (10.94 μs\u002Fi) -    457.674k in   5.008010s\n            Hash#[]=    202.686k (± 0.9%) i\u002Fs    (4.93 μs\u002Fi) -      1.023M in   5.045877s\n\nComparison:\n            Hash#[]=:   202686.0 i\u002Fs\n         Hash#merge!:    91390.8 i\u002Fs - 2.22x  slower\n```\n\n##### `Hash#update` vs `Hash#[]=` [code](code\u002Fhash\u002Fupdate-vs-\\[\\]=.rb)\n\n```\n$ ruby -v code\u002Fhash\u002Fupdate-vs-[]=.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n            Hash#[]=    19.739k i\u002F100ms\n         Hash#update     9.126k i\u002F100ms\nCalculating -------------------------------------\n            Hash#[]=    202.714k (± 1.1%) i\u002Fs    (4.93 μs\u002Fi) -      1.026M in   5.064063s\n         Hash#update     91.615k (± 0.7%) i\u002Fs   (10.92 μs\u002Fi) -    465.426k in   5.080450s\n\nComparison:\n            Hash#[]=:   202713.9 i\u002Fs\n         Hash#update:    91615.2 i\u002Fs - 2.21x  slower\n```\n\n##### `Hash#merge` vs `Hash#**other` [code](code\u002Fhash\u002Fmerge-vs-double-splat-operator.rb)\n\n```\n$ ruby -v code\u002Fhash\u002Fmerge-vs-double-splat-operator.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n        Hash#**other   979.615k i\u002F100ms\n          Hash#merge   798.516k i\u002F100ms\nCalculating -------------------------------------\n        Hash#**other      9.846M (± 0.3%) i\u002Fs  (101.57 ns\u002Fi) -     49.960M in   5.074265s\n          Hash#merge      7.968M (± 0.3%) i\u002Fs  (125.50 ns\u002Fi) -     39.926M in   5.010730s\n\nComparison:\n        Hash#**other:  9845909.6 i\u002Fs\n          Hash#merge:  7968122.7 i\u002Fs - 1.24x  slower\n```\n\n##### `Hash#merge` vs `Hash#merge!` [code](code\u002Fhash\u002Fmerge-vs-merge-bang.rb)\n\n```\n$ ruby -v code\u002Fhash\u002Fmerge-vs-merge-bang.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n          Hash#merge     3.800k i\u002F100ms\n         Hash#merge!     9.310k i\u002F100ms\nCalculating -------------------------------------\n          Hash#merge     38.042k (± 1.9%) i\u002Fs   (26.29 μs\u002Fi) -    193.800k in   5.096234s\n         Hash#merge!     94.284k (± 0.4%) i\u002Fs   (10.61 μs\u002Fi) -    474.810k in   5.036016s\n\nComparison:\n         Hash#merge!:    94284.1 i\u002Fs\n          Hash#merge:    38041.7 i\u002Fs - 2.48x  slower\n```\n\n##### `{}#merge!(Hash)` vs `Hash#merge({})` vs `Hash#dup#merge!({})` [code](code\u002Fhash\u002Fmerge-bang-vs-merge-vs-dup-merge-bang.rb)\n\n> When we don't want to modify the original hash, and we want duplicates to be created \u003Cbr>\n> See [#42](https:\u002F\u002Fgithub.com\u002Ffastruby\u002Ffast-ruby\u002Fpull\u002F42#issue-93502261) for more details.\n\n```\n$ ruby -v code\u002Fhash\u002Fmerge-bang-vs-merge-vs-dup-merge-bang.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n{}#merge!(Hash) do end\n                        11.079k i\u002F100ms\n      Hash#merge({})     9.290k i\u002F100ms\n Hash#dup#merge!({})     6.957k i\u002F100ms\nCalculating -------------------------------------\n{}#merge!(Hash) do end\n                        111.999k (± 0.3%) i\u002Fs    (8.93 μs\u002Fi) -    565.029k in   5.045023s\n      Hash#merge({})     93.149k (± 0.4%) i\u002Fs   (10.74 μs\u002Fi) -    473.790k in   5.086441s\n Hash#dup#merge!({})     69.802k (± 0.4%) i\u002Fs   (14.33 μs\u002Fi) -    354.807k in   5.083113s\n\nComparison:\n{}#merge!(Hash) do end:   111998.6 i\u002Fs\n      Hash#merge({}):    93149.0 i\u002Fs - 1.20x  slower\n Hash#dup#merge!({}):    69802.3 i\u002Fs - 1.60x  slower\n```\n\n##### `Hash#sort_by` vs `Hash#sort` [code](code\u002Fhash\u002Fhash-key-sort_by-vs-sort.rb)\n\nTo sort hash by key.\n\n```\n$ ruby -v code\u002Fhash\u002Fhash-key-sort_by-vs-sort.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n      sort_by + to_h    72.056k i\u002F100ms\n         sort + to_h    26.595k i\u002F100ms\nCalculating -------------------------------------\n      sort_by + to_h    739.508k (± 0.7%) i\u002Fs    (1.35 μs\u002Fi) -      3.747M in   5.067024s\n         sort + to_h    269.700k (± 1.9%) i\u002Fs    (3.71 μs\u002Fi) -      1.356M in   5.030958s\n\nComparison:\n      sort_by + to_h:   739507.8 i\u002Fs\n         sort + to_h:   269700.3 i\u002Fs - 2.74x  slower\n```\n\n##### Native `Hash#slice` vs other slice implementations before native [code](code\u002Fhash\u002Fslice-native-vs-before-native.rb)\n\nSince ruby 2.5, Hash comes with a `slice` method to select hash members by keys.\n\n```\n$ ruby -v code\u002Fhash\u002Fslice-native-vs-before-native.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\nHash#native-slice        1.024M i\u002F100ms\nArray#each             467.292k i\u002F100ms\nArray#each_w\u002F_object   388.528k i\u002F100ms\nHash#select-include    131.358k i\u002F100ms\nCalculating -------------------------------------\nHash#native-slice        10.550M (± 1.4%) i\u002Fs   (94.78 ns\u002Fi) -     53.251M in   5.048257s\nArray#each                4.688M (± 0.5%) i\u002Fs  (213.30 ns\u002Fi) -     23.832M in   5.083384s\nArray#each_w\u002F_object      3.890M (± 0.4%) i\u002Fs  (257.07 ns\u002Fi) -     19.815M in   5.093848s\nHash#select-include       1.343M (± 1.7%) i\u002Fs  (744.63 ns\u002Fi) -      6.831M in   5.087848s\n\nComparison:\nHash#native-slice   : 10550464.1 i\u002Fs\nArray#each          :  4688305.3 i\u002Fs - 2.25x  slower\nArray#each_w\u002F_object:  3890033.7 i\u002Fs - 2.71x  slower\nHash#select-include :  1342942.2 i\u002Fs - 7.86x  slower\n```\n\n\n### Proc & Block\n\n##### Block vs `Symbol#to_proc` [code](code\u002Fproc-and-block\u002Fblock-vs-to_proc.rb)\n\n> `Symbol#to_proc` is considerably more concise than using block syntax. \u003Cbr>\n> ...In some cases, it reduces the number of lines of code. \u003Cbr>\n> —— @sferik [rails\u002Frails#16833](https:\u002F\u002Fgithub.com\u002Frails\u002Frails\u002Fpull\u002F16833)\n\n```\n$ ruby -v code\u002Fproc-and-block\u002Fblock-vs-to_proc.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n               Block    20.147k i\u002F100ms\n      Symbol#to_proc    22.231k i\u002F100ms\nCalculating -------------------------------------\n               Block    202.937k (± 0.4%) i\u002Fs    (4.93 μs\u002Fi) -      1.027M in   5.063220s\n      Symbol#to_proc    222.450k (± 0.9%) i\u002Fs    (4.50 μs\u002Fi) -      1.134M in   5.097179s\n\nComparison:\n      Symbol#to_proc:   222449.5 i\u002Fs\n               Block:   202937.5 i\u002Fs - 1.10x  slower\n```\n\n##### `Proc#call` and block arguments vs `yield` [code](code\u002Fproc-and-block\u002Fproc-call-vs-yield.rb)\n\n```\n$ ruby -v code\u002Fproc-and-block\u002Fproc-call-vs-yield.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n          block.call     2.261M i\u002F100ms\n       block + yield     2.314M i\u002F100ms\n        unused block     3.025M i\u002F100ms\n               yield     2.971M i\u002F100ms\nCalculating -------------------------------------\n          block.call     22.057M (± 6.0%) i\u002Fs   (45.34 ns\u002Fi) -    110.796M in   5.043129s\n       block + yield     23.280M (± 0.6%) i\u002Fs   (42.96 ns\u002Fi) -    117.997M in   5.068779s\n        unused block     30.609M (± 1.3%) i\u002Fs   (32.67 ns\u002Fi) -    154.268M in   5.040991s\n               yield     29.921M (± 0.6%) i\u002Fs   (33.42 ns\u002Fi) -    151.512M in   5.063842s\n\nComparison:\n        unused block: 30608512.5 i\u002Fs\n               yield: 29921356.8 i\u002Fs - 1.02x  slower\n       block + yield: 23279981.0 i\u002Fs - 1.31x  slower\n          block.call: 22056758.6 i\u002Fs - 1.39x  slower\n```\n\n### String\n\n##### `String#dup` vs `String#+` [code](code\u002Fstring\u002Fdup-vs-unary-plus.rb)\n\nNote that `String.new` is not the same as the options compared, since it is\nalways `ASCII-8BIT` encoded instead of the script encoding (usually `UTF-8`).\n\n```\n$ ruby -v code\u002Fstring\u002Fdup-vs-unary-plus.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n           String#+@     2.439M i\u002F100ms\n          String#dup     2.481M i\u002F100ms\nCalculating -------------------------------------\n           String#+@     24.328M (± 0.5%) i\u002Fs   (41.10 ns\u002Fi) -    121.962M in   5.013305s\n          String#dup     24.553M (± 1.0%) i\u002Fs   (40.73 ns\u002Fi) -    124.040M in   5.052462s\n\nComparison:\n          String#dup: 24552887.2 i\u002Fs\n           String#+@: 24328187.6 i\u002Fs - same-ish: difference falls within error\n```\n\n##### `String#casecmp` vs  `String#casecmp?` vs `String#downcase + ==` [code](code\u002Fstring\u002Fcasecmp-vs-downcase-==.rb)\n\n`String#casecmp?` is available on Ruby 2.4 or later.\nNote that `String#casecmp` only works on characters A-Z\u002Fa-z, not all of Unicode.\n\n```\n$ ruby -v code\u002Fstring\u002Fcasecmp-vs-downcase-==.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n     String#casecmp?     1.053M i\u002F100ms\nString#downcase + ==     1.467M i\u002F100ms\n      String#casecmp     1.816M i\u002F100ms\nCalculating -------------------------------------\n     String#casecmp?     10.916M (± 1.4%) i\u002Fs   (91.61 ns\u002Fi) -     54.769M in   5.018429s\nString#downcase + ==     14.673M (± 1.0%) i\u002Fs   (68.15 ns\u002Fi) -     74.808M in   5.098814s\n      String#casecmp     18.210M (± 0.7%) i\u002Fs   (54.91 ns\u002Fi) -     92.594M in   5.084879s\n\nComparison:\n      String#casecmp: 18210413.9 i\u002Fs\nString#downcase + ==: 14673089.8 i\u002Fs - 1.24x  slower\n     String#casecmp?: 10915954.0 i\u002Fs - 1.67x  slower\n```\n\n##### String Concatenation [code](code\u002Fstring\u002Fconcatenation.rb)\n\n```\n$ ruby -v code\u002Fstring\u002Fconcatenation.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n            String#+     1.214M i\u002F100ms\n       String#concat     1.407M i\u002F100ms\n       String#append     1.561M i\u002F100ms\n         \"foo\" \"bar\"     2.723M i\u002F100ms\n  \"#{'foo'}#{'bar'}\"     2.914M i\u002F100ms\nCalculating -------------------------------------\n            String#+     12.616M (± 0.9%) i\u002Fs   (79.27 ns\u002Fi) -     63.138M in   5.005092s\n       String#concat     14.555M (± 1.1%) i\u002Fs   (68.71 ns\u002Fi) -     73.188M in   5.029155s\n       String#append     15.844M (± 0.7%) i\u002Fs   (63.12 ns\u002Fi) -     79.634M in   5.026390s\n         \"foo\" \"bar\"     27.318M (± 0.8%) i\u002Fs   (36.61 ns\u002Fi) -    138.888M in   5.084517s\n  \"#{'foo'}#{'bar'}\"     29.063M (± 0.5%) i\u002Fs   (34.41 ns\u002Fi) -    145.707M in   5.013531s\n\nComparison:\n  \"#{'foo'}#{'bar'}\": 29063458.4 i\u002Fs\n         \"foo\" \"bar\": 27317882.5 i\u002Fs - 1.06x  slower\n       String#append: 15843896.8 i\u002Fs - 1.83x  slower\n       String#concat: 14554534.2 i\u002Fs - 2.00x  slower\n            String#+: 12615859.7 i\u002Fs - 2.30x  slower\n```\n\n##### `String#match` vs `String.match?` vs `String#start_with?`\u002F`String#end_with?` [code (start)](code\u002Fstring\u002Fstart-string-checking-match-vs-start_with.rb) [code (end)](code\u002Fstring\u002Fend-string-checking-match-vs-end_with.rb)\n\nThe regular expression approaches become slower as the tested string becomes\nlonger. For short strings, `String#match?` performs similarly to\n`String#start_with?`\u002F`String#end_with?`.\n\n> :warning: \u003Cbr>\n> Sometimes you cant replace regexp with `start_with?`, \u003Cbr>\n> for example: `\"a\\nb\" =~ \u002F^b\u002F #=> 2` but `\"a\\nb\" =~ \u002F\\Ab\u002F #=> nil`.\u003Cbr>\n> :warning: \u003Cbr>\n\n```\n$ ruby -v code\u002Fstring\u002Fstart-string-checking-match-vs-start_with.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n           String#=~   704.323k i\u002F100ms\n       String#match?     1.696M i\u002F100ms\n  String#start_with?     2.002M i\u002F100ms\nCalculating -------------------------------------\n           String#=~      7.155M (± 0.9%) i\u002Fs  (139.76 ns\u002Fi) -     35.920M in   5.020673s\n       String#match?     17.088M (± 0.7%) i\u002Fs   (58.52 ns\u002Fi) -     86.478M in   5.061156s\n  String#start_with?     20.186M (± 1.0%) i\u002Fs   (49.54 ns\u002Fi) -    102.087M in   5.057969s\n\nComparison:\n  String#start_with?: 20185554.4 i\u002Fs\n       String#match?: 17087554.1 i\u002Fs - 1.18x  slower\n           String#=~:  7155069.8 i\u002Fs - 2.82x  slower\n```\n\n```\n$ ruby -v code\u002Fstring\u002Fend-string-checking-match-vs-end_with.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n           String#=~   459.289k i\u002F100ms\n       String#match?   808.294k i\u002F100ms\n    String#end_with?     1.358M i\u002F100ms\nCalculating -------------------------------------\n           String#=~      4.900M (± 0.7%) i\u002Fs  (204.10 ns\u002Fi) -     24.802M in   5.062282s\n       String#match?      7.999M (± 3.2%) i\u002Fs  (125.02 ns\u002Fi) -     40.415M in   5.058576s\n    String#end_with?     13.797M (± 0.9%) i\u002Fs   (72.48 ns\u002Fi) -     69.248M in   5.019420s\n\nComparison:\n    String#end_with?: 13797085.6 i\u002Fs\n       String#match?:  7998569.4 i\u002Fs - 1.72x  slower\n           String#=~:  4899556.6 i\u002Fs - 2.82x  slower\n```\n\n##### `String#start_with?` vs `String#[].==` [code](code\u002Fstring\u002Fstart_with-vs-substring-==.rb)\n\n```\n$ ruby -v code\u002Fstring\u002Fstart_with-vs-substring-==.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n  String#start_with?   405.198k i\u002F100ms\n    String#[0, n] ==   185.548k i\u002F100ms\n   String#[RANGE] ==   183.537k i\u002F100ms\n   String#[0...n] ==   111.844k i\u002F100ms\nCalculating -------------------------------------\n  String#start_with?      4.336M (± 1.7%) i\u002Fs  (230.64 ns\u002Fi) -     21.881M in   5.048171s\n    String#[0, n] ==      1.911M (± 1.8%) i\u002Fs  (523.18 ns\u002Fi) -      9.648M in   5.049643s\n   String#[RANGE] ==      1.835M (± 1.4%) i\u002Fs  (544.95 ns\u002Fi) -      9.177M in   5.001963s\n   String#[0...n] ==      1.100M (± 1.5%) i\u002Fs  (909.34 ns\u002Fi) -      5.592M in   5.086419s\n\nComparison:\n  String#start_with?:  4335677.0 i\u002Fs\n    String#[0, n] ==:  1911392.8 i\u002Fs - 2.27x  slower\n   String#[RANGE] ==:  1835034.3 i\u002Fs - 2.36x  slower\n   String#[0...n] ==:  1099697.5 i\u002Fs - 3.94x  slower\n```\n\n##### `Regexp#===` vs `Regexp#match` vs `Regexp#match?` vs `String#match` vs `String#=~` vs `String#match?` [code ](code\u002Fstring\u002F===-vs-=~-vs-match.rb)\n\n`String#match?` and `Regexp#match?` are available on Ruby 2.4 or later.\nActiveSupport [provides](http:\u002F\u002Fguides.rubyonrails.org\u002Fv5.1\u002Factive_support_core_extensions.html#match-questionmark)\na forward compatible extension of `Regexp` for older Rubies without the speed\nimprovement.\n\n> :warning: \u003Cbr>\n> Sometimes you can't replace `match` with `match?`, \u003Cbr>\n> This is only useful for cases where you are checking \u003Cbr>\n> for a match and not using the resultant match object. \u003Cbr>\n> :warning: \u003Cbr>\n> `Regexp#===` is also faster than `String#match` but you need to switch the order of arguments.\n\n```\n$ ruby -v code\u002Fstring\u002F===-vs-=~-vs-match.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n       Regexp#match?     2.240M i\u002F100ms\n       String#match?     2.271M i\u002F100ms\n           String#=~     1.322M i\u002F100ms\n          Regexp#===     1.252M i\u002F100ms\n        Regexp#match     1.187M i\u002F100ms\n        String#match     1.024M i\u002F100ms\nCalculating -------------------------------------\n       Regexp#match?     22.395M (± 1.3%) i\u002Fs   (44.65 ns\u002Fi) -    111.995M in   5.001594s\n       String#match?     22.544M (± 1.4%) i\u002Fs   (44.36 ns\u002Fi) -    113.533M in   5.037001s\n           String#=~     13.285M (± 2.6%) i\u002Fs   (75.27 ns\u002Fi) -     67.438M in   5.079611s\n          Regexp#===     12.472M (± 0.6%) i\u002Fs   (80.18 ns\u002Fi) -     62.618M in   5.020860s\n        Regexp#match     11.865M (± 0.8%) i\u002Fs   (84.28 ns\u002Fi) -     59.340M in   5.001611s\n        String#match     10.223M (± 0.7%) i\u002Fs   (97.81 ns\u002Fi) -     51.194M in   5.007796s\n\nComparison:\n       String#match?: 22544340.1 i\u002Fs\n       Regexp#match?: 22395457.7 i\u002Fs - same-ish: difference falls within error\n           String#=~: 13285297.2 i\u002Fs - 1.70x  slower\n          Regexp#===: 12471978.3 i\u002Fs - 1.81x  slower\n        Regexp#match: 11864949.7 i\u002Fs - 1.90x  slower\n        String#match: 10223419.6 i\u002Fs - 2.21x  slower\n```\n\nSee [#59](https:\u002F\u002Fgithub.com\u002Ffastruby\u002Ffast-ruby\u002Fpull\u002F59) and [#62](https:\u002F\u002Fgithub.com\u002Ffastruby\u002Ffast-ruby\u002Fpull\u002F62) for discussions.\n\n\n##### `String#gsub` vs `String#sub` vs `String#[]=` [code](code\u002Fstring\u002Fgsub-vs-sub.rb)\n\n```\n$ ruby -v code\u002Fstring\u002Fgsub-vs-sub.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n         String#gsub   230.980k i\u002F100ms\n          String#sub   465.575k i\u002F100ms\nString#dup[\"string\"]=\n                       838.284k i\u002F100ms\nCalculating -------------------------------------\n         String#gsub      2.338M (± 0.9%) i\u002Fs  (427.64 ns\u002Fi) -     11.780M in   5.038072s\n          String#sub      4.691M (± 1.2%) i\u002Fs  (213.16 ns\u002Fi) -     23.744M in   5.062169s\nString#dup[\"string\"]=\n                          8.433M (± 1.0%) i\u002Fs  (118.58 ns\u002Fi) -     42.752M in   5.070311s\n\nComparison:\nString#dup[\"string\"]=:  8432793.1 i\u002Fs\n          String#sub:  4691246.0 i\u002Fs - 1.80x  slower\n         String#gsub:  2338396.7 i\u002Fs - 3.61x  slower\n```\n\n##### `String#gsub` vs `String#tr` [code](code\u002Fstring\u002Fgsub-vs-tr.rb)\n\n> [rails\u002Frails#17257](https:\u002F\u002Fgithub.com\u002Frails\u002Frails\u002Fpull\u002F17257)\n\n```\n$ ruby -v code\u002Fstring\u002Fgsub-vs-tr.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n         String#gsub   297.314k i\u002F100ms\n           String#tr   914.116k i\u002F100ms\nCalculating -------------------------------------\n         String#gsub      3.032M (± 0.8%) i\u002Fs  (329.83 ns\u002Fi) -     15.163M in   5.001554s\n           String#tr      9.136M (± 0.8%) i\u002Fs  (109.46 ns\u002Fi) -     45.706M in   5.003201s\n\nComparison:\n           String#tr:  9135960.5 i\u002Fs\n         String#gsub:  3031853.2 i\u002Fs - 3.01x  slower\n```\n\n##### `String#gsub` vs `String#tr` vs `String#delete` [code](code\u002Fstring\u002Fgsub-vs-tr-vs-delete.rb)\n\n```\n$ ruby -v code\u002Fstring\u002Fgsub-vs-tr-vs-delete.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n         String#gsub   314.117k i\u002F100ms\n           String#tr   989.154k i\u002F100ms\n       String#delete     1.159M i\u002F100ms\n String#delete const     1.320M i\u002F100ms\nCalculating -------------------------------------\n         String#gsub      3.099M (± 1.1%) i\u002Fs  (322.65 ns\u002Fi) -     15.706M in   5.068096s\n           String#tr      9.868M (± 1.3%) i\u002Fs  (101.34 ns\u002Fi) -     49.458M in   5.012992s\n       String#delete     11.623M (± 0.6%) i\u002Fs   (86.03 ns\u002Fi) -     59.109M in   5.085570s\n String#delete const     13.192M (± 0.8%) i\u002Fs   (75.80 ns\u002Fi) -     65.989M in   5.002525s\n\nComparison:\n String#delete const: 13191917.5 i\u002Fs\n       String#delete: 11623217.0 i\u002Fs - 1.13x  slower\n           String#tr:  9867528.0 i\u002Fs - 1.34x  slower\n         String#gsub:  3099363.7 i\u002Fs - 4.26x  slower\n```\n\n##### `Mutable` vs `Immutable` [code](code\u002Fstring\u002Fmutable_vs_immutable_strings.rb)\n\n```\n$ ruby -v code\u002Fstring\u002Fmutable_vs_immutable_strings.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n      Without Freeze     2.671M i\u002F100ms\n         With Freeze     4.464M i\u002F100ms\nCalculating -------------------------------------\n      Without Freeze     27.091M (± 1.6%) i\u002Fs   (36.91 ns\u002Fi) -    136.216M in   5.029377s\n         With Freeze     44.763M (± 0.9%) i\u002Fs   (22.34 ns\u002Fi) -    227.646M in   5.085943s\n\nComparison:\n         With Freeze: 44763124.8 i\u002Fs\n      Without Freeze: 27091288.1 i\u002Fs - 1.65x  slower\n```\n\n\n##### `String#sub!` vs `String#gsub!` vs `String#[]=` [code](code\u002Fstring\u002Fsub!-vs-gsub!-vs-[]=.rb)\n\nNote that `String#[]` will throw an `IndexError` when given string or regexp not matched.\n\n```\n$ ruby -v code\u002Fstring\u002Fsub!-vs-gsub!-vs-[]=.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n  String#['string']=   867.608k i\u002F100ms\n String#sub!'string'   452.774k i\u002F100ms\nString#gsub!'string'   219.002k i\u002F100ms\n  String#[\u002Fregexp\u002F]=   484.258k i\u002F100ms\n String#sub!\u002Fregexp\u002F   439.965k i\u002F100ms\nString#gsub!\u002Fregexp\u002F   222.202k i\u002F100ms\nCalculating -------------------------------------\n  String#['string']=      8.875M (± 0.9%) i\u002Fs  (112.67 ns\u002Fi) -     45.116M in   5.083636s\n String#sub!'string'      4.648M (± 0.6%) i\u002Fs  (215.15 ns\u002Fi) -     23.544M in   5.065834s\nString#gsub!'string'      2.234M (± 0.6%) i\u002Fs  (447.72 ns\u002Fi) -     11.169M in   5.000776s\n  String#[\u002Fregexp\u002F]=      4.913M (± 0.6%) i\u002Fs  (203.54 ns\u002Fi) -     24.697M in   5.026953s\n String#sub!\u002Fregexp\u002F      4.474M (± 0.4%) i\u002Fs  (223.50 ns\u002Fi) -     22.438M in   5.014974s\nString#gsub!\u002Fregexp\u002F      2.221M (± 0.7%) i\u002Fs  (450.25 ns\u002Fi) -     11.110M in   5.002620s\n\nComparison:\n  String#['string']=:  8875438.0 i\u002Fs\n  String#[\u002Fregexp\u002F]=:  4913121.6 i\u002Fs - 1.81x  slower\n String#sub!'string':  4647843.8 i\u002Fs - 1.91x  slower\n String#sub!\u002Fregexp\u002F:  4474302.7 i\u002Fs - 1.98x  slower\nString#gsub!'string':  2233558.9 i\u002Fs - 3.97x  slower\nString#gsub!\u002Fregexp\u002F:  2220978.6 i\u002Fs - 4.00x  slower\n```\n\n##### `String#sub` vs `String#delete_prefix` [code](code\u002Fstring\u002Fsub-vs-delete_prefix.rb)\n\n[Ruby 2.5 introduced](https:\u002F\u002Fbugs.ruby-lang.org\u002Fissues\u002F12694) `String#delete_prefix`.\nNote that this can only be used for removing characters from the start of a string.\n\n```\n$ ruby -v code\u002Fstring\u002Fsub-vs-delete_prefix.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\nString#delete_prefix     1.446M i\u002F100ms\n          String#sub   473.108k i\u002F100ms\nCalculating -------------------------------------\nString#delete_prefix     14.867M (± 1.3%) i\u002Fs   (67.26 ns\u002Fi) -     75.200M in   5.059147s\n          String#sub      4.726M (± 0.7%) i\u002Fs  (211.58 ns\u002Fi) -     23.655M in   5.005369s\n\nComparison:\nString#delete_prefix: 14866723.8 i\u002Fs\n          String#sub:  4726255.3 i\u002Fs - 3.15x  slower\n```\n\n##### `String#sub` vs `String#chomp` vs `String#delete_suffix` [code](code\u002Fstring\u002Fsub-vs-chomp-vs-delete_suffix.rb)\n\n[Ruby 2.5 introduced](https:\u002F\u002Fbugs.ruby-lang.org\u002Fissues\u002F13665) `String#delete_suffix`\nas a counterpart to `delete_prefix`. The performance gain over `chomp` is\nsmall and during some runs the difference falls within the error margin.\nNote that this can only be used for removing characters from the end of a string.\n\n```\n$ ruby -v code\u002Fstring\u002Fsub-vs-chomp-vs-delete_suffix.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n          String#sub   472.278k i\u002F100ms\n        String#chomp     1.354M i\u002F100ms\nString#delete_suffix     1.477M i\u002F100ms\nCalculating -------------------------------------\n          String#sub      4.809M (± 1.0%) i\u002Fs  (207.93 ns\u002Fi) -     24.086M in   5.008842s\n        String#chomp     13.829M (± 1.2%) i\u002Fs   (72.31 ns\u002Fi) -     70.425M in   5.093208s\nString#delete_suffix     14.936M (± 0.9%) i\u002Fs   (66.95 ns\u002Fi) -     75.317M in   5.042961s\n\nComparison:\nString#delete_suffix: 14936380.8 i\u002Fs\n        String#chomp: 13829135.7 i\u002Fs - 1.08x  slower\n          String#sub:  4809249.5 i\u002Fs - 3.11x  slower\n```\n\n##### `String#unpack1` vs `String#unpack[0]` [code](code\u002Fstring\u002Funpack1-vs-unpack[0].rb)\n\n[Ruby 2.4.0 introduced `unpack1`](https:\u002F\u002Fbugs.ruby-lang.org\u002Fissues\u002F12752) to skip creating the intermediate array object.\n\n```\n$ ruby -v code\u002Fstring\u002Funpack1-vs-unpack[0].rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n      String#unpack1     1.372M i\u002F100ms\n    String#unpack[0]     1.095M i\u002F100ms\nCalculating -------------------------------------\n      String#unpack1     14.219M (± 0.7%) i\u002Fs   (70.33 ns\u002Fi) -     71.349M in   5.018051s\n    String#unpack[0]     11.071M (± 1.2%) i\u002Fs   (90.33 ns\u002Fi) -     55.839M in   5.044380s\n\nComparison:\n      String#unpack1: 14219190.8 i\u002Fs\n    String#unpack[0]: 11071030.6 i\u002Fs - 1.28x  slower\n```\n\n##### Remove extra spaces (or other contiguous characters) [code](code\u002Fstring\u002Fremove-extra-spaces-or-other-chars.rb)\n\nThe code is tested against contiguous spaces but should work for other chars too.\n\n```\n$ ruby -v code\u002Fstring\u002Fremove-extra-spaces-or-other-chars.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n String#gsub\u002Fregex+\u002F    15.087k i\u002F100ms\n      String#squeeze   429.561k i\u002F100ms\nCalculating -------------------------------------\n String#gsub\u002Fregex+\u002F    152.509k (± 0.6%) i\u002Fs    (6.56 μs\u002Fi) -    769.437k in   5.045412s\n      String#squeeze      4.264M (± 1.7%) i\u002Fs  (234.51 ns\u002Fi) -     21.478M in   5.038218s\n\nComparison:\n      String#squeeze:  4264261.4 i\u002Fs\n String#gsub\u002Fregex+\u002F:   152508.7 i\u002Fs - 27.96x  slower\n```\n\n### Time\n\n##### `Time.iso8601` vs `Time.parse` [code](code\u002Ftime\u002Fiso8601-vs-parse.rb)\n\nWhen expecting well-formatted data from e.g. an API, `iso8601` is faster and will raise an `ArgumentError` on malformed input.\n\n```\n$ ruby -v code\u002Ftime\u002Fiso8601-vs-parse.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n        Time.iso8601   105.846k i\u002F100ms\n          Time.parse    19.826k i\u002F100ms\nCalculating -------------------------------------\n        Time.iso8601      1.076M (± 0.5%) i\u002Fs  (929.16 ns\u002Fi) -      5.398M in   5.015850s\n          Time.parse    200.370k (± 0.8%) i\u002Fs    (4.99 μs\u002Fi) -      1.011M in   5.046598s\n\nComparison:\n        Time.iso8601:  1076241.3 i\u002Fs\n          Time.parse:   200370.2 i\u002Fs - 5.37x  slower\n```\n\n### Range\n\n##### `cover?` vs `include?` [code](code\u002Frange\u002Fcover-vs-include.rb)\n\n`cover?` only check if it is within the start and end, `include?` needs to traverse the whole range.\n\n```\n$ ruby -v code\u002Frange\u002Fcover-vs-include.rb\nruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [arm64-darwin24]\nWarming up --------------------------------------\n        range#cover?   811.176k i\u002F100ms\n      range#include?    34.101k i\u002F100ms\n       range#member?    35.591k i\u002F100ms\n       plain compare     1.131M i\u002F100ms\n      value.between?     1.520M i\u002F100ms\nCalculating -------------------------------------\n        range#cover?      8.324M (± 0.3%) i\u002Fs  (120.14 ns\u002Fi) -     42.181M in   5.067623s\n      range#include?    352.846k (± 1.7%) i\u002Fs    (2.83 μs\u002Fi) -      1.773M in   5.027064s\n       range#member?    349.526k (± 1.9%) i\u002Fs    (2.86 μs\u002Fi) -      1.780M in   5.093144s\n       plain compare     11.296M (± 1.3%) i\u002Fs   (88.53 ns\u002Fi) -     56.554M in   5.007498s\n      value.between?     15.214M (± 0.9%) i\u002Fs   (65.73 ns\u002Fi) -     77.527M in   5.096183s\n\nComparison:\n      value.between?: 15213944.1 i\u002Fs\n       plain compare: 11295903.4 i\u002Fs - 1.35x  slower\n        range#cover?:  8323723.8 i\u002Fs - 1.83x  slower\n      range#include?:   352846.2 i\u002Fs - 43.12x  slower\n       range#member?:   349526.0 i\u002Fs - 43.53x  slower\n```\n\n\n## Less idiomatic but with significant performance ruby\n\nCheckout: https:\u002F\u002Fgithub.com\u002Ffastruby\u002Ffast-ruby\u002Fwiki\u002FLess-idiomatic-but-with-significant-performance-difference\n\n\n## Submit New Entry\n\nPlease! [Edit this README.md](https:\u002F\u002Fgithub.com\u002Ffastruby\u002Ffast-ruby\u002Fedit\u002Fmain\u002FREADME.md) then [Submit a Awesome Pull Request](https:\u002F\u002Fgithub.com\u002Ffastruby\u002Ffast-ruby\u002Fpulls)!\n\n\n## Something went wrong\n\nCode example is wrong? :cry: Got better example? :heart_eyes: Excellent!\n\n[Please open an issue](https:\u002F\u002Fgithub.com\u002Ffastruby\u002Ffast-ruby\u002Fissues\u002Fnew) or [Open a Pull","Fast Ruby 是一个专注于收集和分享 Ruby 编程中高效编码习惯的项目。它通过对比不同实现方式的性能，帮助开发者编写更快的 Ruby 代码。项目利用 benchmark-ips 工具进行基准测试，并提供详细的代码示例来展示各种常见操作如数组、哈希表、字符串等的最佳实践。此外，Fast Ruby 还推荐了 fasterer 静态分析工具以辅助识别代码中的潜在性能瓶颈。适合那些希望优化现有 Ruby 应用程序性能或学习如何从一开始就写出更高效代码的开发者使用。","2026-06-11 03:13:57","top_language"]