Skip to content

Commit 7874ea8

Browse files
committed
Update Proc#call and block arguments vs yield for Ruby 2.5
In Ruby 2.5, passing through a `block` argument has become a lot faster. I renamed the 'block argument' benchmark because I felt the old name was misleading as the fastest on Ruby 2.5.
1 parent dff1d87 commit 7874ea8

File tree

2 files changed

+29
-16
lines changed

2 files changed

+29
-16
lines changed

README.md

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -963,27 +963,40 @@ Comparison:
963963

964964
##### `Proc#call` and block arguments vs `yield`[code](code/proc-and-block/proc-call-vs-yield.rb)
965965

966-
In MRI Ruby, block arguments [are converted to Procs](https://www.omniref.com/ruby/2.2.0/symbols/Proc/yield?#annotation=4087638&line=711), which incurs a heap allocation.
966+
In MRI Ruby before 2.5, block arguments [are converted to Procs](https://www.omniref.com/ruby/2.2.0/symbols/Proc/yield?#annotation=4087638&line=711), which incurs a heap allocation.
967967

968968
```
969969
$ ruby -v code/proc-and-block/proc-call-vs-yield.rb
970-
ruby 2.2.3p173 (2015-08-18 revision 51636) [x86_64-darwin15]
970+
ruby 2.4.4p296 (2018-03-28 revision 63013) [x86_64-darwin17]
971971
Calculating -------------------------------------
972-
block.call 41.978k i/100ms
973-
block + yield 42.674k i/100ms
974-
block argument 41.722k i/100ms
975-
yield 62.681k i/100ms
976-
-------------------------------------------------
977-
block.call 842.581k (±12.5%) i/s - 4.114M
978-
block + yield 941.468k (±11.7%) i/s - 4.651M
979-
block argument 1.043M (± 7.1%) i/s - 5.215M
980-
yield 3.828M (±11.3%) i/s - 18.930M
972+
block.call 1.761M (± 1.7%) i/s - 8.854M in 5.028508s
973+
block + yield 1.910M (± 1.9%) i/s - 9.627M in 5.041105s
974+
unused block 2.045M (± 1.7%) i/s - 10.290M in 5.033036s
975+
yield 8.568M (± 1.7%) i/s - 43.004M in 5.020998s
976+
977+
Comparison:
978+
yield: 8567538.2 i/s
979+
unused block: 2045057.9 i/s - 4.19x slower
980+
block + yield: 1910340.9 i/s - 4.48x slower
981+
block.call: 1761210.1 i/s - 4.86x slower
982+
```
983+
984+
MRI Ruby 2.5 implements [Lazy Proc allocation for block parameters](https://bugs.ruby-lang.org/issues/14045):
985+
986+
```
987+
$ ruby -v code/proc-and-block/proc-call-vs-yield.rb
988+
ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-darwin17]
989+
Calculating -------------------------------------
990+
block.call 1.738M (± 2.0%) i/s - 8.771M in 5.048684s
991+
block + yield 7.503M (± 1.6%) i/s - 37.593M in 5.011670s
992+
unused block 8.914M (± 2.2%) i/s - 44.656M in 5.012279s
993+
yield 8.537M (± 2.1%) i/s - 42.681M in 5.002066s
981994
982995
Comparison:
983-
yield: 3828436.1 i/s
984-
block argument: 1042509.6 i/s - 3.67x slower
985-
block + yield: 941467.7 i/s - 4.07x slower
986-
block.call: 842581.2 i/s - 4.54x slower
996+
unused block: 8913860.7 i/s
997+
yield: 8536544.5 i/s - 1.04x slower
998+
block + yield: 7503151.2 i/s - 1.19x slower
999+
block.call: 1737948.9 i/s - 5.13x slower
9871000
```
9881001

9891002

code/proc-and-block/proc-call-vs-yield.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ def fast
1919
Benchmark.ips do |x|
2020
x.report('block.call') { slow { 1 + 1 } }
2121
x.report('block + yield') { slow2 { 1 + 1 } }
22-
x.report('block argument') { slow3 { 1 + 1 } }
22+
x.report('unused block') { slow3 { 1 + 1 } }
2323
x.report('yield') { fast { 1 + 1 } }
2424
x.compare!
2525
end

0 commit comments

Comments
 (0)