mirror of
https://github.com/ruby/ruby.git
synced 2026-10-28 16:36:20 +08:00
A common Ruby idiom for variadic methods is to flatten the argument list so that it can be called with either variadic arguments or an Array. e.g. from the sqlite3 gem: ```ruby def bind_params(*bind_vars) bind_vars.flatten.each do |var| # ... ``` However, as soon as `flatten` encounter another array, it has to protect against recursion, which requires allocating an expensive identity Hash. So this pattern has a relatively high cost when called with a single array argument (e.g. `bind_params [1, 2, 3]`). We can specialize for that common case without noticeably impacting other usages of `Array#flatten`: | |compare-ruby|built-ruby| |:-----------------------------|-----------:|---------:| |small_flat_ary.flatten | 7.547M| 7.974M| | | -| 1.06x| |small_flat_ary.flatten! | 6.031M| 6.105M| | | -| 1.01x| |large_flat_ary.flatten | 465.896k| 485.861k| | | -| 1.04x| |large_flat_ary.flatten! | 455.872k| 478.103k| | | -| 1.05x| |small_pairs_ary.flatten | 1.327M| 1.407M| | | -| 1.06x| |small_pairs_ary.flatten! | 1.165M| 1.153M| | | 1.01x| -| |large_pairs_ary.flatten | 96.612k| 96.976k| | | -| 1.00x| |large_pairs_ary.flatten! | 94.108k| 97.289k| | | -| 1.03x| |mostly_flat_ary.flatten | 399.648k| 417.327k| | | -| 1.04x| |mostly_flat_ary.flatten! | 378.315k| 395.946k| | | -| 1.05x| |small_nested_ary.flatten | 2.513M| 7.788M| | | -| 3.10x| |small_nested_ary.flatten! | 2.024M| 5.914M| | | -| 2.92x| |large_nested_ary.flatten | 341.635k| 485.319k| | | -| 1.42x| |large_nested_ary.flatten! | 329.837k| 475.014k| | | -| 1.44x| |small_nested_ary.flatten(1) | 9.497M| 61.350M| | | -| 6.46x| |small_nested_ary.flatten!(1) | 5.136M| 17.668M| | | -| 3.44x| |large_nested_ary.flatten(1) | 1.575M| 60.241M| | | -| 38.26x| |large_nested_ary.flatten!(1) | 1.369M| 16.835M| | | -| 12.30x|
30 lines
1.3 KiB
YAML
30 lines
1.3 KiB
YAML
prelude: |
|
|
small_flat_ary = 5.times.to_a
|
|
large_flat_ary = 100.times.to_a
|
|
small_pairs_ary = [[1, 2]] * 5
|
|
large_pairs_ary = [[1, 2]] * 100
|
|
mostly_flat_ary = 100.times.to_a.push([101, 102])
|
|
small_nested_ary = [small_flat_ary]
|
|
large_nested_ary = [large_flat_ary]
|
|
|
|
benchmark:
|
|
small_flat_ary.flatten: small_flat_ary.flatten
|
|
small_flat_ary.flatten!: small_flat_ary.dup.flatten!
|
|
large_flat_ary.flatten: large_flat_ary.flatten
|
|
large_flat_ary.flatten!: large_flat_ary.dup.flatten!
|
|
small_pairs_ary.flatten: small_pairs_ary.flatten
|
|
small_pairs_ary.flatten!: small_pairs_ary.dup.flatten!
|
|
large_pairs_ary.flatten: large_pairs_ary.flatten
|
|
large_pairs_ary.flatten!: large_pairs_ary.dup.flatten!
|
|
mostly_flat_ary.flatten: mostly_flat_ary.flatten
|
|
mostly_flat_ary.flatten!: mostly_flat_ary.dup.flatten!
|
|
small_nested_ary.flatten: small_nested_ary.flatten
|
|
small_nested_ary.flatten!: small_nested_ary.dup.flatten!
|
|
large_nested_ary.flatten: large_nested_ary.flatten
|
|
large_nested_ary.flatten!: large_nested_ary.dup.flatten!
|
|
small_nested_ary.flatten(1): small_nested_ary.flatten(1)
|
|
small_nested_ary.flatten!(1): small_nested_ary.dup.flatten!(1)
|
|
large_nested_ary.flatten(1): large_nested_ary.flatten(1)
|
|
large_nested_ary.flatten!(1): large_nested_ary.dup.flatten!(1)
|
|
loop_count: 10000
|