Skip to content

Commit 013fa34

Browse files
authored
Merge pull request #163 from bdewater/update-proc-call-vs-yield
Update `Proc#call` and block arguments vs `yield` for Ruby 2.5 and 2.6
2 parents dff1d87 + 7a52c19 commit 013fa34

File tree

2 files changed

+46
-16
lines changed

2 files changed

+46
-16
lines changed

README.md

+45-15
Original file line numberDiff line numberDiff line change
@@ -963,29 +963,59 @@ 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-darwin18]
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.967M (± 2.0%) i/s - 9.871M in 5.019328s
973+
block + yield 2.147M (± 3.3%) i/s - 10.814M in 5.044319s
974+
unused block 2.265M (± 1.9%) i/s - 11.333M in 5.004522s
975+
yield 10.436M (± 1.6%) i/s - 52.260M in 5.008851s
976+
977+
Comparison:
978+
yield: 10436414.0 i/s
979+
unused block: 2265399.0 i/s - 4.61x slower
980+
block + yield: 2146619.0 i/s - 4.86x slower
981+
block.call: 1967300.9 i/s - 5.30x 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.3p105 (2018-10-18 revision 65156) [x86_64-darwin18]
989+
Calculating -------------------------------------
990+
block.call 1.970M (± 2.3%) i/s - 9.863M in 5.009599s
991+
block + yield 9.075M (± 2.6%) i/s - 45.510M in 5.018369s
992+
unused block 11.176M (± 2.7%) i/s - 55.977M in 5.012741s
993+
yield 10.588M (± 1.9%) i/s - 53.108M in 5.017755s
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: 11176355.0 i/s
997+
yield: 10588342.3 i/s - 1.06x slower
998+
block + yield: 9075355.5 i/s - 1.23x slower
999+
block.call: 1969834.0 i/s - 5.67x slower
1000+
```
1001+
1002+
MRI Ruby 2.6 implements [an optimization for block.call where a block parameter is passed](https://bugs.ruby-lang.org/issues/14330):
1003+
9871004
```
1005+
$ ruby -v code/proc-and-block/proc-call-vs-yield.rb
1006+
ruby 2.6.1p33 (2019-01-30 revision 66950) [x86_64-darwin18]
1007+
Calculating -------------------------------------
1008+
block.call 10.587M (± 1.2%) i/s - 52.969M in 5.003808s
1009+
block + yield 12.630M (± 0.3%) i/s - 63.415M in 5.020910s
1010+
unused block 15.981M (± 0.8%) i/s - 80.255M in 5.022305s
1011+
yield 15.352M (± 3.1%) i/s - 76.816M in 5.009404s
9881012
1013+
Comparison:
1014+
unused block: 15980789.4 i/s
1015+
yield: 15351931.0 i/s - 1.04x slower
1016+
block + yield: 12630378.1 i/s - 1.27x slower
1017+
block.call: 10587315.1 i/s - 1.51x slower
1018+
```
9891019

9901020
### String
9911021

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

+1-1
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)