|
| 1 | +require 'benchmark/ips' |
| 2 | + |
| 3 | +module RandStr |
| 4 | + RND_STRINGS_AMOUNT = 1000 |
| 5 | + @rand_strs = { |
| 6 | + lt100: [], |
| 7 | + lt10: [], |
| 8 | + lt1000: [], |
| 9 | + eq10: [], |
| 10 | + eq100: [], |
| 11 | + } |
| 12 | + |
| 13 | + def self.generate_rand_strs |
| 14 | + chars = ('A'..'z').to_a * 20 |
| 15 | + @rand_strs[:lt10] = Array.new(RND_STRINGS_AMOUNT) { chars.sample(rand(10)).join } |
| 16 | + @rand_strs[:lt100] = Array.new(RND_STRINGS_AMOUNT) { chars.sample(rand(100)).join } |
| 17 | + @rand_strs[:lt1000] = Array.new(RND_STRINGS_AMOUNT) { chars.sample(rand(1000)).join } |
| 18 | + @rand_strs[:eq10] = Array.new(RND_STRINGS_AMOUNT) { chars.sample(10).join } |
| 19 | + @rand_strs[:eq100] = Array.new(RND_STRINGS_AMOUNT) { chars.sample(100).join } |
| 20 | + end |
| 21 | + |
| 22 | + self.generate_rand_strs |
| 23 | + |
| 24 | + def self.rand_str(named_range) |
| 25 | + @rand_strs[named_range][rand(RND_STRINGS_AMOUNT)] |
| 26 | + end |
| 27 | + |
| 28 | + def self.method_missing(symbol) |
| 29 | + return super unless @rand_strs.keys.include?(symbol) |
| 30 | + |
| 31 | + define_singleton_method(symbol) { rand_str(symbol) } |
| 32 | + return rand_str(symbol) |
| 33 | + end |
| 34 | + |
| 35 | +end |
| 36 | + |
| 37 | + |
| 38 | +# 2 + 1 = 3 object |
| 39 | +def fastest_plus(foo, bar) |
| 40 | + foo + bar |
| 41 | +end |
| 42 | + |
| 43 | +# 2 + 1 = 3 object |
| 44 | +def slow_concat(foo, bar) |
| 45 | + foo.concat bar |
| 46 | +end |
| 47 | + |
| 48 | +# 2 + 1 = 3 object |
| 49 | +def slow_append(foo, bar) |
| 50 | + foo << bar |
| 51 | +end |
| 52 | + |
| 53 | + |
| 54 | +def fast_interpolation(foo, bar) |
| 55 | + "#{foo}#{bar}" |
| 56 | +end |
| 57 | + |
| 58 | +# bench_100_to_100 |
| 59 | +# Rehearsal ----------------------------------------------------------- |
| 60 | +# String#+ 1.263725 0.027868 1.291593 ( 1.292498) |
| 61 | +# "#{foo}#{bar}" 1.139442 0.022956 1.162398 ( 1.163574) |
| 62 | +# String#concat 2.017746 0.014836 2.032582 ( 2.034682) |
| 63 | +# String#append 1.320778 0.000000 1.320778 ( 1.321896) |
| 64 | +# Collateral actions only 0.713309 0.000000 0.713309 ( 0.714402) |
| 65 | +# -------------------------------------------------- total: 6.520660sec |
| 66 | +# |
| 67 | +# user system total real nomalized ratio |
| 68 | +# Collateral actions only 0.703668 0.000000 0.703668 ( 0.705658) |
| 69 | +# String#+ 1.014123 0.000000 1.014123 ( 1.015003) 0.30934 |
| 70 | +# "#{foo}#{bar}" 1.101751 0.000585 1.102336 ( 1.103558) 0.3979 x 1.3 slower |
| 71 | +# String#concat 1.382647 0.000000 1.382647 ( 1.385333) 0.679675 x 2.2 slower |
| 72 | +# String#append 1.319974 0.000000 1.319974 ( 1.324772) 0.619114 x 2 slower |
| 73 | + |
| 74 | +def bench_100_to_100 |
| 75 | + Benchmark.ips do |x| |
| 76 | + # 1M for rehearsal + 1M for bm |
| 77 | + sarr1 = Array.new(2_000_000) { RandStr.eq100.dup } |
| 78 | + sarr2 = Array.new(2_000_000) { RandStr.eq100.dup } |
| 79 | + |
| 80 | + i, j = 0, 0 |
| 81 | + # if we want compare apples with apples, we need to measure and exclude "collateral" operations: |
| 82 | + # integer += 1, access to an array of randomized strings 100 symbols length, |
| 83 | + # then two methods invocation from RandStr module eq100 / lt100. |
| 84 | + # |
| 85 | + # and only then we can compare string concat methods properly |
| 86 | + x.report("Collateral actions only") { k=0; 1_000_000.times { k+=1; RandStr.eq100; sarr2[k]; RandStr.lt100; } } |
| 87 | + |
| 88 | + x.report("String#+") { k=0; 1_000_000.times { k+=1; sarr1[k]; fastest_plus(RandStr.eq100, RandStr.lt100) } } |
| 89 | + x.report('"#{foo}#{bar}"') { k=0; 1_000_000.times { k+=1; sarr2[k]; fast_interpolation(RandStr.eq100, RandStr.lt100) } } |
| 90 | + x.report("String#concat") { 1_000_000.times { RandStr.eq100; slow_concat(sarr1[i], RandStr.lt100); i+=1; } } |
| 91 | + x.report("String#append") { 1_000_000.times { RandStr.eq100; slow_append(sarr2[j], RandStr.lt100); j+=1; } } |
| 92 | + end |
| 93 | +end |
| 94 | + |
| 95 | +# bench_100_to_1000 |
| 96 | +# Rehearsal ----------------------------------------------------------- |
| 97 | +# Collateral actions only 0.674168 0.000016 0.674184 ( 0.675031) |
| 98 | +# String#+ 2.148756 0.032954 2.181710 ( 2.187042) |
| 99 | +# "#{foo}#{bar}" 1.570816 0.004948 1.575764 ( 1.579080) |
| 100 | +# String#concat 2.223220 0.160917 2.384137 ( 2.387601) |
| 101 | +# String#append 2.005056 0.202962 2.208018 ( 2.211476) |
| 102 | +# -------------------------------------------------- total: 9.023813sec |
| 103 | +# |
| 104 | +# user system total real nomalized ratio |
| 105 | +# Collateral actions only 0.666190 0.000000 0.666190 ( 0.666398) |
| 106 | +# String#+ 1.077629 0.036944 1.114573 ( 1.115465) 0.449067 |
| 107 | +# "#{foo}#{bar}" 1.230489 0.001029 1.231518 ( 1.232423) 0.566025 x 1.25 slower |
| 108 | +# String#concat 1.881313 0.149949 2.031262 ( 2.033965) 1.367567 x 3.05 slower |
| 109 | +# String#append 1.913785 0.177921 2.091706 ( 2.094298) 1.4279 x 3.18 slower |
| 110 | + |
| 111 | +def bench_100_to_1000 |
| 112 | + Benchmark.ips do |x| |
| 113 | + sarr1 = Array.new(2_000_000) { RandStr.eq100.dup } |
| 114 | + sarr2 = Array.new(2_000_000) { RandStr.eq100.dup } |
| 115 | + |
| 116 | + i, j = 0, 0 |
| 117 | + x.report("Collateral actions only") { k=0; 1_000_000.times { k+=1; RandStr.eq100; sarr2[k]; RandStr.lt1000; } } |
| 118 | + |
| 119 | + x.report("String#+") { k=0; 1_000_000.times { k+=1; sarr1[k]; fastest_plus(RandStr.eq100, RandStr.lt1000) } } |
| 120 | + x.report('"#{foo}#{bar}"') { k=0; 1_000_000.times { k+=1; sarr2[k]; fast_interpolation(RandStr.eq100, RandStr.lt1000) } } |
| 121 | + x.report("String#concat") { 1_000_000.times { RandStr.eq100; slow_concat(sarr1[i], RandStr.lt1000); i+=1; } } |
| 122 | + x.report("String#append") { 1_000_000.times { RandStr.eq100; slow_append(sarr2[j], RandStr.lt1000); j+=1; } } |
| 123 | + end |
| 124 | +end |
| 125 | + |
| 126 | +# bench_10_to_100 |
| 127 | +# Rehearsal ----------------------------------------------------------- |
| 128 | +# Collateral actions only 0.681273 0.000000 0.681273 ( 0.681611) |
| 129 | +# String#+ 1.188326 0.000701 1.189027 ( 1.196455) |
| 130 | +# "#{foo}#{bar}" 1.182554 0.003851 1.186405 ( 1.191678) |
| 131 | +# String#concat 1.707191 0.006764 1.713955 ( 1.720055) |
| 132 | +# String#append 1.177368 0.000831 1.178199 ( 1.184116) |
| 133 | +# -------------------------------------------------- total: 5.948859sec |
| 134 | +# |
| 135 | +# user system total real nomalized ratio |
| 136 | +# Collateral actions only 0.682486 0.000000 0.682486 ( 0.682818) |
| 137 | +# String#+ 0.914002 0.000000 0.914002 ( 0.917294) 0.234476 |
| 138 | +# "#{foo}#{bar}" 1.096633 0.000966 1.097599 ( 1.100782) 0.417964 x 1.78 slower |
| 139 | +# String#concat 1.373582 0.000910 1.374492 ( 1.375239) 0.692421 x 2.95 slower |
| 140 | +# String#append 1.300632 0.000000 1.300632 ( 1.300807) 0.617989 x 2.63 slower |
| 141 | + |
| 142 | +def bench_10_to_100 |
| 143 | + Benchmark.ips do |x| |
| 144 | + sarr1 = Array.new(2_000_000) { RandStr.eq100.dup } |
| 145 | + sarr2 = Array.new(2_000_000) { RandStr.eq100.dup } |
| 146 | + |
| 147 | + i, j = 0, 0 |
| 148 | + x.report("Collateral actions only") { k=0; 1_000_000.times { k+=1; RandStr.eq10; sarr2[k]; RandStr.lt100; } } |
| 149 | + x.report("String#+") { k=0; 1_000_000.times { k+=1; sarr1[k]; fastest_plus(RandStr.eq10, RandStr.lt100) } } |
| 150 | + x.report('"#{foo}#{bar}"') { k=0; 1_000_000.times { k+=1; sarr2[k]; fast_interpolation(RandStr.eq10, RandStr.lt100) } } |
| 151 | + x.report("String#concat") { 1_000_000.times { RandStr.eq10; slow_concat(sarr1[i], RandStr.lt100); i+=1; } } |
| 152 | + x.report("String#append") { 1_000_000.times { RandStr.eq10; slow_append(sarr2[j], RandStr.lt100); j+=1; } } |
| 153 | + end |
| 154 | +end |
0 commit comments