diff options
Diffstat (limited to 'benchmark')
229 files changed, 3145 insertions, 185 deletions
diff --git a/benchmark/README.md b/benchmark/README.md index 24a2669143..9f9192685e 100644 --- a/benchmark/README.md +++ b/benchmark/README.md @@ -27,17 +27,20 @@ benchmark-driver benchmark/*.yml See also: ```console +benchmark-driver --help Usage: benchmark-driver [options] RUBY|YAML... - -r, --runner TYPE Specify runner type: ips, time, memory, once (default: ips) - -o, --output TYPE Specify output type: compare, simple, markdown, record (default: compare) + -r, --runner TYPE Specify runner type: ips, time, memory, once, block (default: ips) + -o, --output TYPE Specify output type: compare, simple, markdown, record, all (default: compare) -e, --executables EXECS Ruby executables (e1::path1 arg1; e2::path2 arg2;...) --rbenv VERSIONS Ruby executables in rbenv (x.x.x arg1;y.y.y arg2;...) --repeat-count NUM Try benchmark NUM times and use the fastest result or the worst memory usage --repeat-result TYPE Yield "best", "average" or "worst" result with --repeat-count (default: best) + --alternate Alternate executables instead of running the same executable in a row with --repeat-count --bundler Install and use gems specified in Gemfile --filter REGEXP Filter out benchmarks with given regexp --run-duration SECONDS Warmup estimates loop_count to run for this duration (default: 3) - -v, --verbose Verbose mode. Multiple -v options increase visilibity (max: 2) + --timeout SECONDS Timeout ruby command execution with timeout(1) + -v, --verbose Verbose mode. Multiple -v options increase visibility (max: 2) ``` ## make benchmark @@ -53,20 +56,20 @@ make benchmark # Or compare with specific ruby binary make benchmark COMPARE_RUBY="/path/to/ruby --jit" -# Run vm1 benchmarks -make benchmark ITEM=vm1 +# Run vm benchmarks +make benchmark ITEM=vm # Run some limited benchmarks in ITEM-matched files -make benchmark ITEM=vm1 OPTS=--filter=block +make benchmark ITEM=vm OPTS=--filter=block # You can specify the benchmark by an exact filename instead of using the default argument: # ARGS = $$(find $(srcdir)/benchmark -maxdepth 1 -name '*$(ITEM)*.yml' -o -name '*$(ITEM)*.rb') -make benchmark ARGS=../benchmark/erb_render.yml +make benchmark ARGS=benchmark/erb_render.yml # You can specify any option via $OPTS make benchmark OPTS="--help" # With `make benchmark`, some special runner plugins are available: # -r peak, -r size, -r total, -r utime, -r stime, -r cutime, -r cstime -make benchmark ITEM=vm2_bigarray OPTS="-r peak" +make benchmark ITEM=vm_bigarray OPTS="-r peak" ``` diff --git a/benchmark/app_aobench.rb b/benchmark/app_aobench.rb index 16296af12b..c1546e08ab 100644 --- a/benchmark/app_aobench.rb +++ b/benchmark/app_aobench.rb @@ -151,7 +151,7 @@ def clamp(f) i.to_i end -def otherBasis(basis, n) +def orthoBasis(basis, n) basis[2] = Vec.new(n.x, n.y, n.z) basis[1] = Vec.new(0.0, 0.0, 0.0) @@ -183,7 +183,7 @@ class Scene def ambient_occlusion(isect) basis = Array.new - otherBasis(basis, isect.n) + orthoBasis(basis, isect.n) ntheta = NAO_SAMPLES nphi = NAO_SAMPLES diff --git a/benchmark/app_fib.rb b/benchmark/app_fib.rb index 34a7b2e725..e61bc8aa32 100644 --- a/benchmark/app_fib.rb +++ b/benchmark/app_fib.rb @@ -1,4 +1,4 @@ -def fib n +def fib(n) if n < 3 1 else diff --git a/benchmark/array_flatten.yml b/benchmark/array_flatten.yml new file mode 100644 index 0000000000..88ef544ba0 --- /dev/null +++ b/benchmark/array_flatten.yml @@ -0,0 +1,19 @@ +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]) + +benchmark: + small_flat_ary.flatten: small_flat_ary.flatten + small_flat_ary.flatten!: small_flat_ary.flatten! + large_flat_ary.flatten: large_flat_ary.flatten + large_flat_ary.flatten!: large_flat_ary.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! +loop_count: 10000 diff --git a/benchmark/array_intersection.yml b/benchmark/array_intersection.yml new file mode 100644 index 0000000000..26705323fd --- /dev/null +++ b/benchmark/array_intersection.yml @@ -0,0 +1,14 @@ +prelude: | + small1 = [1, 2, 3] + small2 = [1, 2, 3, 4, 5] + small3 = [2, 3, 4, 5] + small4 = [2] + big1 = [1, 2, 3, 4] * 64 + big2 = [1, 2, 3] * 64 + big3 = [1, 2] * 64 + +benchmark: + small-&: small1 & small2 & small3 & small4 + small-intersection: small1.intersection(small2, small3, small4) + big-&: big1 & big2 & big3 + big-intersection: big1.intersection(big2, big3) diff --git a/benchmark/array_large_literal.yml b/benchmark/array_large_literal.yml new file mode 100644 index 0000000000..423d68391f --- /dev/null +++ b/benchmark/array_large_literal.yml @@ -0,0 +1,19 @@ +prelude: | + def def_array(size) + Object.class_eval(<<-END) + def array_#{size} + x = 1 + [#{(['x'] * size).join(',')}] + end + END + end + def_array(100) + def_array(1000) + def_array(10000) + def_array(100000) +benchmark: + array_100: array_100 + array_1000: array_1000 + array_10000: array_10000 + array_100000: array_100000 + diff --git a/benchmark/array_max_float.yml b/benchmark/array_max_float.yml new file mode 100644 index 0000000000..ace1ae2e14 --- /dev/null +++ b/benchmark/array_max_float.yml @@ -0,0 +1,30 @@ +prelude: | + ary2 = 2.times.map(&:to_f).shuffle + ary10 = 10.times.map(&:to_f).shuffle + ary100 = 100.times.map(&:to_f).shuffle + ary500 = 500.times.map(&:to_f).shuffle + ary1000 = 1000.times.map(&:to_f).shuffle + ary2000 = 2500.times.map(&:to_f).shuffle + ary3000 = 2500.times.map(&:to_f).shuffle + ary5000 = 5000.times.map(&:to_f).shuffle + ary10000 = 10000.times.map(&:to_f).shuffle + ary20000 = 20000.times.map(&:to_f).shuffle + ary50000 = 50000.times.map(&:to_f).shuffle + ary100000 = 100000.times.map(&:to_f).shuffle + +benchmark: + ary2.max: ary2.max + ary10.max: ary10.max + ary100.max: ary100.max + ary500.max: ary500.max + ary1000.max: ary1000.max + ary2000.max: ary2000.max + ary3000.max: ary3000.max + ary5000.max: ary5000.max + ary10000.max: ary10000.max + ary20000.max: ary20000.max + ary50000.max: ary50000.max + ary100000.max: ary100000.max + +loop_count: 10000 + diff --git a/benchmark/array_max_int.yml b/benchmark/array_max_int.yml new file mode 100644 index 0000000000..acd83684d0 --- /dev/null +++ b/benchmark/array_max_int.yml @@ -0,0 +1,31 @@ +prelude: | + ary2 = 2.times.to_a.shuffle + ary10 = 10.times.to_a.shuffle + ary100 = 100.times.to_a.shuffle + ary500 = 500.times.to_a.shuffle + ary1000 = 1000.times.to_a.shuffle + ary2000 = 2500.times.to_a.shuffle + ary3000 = 2500.times.to_a.shuffle + ary5000 = 5000.times.to_a.shuffle + ary10000 = 10000.times.to_a.shuffle + ary20000 = 20000.times.to_a.shuffle + ary50000 = 50000.times.to_a.shuffle + ary100000 = 100000.times.to_a.shuffle + ary1000000 = 1000000.times.to_a.shuffle + +benchmark: + ary2.max: ary2.max + ary10.max: ary10.max + ary100.max: ary100.max + ary500.max: ary500.max + ary1000.max: ary1000.max + ary2000.max: ary2000.max + ary3000.max: ary3000.max + ary5000.max: ary5000.max + ary10000.max: ary10000.max + ary20000.max: ary20000.max + ary50000.max: ary50000.max + ary100000.max: ary100000.max + ary1000000.max: ary1000000.max + +loop_count: 10000 diff --git a/benchmark/array_max_str.yml b/benchmark/array_max_str.yml new file mode 100644 index 0000000000..2aeed010f2 --- /dev/null +++ b/benchmark/array_max_str.yml @@ -0,0 +1,30 @@ +prelude: | + ary2 = 2.times.map(&:to_s).shuffle + ary10 = 10.times.map(&:to_s).shuffle + ary100 = 100.times.map(&:to_s).shuffle + ary500 = 500.times.map(&:to_s).shuffle + ary1000 = 1000.times.map(&:to_s).shuffle + ary2000 = 2500.times.map(&:to_s).shuffle + ary3000 = 2500.times.map(&:to_s).shuffle + ary5000 = 5000.times.map(&:to_s).shuffle + ary10000 = 10000.times.map(&:to_s).shuffle + ary20000 = 20000.times.map(&:to_s).shuffle + ary50000 = 50000.times.map(&:to_s).shuffle + ary100000 = 100000.times.map(&:to_s).shuffle + +benchmark: + ary2.max: ary2.max + ary10.max: ary10.max + ary100.max: ary100.max + ary500.max: ary500.max + ary1000.max: ary1000.max + ary2000.max: ary2000.max + ary3000.max: ary3000.max + ary5000.max: ary5000.max + ary10000.max: ary10000.max + ary20000.max: ary20000.max + ary50000.max: ary50000.max + ary100000.max: ary100000.max + +loop_count: 10000 + diff --git a/benchmark/array_min.yml b/benchmark/array_min.yml new file mode 100644 index 0000000000..53e5072b14 --- /dev/null +++ b/benchmark/array_min.yml @@ -0,0 +1,31 @@ +prelude: | + ary2 = 2.times.to_a.shuffle + ary10 = 10.times.to_a.shuffle + ary100 = 100.times.to_a.shuffle + ary500 = 500.times.to_a.shuffle + ary1000 = 1000.times.to_a.shuffle + ary2000 = 2500.times.to_a.shuffle + ary3000 = 2500.times.to_a.shuffle + ary5000 = 5000.times.to_a.shuffle + ary10000 = 10000.times.to_a.shuffle + ary20000 = 20000.times.to_a.shuffle + ary50000 = 50000.times.to_a.shuffle + ary100000 = 100000.times.to_a.shuffle + ary1000000 = 1000000.times.to_a.shuffle + +benchmark: + ary2.min: ary2.min + ary10.min: ary10.min + ary100.min: ary100.min + ary500.min: ary500.min + ary1000.min: ary1000.min + ary2000.min: ary2000.min + ary3000.min: ary3000.min + ary5000.min: ary5000.min + ary10000.min: ary10000.min + ary20000.min: ary20000.min + ary50000.min: ary50000.min + ary100000.min: ary100000.min + ary1000000.min: ary1000000.min + +loop_count: 10000 diff --git a/benchmark/array_sample.yml b/benchmark/array_sample.yml new file mode 100644 index 0000000000..1cd2b34794 --- /dev/null +++ b/benchmark/array_sample.yml @@ -0,0 +1,4 @@ +prelude: ary = (1..10_000).to_a +benchmark: + - ary.sample + - ary.sample(2) diff --git a/benchmark/array_sort_int.yml b/benchmark/array_sort_int.yml new file mode 100644 index 0000000000..7b9027ebf7 --- /dev/null +++ b/benchmark/array_sort_int.yml @@ -0,0 +1,15 @@ +prelude: | + ary2 = 2.times.to_a.shuffle + ary10 = 10.times.to_a.shuffle + ary100 = 100.times.to_a.shuffle + ary1000 = 1000.times.to_a.shuffle + ary10000 = 10000.times.to_a.shuffle + +benchmark: + ary2.sort: ary2.sort + ary10.sort: ary10.sort + ary100.sort: ary100.sort + ary1000.sort: ary1000.sort + ary10000.sort: ary10000.sort + +loop_count: 10000 diff --git a/benchmark/attr_accessor.yml b/benchmark/attr_accessor.yml new file mode 100644 index 0000000000..82134cdf9b --- /dev/null +++ b/benchmark/attr_accessor.yml @@ -0,0 +1,29 @@ +prelude: | + class C + attr_accessor :x + def initialize + @x = nil + end + class_eval <<-END + def ar + #{'x;'*256} + end + def aw + #{'self.x = nil;'*256} + end + def arm + m = method(:x) + #{'m.call;'*256} + end + def awm + m = method(:x=) + #{'m.call(nil);'*256} + end + END + end + obj = C.new +benchmark: + attr_reader: "obj.ar" + attr_writer: "obj.aw" + attr_reader_method: "obj.arm" + attr_writer_method: "obj.awm" diff --git a/benchmark/buffer_each.yml b/benchmark/buffer_each.yml new file mode 100644 index 0000000000..417941104e --- /dev/null +++ b/benchmark/buffer_each.yml @@ -0,0 +1,27 @@ +prelude: | + # frozen_string_literal: true + Warning[:experimental] = false + string = "The quick brown fox jumped over the lazy dog." + array = string.bytes + buffer = IO::Buffer.for(string) +benchmark: + string.each_byte: | + upcased = String.new + string.each_byte do |byte| + upcased << (byte ^ 32) + end + array.each: | + upcased = String.new + array.each do |byte| + upcased << (byte ^ 32) + end + buffer.each: | + upcased = String.new + buffer.each(:U8) do |offset, byte| + upcased << (byte ^ 32) + end + buffer.each_byte: | + upcased = String.new + buffer.each_byte do |byte| + upcased << (byte ^ 32) + end diff --git a/benchmark/buffer_get.yml b/benchmark/buffer_get.yml new file mode 100644 index 0000000000..9e1f99d64e --- /dev/null +++ b/benchmark/buffer_get.yml @@ -0,0 +1,25 @@ +prelude: | + # frozen_string_literal: true + Warning[:experimental] = false + string = "The quick brown fox jumped over the lazy dog." + buffer = IO::Buffer.for(string) + format = [:U32, :U32, :U32, :U32] +benchmark: + string.unpack1: | + [ + string.unpack1("N"), + string.unpack1("N", offset: 4), + string.unpack1("N", offset: 8), + string.unpack1("N", offset: 12), + ] + buffer.get_value: | + [ + buffer.get_value(:U32, 0), + buffer.get_value(:U32, 4), + buffer.get_value(:U32, 8), + buffer.get_value(:U32, 12), + ] + buffer.get_values: | + buffer.get_values(format, 0) + string.unpack: | + string.unpack("NNNN") diff --git a/benchmark/cgi_escape_html.yml b/benchmark/cgi_escape_html.yml index af6abd08ac..655be9d7d8 100644 --- a/benchmark/cgi_escape_html.yml +++ b/benchmark/cgi_escape_html.yml @@ -1,32 +1,23 @@ -prelude: require 'cgi/escape' +prelude: | + # frozen_string_literal: true + require 'cgi/escape' benchmark: - - name: escape_html_blank - prelude: str = "" - script: CGI.escapeHTML(str) + - script: CGI.escapeHTML("") loop_count: 20000000 - - name: escape_html_short_none - prelude: str = "abcde" - script: CGI.escapeHTML(str) + - script: CGI.escapeHTML("abcde") loop_count: 20000000 - - name: escape_html_short_one - prelude: str = "abcd<" - script: CGI.escapeHTML(str) + - script: CGI.escapeHTML("abcd<") loop_count: 20000000 - - name: escape_html_short_all - prelude: str = "'&\"<>" - script: CGI.escapeHTML(str) + - script: CGI.escapeHTML("'&\"<>") loop_count: 5000000 - - name: escape_html_long_none - prelude: str = "abcde" * 300 - script: CGI.escapeHTML(str) + - prelude: long_no_escape = "abcde" * 300 + script: CGI.escapeHTML(long_no_escape) loop_count: 1000000 - - name: escape_html_long_all - prelude: str = "'&\"<>" * 10 - script: CGI.escapeHTML(str) + - prelude: long_all_escape = "'&\"<>" * 10 + script: CGI.escapeHTML(long_all_escape) loop_count: 1000000 - - name: escape_html_real - prelude: | # http://example.com/ - str = <<~HTML + - prelude: | # http://example.com/ + example_html = <<~HTML <body> <div> <h1>Example Domain</h1> @@ -36,5 +27,5 @@ benchmark: </div> </body> HTML - script: CGI.escapeHTML(str) + script: CGI.escapeHTML(example_html) loop_count: 1000000 diff --git a/benchmark/class_superclass.yml b/benchmark/class_superclass.yml new file mode 100644 index 0000000000..847ff811f1 --- /dev/null +++ b/benchmark/class_superclass.yml @@ -0,0 +1,23 @@ +prelude: | + class SimpleClass; end + class OneModuleClass + 1.times { include Module.new } + end + class MediumClass + 10.times { include Module.new } + end + class LargeClass + 100.times { include Module.new } + end +benchmark: + object_class_superclass: | + Object.superclass + simple_class_superclass: | + SimpleClass.superclass + one_module_class: | + OneModuleClass.superclass + medium_class_superclass: | + MediumClass.superclass + large_class_superclass: | + LargeClass.superclass +loop_count: 20000000 diff --git a/benchmark/constant_invalidation.rb b/benchmark/constant_invalidation.rb new file mode 100644 index 0000000000..a95ec6f37e --- /dev/null +++ b/benchmark/constant_invalidation.rb @@ -0,0 +1,22 @@ +$VERBOSE = nil + +CONSTANT1 = 1 +CONSTANT2 = 1 +CONSTANT3 = 1 +CONSTANT4 = 1 +CONSTANT5 = 1 + +def constants + [CONSTANT1, CONSTANT2, CONSTANT3, CONSTANT4, CONSTANT5] +end + +500_000.times do + constants + + # With previous behavior, this would cause all of the constant caches + # associated with the constant lookups listed above to invalidate, meaning + # they would all have to be fetched again. With current behavior, it only + # invalidates when a name matches, so the following constant set shouldn't + # impact the constant lookups listed above. + INVALIDATE = true +end diff --git a/benchmark/enum_lazy_flat_map.yml b/benchmark/enum_lazy_flat_map.yml new file mode 100644 index 0000000000..0ee390a441 --- /dev/null +++ b/benchmark/enum_lazy_flat_map.yml @@ -0,0 +1,16 @@ +prelude: | + num = (1..).lazy.take(100) + ary2 = [[1,2]].cycle.lazy.take(10) + ary10 = [[*1..10]].cycle.lazy.take(10) + ary20 = [[*1..20]].cycle.lazy.take(10) + ary50 = [[*1..50]].cycle.lazy.take(10) + ary100 = [[*1..100]].cycle.lazy.take(10) + +benchmark: + num3: num.flat_map {|x| x}.take(3).to_a + num10: num.flat_map {|x| x}.take(3).to_a + ary2: ary2.flat_map {|x| x}.take(3).to_a + ary10: ary10.flat_map {|x| x}.take(3).to_a + ary20: ary20.flat_map {|x| x}.take(3).to_a + ary50: ary50.flat_map {|x| x}.take(3).to_a + ary100: ary100.flat_map {|x| x}.take(3).to_a diff --git a/benchmark/enum_lazy_zip.yml b/benchmark/enum_lazy_zip.yml new file mode 100644 index 0000000000..4566ff0261 --- /dev/null +++ b/benchmark/enum_lazy_zip.yml @@ -0,0 +1,22 @@ +prelude: | + a = (1..3).lazy + b = a.map {|x| x} + +benchmark: + first_ary: a.zip(["a", "b", "c"]).first + first_nonary: a.zip("a".."c").first + first_noarg: a.zip.first + + take3_ary: a.zip(["a", "b", "c"]).take(3).force + take3_nonary: a.zip("a".."c").take(3).force + take3_noarg: a.zip.take(3).force + + chain-first_ary: b.zip(["a", "b", "c"]).first + chain-first_nonary: b.zip("a".."c").first + chain-first_noarg: b.zip.first + + chain-take3_ary: b.zip(["a", "b", "c"]).take(3).force + chain-take3_nonary: b.zip("a".."c").take(3).force + chain-take3_noarg: b.zip.take(3).force + + block: a.zip("a".."c") {|x, y| [x, y]} diff --git a/benchmark/enum_minmax.yml b/benchmark/enum_minmax.yml new file mode 100644 index 0000000000..9d01731abb --- /dev/null +++ b/benchmark/enum_minmax.yml @@ -0,0 +1,25 @@ +prelude: | + set2 = 2.times.to_a.shuffle.to_set + set10 = 10.times.to_a.shuffle.to_set + set100 = 100.times.to_a.shuffle.to_set + set1000 = 1000.times.to_a.shuffle.to_set + set10000 = 10000.times.to_a.shuffle.to_set + +benchmark: + set2.min: set2.min + set10.min: set10.min + set100.min: set100.min + set1000.min: set1000.min + set10000.min: set10000.min + set2.max: set2.max + set10.max: set10.max + set100.max: set100.max + set1000.max: set1000.max + set10000.max: set10000.max + set2.minmax: set2.minmax + set10.minmax: set10.minmax + set100.minmax: set100.minmax + set1000.minmax: set1000.minmax + set10000.minmax: set10000.minmax + +loop_count: 10000 diff --git a/benchmark/enum_sort.yml b/benchmark/enum_sort.yml new file mode 100644 index 0000000000..6f26e748c6 --- /dev/null +++ b/benchmark/enum_sort.yml @@ -0,0 +1,15 @@ +prelude: | + set2 = 2.times.to_a.shuffle.to_set + set10 = 10.times.to_a.shuffle.to_set + set100 = 100.times.to_a.shuffle.to_set + set1000 = 1000.times.to_a.shuffle.to_set + set10000 = 10000.times.to_a.shuffle.to_set + +benchmark: + set2.sort_by: set2.sort_by { 0 } + set10.sort_by: set10.sort_by { 0 } + set100.sort_by: set100.sort_by { 0 } + set1000.sort_by: set1000.sort_by { 0 } + set10000.sort_by: set10000.sort_by { 0 } + +loop_count: 10000 diff --git a/benchmark/enum_sort_by.yml b/benchmark/enum_sort_by.yml new file mode 100644 index 0000000000..d386353888 --- /dev/null +++ b/benchmark/enum_sort_by.yml @@ -0,0 +1,53 @@ +prelude: | + array_length = 2 + fixnum_array2 = array_length.times.to_a.map {rand(10000)} + float_array2 = array_length.times.to_a.map {rand(10000.0).to_f} + string_array2 = array_length.times.to_a.map {"r" * rand(1..10000)} + mix_array2 = array_length.times.to_a.map {if rand(1..100) <= 50 then rand(1..10000).to_f else rand(1..10000) end} + all_zero_array2 =array_length.times.to_a.map {0} + + array_length = 10 + fixnum_array10 = array_length.times.to_a.map {rand(10000)} + float_array10 = array_length.times.to_a.map {rand(10000.0).to_f} + string_array10 = array_length.times.to_a.map {"r" * rand(1..10000)} + mix_array10 = array_length.times.to_a.map {if rand(1..100) <= 50 then rand(1..10000).to_f else rand(1..10000) end} + all_zero_array10 =array_length.times.to_a.map {0} + + array_length = 1000 + fixnum_array1000 = array_length.times.to_a.map {rand(10000)} + float_array1000 = array_length.times.to_a.map {rand(10000.0).to_f} + string_array1000 = array_length.times.to_a.map {"r" * rand(1..10000)} + mix_array1000 = array_length.times.to_a.map {if rand(1..100) <= 50 then rand(1..10000).to_f else rand(1..10000) end} + all_zero_array1000 =array_length.times.to_a.map {0} + + array_length = 100000 + fixnum_array100000 = array_length.times.to_a.map {rand(10000)} + float_array100000 = array_length.times.to_a.map {rand(10000.0).to_f} + string_array100000 = array_length.times.to_a.map {"r" * rand(1..10000)} + mix_array100000 = array_length.times.to_a.map {if rand(1..100) <= 50 then rand(1..10000).to_f else rand(1..10000) end} + all_zero_array100000 =array_length.times.to_a.map {0} + +benchmark: + fixnum_array2.sort_by: fixnum_array2.sort_by {|a| a} + float_array2.sort_by: float_array2.sort_by {|a| a} + string_length2.sort_by: string_array2.sort_by {|a| a.length} + mix_array2.sort_by: mix_array2.sort_by {|a| a} + all_zero2.sort_by: all_zero_array2.sort_by{|a| a} + + fixnum_array10.sort_by: fixnum_array10.sort_by {|a| a} + float_array10.sort_by: float_array10.sort_by {|a| a} + string_length10.sort_by: string_array10.sort_by {|a| a.length} + mix_array10.sort_by: mix_array10.sort_by {|a| a} + all_zero10.sort_by: all_zero_array10.sort_by{|a| a} + + fixnum_array1000.sort_by: fixnum_array1000.sort_by {|a| a} + float_array1000.sort_by: float_array1000.sort_by {|a| a} + string_length1000.sort_by: string_array1000.sort_by {|a| a.length} + mix_array1000.sort_by: mix_array1000.sort_by {|a| a} + all_zero1000.sort_by: all_zero_array1000.sort_by{|a| a} + + fixnum_array100000.sort_by: fixnum_array100000.sort_by {|a| a} + float_array100000.sort_by: float_array100000.sort_by {|a| a} + string_length100000.sort_by: string_array100000.sort_by {|a| a.length} + mix_array100000.sort_by: mix_array100000.sort_by {|a| a} + all_zero100000.sort_by: all_zero_array100000.sort_by{|a| a} diff --git a/benchmark/enum_tally.yml b/benchmark/enum_tally.yml new file mode 100644 index 0000000000..edd2e040a0 --- /dev/null +++ b/benchmark/enum_tally.yml @@ -0,0 +1,4 @@ +prelude: | + list = ("aaa".."zzz").to_a*10 +benchmark: + tally: list.tally diff --git a/benchmark/erb_escape_html.yml b/benchmark/erb_escape_html.yml new file mode 100644 index 0000000000..ca28d756e7 --- /dev/null +++ b/benchmark/erb_escape_html.yml @@ -0,0 +1,31 @@ +prelude: | + # frozen_string_literal: true + require 'erb' +benchmark: + - script: ERB::Util.html_escape("") + loop_count: 20000000 + - script: ERB::Util.html_escape("abcde") + loop_count: 20000000 + - script: ERB::Util.html_escape("abcd<") + loop_count: 20000000 + - script: ERB::Util.html_escape("'&\"<>") + loop_count: 5000000 + - prelude: long_no_escape = "abcde" * 300 + script: ERB::Util.html_escape(long_no_escape) + loop_count: 1000000 + - prelude: long_all_escape = "'&\"<>" * 10 + script: ERB::Util.html_escape(long_all_escape) + loop_count: 1000000 + - prelude: | # http://example.com/ + example_html = <<~HTML + <body> + <div> + <h1>Example Domain</h1> + <p>This domain is established to be used for illustrative examples in documents. You may use this + domain in examples without prior coordination or asking for permission.</p> + <p><a href="http://www.iana.org/domains/example">More information...</a></p> + </div> + </body> + HTML + script: ERB::Util.html_escape(example_html) + loop_count: 1000000 diff --git a/benchmark/fiber_chain.yml b/benchmark/fiber_chain.yml index a36c759f8e..a36c759f8e 100755..100644 --- a/benchmark/fiber_chain.yml +++ b/benchmark/fiber_chain.yml diff --git a/benchmark/fiber_locals.yml b/benchmark/fiber_locals.yml new file mode 100644 index 0000000000..8588686477 --- /dev/null +++ b/benchmark/fiber_locals.yml @@ -0,0 +1,8 @@ +prelude: | + th = Thread.current + th[:key] = :val +benchmark: + key?: th.key?(:key) + []: th[:key] + keys: th.keys +loop_count: 1_000_000 diff --git a/benchmark/file_join.yml b/benchmark/file_join.yml new file mode 100644 index 0000000000..845257cf1e --- /dev/null +++ b/benchmark/file_join.yml @@ -0,0 +1,7 @@ +prelude: | + # frozen_string_literal: true +benchmark: + two_strings: File.join(__FILE__, "path") + many_strings: File.join(__FILE__, "path", "a", "b", "c", "d") + array: File.join([__FILE__, "path", "a", "b", "c", "d"]) + mixed: File.join(__FILE__, "path", "a", "b", ["c", "d"]) diff --git a/benchmark/float_methods.yml b/benchmark/float_methods.yml new file mode 100644 index 0000000000..56ea41effc --- /dev/null +++ b/benchmark/float_methods.yml @@ -0,0 +1,14 @@ +prelude: | + flo = 4.2 +benchmark: + to_f: | + flo.to_f + abs: | + flo.abs + magnitude: | + flo.magnitude + -@: | + -flo + zero?: | + flo.zero? +loop_count: 20000000 diff --git a/benchmark/float_neg_posi.yml b/benchmark/float_neg_posi.yml new file mode 100644 index 0000000000..172db1bf6d --- /dev/null +++ b/benchmark/float_neg_posi.yml @@ -0,0 +1,8 @@ +prelude: | + flo = 4.2 +benchmark: + negative?: | + flo.negative? + positive?: | + flo.positive? +loop_count: 20000000 diff --git a/benchmark/float_to_s.yml b/benchmark/float_to_s.yml new file mode 100644 index 0000000000..0abae5cdb8 --- /dev/null +++ b/benchmark/float_to_s.yml @@ -0,0 +1,7 @@ +prelude: | + floats = [*0.0.step(1.0, 0.0001)] + +benchmark: + to_s: floats.each {|f| f.to_s} + +loop_count: 1000 diff --git a/benchmark/hash_aref_array.rb b/benchmark/hash_aref_array.rb new file mode 100644 index 0000000000..ac7a683d95 --- /dev/null +++ b/benchmark/hash_aref_array.rb @@ -0,0 +1,5 @@ +h = {} +arrays = (0..99).each_slice(10).to_a +#STDERR.puts arrays.inspect +arrays.each { |s| h[s] = s } +200_000.times { arrays.each { |s| h[s] } } diff --git a/benchmark/hash_aref_str_lit.yml b/benchmark/hash_aref_str_lit.yml new file mode 100644 index 0000000000..ed8142bcf1 --- /dev/null +++ b/benchmark/hash_aref_str_lit.yml @@ -0,0 +1,20 @@ +prelude: | + # frozen_string_literal: true + hash = 10.times.to_h do |i| + [i, i] + end + dyn_sym = "dynamic_symbol".to_sym + binary = RubyVM::InstructionSequence.compile("# frozen_string_literal: true\n'iseq_load'").to_binary + iseq_literal_string = RubyVM::InstructionSequence.load_from_binary(binary).eval + + hash[:some_symbol] = 1 + hash[dyn_sym] = 2 + hash["small"] = 3 + hash["frozen_string_literal"] = 4 + hash[iseq_literal_string] = 5 +benchmark: + symbol: hash[:some_symbol] + dyn_symbol: hash[dyn_sym] + small_lit: hash["small"] + frozen_lit: hash["frozen_string_literal"] + iseq_lit: hash[iseq_literal_string] diff --git a/benchmark/hash_defaults.yml b/benchmark/hash_defaults.yml new file mode 100644 index 0000000000..833f10e1c7 --- /dev/null +++ b/benchmark/hash_defaults.yml @@ -0,0 +1,6 @@ +prelude: | + h = Hash.new { :foo } +benchmark: + default_aref: h[1] + default_method: h.default(1) +loop_count: 1000000 diff --git a/benchmark/hash_dup.yml b/benchmark/hash_dup.yml new file mode 100644 index 0000000000..65f521ec94 --- /dev/null +++ b/benchmark/hash_dup.yml @@ -0,0 +1,8 @@ +prelude: | + small_hash = { a: 1 } + larger_hash = 20.times.map { |i| [('a'.ord + i).chr.to_sym, i] }.to_h + +benchmark: + dup_small: small_hash.dup + dup_larger: larger_hash.dup +loop_count: 10000 diff --git a/benchmark/hash_first.yml b/benchmark/hash_first.yml new file mode 100644 index 0000000000..c26df1a7ed --- /dev/null +++ b/benchmark/hash_first.yml @@ -0,0 +1,11 @@ +prelude: | + hash1 = 1_000_000.times.to_h { [rand, true]} + hash2 = hash1.dup + hash2.keys[1..100_000].each { hash2.delete _1 } + hash2.delete hash2.first[0] + +benchmark: + hash1: hash1.first + hash2: hash2.first + +loop_count: 100_000 diff --git a/benchmark/hash_key.yml b/benchmark/hash_key.yml new file mode 100644 index 0000000000..cab4cf9ca4 --- /dev/null +++ b/benchmark/hash_key.yml @@ -0,0 +1,5 @@ +prelude: | + obj = Object.new + hash = { obj => true } +benchmark: hash.key?(obj) +loop_count: 30000000 diff --git a/benchmark/hash_new.yml b/benchmark/hash_new.yml new file mode 100644 index 0000000000..9d8e34187f --- /dev/null +++ b/benchmark/hash_new.yml @@ -0,0 +1,16 @@ +prelude: | + has_hash_with_capa = Hash.instance_method(:initialize).parameters.include?([:key, :capacity]) + strings_1k = 1_000.times.map { |i| -i.to_s.freeze } + strings_100k = 100_000.times.map { |i| -i.to_s.freeze } +benchmark: + new: Hash.new + new_with_capa_1k: | + h = has_hash_with_capa ? Hash.new(capacity: strings_1k.size) : {} + strings_1k.each do |x| + h[x] = true + end + new_with_capa_100k: | + h = has_hash_with_capa ? Hash.new(capacity: strings_100k.size) : {} + strings_100k.each do |x| + h[x] = true + end diff --git a/benchmark/io_close.yml b/benchmark/io_close.yml new file mode 100644 index 0000000000..a552872884 --- /dev/null +++ b/benchmark/io_close.yml @@ -0,0 +1,13 @@ +prelude: | + ios = 1000.times.map do + 100.times.map{IO.pipe} + end +benchmark: + # Close IO + io_close: | + # Process each batch of ios per iteration of the benchmark. + ios.pop.each do |r, w| + r.close + w.close + end +loop_count: 100 diff --git a/benchmark/io_close_contended.yml b/benchmark/io_close_contended.yml new file mode 100644 index 0000000000..1d9e4e0d0f --- /dev/null +++ b/benchmark/io_close_contended.yml @@ -0,0 +1,21 @@ +prelude: | + ios = 100.times.map do + 10.times.map do + pipe = IO.pipe.tap do |r, w| + Thread.new do + r.read + rescue IOError + # Ignore + end + end + end + end +benchmark: + # Close IO + io_close_contended: | + # Process each batch of ios per iteration of the benchmark. + ios.pop.each do |r, w| + r.close + w.close + end +loop_count: 10 diff --git a/benchmark/io_write.rb b/benchmark/io_write.rb new file mode 100644 index 0000000000..cdb409948b --- /dev/null +++ b/benchmark/io_write.rb @@ -0,0 +1,22 @@ +#!/usr/bin/env ruby + +require 'benchmark' + +i, o = IO.pipe +o.sync = true + +DOT = ".".freeze + +chunks = 100_000.times.collect{DOT} + +thread = Thread.new do + while i.read(1024) + end +end + +100.times do + o.write(*chunks) +end + +o.close +thread.join diff --git a/benchmark/iseq_load_from_binary.yml b/benchmark/iseq_load_from_binary.yml new file mode 100644 index 0000000000..7e9d73bdd4 --- /dev/null +++ b/benchmark/iseq_load_from_binary.yml @@ -0,0 +1,25 @@ +prelude: | + symbol = RubyVM::InstructionSequence.compile(":foo; :bar; :baz; :egg; :spam").to_binary + + define_method = RubyVM::InstructionSequence.compile(%{ + def foo; end + def bar; end + def baz; end + def egg; end + def spam; end + }).to_binary + + all = RubyVM::InstructionSequence.compile(%{ + module Foo; def foo; :foo; end; end + module Bar; def bar; :bar; end; end + module Baz; def baz; :baz; end; end + class Egg; def egg; :egg; end; end + class Spaml; def spam; :spam; end; end + }).to_binary + +benchmark: + symbol: RubyVM::InstructionSequence.load_from_binary(symbol) + define_method: RubyVM::InstructionSequence.load_from_binary(define_method) + all: RubyVM::InstructionSequence.load_from_binary(all) + +loop_count: 100_000 diff --git a/benchmark/ivar_extend.yml b/benchmark/ivar_extend.yml new file mode 100644 index 0000000000..eb9ee923f5 --- /dev/null +++ b/benchmark/ivar_extend.yml @@ -0,0 +1,23 @@ +prelude: | + class Embedded + def initialize + @a = 1 + @b = 1 + @c = 1 + end + end + + class Extended + def initialize + @a = 1 + @b = 1 + @c = 1 + @d = 1 + @e = 1 + @f = 1 + end + end +benchmark: + embedded: Embedded.new + extended: Extended.new +loop_count: 20_000_000 diff --git a/benchmark/kernel_clone.yml b/benchmark/kernel_clone.yml new file mode 100644 index 0000000000..069b23abcd --- /dev/null +++ b/benchmark/kernel_clone.yml @@ -0,0 +1,6 @@ +prelude: "object = Object.new" +benchmark: + clone: "object.clone" + clone_true: "object.clone(freeze: true)" + clone_false: "object.clone(freeze: false)" +loop_count: 10000 diff --git a/benchmark/kernel_float.yml b/benchmark/kernel_float.yml new file mode 100644 index 0000000000..215f6750fc --- /dev/null +++ b/benchmark/kernel_float.yml @@ -0,0 +1,5 @@ +benchmark: + float: "Float(42)" + float_true: "Float(42, exception: true)" + float_false: "Float(42, exception: false)" +loop_count: 10000 diff --git a/benchmark/kernel_tap.yml b/benchmark/kernel_tap.yml new file mode 100644 index 0000000000..4dcbb31b4d --- /dev/null +++ b/benchmark/kernel_tap.yml @@ -0,0 +1,6 @@ +prelude: | + obj = Object.new + x = nil +benchmark: + kernel_tap: obj.tap { |o| x = o } +loop_count: 20000000 diff --git a/benchmark/kernel_then.yml b/benchmark/kernel_then.yml new file mode 100644 index 0000000000..85f7341e33 --- /dev/null +++ b/benchmark/kernel_then.yml @@ -0,0 +1,6 @@ +benchmark: + kernel_then: 1.then { |i| i + 1 } + kernel_then_enum: 1.then + kernel_yield_self: 1.yield_self { |i| i + 1 } + kernel_yield_self_enum: 1.yield_self +loop_count: 20000000 diff --git a/benchmark/keyword_arguments.yml b/benchmark/keyword_arguments.yml new file mode 100644 index 0000000000..fce6bce0b8 --- /dev/null +++ b/benchmark/keyword_arguments.yml @@ -0,0 +1,13 @@ +prelude: | + h = {a: 1} + def kw(a: 1) a end + def kws(**kw) kw end +benchmark: + kw_to_kw: "kw(a: 1)" + kw_splat_to_kw: "kw(**h)" + kw_to_kw_splat: "kws(a: 1)" + kw_splat_to_kw_splat: "kws(**h)" + kw_and_splat_to_kw: "kw(a: 1, **h)" + kw_splats_to_kw: "kw(**h, **h)" + kw_and_splat_to_kw_splat: "kws(a: 1, **h)" + kw_splats_to_kw_splat: "kws(**h, **h)" diff --git a/benchmark/lib/benchmark_driver/runner/ractor.rb b/benchmark/lib/benchmark_driver/runner/ractor.rb new file mode 100644 index 0000000000..fd9c2dd4db --- /dev/null +++ b/benchmark/lib/benchmark_driver/runner/ractor.rb @@ -0,0 +1,122 @@ +require 'erb' + +# A runner to measure performance *inside* Ractor +class BenchmarkDriver::Runner::Ractor < BenchmarkDriver::Runner::Ips + # JobParser returns this, `BenchmarkDriver::Runner.runner_for` searches "*::Job" + Job = Class.new(BenchmarkDriver::DefaultJob) do + attr_accessor :ractor + end + + # Dynamically fetched and used by `BenchmarkDriver::JobParser.parse` + JobParser = BenchmarkDriver::DefaultJobParser.for(klass: Job, metrics: [METRIC]).extend(Module.new{ + def parse(ractor: 1, **kwargs) + super(**kwargs).each do |job| + job.ractor = ractor + end + end + }) + + private + + unless private_instance_methods.include?(:run_benchmark) + raise "#run_benchmark is no longer defined in BenchmarkDriver::Runner::Ips" + end + + # @param [BenchmarkDriver::Runner::Ips::Job] job - loop_count is not nil + # @param [BenchmarkDriver::Context] context + # @return [BenchmarkDriver::Metrics] + def run_benchmark(job, context:) + benchmark = BenchmarkScript.new( + preludes: [context.prelude, job.prelude], + script: job.script, + teardown: job.teardown, + loop_count: job.loop_count, + ) + + results = job.ractor.times.map do + Tempfile.open('benchmark_driver_result') + end + duration = with_script(benchmark.render(results: results.map(&:path))) do |path| + success = execute(*context.executable.command, path, exception: false) + if success && ((value = results.map { |f| Float(f.read) }.max) > 0) + value + else + BenchmarkDriver::Result::ERROR + end + end + results.each(&:close) + + value_duration( + loop_count: job.loop_count, + duration: duration, + ) + end + + # @param [String] prelude + # @param [String] script + # @param [String] teardown + # @param [Integer] loop_count + BenchmarkScript = ::BenchmarkDriver::Struct.new(:preludes, :script, :teardown, :loop_count) do + # @param [String] result - A file to write result + def render(results:) + prelude = preludes.reject(&:nil?).reject(&:empty?).join("\n") + ERB.new(<<-RUBY).result_with_hash(results: results) +Warning[:experimental] = false +# shareable-constant-value: experimental_everything +#{prelude} + +if #{loop_count} == 1 + __bmdv_loop_before = 0 + __bmdv_loop_after = 0 +else + __bmdv_loop_before = Time.new + #{while_loop('', loop_count, id: 0)} + __bmdv_loop_after = Time.new +end + +__bmdv_ractors = [] +<% results.size.times do %> +__bmdv_ractors << Ractor.new(__bmdv_loop_after - __bmdv_loop_before) { |__bmdv_loop_time| + __bmdv_time = Time + __bmdv_script_before = __bmdv_time.new + #{while_loop(script, loop_count, id: 1)} + __bmdv_script_after = __bmdv_time.new + + (__bmdv_script_after - __bmdv_script_before) - __bmdv_loop_time +} +<% end %> + +# Wait for all Ractors before executing code to write results +__bmdv_ractors.map!(&:value) + +<% results.each do |result| %> +File.write(<%= result.dump %>, __bmdv_ractors.shift) +<% end %> + +#{teardown} + RUBY + end + + private + + # id is to prevent: + # can not isolate a Proc because it accesses outer variables (__bmdv_i) + def while_loop(content, times, id:) + if !times.is_a?(Integer) || times <= 0 + raise ArgumentError.new("Unexpected times: #{times.inspect}") + elsif times == 1 + return content + end + + # TODO: execute in batch + <<-RUBY +__bmdv_i#{id} = 0 +while __bmdv_i#{id} < #{times} + #{content} + __bmdv_i#{id} += 1 +end + RUBY + end + end + private_constant :BenchmarkScript +end diff --git a/benchmark/lib/load.rb b/benchmark/lib/load.rb index 4d73a63323..31b770c484 100755..100644 --- a/benchmark/lib/load.rb +++ b/benchmark/lib/load.rb @@ -1,2 +1,18 @@ +# How to use this file: +# 1. write a `$(srcdir)/test.rb` like: +=begin +require_relative 'benchmark/lib/load' + +Benchmark.driver(repeat_count: 5){|x| + x.executable name: 'clean-miniruby', command: %w'../clean-trunk/miniruby' + x.executable name: 'modif-miniruby', command: %w'./miniruby' + + x.report %q{ + h = {a: 1, b: 2, c: 3, d: 4} + } +} +=end +# +# 2. `make run` $:.unshift(File.join(__dir__, '../benchmark-driver/lib')) require 'benchmark_driver' diff --git a/benchmark/loop_each.yml b/benchmark/loop_each.yml new file mode 100644 index 0000000000..1c757185a8 --- /dev/null +++ b/benchmark/loop_each.yml @@ -0,0 +1,4 @@ +prelude: | + arr = [nil] * 30_000_000 +benchmark: + loop_each: arr.each{|e|} diff --git a/benchmark/loop_generator.rb b/benchmark/loop_generator.rb index d3375c744c..6a3194b670 100644 --- a/benchmark/loop_generator.rb +++ b/benchmark/loop_generator.rb @@ -1,4 +1,4 @@ -max = 600000 +max = 6000000 if defined? Fiber gen = (1..max).each diff --git a/benchmark/loop_times_megamorphic.yml b/benchmark/loop_times_megamorphic.yml new file mode 100644 index 0000000000..f9343ba897 --- /dev/null +++ b/benchmark/loop_times_megamorphic.yml @@ -0,0 +1,7 @@ +prelude: | + eval(<<~EOS) + def loop_times_megamorphic + #{"1.times {|i|};" * 1000} + end + EOS +benchmark: loop_times_megamorphic diff --git a/benchmark/marshal_dump_load_integer.yml b/benchmark/marshal_dump_load_integer.yml new file mode 100644 index 0000000000..78ebf823d2 --- /dev/null +++ b/benchmark/marshal_dump_load_integer.yml @@ -0,0 +1,22 @@ +prelude: | + smallint_array = 1000.times.map { |x| x } + bigint32_array = 1000.times.map { |x| x + 2**32 } + bigint64_array = 1000.times.map { |x| x + 2**64 } + + smallint_dump = Marshal.dump(smallint_array) + bigint32_dump = Marshal.dump(bigint32_array) + bigint64_dump = Marshal.dump(bigint64_array) +benchmark: + marshal_dump_integer_small: | + Marshal.dump(smallint_array) + marshal_dump_integer_over_32_bit: | + Marshal.dump(bigint32_array) + marshal_dump_integer_over_64_bit: | + Marshal.dump(bigint64_array) + marshal_load_integer_small: | + Marshal.load(smallint_dump) + marshal_load_integer_over_32_bit: | + Marshal.load(bigint32_dump) + marshal_load_integer_over_64_bit: | + Marshal.load(bigint64_dump) +loop_count: 4000 diff --git a/benchmark/masgn.yml b/benchmark/masgn.yml new file mode 100644 index 0000000000..31cb8ee4a3 --- /dev/null +++ b/benchmark/masgn.yml @@ -0,0 +1,53 @@ +prelude: | + a = [nil] * 3 + b = Class.new{attr_writer :a, :b, :c}.new + c = d = e = f = g = h = i = nil +benchmark: + array2_2: "c = (a[0], a[1] = 1, 2)" + array2_3: "c = (a[0], a[1] = 1, 2, 3)" + array3_2: "c = (a[0], a[1], a[2] = 1, 2)" + array3_3: "c = (a[0], a[1], a[2] = 1, 2, 3)" + attr2_2: "c = (b.a, b.b = 1, 2)" + attr2_3: "c = (b.a, b.b = 1, 2, 3)" + attr3_2: "c = (b.a, b.b, b.c = 1, 2)" + attr3_3: "c = (b.a, b.b, b.c = 1, 2, 3)" + lvar2_2: "c = (d, e = 1, 2)" + lvar2_3: "c = (d, e = 1, 2, 3)" + lvar3_2: "c = (d, e, f = 1, 2)" + lvar3_3: "c = (d, e, f = 1, 2, 3)" + array2_2p: "(a[0], a[1] = 1, 2; nil)" + array2_3p: "(a[0], a[1] = 1, 2, 3; nil)" + array3_2p: "(a[0], a[1], a[2] = 1, 2; nil)" + array3_3p: "(a[0], a[1], a[2] = 1, 2, 3; nil)" + attr2_2p: "(b.a, b.b = 1, 2; nil)" + attr2_3p: "(b.a, b.b = 1, 2, 3; nil)" + attr3_2p: "(b.a, b.b, b.c = 1, 2; nil)" + attr3_3p: "(b.a, b.b, b.c = 1, 2, 3; nil)" + lvar2_2p: "(d, e = 1, 2; nil)" + lvar2_3p: "(d, e = 1, 2, 3; nil)" + lvar3_2p: "(d, e, f = 1, 2; nil)" + lvar3_3p: "(d, e, f = 1, 2, 3; nil)" + array2_2lv: "c = (a[0], a[1] = g, h)" + array2_ilv: "c = (a[0], a[1] = g, h, i)" + arrayi_2lv: "c = (a[0], a[1], a[2] = g, h)" + arrayi_ilv: "c = (a[0], a[1], a[2] = g, h, i)" + attr2_2lv: "c = (b.a, b.b = g, h)" + attr2_ilv: "c = (b.a, b.b = g, h, i)" + attri_2lv: "c = (b.a, b.b, b.c = g, h)" + attri_ilv: "c = (b.a, b.b, b.c = g, h, i)" + lvar2_2lv: "c = (d, e = g, h)" + lvar2_ilv: "c = (d, e = g, h, i)" + lvari_2lv: "c = (d, e, f = g, h)" + lvari_ilv: "c = (d, e, f = g, h, i)" + array2_2plv: "(a[0], a[1] = g, h; nil)" + array2_iplv: "(a[0], a[1] = g, h, i; nil)" + arrayi_2plv: "(a[0], a[1], a[2] = g, h; nil)" + arrayi_iplv: "(a[0], a[1], a[2] = g, h, i; nil)" + attr2_2plv: "(b.a, b.b = g, h; nil)" + attr2_iplv: "(b.a, b.b = g, h, i; nil)" + attri_2plv: "(b.a, b.b, b.c = g, h; nil)" + attri_iplv: "(b.a, b.b, b.c = g, h, i; nil)" + lvar2_2plv: "(d, e = g, h; nil)" + lvar2_iplv: "(d, e = g, h, i; nil)" + lvari_2plv: "(d, e, f = g, h; nil)" + lvari_iplv: "(d, e, f = g, h, i; nil)" diff --git a/benchmark/method_bind_call.yml b/benchmark/method_bind_call.yml new file mode 100644 index 0000000000..9e0e046ed4 --- /dev/null +++ b/benchmark/method_bind_call.yml @@ -0,0 +1,16 @@ +prelude: | + named_module = Kernel + + module FakeName + def self.name + "NotMyame".freeze + end + end + + MOD_NAME = Module.instance_method(:name) + +benchmark: + fastpath: MOD_NAME.bind_call(Kernel) + slowpath: MOD_NAME.bind_call(FakeName) + +loop_count: 100_000 diff --git a/benchmark/module_eqq.yml b/benchmark/module_eqq.yml new file mode 100644 index 0000000000..2f9c490d92 --- /dev/null +++ b/benchmark/module_eqq.yml @@ -0,0 +1,32 @@ +prelude: | + module SomeModule; end + class SimpleClass; end + class MediumClass + 10.times { include Module.new } + end + class LargeClass + 100.times { include Module.new } + end + class HugeClass + 300.times { include Module.new } + end + SimpleObj = SimpleClass.new + MediumObj = MediumClass.new + LargeObj = LargeClass.new + HugeObj = HugeClass.new +benchmark: + simple_class_eqq_simple_obj: | + SimpleClass === SimpleObj + medium_class_eqq_simple_obj: | + MediumClass === SimpleObj + simple_class_eqq_medium_obj: | + SimpleClass === MediumObj + simple_class_eqq_large_obj: | + SimpleClass === LargeObj + simple_class_eqq_huge_obj: | + SimpleClass === HugeObj + simple_class_eqq_module: | + SimpleClass === HugeObj + module_eqq_module: | + SomeModule === HugeObj +loop_count: 10000000 diff --git a/benchmark/nil_p.yml b/benchmark/nil_p.yml new file mode 100644 index 0000000000..79ba4f2177 --- /dev/null +++ b/benchmark/nil_p.yml @@ -0,0 +1,9 @@ +prelude: | + class Niller; def nil?; true; end; end + xnil, notnil = nil, Object.new + niller = Niller.new +benchmark: + - xnil.nil? + - notnil.nil? + - niller.nil? +loop_count: 10000000 diff --git a/benchmark/nilclass.yml b/benchmark/nilclass.yml new file mode 100644 index 0000000000..66234c4cdf --- /dev/null +++ b/benchmark/nilclass.yml @@ -0,0 +1,16 @@ +prelude: | + def a = nil +benchmark: + rationalize: + nil.rationalize + to_c: | + nil.to_c + to_i: | + nil.to_i + to_f: | + nil.to_f + to_r: | + nil.to_r + splat: | + a(*nil) +loop_count: 100000 diff --git a/benchmark/num_zero_p.yml b/benchmark/num_zero_p.yml new file mode 100644 index 0000000000..2195963433 --- /dev/null +++ b/benchmark/num_zero_p.yml @@ -0,0 +1,8 @@ +benchmark: + - 0.zero? + - 1.zero? + - 0r.zero? + - 1r.zero? + - 0i.zero? + - 1i.zero? +loop_count: 50000000 diff --git a/benchmark/numeric_methods.yml b/benchmark/numeric_methods.yml new file mode 100644 index 0000000000..1384902935 --- /dev/null +++ b/benchmark/numeric_methods.yml @@ -0,0 +1,29 @@ +prelude: | + int = 42 + flo = 4.2 +benchmark: + real?: | + int.real? + integer?: | + flo.integer? + finite?: | + int.finite? + infinite?: | + int.infinite? + integer_real: | + int.real + float_real: | + flo.real + integr_imag: | + int.imag + float_imag: | + flo.imag + integer_conj: | + int.conj + float_conj: | + flo.conj + integer_numerator: | + int.numerator + integer_denominator: | + int.denominator +loop_count: 20000000 diff --git a/benchmark/object_allocate.yml b/benchmark/object_allocate.yml new file mode 100644 index 0000000000..c6269923f0 --- /dev/null +++ b/benchmark/object_allocate.yml @@ -0,0 +1,49 @@ +prelude: | + class Eight + 8.times { include(Module.new) } + end + class ThirtyTwo + 32.times { include(Module.new) } + end + class SixtyFour + 64.times { include(Module.new) } + end + class OneTwentyEight + 128.times { include(Module.new) } + end + class OnePositional + def initialize a; end + end + class TwoPositional + def initialize a, b; end + end + class ThreePositional + def initialize a, b, c; end + end + class FourPositional + def initialize a, b, c, d; end + end + class KWArg + def initialize a:, b:, c:, d: + end + end + class Mixed + def initialize a, b, c:, d: + end + end + # Disable GC to see raw throughput: + GC.disable +benchmark: + allocate_8_deep: Eight.new + allocate_32_deep: ThirtyTwo.new + allocate_64_deep: SixtyFour.new + allocate_128_deep: OneTwentyEight.new + allocate_1_positional_params: OnePositional.new(1) + allocate_2_positional_params: TwoPositional.new(1, 2) + allocate_3_positional_params: ThreePositional.new(1, 2, 3) + allocate_4_positional_params: FourPositional.new(1, 2, 3, 4) + allocate_kwarg_params: "KWArg.new(a: 1, b: 2, c: 3, d: 4)" + allocate_mixed_params: "Mixed.new(1, 2, c: 3, d: 4)" + allocate_no_params: "Object.new" + allocate_allocate: "Object.allocate" +loop_count: 100000 diff --git a/benchmark/object_class.yml b/benchmark/object_class.yml new file mode 100644 index 0000000000..1e5409d1e2 --- /dev/null +++ b/benchmark/object_class.yml @@ -0,0 +1,40 @@ +prelude: | + def get_class(obj) + i = 10_000 + while i > 0 + i -= 1 + # 100 times per loop + obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; + obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; + obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; + obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; + obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; + obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; + obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; + obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; + obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; + obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; + obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; + end + end + + class Obj + end + obj = Obj.new + + singleton = Obj.new + def singleton.bar + end + + extended = Obj.new + 2.times do + extended.extend Module.new + end + + immediate = 1.4 +benchmark: + obj: get_class(obj) + extended: get_class(extended) + singleton: get_class(singleton) + immediate: get_class(immediate) +loop_count: 1000 diff --git a/benchmark/object_id.yml b/benchmark/object_id.yml new file mode 100644 index 0000000000..2bd52b923f --- /dev/null +++ b/benchmark/object_id.yml @@ -0,0 +1,4 @@ +benchmark: + baseline: "Object.new" + object_id: "Object.new.object_id" +# loop_count: 100000 diff --git a/benchmark/objspace_dump_all.yml b/benchmark/objspace_dump_all.yml new file mode 100644 index 0000000000..ebab562d2e --- /dev/null +++ b/benchmark/objspace_dump_all.yml @@ -0,0 +1,13 @@ +prelude: | + require 'objspace' + require 'tempfile' + $objs = 1_000.times.map { Object.new } + $strings = 1_000.times.map { |i| "string #{i}" } + $file = Tempfile.new('heap') + $dev_null = File.open(File::NULL, 'w+') + +benchmark: + dump_all_string: "ObjectSpace.dump_all(output: :string)" + dump_all_file: "ObjectSpace.dump_all(output: $file)" + dump_all_dev_null: "ObjectSpace.dump_all(output: $dev_null)" +loop_count: 1 diff --git a/benchmark/other-lang/fact.py b/benchmark/other-lang/fact.py index 01593965d9..1ce9f76275 100644 --- a/benchmark/other-lang/fact.py +++ b/benchmark/other-lang/fact.py @@ -3,7 +3,7 @@ def factL(n): r = 1 - for x in range(2, n): + for x in range(2, n+1): r *= x return r diff --git a/benchmark/pm_array.yml b/benchmark/pm_array.yml new file mode 100644 index 0000000000..babb65a289 --- /dev/null +++ b/benchmark/pm_array.yml @@ -0,0 +1,19 @@ +prelude: | + def call(*val) + case val + in [String => body] + [200, {}, [body]] + in [Integer => status] + [status, {}, [""]] + in [Integer, String] => response + [response[0], {}, [response[1]]] + in [Integer, Hash, String] => response + [response[0], response[1], [response[2]]] + end + end + +benchmark: + first_match: call("ok") + second_match: call(401) + third_match: call(200, "ok") + fourth_match: call(201, {}, "created") diff --git a/benchmark/ractor_const.yml b/benchmark/ractor_const.yml new file mode 100644 index 0000000000..d7ab74bdca --- /dev/null +++ b/benchmark/ractor_const.yml @@ -0,0 +1,4 @@ +type: lib/benchmark_driver/runner/ractor +benchmark: + ractor_const: Object +ractor: 1 diff --git a/benchmark/ractor_float_to_s.yml b/benchmark/ractor_float_to_s.yml new file mode 100644 index 0000000000..8f492be668 --- /dev/null +++ b/benchmark/ractor_float_to_s.yml @@ -0,0 +1,8 @@ +type: lib/benchmark_driver/runner/ractor +prelude: | + FLOATS = [*0.0.step(1.0, 0.001)] +benchmark: + ractor_float_to_s: | + FLOATS.each {|f| f.to_s} +loop_count: 100 +ractor: 2 diff --git a/benchmark/ractor_string_fstring.yml b/benchmark/ractor_string_fstring.yml new file mode 100644 index 0000000000..14b92d8fd8 --- /dev/null +++ b/benchmark/ractor_string_fstring.yml @@ -0,0 +1,18 @@ +type: lib/benchmark_driver/runner/ractor +benchmark: + ractor_fstring_random: | + i = 0 + str = "same".dup + while i < 2000000 + -(i.to_s.freeze) + i += 1 + end + ractor_fstring_same: | + i = 0 + str = "same".dup + while i < 2000000 + -str + i += 1 + end +loop_count: 1 +ractor: 4 diff --git a/benchmark/range_bsearch_bignum.yml b/benchmark/range_bsearch_bignum.yml new file mode 100644 index 0000000000..5730c93fcf --- /dev/null +++ b/benchmark/range_bsearch_bignum.yml @@ -0,0 +1,10 @@ +prelude: | + first = 2**100 + last = 2**1000 + mid = (first + last) / 2 + r = first..last + +benchmark: + first: r.bsearch { |x| x >= first } + mid: r.bsearch { |x| x >= mid } + last: r.bsearch { |x| x >= last } diff --git a/benchmark/range_bsearch_endpointless.yml b/benchmark/range_bsearch_endpointless.yml new file mode 100644 index 0000000000..8d7bedb662 --- /dev/null +++ b/benchmark/range_bsearch_endpointless.yml @@ -0,0 +1,21 @@ +prelude: | + re = (1..) + rb = (..0) + +benchmark: + 'endless 10**0': re.bsearch { |x| x >= 1 } + 'endless 10**1': re.bsearch { |x| x >= 10 } + 'endless 10**2': re.bsearch { |x| x >= 100 } + 'endless 10**3': re.bsearch { |x| x >= 1000 } + 'endless 10**4': re.bsearch { |x| x >= 10000 } + 'endless 10**5': re.bsearch { |x| x >= 100000 } + 'endless 10**10': re.bsearch { |x| x >= 10000000000 } + 'endless 10**100': re.bsearch { |x| x >= 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 } + 'beginless -10**0': rb.bsearch { |x| x >= -1 } + 'beginless -10**1': rb.bsearch { |x| x >= -10 } + 'beginless -10**2': rb.bsearch { |x| x >= -100 } + 'beginless -10**3': rb.bsearch { |x| x >= -1000 } + 'beginless -10**4': rb.bsearch { |x| x >= -10000 } + 'beginless -10**5': rb.bsearch { |x| x >= -100000 } + 'beginless -10**10': rb.bsearch { |x| x >= -10000000000 } + 'beginless -10**100': rb.bsearch { |x| x >= -10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 } diff --git a/benchmark/range_bsearch_fixnum.yml b/benchmark/range_bsearch_fixnum.yml new file mode 100644 index 0000000000..59416531b9 --- /dev/null +++ b/benchmark/range_bsearch_fixnum.yml @@ -0,0 +1,10 @@ +prelude: | + first = 1 + last = 10000 + mid = (first + last) / 2 + r = first..last + +benchmark: + first: r.bsearch { |x| x >= first } + mid: r.bsearch { |x| x >= mid } + last: r.bsearch { |x| x >= last } diff --git a/benchmark/range_count.yml b/benchmark/range_count.yml new file mode 100644 index 0000000000..58f53a0236 --- /dev/null +++ b/benchmark/range_count.yml @@ -0,0 +1,11 @@ +prelude: | + r_1 = 1..1 + r_1k = 1..1000 + r_1m = 1..1000000 + r_str = 'a'..'z' + +benchmark: + 'int 1': r_1.count + 'int 1K': r_1k.count + 'int 1M': r_1m.count + string: r_str.count diff --git a/benchmark/range_min.yml b/benchmark/range_min.yml new file mode 100644 index 0000000000..9e60dd7308 --- /dev/null +++ b/benchmark/range_min.yml @@ -0,0 +1,2 @@ +benchmark: + - (1..10).min diff --git a/benchmark/range_overlap.yml b/benchmark/range_overlap.yml new file mode 100644 index 0000000000..700a00053c --- /dev/null +++ b/benchmark/range_overlap.yml @@ -0,0 +1,19 @@ +prelude: | + class Range + unless method_defined?(:overlap?) + def overlap?(other) + other.begin == self.begin || cover?(other.begin) || other.cover?(self.begin) + end + end + end + +benchmark: + - (2..3).overlap?(1..1) + - (2..3).overlap?(2..4) + - (2..3).overlap?(4..5) + - (2..3).overlap?(2..1) + - (2..3).overlap?(0..1) + - (2..3).overlap?(...1) + - (2...3).overlap?(..2) + - (2...3).overlap?(3...) + - (2..3).overlap?('a'..'d') diff --git a/benchmark/range_reverse_each.yml b/benchmark/range_reverse_each.yml new file mode 100644 index 0000000000..a32efeccc6 --- /dev/null +++ b/benchmark/range_reverse_each.yml @@ -0,0 +1,16 @@ +prelude: | + rf_1 = 0..1 + rf_1k = 0..1000 + rf_1m = 0..1000000 + big = 2**1000 + rb_1 = big..big+1 + rb_1k = big..big+1000 + rb_1m = big..big+1000000 + +benchmark: + "Fixnum 1": rf_1.reverse_each { _1 } + "Fixnum 1K": rf_1k.reverse_each { _1 } + "Fixnum 1M": rf_1m.reverse_each { _1 } + "Bignum 1": rb_1.reverse_each { _1 } + "Bignum 1K": rb_1k.reverse_each { _1 } + "Bignum 1M": rb_1m.reverse_each { _1 } diff --git a/benchmark/realpath.yml b/benchmark/realpath.yml index 90a029d5b9..6b6a4836b0 100644 --- a/benchmark/realpath.yml +++ b/benchmark/realpath.yml @@ -12,6 +12,9 @@ prelude: | relative_dir = 'b/c' absolute_dir = File.join(pwd, relative_dir) file_dir = 'c' +teardown: | + require 'fileutils' + FileUtils.rm_rf('b') benchmark: relative_nil: "f.realpath(relative, nil)" absolute_nil: "f.realpath(absolute, nil)" diff --git a/benchmark/regexp_dup.yml b/benchmark/regexp_dup.yml new file mode 100644 index 0000000000..52f89991cd --- /dev/null +++ b/benchmark/regexp_dup.yml @@ -0,0 +1,6 @@ +prelude: | + str = "a" * 1000 + re = Regexp.new(str) + +benchmark: + dup: re.dup diff --git a/benchmark/regexp_new.yml b/benchmark/regexp_new.yml new file mode 100644 index 0000000000..bc9ab3ca21 --- /dev/null +++ b/benchmark/regexp_new.yml @@ -0,0 +1,7 @@ +prelude: | + str = "a" * 1000 + re = Regexp.new(str) + +benchmark: + string: Regexp.new(str) + regexp: Regexp.new(re) diff --git a/benchmark/require.yml b/benchmark/require.yml index 711d8e11e9..09f218cf08 100644 --- a/benchmark/require.yml +++ b/benchmark/require.yml @@ -15,11 +15,7 @@ prelude: | FileUtils.mkdir_p(data_dir) 1.upto(num_files) do |i| - f = File.open("#{data_dir}/c#{i}.rb", "w") - f.puts <<-END - class C#{i} - end - END + File.write("#{data_dir}/c#{i}.rb", "class C#{i}\n""end\n") end end diff --git a/benchmark/require_thread.yml b/benchmark/require_thread.yml index 87e0ba888b..0c63257106 100644 --- a/benchmark/require_thread.yml +++ b/benchmark/require_thread.yml @@ -15,11 +15,7 @@ prelude: | FileUtils.mkdir_p(data_dir) 1.upto(num_files) do |i| - f = File.open("#{data_dir}/c#{i}.rb", "w") - f.puts <<-END - class C#{i} - end - END + File.write("#{data_dir}/c#{i}.rb", "class C#{i}\n""end\n") end end diff --git a/benchmark/scan.yaml b/benchmark/scan.yaml new file mode 100644 index 0000000000..62ad1d6862 --- /dev/null +++ b/benchmark/scan.yaml @@ -0,0 +1,16 @@ +prelude: | + $LOAD_PATH.unshift(File.expand_path("lib")) + require "strscan" + str = "test string" + scanner = StringScanner.new(str) + str = "test" + reg = /test/ +benchmark: + check(reg): | + scanner.check(reg) + check(str): | + scanner.check(str) + match?(reg): | + scanner.match?(reg) + match?(str): | + scanner.match?(str) diff --git a/benchmark/search.yaml b/benchmark/search.yaml new file mode 100644 index 0000000000..42a50c90e6 --- /dev/null +++ b/benchmark/search.yaml @@ -0,0 +1,16 @@ +prelude: | + $LOAD_PATH.unshift(File.expand_path("lib")) + require "strscan" + str = "test string" + scanner = StringScanner.new(str) + str = "string" + reg = /string/ +benchmark: + check_until(reg): | + scanner.check_until(reg) + check_until(str): | + scanner.check_until(str) + exist?(reg): | + scanner.exist?(reg) + exist?(str): | + scanner.exist?(str) diff --git a/benchmark/set.yml b/benchmark/set.yml new file mode 100644 index 0000000000..061509cb1f --- /dev/null +++ b/benchmark/set.yml @@ -0,0 +1,261 @@ +prelude: | + # First 1000 digits of pi + pi = <<~END.gsub(/\D/, '') + 31415926535897932384626433832795028841971693993751058209749445923078164062862089 + 98628034825342117067982148086513282306647093844609550582231725359408128481117450 + 28410270193852110555964462294895493038196442881097566593344612847564823378678316 + 52712019091456485669234603486104543266482133936072602491412737245870066063155881 + 74881520920962829254091715364367892590360011330530548820466521384146951941511609 + 43305727036575959195309218611738193261179310511854807446237996274956735188575272 + 48912279381830119491298336733624406566430860213949463952247371907021798609437027 + 70539217176293176752384674818467669405132000568127145263560827785771342757789609 + 17363717872146844090122495343014654958537105079227968925892354201995611212902196 + 08640344181598136297747713099605187072113499999983729780499510597317328160963185 + 95024459455346908302642522308253344685035261931188171010003137838752886587533208 + 38142061717766914730359825349042875546873115956286388235378759375195778185778053 + 21712268066130019278766111959092164201989380952572010654505906988788448549 + END + array1 = 10.times.flat_map do |i| + pi[i...].chars.each_slice(10).map(&:join) + end + array2 = array1.map(&:reverse) + array1.map!(&:to_i) + array2.map!(&:to_i) + a1 = array1[...10] + a2 = array1[...100] + a3 = array1 + oa1 = array2[...10] + oa2 = array2[...100] + oa3 = array2 + s0 = Set.new + s0 = Set.new + s1 = Set.new(a1) + s2 = Set.new(a2) + s3 = Set.new(a3) + o0 = Set.new + o1 = Set.new(array2[...10]) + o2 = Set.new(array2[...100]) + o3 = Set.new(array2) + d0 = s0.dup + d1 = s1.dup + d2 = s2.dup + d3 = s3.dup + ss1 = s1 - a1[-1..-1] + ss2 = s2 - a2[-1..-1] + ss3 = s3 - a3[-1..-1] + os1 = o1 - oa1[-1..-1] + os2 = o2 - oa2[-1..-1] + os3 = o3 - oa3[-1..-1] + member = a1.first + cbi = s0.dup.compare_by_identity + ns = Set[s3, o3, d3] + set_subclass = Class.new(Set) + +benchmark: + new_0: Set.new + new_10: Set.new(a1) + new_100: Set.new(a2) + new_1000: Set.new(a3) + aref_0: Set[] + aref_10: Set[*a1] + aref_100: Set[*a2] + aref_1000: Set[*a3] + amp_0: s0 & o0 + amp_10: s1 & o1 + amp_100: s2 & o2 + amp_1000: s3 & o3 + amp_same_0: s0 & d0 + amp_same_10: s1 & d1 + amp_same_100: s2 & d2 + amp_same_1000: s3 & d3 + minus_0: s0 - o0 + minus_10: s1 - o1 + minus_100: s2 - o2 + minus_1000: s3 - o3 + minus_same_0: s0 - d0 + minus_same_10: s1 - d1 + minus_same_100: s2 - d2 + minus_same_1000: s3 - d3 + spaceship_0: s0 <=> o0 + spaceship_diff_10: s1 <=> o1 + spaceship_diff_100: s2 <=> o2 + spaceship_diff_1000: s2 <=> o3 + spaceship_sub_10: s1 <=> ss1 + spaceship_sub_100: s2 <=> ss2 + spaceship_sub_1000: s2 <=> ss3 + spaceship_sup_10: ss1 <=> s1 + spaceship_sup_100: ss2 <=> s2 + spaceship_sup_1000: ss2 <=> s3 + eq_0: s0 == o0 + eq_10: s1 == o1 + eq_100: s2 == o2 + eq_1000: s3 == o3 + eq_same_0: s0 == d0 + eq_same_10: s1 == d1 + eq_same_100: s2 == d2 + eq_same_1000: s3 == d3 + xor_0: s0 ^ o0 + xor_10: s1 ^ o1 + xor_100: s2 ^ o2 + xor_1000: s3 ^ o3 + xor_same_0: s0 ^ d0 + xor_same_10: s1 ^ d1 + xor_same_100: s2 ^ d2 + xor_same_1000: s3 ^ d3 + pipe_0: s0 | o0 + pipe_10: s1 | o1 + pipe_100: s2 | o2 + pipe_1000: s3 | o3 + pipe_same_0: s0 | d0 + pipe_same_10: s1 | d1 + pipe_same_100: s2 | d2 + pipe_same_1000: s3 | d3 + add: a3.each { s0.add(it) } + add_exist: a3.each { s3.add(it) } + addq: a3.each { s0.add?(it) } + addq_exist: a3.each { s3.add?(it) } + classify_0: s0.classify { it } + classify_10: s1.classify { it & 2 } + classify_100: s2.classify { it & 8 } + classify_1000: s3.classify { it & 32 } + clear: s0.clear + collect_0: s0.collect! { it } + collect_10: s1.collect! { it } + collect_100: s2.collect! { it } + collect_1000: s3.collect! { it } + compare_by_identity_0: s0.dup.compare_by_identity + compare_by_identity_10: s1.dup.compare_by_identity + compare_by_identity_100: s2.dup.compare_by_identity + compare_by_identity_1000: s3.dup.compare_by_identity + compare_by_identityq_false: s0.compare_by_identity? + compare_by_identityq_true: cbi.compare_by_identity? + clone_0: s0.clone + clone_10: s1.clone + clone_100: s2.clone + clone_1000: s3.clone + delete: a3.each { s3.delete(it) } + delete_not_exist: a3.each { o3.delete(it) } + deleteq: a3.each { s3.delete?(it) } + deleteq_not_exist: a3.each { o3.delete?(it) } + delete_if_0: s0.delete_if { it } + delete_if_10: s1.delete_if { it & 2 == 0 } + delete_if_100: s2.delete_if { it & 2 == 0 } + delete_if_1000: s3.delete_if { it & 2 == 0 } + disjoint_0: s0.disjoint? o0 + disjoint_10: s1.disjoint? o1 + disjoint_100: s2.disjoint? o2 + disjoint_1000: s3.disjoint? o3 + disjoint_same_0: s0.disjoint? d0 + disjoint_same_10: s1.disjoint? d1 + disjoint_same_100: s2.disjoint? d2 + disjoint_same_1000: s3.disjoint? d3 + divide_1arity_0: s0.divide { true } + divide_1arity_10: s1.divide { it & 2 } + divide_1arity_100: s2.divide { it & 8 } + divide_1arity_1000: s3.divide { it & 32 } + divide_2arity_0: s0.divide { true } + divide_2arity_10: s1.divide { (_1 & 2) == (_2 & 2) } + divide_2arity_100: s2.divide { (_1 & 8) == (_2 & 8) } + divide_2arity_1000: s3.divide { (_1 & 32) == (_2 & 32) } + dup_0: s0.dup + dup_10: s1.dup + dup_100: s2.dup + dup_1000: s3.dup + each_0: s0.each { it } + each_10: s1.each { it } + each_100: s2.each { it } + each_1000: s3.each { it } + empty_true: s0.empty? + empty_false: s3.empty? + flatten: ns.flatten + flattenb: ns.flatten! + include_true_0: s0.include? member + include_true_10: s1.include? member + include_true_100: s2.include? member + include_true_1000: s3.include? member + include_false_0: s0.include?(-1) + include_false_10: s1.include?(-1) + include_false_100: s2.include?(-1) + include_false_1000: s3.include?(-1) + intersect_0: s0.intersect? o0 + intersect_10: s1.intersect? o1 + intersect_100: s2.intersect? o2 + intersect_1000: s3.intersect? o3 + intersect_same_0: s0.intersect? d0 + intersect_same_10: s1.intersect? d1 + intersect_same_100: s2.intersect? d2 + intersect_same_1000: s3.intersect? d3 + join_0: s0.join + join_10: s1.join + join_100: s2.join + join_1000: s3.join + join_arg_0: s0.join "" + join_arg_10: s1.join "" + join_arg_100: s2.join "" + join_arg_1000: s3.join "" + keep_if_0: s0.keep_if { it } + keep_if_10: s1.keep_if { it & 2 == 0 } + keep_if_100: s2.keep_if { it & 2 == 0 } + keep_if_1000: s3.keep_if { it & 2 == 0 } + merge_set: s0.dup.merge(s3, o3) + merge_enum: s0.dup.merge(array1, array2) + proper_subset_0: s0.proper_subset? s0 + proper_subset_10: s1.proper_subset? ss1 + proper_subset_100: s2.proper_subset? ss2 + proper_subset_1000: s3.proper_subset? ss3 + proper_subset_false_10: s1.proper_subset? os1 + proper_subset_false_100: s2.proper_subset? os2 + proper_subset_false_1000: s3.proper_subset? os3 + proper_superset_0: s0.proper_superset? s0 + proper_superset_10: ss1.proper_superset? s1 + proper_superset_100: ss2.proper_superset? s2 + proper_superset_1000: ss3.proper_superset? s3 + proper_superset_false_10: os1.proper_superset? s1 + proper_superset_false_100: os2.proper_superset? s2 + proper_superset_false_1000: os3.proper_superset? s3 + reject_0: s0.reject! { it } + reject_10: s1.reject! { it & 2 == 0 } + reject_100: s2.reject! { it & 2 == 0 } + reject_1000: s3.reject! { it & 2 == 0 } + replace_0: s = Set.new; array1.each { s.replace(s0) } + replace_10: s = Set.new; array1.each { s.replace(s1) } + replace_100: s = Set.new; array1.each { s.replace(s2) } + replace_1000: s = Set.new; array1.each { s.replace(s3) } + reset_0: s0.reset + reset_10: s1.reset + reset_100: s2.reset + reset_1000: s3.reset + select_0: s0.select! { it } + select_10: s1.select! { it & 2 == 0 } + select_100: s2.select! { it & 2 == 0 } + select_1000: s3.select! { it & 2 == 0 } + size_0: s0.size + size_10: s1.size + size_100: s2.size + size_1000: s3.size + subtract_set: s3.dup.subtract(os3) + subtract_enum: s3.dup.subtract(oa3) + subtract_same_set: s3.dup.subtract(s3) + subtract_same_enum: s3.dup.subtract(a3) + subset_0: s0.subset? s0 + subset_10: s1.subset? ss1 + subset_100: s2.subset? ss2 + subset_1000: s3.subset? ss3 + subset_false_10: s1.subset? os1 + subset_false_100: s2.subset? os2 + subset_false_1000: s3.subset? os3 + superset_0: s0.superset? s0 + superset_10: ss1.superset? s1 + superset_100: ss2.superset? s2 + superset_1000: ss3.superset? s3 + superset_false_10: os1.superset? s1 + superset_false_100: os2.superset? s2 + superset_false_1000: os3.superset? s3 + to_a_0: s0.to_a + to_a_10: s1.to_a + to_a_100: s2.to_a + to_a_1000: s3.to_a + to_set_0: s0.to_set + to_set_10: s1.to_set + to_set_100: s2.to_set + to_set_1000: s3.to_set diff --git a/benchmark/so_count_words.yml b/benchmark/so_count_words.yml index 99683505f9..f7322a8541 100644 --- a/benchmark/so_count_words.yml +++ b/benchmark/so_count_words.yml @@ -15,13 +15,13 @@ prelude: | Newsgroups: rec.games.roguelike.nethack X-Mailer: Mozilla 1.1N (Macintosh; I; 68K) - Hello there, Izchak Miller was my father. When I was younger I spent - many a night, hunched over the keyboard with a cup of tea, playing - nethack with him and my brother. my dad was a philosopher with a strong - weakness for fantasy/sci fi. I remember when he started to get involved - with the Nethack team- my brother's Dungeons and Dragons monster book - found a regular place beside my dad's desk. it's nice to see him living - on in the game he loved so much :-). + Hello there, Izchak Miller was my father. When I was younger I spent + many a night, hunched over the keyboard with a cup of tea, playing + nethack with him and my brother. my dad was a philosopher with a strong + weakness for fantasy/sci fi. I remember when he started to get involved + with the Nethack team- my brother's Dungeons and Dragons monster book + found a regular place beside my dad's desk. it's nice to see him living + on in the game he loved so much :-). Tamar Miller The following is a really long word of 5000 characters: @@ -38,8 +38,9 @@ prelude: | 13.times{ data << data } - open(wcinput, 'w'){|f| f.write data} + File.write(wcinput, data) end + at_exit {File.unlink(wcinput) rescue nil} end prepare_wc_input(wc_input_base) @@ -49,16 +50,16 @@ benchmark: # $Id: wc-ruby.code,v 1.4 2004/11/13 07:43:32 bfulgham Exp $ # http://www.bagley.org/~doug/shootout/ # with help from Paul Brannan - input = open(File.join(File.dirname($0), 'wc.input'), 'rb') nl = nw = nc = 0 - while true - tmp = input.read(4096) or break - data = tmp << (input.gets || "") - nc += data.length - nl += data.count("\n") - ((data.strip! || data).tr!("\n", " ") || data).squeeze! - nw += data.count(" ") + 1 + File.open(File.join(File.dirname($0), 'wc.input'), 'rb') do |input| + while tmp = input.read(4096) + data = tmp << (input.gets || "") + nc += data.length + nl += data.count("\n") + ((data.strip! || data).tr!("\n", " ") || data).squeeze! + nw += data.count(" ") + 1 + end end # STDERR.puts "#{nl} #{nw} #{nc}" diff --git a/benchmark/so_meteor_contest.rb b/benchmark/so_meteor_contest.rb index 8c136baa6c..d8c8e3ab9c 100644 --- a/benchmark/so_meteor_contest.rb +++ b/benchmark/so_meteor_contest.rb @@ -447,7 +447,7 @@ end # as an inverse. The inverse will ALWAYS be 3 one of the piece configurations that is exactly 3 rotations away # (an odd number). Checking even vs odd then produces a higher probability of finding more pieces earlier # in the cycle. We still need to keep checking all the permutations, but our probability of finding one will -# diminsh over time. Since we are TOLD how many to search for this lets us exit before checking all pieces +# diminish over time. Since we are TOLD how many to search for this lets us exit before checking all pieces # this bennifit is very great when seeking small numbers of solutions and is 0 when looking for more than the # maximum number def find_top( rotation_skip) diff --git a/benchmark/so_nbody.rb b/benchmark/so_nbody.rb index d6c5bb9e61..9884fc4edc 100644 --- a/benchmark/so_nbody.rb +++ b/benchmark/so_nbody.rb @@ -12,38 +12,38 @@ def _puts *args end class Planet - attr_accessor :x, :y, :z, :vx, :vy, :vz, :mass + attr_accessor :x, :y, :z, :vx, :vy, :vz, :mass - def initialize(x, y, z, vx, vy, vz, mass) - @x, @y, @z = x, y, z - @vx, @vy, @vz = vx * DAYS_PER_YEAR, vy * DAYS_PER_YEAR, vz * DAYS_PER_YEAR - @mass = mass * SOLAR_MASS - end - - def move_from_i(bodies, nbodies, dt, i) - while i < nbodies - b2 = bodies[i] - dx = @x - b2.x - dy = @y - b2.y - dz = @z - b2.z - - distance = Math.sqrt(dx * dx + dy * dy + dz * dz) - mag = dt / (distance * distance * distance) - b_mass_mag, b2_mass_mag = @mass * mag, b2.mass * mag - - @vx -= dx * b2_mass_mag - @vy -= dy * b2_mass_mag - @vz -= dz * b2_mass_mag - b2.vx += dx * b_mass_mag - b2.vy += dy * b_mass_mag - b2.vz += dz * b_mass_mag - i += 1 + def initialize(x, y, z, vx, vy, vz, mass) + @x, @y, @z = x, y, z + @vx, @vy, @vz = vx * DAYS_PER_YEAR, vy * DAYS_PER_YEAR, vz * DAYS_PER_YEAR + @mass = mass * SOLAR_MASS end - @x += dt * @vx - @y += dt * @vy - @z += dt * @vz - end + def move_from_i(bodies, nbodies, dt, i) + while i < nbodies + b2 = bodies[i] + dx = @x - b2.x + dy = @y - b2.y + dz = @z - b2.z + + distance = Math.sqrt(dx * dx + dy * dy + dz * dz) + mag = dt / (distance * distance * distance) + b_mass_mag, b2_mass_mag = @mass * mag, b2.mass * mag + + @vx -= dx * b2_mass_mag + @vy -= dy * b2_mass_mag + @vz -= dz * b2_mass_mag + b2.vx += dx * b_mass_mag + b2.vy += dy * b_mass_mag + b2.vz += dz * b_mass_mag + i += 1 + end + + @x += dt * @vx + @y += dt * @vy + @z += dt * @vz + end end def energy(bodies) diff --git a/benchmark/string_casecmp.yml b/benchmark/string_casecmp.yml new file mode 100644 index 0000000000..88a3555c8a --- /dev/null +++ b/benchmark/string_casecmp.yml @@ -0,0 +1,28 @@ +prelude: | + lstr1 = [*"a".."z",*"0".."9"].join("") + lstr10 = lstr1 * 10 + lstr100 = lstr10 * 10 + lstr1000 = lstr100 * 10 + lnonascii1 = [*"\u{e0}".."\u{ff}"].join("") + lnonascii10 = lnonascii1 * 10 + lnonascii100 = lnonascii10 * 10 + lnonascii1000 = lnonascii100 * 10 + ustr1 = [*"A".."Z",*"0".."9"].join("") + ustr10 = ustr1 * 10 + ustr100 = ustr10 * 10 + ustr1000 = ustr100 * 10 + unonascii1 = [*"\u{c0}".."\u{df}"].join("") + unonascii10 = unonascii1 * 10 + unonascii100 = unonascii10 * 10 + unonascii1000 = unonascii100 * 10 +benchmark: + casecmp-1: lstr1.casecmp(ustr1) + casecmp-10: lstr10.casecmp(ustr10) + casecmp-100: lstr100.casecmp(ustr100) + casecmp-1000: lstr1000.casecmp(ustr1000) + casecmp-1000vs10: lstr1000.casecmp(ustr10) + casecmp-nonascii1: lnonascii1.casecmp(unonascii1) + casecmp-nonascii10: lnonascii10.casecmp(unonascii10) + casecmp-nonascii100: lnonascii100.casecmp(unonascii100) + casecmp-nonascii1000: lnonascii1000.casecmp(unonascii1000) + casecmp-nonascii1000vs10: lnonascii1000.casecmp(unonascii10) diff --git a/benchmark/string_casecmp_p.yml b/benchmark/string_casecmp_p.yml new file mode 100644 index 0000000000..a790ce7d55 --- /dev/null +++ b/benchmark/string_casecmp_p.yml @@ -0,0 +1,26 @@ +prelude: | + lstr1 = [*"a".."z",*"0".."9"].join("") + lstr10 = lstr1 * 10 + lstr100 = lstr10 * 10 + lstr1000 = lstr100 * 10 + lnonascii1 = [*"\u{e0}".."\u{ff}"].join("") + lnonascii10 = lnonascii1 * 10 + lnonascii100 = lnonascii10 * 10 + lnonascii1000 = lnonascii100 * 10 + ustr1 = [*"A".."Z",*"0".."9"].join("") + ustr10 = ustr1 * 10 + ustr100 = ustr10 * 10 + ustr1000 = ustr100 * 10 + unonascii1 = [*"\u{c0}".."\u{df}"].join("") + unonascii10 = unonascii1 * 10 + unonascii100 = unonascii10 * 10 + unonascii1000 = unonascii100 * 10 +benchmark: + casecmp_p-1: lstr1.casecmp?(ustr1) + casecmp_p-10: lstr10.casecmp?(ustr10) + casecmp_p-100: lstr100.casecmp?(ustr100) + casecmp_p-1000: lstr1000.casecmp?(ustr1000) + casecmp_p-nonascii1: lnonascii1.casecmp?(unonascii1) + casecmp_p-nonascii10: lnonascii10.casecmp?(unonascii10) + casecmp_p-nonascii100: lnonascii100.casecmp?(unonascii100) + casecmp_p-nonascii1000: lnonascii1000.casecmp?(unonascii1000) diff --git a/benchmark/string_concat.yml b/benchmark/string_concat.yml new file mode 100644 index 0000000000..f11f95ee9a --- /dev/null +++ b/benchmark/string_concat.yml @@ -0,0 +1,51 @@ +prelude: | + CHUNK = "a" * 64 + UCHUNK = "é" * 32 + SHORT = "a" * (GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE] / 2) + LONG = "a" * (GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE] * 2) + GC.disable # GC causes a lot of variance +benchmark: + binary_concat_7bit: | + buffer = String.new(capacity: 4096, encoding: Encoding::BINARY) + buffer << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK + buffer << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK + buffer << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK + buffer << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK + buffer << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK + buffer << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK + buffer << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK + buffer << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK + utf8_concat_7bit: | + buffer = String.new(capacity: 4096, encoding: Encoding::UTF_8) + buffer << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK + buffer << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK + buffer << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK + buffer << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK + buffer << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK + buffer << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK + buffer << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK + buffer << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK << CHUNK + utf8_concat_UTF8: | + buffer = String.new(capacity: 4096, encoding: Encoding::UTF_8) + buffer << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK + buffer << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK + buffer << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK + buffer << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK + buffer << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK + buffer << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK + buffer << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK + buffer << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK << UCHUNK + interpolation: | + buffer = "#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}" \ + "#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}" \ + "#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}" \ + "#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}" \ + "#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}" \ + "#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}" \ + "#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}" \ + "#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}" \ + "#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}" + interpolation_same_heap: | + buffer = "#{SHORT}#{SHORT}" + interpolation_switching_heaps: | + buffer = "#{SHORT}#{LONG}" diff --git a/benchmark/string_downcase.yml b/benchmark/string_downcase.yml index a31c3ac712..1fea6afbec 100644 --- a/benchmark/string_downcase.yml +++ b/benchmark/string_downcase.yml @@ -3,8 +3,16 @@ prelude: | str10 = str1 * 10 str100 = str10 * 10 str1000 = str100 * 10 + nonascii1 = [*"\u{c0}".."\u{df}"].join("") + nonascii10 = nonascii1 * 10 + nonascii100 = nonascii10 * 10 + nonascii1000 = nonascii100 * 10 benchmark: downcase-1: str1.upcase downcase-10: str10.upcase downcase-100: str100.upcase downcase-1000: str1000.upcase + downcase-nonascii1: nonascii1.downcase + downcase-nonascii10: nonascii10.downcase + downcase-nonascii100: nonascii100.downcase + downcase-nonascii1000: nonascii1000.downcase diff --git a/benchmark/string_dup.yml b/benchmark/string_dup.yml new file mode 100644 index 0000000000..90793f9f2a --- /dev/null +++ b/benchmark/string_dup.yml @@ -0,0 +1,7 @@ +prelude: | + # frozen_string_literal: true +benchmark: + uplus: | + +"A" + dup: | + "A".dup diff --git a/benchmark/string_fstring.yml b/benchmark/string_fstring.yml new file mode 100644 index 0000000000..cafef1f3fe --- /dev/null +++ b/benchmark/string_fstring.yml @@ -0,0 +1,16 @@ +benchmark: + fstring_random: | + i = 0 + str = "same".dup + while i < 5_000_000 + -(i.to_s.freeze) + i += 1 + end + fstring_same: | + i = 0 + str = "same".dup + while i < 10_000_000 + -str + i += 1 + end +loop_count: 1 diff --git a/benchmark/string_gsub.yml b/benchmark/string_gsub.yml new file mode 100644 index 0000000000..0f964337dd --- /dev/null +++ b/benchmark/string_gsub.yml @@ -0,0 +1,43 @@ +prelude: | + # frozen_string_literal: true + STR = ((("a" * 31) + "<") * 1000).freeze + STR_UNICODE = ((("a" * 30) + "\u2028") * 1000).freeze + ESCAPED_CHARS_BINARY = { + "\u2028".b => '\u2028'.b, + "\u2029".b => '\u2029'.b, + ">".b => '\u003e'.b.freeze, + "<".b => '\u003c'.b.freeze, + "&".b => '\u0026'.b.freeze, + } + BINARY_PATTERN = Regexp.union(ESCAPED_CHARS_BINARY.keys) + + ESCAPED_CHARS = { + "\u2028" => '\u2028', + "\u2029" => '\u2029', + ">" => '\u003e', + "<" => '\u003c', + "&" => '\u0026', + } + ESCAPE_PATTERN = Regexp.union(ESCAPED_CHARS.keys) + + +benchmark: + escape: | + str = STR.dup + str.gsub!(ESCAPE_PATTERN, ESCAPED_CHARS) + str + + escape_bin: | + str = STR.b + str.gsub!(BINARY_PATTERN, ESCAPED_CHARS_BINARY) + str.force_encoding(Encoding::UTF_8) + + escape_utf8: | + str = STR_UNICODE.dup + str.gsub!(ESCAPE_PATTERN, ESCAPED_CHARS) + str + + escape_utf8_bin: | + str = STR_UNICODE.b + str.gsub!(BINARY_PATTERN, ESCAPED_CHARS_BINARY) + str.force_encoding(Encoding::UTF_8) diff --git a/benchmark/string_rpartition.yml b/benchmark/string_rpartition.yml new file mode 100644 index 0000000000..37e9d1b071 --- /dev/null +++ b/benchmark/string_rpartition.yml @@ -0,0 +1,18 @@ +prelude: | + str1 = [*"a".."z",*"0".."9"].join("") + str10 = str1 * 10 + ":" + str100 = str1 * 100 + ":" + str1000 = str1 * 1000 + ":" + nonascii1 = [*"\u{e0}".."\u{ff}"].join("") + nonascii10 = nonascii1 * 10 + ":" + nonascii100 = nonascii1 * 100 + ":" + nonascii1000 = nonascii1 * 1000 + ":" +benchmark: + rpartition-1: str1.rpartition(":") + rpartition-10: str10.rpartition(":") + rpartition-100: str100.rpartition(":") + rpartition-1000: str1000.rpartition(":") + rpartition-nonascii1: nonascii1.rpartition(":") + rpartition-nonascii10: nonascii10.rpartition(":") + rpartition-nonascii100: nonascii100.rpartition(":") + rpartition-nonascii1000: nonascii1000.rpartition(":") diff --git a/benchmark/string_slice.yml b/benchmark/string_slice.yml new file mode 100644 index 0000000000..fc2393c5d1 --- /dev/null +++ b/benchmark/string_slice.yml @@ -0,0 +1,11 @@ +prelude: | + long_string = "x"*1000+"-hår" +benchmark: + regexp-short: | + "x-hår".slice!(/-(.)(.)(.)/, 3) + regexp-long: | + long_string.dup.slice!(/-(.)(.)(.)/, 3) + string-short: | + "x-hår".slice!("r") + string-long: | + long_string.dup.slice!("r") diff --git a/benchmark/string_split.yml b/benchmark/string_split.yml index 84ffe8f6a7..cc2c7d7855 100644 --- a/benchmark/string_split.yml +++ b/benchmark/string_split.yml @@ -1,7 +1,22 @@ prelude: | - str0 = [*0..9].join("") + str1 = [*0..5].join(" ") + " " + str10 = str1 * 10 + str100 = str10 * 10 + str1000 = str100 * 10 benchmark: - to_chars-1: str0.split('') - to_chars-10: (str0 * 10).split('') - to_chars-100: (str0 * 100).split('') - to_chars-1000: (str0 * 1000).split('') + to_chars-1: str1.split('') + to_chars-10: str10.split('') + to_chars-100: str100.split('') + to_chars-1000: str1000.split('') + to_words-1: str1.split(' ') + to_words-10: str10.split(' ') + to_words-100: str100.split(' ') + to_words-1000: str1000.split(' ') + re_chars-1: str1.split(//) + re_chars-10: str10.split(//) + re_chars-100: str100.split(//) + re_chars-1000: str1000.split(//) + re_space-1: str1.split(/ /) + re_space-10: str10.split(/ /) + re_space-100: str100.split(/ /) + re_space-1000: str1000.split(/ /) diff --git a/benchmark/string_swapcase.yml b/benchmark/string_swapcase.yml index afaae3f696..eeb5928907 100644 --- a/benchmark/string_swapcase.yml +++ b/benchmark/string_swapcase.yml @@ -3,8 +3,16 @@ prelude: | str10 = str1 * 10 str100 = str10 * 10 str1000 = str100 * 10 + nonascii1 = [*"\u{c0}".."\u{cf}",*"\u{f0}".."\u{ff}"].join("") + nonascii10 = nonascii1 * 10 + nonascii100 = nonascii10 * 10 + nonascii1000 = nonascii100 * 10 benchmark: swapcase-1: str1.swapcase swapcase-10: str10.swapcase swapcase-100: str100.swapcase swapcase-1000: str1000.swapcase + swapcase-nonascii1: nonascii1.swapcase + swapcase-nonascii10: nonascii10.swapcase + swapcase-nonascii100: nonascii100.swapcase + swapcase-nonascii1000: nonascii1000.swapcase diff --git a/benchmark/string_upcase.yml b/benchmark/string_upcase.yml index 456d213c74..dab84bbde2 100644 --- a/benchmark/string_upcase.yml +++ b/benchmark/string_upcase.yml @@ -3,8 +3,16 @@ prelude: | str10 = str1 * 10 str100 = str10 * 10 str1000 = str100 * 10 + nonascii1 = [*"\u{e0}".."\u{ff}"].join("") + nonascii10 = nonascii1 * 10 + nonascii100 = nonascii10 * 10 + nonascii1000 = nonascii100 * 10 benchmark: upcase-1: str1.upcase upcase-10: str10.upcase upcase-100: str100.upcase upcase-1000: str1000.upcase + upcase-nonascii1: nonascii1.upcase + upcase-nonascii10: nonascii10.upcase + upcase-nonascii100: nonascii100.upcase + upcase-nonascii1000: nonascii1000.upcase diff --git a/benchmark/struct_accessor.yml b/benchmark/struct_accessor.yml new file mode 100644 index 0000000000..d95240e2dd --- /dev/null +++ b/benchmark/struct_accessor.yml @@ -0,0 +1,37 @@ +prelude: | + C = Struct.new(:x) do + def initialize(...) + super + @ivar = 42 + end + + attr_accessor :ivar + + class_eval <<-END + def r + #{'x;'*256} + end + def w + #{'self.x = nil;'*256} + end + def rm + m = method(:x) + #{'m.call;'*256} + end + def wm + m = method(:x=) + #{'m.call(nil);'*256} + end + def r_ivar + #{'ivar;'*256} + end + END + end + C.new(nil) # ensure common shape is known + obj = C.new(nil) +benchmark: + member_reader: "obj.r" + member_writer: "obj.w" + member_reader_method: "obj.rm" + member_writer_method: "obj.wm" + ivar_reader: "obj.r_ivar" diff --git a/benchmark/time_at.yml b/benchmark/time_at.yml new file mode 100644 index 0000000000..3247efbe77 --- /dev/null +++ b/benchmark/time_at.yml @@ -0,0 +1,7 @@ +prelude: | + # frozen_string_literal: true +benchmark: + - 'Time.at(0)' + - 'Time.at(0, 500)' + - 'Time.at(0, in: "+09:00")' + - 'Time.at(0, 500, in: "+09:00")' diff --git a/benchmark/time_new.yml b/benchmark/time_new.yml new file mode 100644 index 0000000000..5947dd3a41 --- /dev/null +++ b/benchmark/time_new.yml @@ -0,0 +1,4 @@ +benchmark: + - 'Time.new(2021)' + - 'Time.new(2021, 8, 22)' + - 'Time.new(2021, 8, 22, in: "+09:00")' diff --git a/benchmark/time_now.yml b/benchmark/time_now.yml new file mode 100644 index 0000000000..9336877cd4 --- /dev/null +++ b/benchmark/time_now.yml @@ -0,0 +1,4 @@ +benchmark: + - 'Time.now' + - 'Time.now(in: "+09:00")' + - 'Time.now.year' diff --git a/benchmark/time_parse.yml b/benchmark/time_parse.yml new file mode 100644 index 0000000000..6060b58bc6 --- /dev/null +++ b/benchmark/time_parse.yml @@ -0,0 +1,10 @@ +prelude: | + require 'time' + inspect = "2021-08-23 09:57:02 +0900" + iso8601 = "2021-08-23T09:57:02+09:00" +benchmark: + - Time.iso8601(iso8601) + - Time.parse(iso8601) + - Time.parse(inspect) + - Time.new(iso8601) rescue Time.iso8601(iso8601) + - Time.new(inspect) rescue Time.parse(inspect) diff --git a/benchmark/time_strftime.yml b/benchmark/time_strftime.yml new file mode 100644 index 0000000000..28f62aec87 --- /dev/null +++ b/benchmark/time_strftime.yml @@ -0,0 +1,7 @@ +prelude: | + # frozen_string_literal: true + time = Time.now +benchmark: + - time.strftime("%FT%T") # 19B + - time.strftime("%FT%T.%3N") # 23B + - time.strftime("%FT%T.%6N") # 26B diff --git a/benchmark/time_xmlschema.yml b/benchmark/time_xmlschema.yml new file mode 100644 index 0000000000..654e5cfcbc --- /dev/null +++ b/benchmark/time_xmlschema.yml @@ -0,0 +1,27 @@ +prelude: | + # frozen_string_literal + unless Time.method_defined?(:xmlschema) + class Time + def xmlschema(fraction_digits=0) + fraction_digits = fraction_digits.to_i + s = strftime("%FT%T") + if fraction_digits > 0 + s << strftime(".%#{fraction_digits}N") + end + s << (utc? ? 'Z' : strftime("%:z")) + end + end + end + time = Time.now + utc_time = Time.now.utc + fraction_sec = Time.at(123456789.quo(9999999999)).getlocal("+09:00") + future_time = Time.utc(10000) +benchmark: + - time.xmlschema + - utc_time.xmlschema + - time.xmlschema(6) + - utc_time.xmlschema(6) + - time.xmlschema(9) + - utc_time.xmlschema(9) + - fraction_sec.xmlschema(10) + - future_time.xmlschema diff --git a/benchmark/vm1_const.yml b/benchmark/vm1_const.yml deleted file mode 100644 index b98db1545c..0000000000 --- a/benchmark/vm1_const.yml +++ /dev/null @@ -1,7 +0,0 @@ -prelude: | - Const = 1 -benchmark: - vm1_const: | - j = Const - k = Const -loop_count: 30000000 diff --git a/benchmark/vm2_array.yml b/benchmark/vm_array.yml index 7373098d5e..2a177237ef 100644 --- a/benchmark/vm2_array.yml +++ b/benchmark/vm_array.yml @@ -1,4 +1,4 @@ benchmark: - vm2_array: | + vm_array: | a = [1,2,3,4,5,6,7,8,9,10] loop_count: 6000000 diff --git a/benchmark/vm1_attr_ivar.yml b/benchmark/vm_attr_ivar.yml index f714dd9bd9..75b803478e 100644 --- a/benchmark/vm1_attr_ivar.yml +++ b/benchmark/vm_attr_ivar.yml @@ -8,7 +8,7 @@ prelude: | end obj = C.new benchmark: - vm1_attr_ivar: | + vm_attr_ivar: | j = obj.a k = obj.b loop_count: 30000000 diff --git a/benchmark/vm1_attr_ivar_set.yml b/benchmark/vm_attr_ivar_set.yml index f383e59ef4..a0d379b18a 100644 --- a/benchmark/vm1_attr_ivar_set.yml +++ b/benchmark/vm_attr_ivar_set.yml @@ -8,7 +8,7 @@ prelude: | end obj = C.new benchmark: - vm1_attr_ivar_set: | + vm_attr_ivar_set: | obj.a = 1 obj.b = 2 loop_count: 30000000 diff --git a/benchmark/vm3_backtrace.rb b/benchmark/vm_backtrace.rb index 0fbf73e1ca..0fbf73e1ca 100644 --- a/benchmark/vm3_backtrace.rb +++ b/benchmark/vm_backtrace.rb diff --git a/benchmark/vm2_bigarray.yml b/benchmark/vm_bigarray.yml index 2ad6da3905..8b2d3f3443 100644 --- a/benchmark/vm2_bigarray.yml +++ b/benchmark/vm_bigarray.yml @@ -1,5 +1,5 @@ benchmark: - vm2_bigarray: | + vm_bigarray: | a = [ 1,2,3,4,5,6,7,8,9,10, 1,2,3,4,5,6,7,8,9,10, diff --git a/benchmark/vm2_bighash.yml b/benchmark/vm_bighash.yml index e9154e4ba9..4dacfde793 100644 --- a/benchmark/vm2_bighash.yml +++ b/benchmark/vm_bighash.yml @@ -1,4 +1,4 @@ benchmark: - vm2_bighash: | + vm_bighash: | a = {0=>0, 1=>1, 2=>2, 3=>3, 4=>4, 5=>5, 6=>6, 7=>7, 8=>8, 9=>9, 10=>10, 11=>11, 12=>12, 13=>13, 14=>14, 15=>15, 16=>16, 17=>17, 18=>18, 19=>19, 20=>20, 21=>21, 22=>22, 23=>23, 24=>24, 25=>25, 26=>26, 27=>27, 28=>28, 29=>29, 30=>30, 31=>31, 32=>32, 33=>33, 34=>34, 35=>35, 36=>36, 37=>37, 38=>38, 39=>39, 40=>40, 41=>41, 42=>42, 43=>43, 44=>44, 45=>45, 46=>46, 47=>47, 48=>48, 49=>49, 50=>50, 51=>51, 52=>52, 53=>53, 54=>54, 55=>55, 56=>56, 57=>57, 58=>58, 59=>59, 60=>60, 61=>61, 62=>62, 63=>63, 64=>64, 65=>65, 66=>66, 67=>67, 68=>68, 69=>69, 70=>70, 71=>71, 72=>72, 73=>73, 74=>74, 75=>75, 76=>76, 77=>77, 78=>78, 79=>79, 80=>80, 81=>81, 82=>82, 83=>83, 84=>84, 85=>85, 86=>86, 87=>87, 88=>88, 89=>89, 90=>90, 91=>91, 92=>92, 93=>93, 94=>94, 95=>95, 96=>96, 97=>97, 98=>98, 99=>99, 100=>100, 101=>101, 102=>102, 103=>103, 104=>104, 105=>105, 106=>106, 107=>107, 108=>108, 109=>109, 110=>110, 111=>111, 112=>112, 113=>113, 114=>114, 115=>115, 116=>116, 117=>117, 118=>118, 119=>119, 120=>120, 121=>121, 122=>122, 123=>123, 124=>124, 125=>125, 126=>126, 127=>127, 128=>128, 129=>129, 130=>130, 131=>131, 132=>132, 133=>133, 134=>134, 135=>135, 136=>136, 137=>137, 138=>138, 139=>139, 140=>140, 141=>141, 142=>142, 143=>143, 144=>144, 145=>145, 146=>146, 147=>147, 148=>148, 149=>149, 150=>150, 151=>151, 152=>152, 153=>153, 154=>154, 155=>155, 156=>156, 157=>157, 158=>158, 159=>159, 160=>160, 161=>161, 162=>162, 163=>163, 164=>164, 165=>165, 166=>166, 167=>167, 168=>168, 169=>169, 170=>170, 171=>171, 172=>172, 173=>173, 174=>174, 175=>175, 176=>176, 177=>177, 178=>178, 179=>179, 180=>180, 181=>181, 182=>182, 183=>183, 184=>184, 185=>185, 186=>186, 187=>187, 188=>188, 189=>189, 190=>190, 191=>191, 192=>192, 193=>193, 194=>194, 195=>195, 196=>196, 197=>197, 198=>198, 199=>199, 200=>200, 201=>201, 202=>202, 203=>203, 204=>204, 205=>205, 206=>206, 207=>207, 208=>208, 209=>209, 210=>210, 211=>211, 212=>212, 213=>213, 214=>214, 215=>215, 216=>216, 217=>217, 218=>218, 219=>219, 220=>220, 221=>221, 222=>222, 223=>223, 224=>224, 225=>225, 226=>226, 227=>227, 228=>228, 229=>229, 230=>230, 231=>231, 232=>232, 233=>233, 234=>234, 235=>235, 236=>236, 237=>237, 238=>238, 239=>239, 240=>240, 241=>241, 242=>242, 243=>243, 244=>244, 245=>245, 246=>246, 247=>247, 248=>248, 249=>249, 250=>250, 251=>251, 252=>252, 253=>253, 254=>254, 255=>255, 256=>256, 257=>257, 258=>258, 259=>259, 260=>260, 261=>261, 262=>262, 263=>263, 264=>264, 265=>265, 266=>266, 267=>267, 268=>268, 269=>269, 270=>270, 271=>271, 272=>272, 273=>273, 274=>274, 275=>275, 276=>276, 277=>277, 278=>278, 279=>279, 280=>280, 281=>281, 282=>282, 283=>283, 284=>284, 285=>285, 286=>286, 287=>287, 288=>288, 289=>289, 290=>290, 291=>291, 292=>292, 293=>293, 294=>294, 295=>295, 296=>296, 297=>297, 298=>298, 299=>299, 300=>300, 301=>301, 302=>302, 303=>303, 304=>304, 305=>305, 306=>306, 307=>307, 308=>308, 309=>309, 310=>310, 311=>311, 312=>312, 313=>313, 314=>314, 315=>315, 316=>316, 317=>317, 318=>318, 319=>319, 320=>320, 321=>321, 322=>322, 323=>323, 324=>324, 325=>325, 326=>326, 327=>327, 328=>328, 329=>329, 330=>330, 331=>331, 332=>332, 333=>333, 334=>334, 335=>335, 336=>336, 337=>337, 338=>338, 339=>339, 340=>340, 341=>341, 342=>342, 343=>343, 344=>344, 345=>345, 346=>346, 347=>347, 348=>348, 349=>349, 350=>350, 351=>351, 352=>352, 353=>353, 354=>354, 355=>355, 356=>356, 357=>357, 358=>358, 359=>359, 360=>360, 361=>361, 362=>362, 363=>363, 364=>364, 365=>365, 366=>366, 367=>367, 368=>368, 369=>369, 370=>370, 371=>371, 372=>372, 373=>373, 374=>374, 375=>375, 376=>376, 377=>377, 378=>378, 379=>379, 380=>380, 381=>381, 382=>382, 383=>383, 384=>384, 385=>385, 386=>386, 387=>387, 388=>388, 389=>389, 390=>390, 391=>391, 392=>392, 393=>393, 394=>394, 395=>395, 396=>396, 397=>397, 398=>398, 399=>399, 400=>400, 401=>401, 402=>402, 403=>403, 404=>404, 405=>405, 406=>406, 407=>407, 408=>408, 409=>409, 410=>410, 411=>411, 412=>412, 413=>413, 414=>414, 415=>415, 416=>416, 417=>417, 418=>418, 419=>419, 420=>420, 421=>421, 422=>422, 423=>423, 424=>424, 425=>425, 426=>426, 427=>427, 428=>428, 429=>429, 430=>430, 431=>431, 432=>432, 433=>433, 434=>434, 435=>435, 436=>436, 437=>437, 438=>438, 439=>439, 440=>440, 441=>441, 442=>442, 443=>443, 444=>444, 445=>445, 446=>446, 447=>447, 448=>448, 449=>449, 450=>450, 451=>451, 452=>452, 453=>453, 454=>454, 455=>455, 456=>456, 457=>457, 458=>458, 459=>459, 460=>460, 461=>461, 462=>462, 463=>463, 464=>464, 465=>465, 466=>466, 467=>467, 468=>468, 469=>469, 470=>470, 471=>471, 472=>472, 473=>473, 474=>474, 475=>475, 476=>476, 477=>477, 478=>478, 479=>479, 480=>480, 481=>481, 482=>482, 483=>483, 484=>484, 485=>485, 486=>486, 487=>487, 488=>488, 489=>489, 490=>490, 491=>491, 492=>492, 493=>493, 494=>494, 495=>495, 496=>496, 497=>497, 498=>498, 499=>499, 500=>500,} loop_count: 60000 diff --git a/benchmark/vm1_block.yml b/benchmark/vm_block.yml index ac7c940f93..68b3e40bf5 100644 --- a/benchmark/vm1_block.yml +++ b/benchmark/vm_block.yml @@ -3,7 +3,7 @@ prelude: | yield end benchmark: - vm1_block: | + vm_block: | m{ } loop_count: 30000000 diff --git a/benchmark/vm_block_handler.yml b/benchmark/vm_block_handler.yml new file mode 100644 index 0000000000..461d7953ad --- /dev/null +++ b/benchmark/vm_block_handler.yml @@ -0,0 +1,27 @@ +# :FIXME: is there a way to benchmark block_handler_type_ifunc? + +prelude: | + p = proc{_1} + o = Object.new + def o.each + i = 0 + while i < 3_000_000 do + yield i + i += 1 + end + end + +benchmark: + - name: block_handler_type_iseq + script: | + o.each{_1} + + - name: block_handler_type_symbol + script: | + o.each(&:itself) + + - name: block_handler_type_proc + script: | + o.each(&p) + +loop_count: 1 diff --git a/benchmark/vm1_blockparam.yml b/benchmark/vm_blockparam.yml index 947b8c53d5..5e5a0170a2 100644 --- a/benchmark/vm1_blockparam.yml +++ b/benchmark/vm_blockparam.yml @@ -2,6 +2,6 @@ prelude: | def m &b end benchmark: - vm1_blockparam: | + vm_blockparam: | m{} loop_count: 30000000 diff --git a/benchmark/vm1_blockparam_call.yml b/benchmark/vm_blockparam_call.yml index e2817a3ce2..a7d8d366ea 100644 --- a/benchmark/vm1_blockparam_call.yml +++ b/benchmark/vm_blockparam_call.yml @@ -3,6 +3,6 @@ prelude: | b.call end benchmark: - vm1_blockparam_call: | + vm_blockparam_call: | m{} loop_count: 30000000 diff --git a/benchmark/vm1_blockparam_pass.yml b/benchmark/vm_blockparam_pass.yml index ca1bef3369..841f5e7a63 100644 --- a/benchmark/vm1_blockparam_pass.yml +++ b/benchmark/vm_blockparam_pass.yml @@ -7,6 +7,6 @@ prelude: | bp_yield &b end benchmark: - vm1_blockparam_pass: | + vm_blockparam_pass: | bp_pass{} loop_count: 30000000 diff --git a/benchmark/vm1_blockparam_yield.yml b/benchmark/vm_blockparam_yield.yml index 56ae617798..8ea9b46ed2 100644 --- a/benchmark/vm1_blockparam_yield.yml +++ b/benchmark/vm_blockparam_yield.yml @@ -3,6 +3,6 @@ prelude: | yield end benchmark: - vm1_blockparam_yield: | + vm_blockparam_yield: | bp_yield{} loop_count: 30000000 diff --git a/benchmark/vm_call_bmethod.yml b/benchmark/vm_call_bmethod.yml new file mode 100644 index 0000000000..40136e5aa4 --- /dev/null +++ b/benchmark/vm_call_bmethod.yml @@ -0,0 +1,37 @@ +prelude: | + define_method(:a0){} + define_method(:a1){|a| a} + define_method(:s){|*a| a} + define_method(:b){|kw: 1| kw} + + t0 = 0.times.to_a + t1 = 1.times.to_a + t10 = 10.times.to_a + t100 = 100.times.to_a + kw = {kw: 2} +benchmark: + bmethod_simple_0: | + a0 + bmethod_simple_1: | + a1(1) + bmethod_simple_0_splat: | + a0(*t0) + bmethod_simple_1_splat: | + a1(*t1) + bmethod_no_splat: | + s + bmethod_0_splat: | + s(*t0) + bmethod_1_splat: | + s(*t1) + bmethod_10_splat: | + s(*t10) + bmethod_100_splat: | + s(*t100) + bmethod_kw: | + b(kw: 1) + bmethod_no_kw: | + b + bmethod_kw_splat: | + b(**kw) +loop_count: 6000000 diff --git a/benchmark/vm_call_kw_and_kw_splat.yml b/benchmark/vm_call_kw_and_kw_splat.yml new file mode 100644 index 0000000000..aa6e549e0c --- /dev/null +++ b/benchmark/vm_call_kw_and_kw_splat.yml @@ -0,0 +1,25 @@ +prelude: | + h1, h10, h100, h1000 = [1, 10, 100, 1000].map do |n| + h = {kw: 1} + n.times{|i| h[i.to_s.to_sym] = i} + h + end + eh = {} + def kw(kw: nil, **kws) end +benchmark: + 1: | + kw(**h1) + 1_mutable: | + kw(**eh, **h1) + 10: | + kw(**h10) + 10_mutable: | + kw(**eh, **h10) + 100: | + kw(**h100) + 100_mutable: | + kw(**eh, **h100) + 1000: | + kw(**h1000) + 1000_mutable: | + kw(**eh, **h1000) diff --git a/benchmark/vm_call_method_missing.yml b/benchmark/vm_call_method_missing.yml new file mode 100644 index 0000000000..f890796f11 --- /dev/null +++ b/benchmark/vm_call_method_missing.yml @@ -0,0 +1,62 @@ +prelude: | + class A0 + def method_missing(m); m end + end + class A1 + def method_missing(m, a) a; end + end + class S + def method_missing(m, *a) a; end + end + class B + def method_missing(m, kw: 1) kw end + end + class SB + def method_missing(m, *a, kw: 1) kw end + end + + t0 = 0.times.to_a + t1 = 1.times.to_a + t10 = 10.times.to_a + t200 = 200.times.to_a + kw = {kw: 2} + + a0 = A0.new + a1 = A1.new + s = S.new + b = B.new + sb = SB.new +benchmark: + method_missing_simple_0: | + a0.() + method_missing_simple_1: | + a1.x(1) + method_missing_simple_0_splat: | + a0.(*t0) + method_missing_simple_1_splat: | + a1.(*t1) + method_missing_no_splat: | + s.() + method_missing_0_splat: | + s.(*t0) + method_missing_1_splat: | + s.(*t1) + method_missing_10_splat: | + s.(*t10) + method_missing_200_splat: | + s.(*t200) + method_missing_kw: | + b.(kw: 1) + method_missing_no_kw: | + b.() + method_missing_kw_splat: | + b.(**kw) + method_missing_0_splat_kw: | + sb.(*t0, **kw) + method_missing_1_splat_kw: | + sb.(*t1, **kw) + method_missing_10_splat_kw: | + sb.(*t10, **kw) + method_missing_200_splat_kw: | + sb.(*t200, **kw) +loop_count: 1000000 diff --git a/benchmark/vm_call_send_iseq.yml b/benchmark/vm_call_send_iseq.yml new file mode 100644 index 0000000000..60ff23c475 --- /dev/null +++ b/benchmark/vm_call_send_iseq.yml @@ -0,0 +1,77 @@ +prelude: | + def a0; end + def a1(a) a; end + def s(*a) a; end + def b(kw: 1) kw end + def sb(*a, kw: 1) kw end + + t0 = 0.times.to_a + t1 = 1.times.to_a + t10 = 10.times.to_a + t200 = 200.times.to_a + + a0_t0 = [:a0, *t0] + a1_t1 = [:a1, *t1] + s_t0 = [:s, *t0] + s_t1 = [:s, *t1] + s_t10 = [:s, *t10] + s_t200 = [:s, *t200] + sb_t0 = [:sb, *t0] + sb_t1 = [:sb, *t1] + sb_t10 = [:sb, *t10] + sb_t200 = [:sb, *t200] + kw = {kw: 2} +benchmark: + send_simple_0: | + send(:a0) + send_simple_1: | + send(:a1, 1) + send_simple_0_splat: | + send(:a0, *t0) + send_simple_1_splat: | + send(:a1, *t1) + send_simple_0_splat_comb: | + send(*a0_t0) + send_simple_1_splat_comb: | + send(*a1_t1) + send_no_splat: | + send(:s) + send_0_splat: | + send(:s, *t0) + send_1_splat: | + send(:s, *t1) + send_10_splat: | + send(:s, *t10) + send_200_splat: | + send(:s, *t200) + send_0_splat_comb: | + send(*s_t0) + send_1_splat_comb: | + send(*s_t1) + send_10_splat_comb: | + send(*s_t10) + send_200_splat_comb: | + send(*s_t200) + send_kw: | + send(:b, kw: 1) + send_no_kw: | + send(:b) + send_kw_splat: | + send(:b, **kw) + send_0_splat_kw: | + send(:sb, *t0, **kw) + send_1_splat_kw: | + send(:sb, *t1, **kw) + send_10_splat_kw: | + send(:sb, *t10, **kw) + send_200_splat_kw: | + send(:sb, *t200, **kw) + send_0_splat_comb_kw: | + send(*sb_t0, **kw) + send_1_splat_comb_kw: | + send(*sb_t1, **kw) + send_10_splat_comb_kw: | + send(*sb_t10, **kw) + send_200_splat_comb_kw: | + send(*sb_t200, **kw) +loop_count: 3000000 diff --git a/benchmark/vm_call_symproc.yml b/benchmark/vm_call_symproc.yml new file mode 100644 index 0000000000..16e0ac579e --- /dev/null +++ b/benchmark/vm_call_symproc.yml @@ -0,0 +1,83 @@ +prelude: | + def self.a0; end + def self.a1(a) a; end + def self.s(*a) a; end + def self.b(kw: 1) kw end + def self.sb(*a, kw: 1) kw end + + t0 = 0.times.to_a + t1 = 1.times.to_a + t10 = 10.times.to_a + t200 = 200.times.to_a + + a0_t0 = [self, *t0] + a1_t1 = [self, *t1] + s_t0 = [self, *t0] + s_t1 = [self, *t1] + s_t10 = [self, *t10] + s_t200 = [self, *t200] + sb_t0 = [self, *t0] + sb_t1 = [self, *t1] + sb_t10 = [self, *t10] + sb_t200 = [self, *t200] + kw = {kw: 2} + + a0 = :a0.to_proc + a1 = :a1.to_proc + s = :s.to_proc + b = :b.to_proc + sb = :sb.to_proc +benchmark: + symproc_simple_0: | + a0.(self) + symproc_simple_1: | + a1.(self, 1) + symproc_simple_0_splat: | + a0.(self, *t0) + symproc_simple_1_splat: | + a1.(self, *t1) + symproc_simple_0_splat_comb: | + a0.(*a0_t0) + symproc_simple_1_splat_comb: | + a1.(*a1_t1) + symproc_no_splat: | + s.(self) + symproc_0_splat: | + s.(self, *t0) + symproc_1_splat: | + s.(self, *t1) + symproc_10_splat: | + s.(self, *t10) + symproc_200_splat: | + s.(self, *t200) + symproc_0_splat_comb: | + s.(*s_t0) + symproc_1_splat_comb: | + s.(*s_t1) + symproc_10_splat_comb: | + s.(*s_t10) + symproc_200_splat_comb: | + s.(*s_t200) + symproc_kw: | + b.(self, kw: 1) + symproc_no_kw: | + b.(self) + symproc_kw_splat: | + b.(self, **kw) + symproc_0_splat_kw: | + sb.(self, *t0, **kw) + symproc_1_splat_kw: | + sb.(self, *t1, **kw) + symproc_10_splat_kw: | + sb.(self, *t10, **kw) + symproc_200_splat_kw: | + sb.(self, *t200, **kw) + symproc_0_splat_comb_kw: | + sb.(*sb_t0, **kw) + symproc_1_splat_comb_kw: | + sb.(*sb_t1, **kw) + symproc_10_splat_comb_kw: | + sb.(*sb_t10, **kw) + symproc_200_splat_comb_kw: | + sb.(*sb_t200, **kw) +loop_count: 1000000 diff --git a/benchmark/vm2_case.yml b/benchmark/vm_case.yml index 7716783c09..b26a491a15 100644 --- a/benchmark/vm2_case.yml +++ b/benchmark/vm_case.yml @@ -1,5 +1,5 @@ benchmark: - vm2_case: | + vm_case: | case :foo when :bar raise diff --git a/benchmark/vm_case_classes.yml b/benchmark/vm_case_classes.yml new file mode 100644 index 0000000000..cacc4f0464 --- /dev/null +++ b/benchmark/vm_case_classes.yml @@ -0,0 +1,9 @@ +benchmark: + vm_case_classes: | + case :foo + when Hash + raise + when Array + raise + end +loop_count: 6000000 diff --git a/benchmark/vm2_case_lit.yml b/benchmark/vm_case_lit.yml index c49b8dfe5e..9f91801544 100644 --- a/benchmark/vm2_case_lit.yml +++ b/benchmark/vm_case_lit.yml @@ -1,6 +1,6 @@ # loop_count is not utilized since `i` is involved in the script benchmark: - vm2_case_lit: | + vm_case_lit: | i = 0 @ret = [ "foo", true, false, :sym, 6, nil, 0.1, 0xffffffffffffffff ] def foo(i) diff --git a/benchmark/vm3_clearmethodcache.rb b/benchmark/vm_clearmethodcache.rb index 9661323cd2..9661323cd2 100644 --- a/benchmark/vm3_clearmethodcache.rb +++ b/benchmark/vm_clearmethodcache.rb diff --git a/benchmark/vm_const.yml b/benchmark/vm_const.yml new file mode 100644 index 0000000000..8939ca0cd3 --- /dev/null +++ b/benchmark/vm_const.yml @@ -0,0 +1,13 @@ +prelude: | + Const = 1 + A = B = C = D = E = F = G = H = I = J = K = L = M = N = O = P = Q = R = S = T = U = V = W = X = Y = Z = 1 + def foo + A; B; C; D; E; F; G; H; I; J; K; L; M; N; O; P; Q; R; S; T; U; V; W; X; Y; Z + end +benchmark: + vm_const: | + j = Const + k = Const + vm_const_many: | + foo +loop_count: 30000000 diff --git a/benchmark/vm_cvar.yml b/benchmark/vm_cvar.yml new file mode 100644 index 0000000000..1d0e161829 --- /dev/null +++ b/benchmark/vm_cvar.yml @@ -0,0 +1,20 @@ +prelude: | + class A + @@foo = 1 + + def self.foo + @@foo + end + + ("A".."Z").each do |module_name| + eval <<-EOM + module #{module_name} + end + + include #{module_name} + EOM + end + end +benchmark: + vm_cvar: A.foo +loop_count: 600000 diff --git a/benchmark/vm2_defined_method.yml b/benchmark/vm_defined_method.yml index e1b0d55674..347e0cfd33 100644 --- a/benchmark/vm2_defined_method.yml +++ b/benchmark/vm_defined_method.yml @@ -3,6 +3,6 @@ prelude: | define_method(:m){} end benchmark: - vm2_defined_method: | + vm_defined_method: | m; m; m; m; m; m; m; m; loop_count: 6000000 diff --git a/benchmark/vm2_dstr.yml b/benchmark/vm_dstr.yml index f8bd6e0133..30c7a3193c 100644 --- a/benchmark/vm2_dstr.yml +++ b/benchmark/vm_dstr.yml @@ -1,6 +1,6 @@ prelude: | x = y = 'z' benchmark: - vm2_dstr: | + vm_dstr: | str = "foo#{x}bar#{y}baz" loop_count: 6000000 diff --git a/benchmark/vm_dstr_ary.rb b/benchmark/vm_dstr_ary.rb new file mode 100644 index 0000000000..1d3aa3b97b --- /dev/null +++ b/benchmark/vm_dstr_ary.rb @@ -0,0 +1,6 @@ +i = 0 +x = y = [] +while i<6_000_000 # benchmark loop 2 + i += 1 + str = "foo#{x}bar#{y}baz" +end diff --git a/benchmark/vm_dstr_bool.rb b/benchmark/vm_dstr_bool.rb new file mode 100644 index 0000000000..631ca54755 --- /dev/null +++ b/benchmark/vm_dstr_bool.rb @@ -0,0 +1,7 @@ +i = 0 +x = true +y = false +while i<6_000_000 # benchmark loop 2 + i += 1 + str = "foo#{x}bar#{y}baz" +end diff --git a/benchmark/vm_dstr_class_module.rb b/benchmark/vm_dstr_class_module.rb new file mode 100644 index 0000000000..becf0861c7 --- /dev/null +++ b/benchmark/vm_dstr_class_module.rb @@ -0,0 +1,10 @@ +i = 0 +class A; end unless defined?(A) +module B; end unless defined?(B) +x = A +y = B +while i<6_000_000 # benchmark loop 2 + i += 1 + str = "foo#{x}bar#{y}baz" +end + diff --git a/benchmark/vm_dstr_digit.rb b/benchmark/vm_dstr_digit.rb new file mode 100644 index 0000000000..caaa395192 --- /dev/null +++ b/benchmark/vm_dstr_digit.rb @@ -0,0 +1,7 @@ +i = 0 +x = 0 +y = 9 +while i<6_000_000 # benchmark loop 2 + i += 1 + str = "foo#{x}bar#{y}baz" +end diff --git a/benchmark/vm_dstr_int.rb b/benchmark/vm_dstr_int.rb new file mode 100644 index 0000000000..ed380d7595 --- /dev/null +++ b/benchmark/vm_dstr_int.rb @@ -0,0 +1,5 @@ +i = 0 +while i<6_000_000 # benchmark loop 2 + i += 1 + str = "foo#{i}bar#{i}baz" +end diff --git a/benchmark/vm_dstr_nil.rb b/benchmark/vm_dstr_nil.rb new file mode 100644 index 0000000000..ec4f5d6c67 --- /dev/null +++ b/benchmark/vm_dstr_nil.rb @@ -0,0 +1,6 @@ +i = 0 +x = y = nil +while i<6_000_000 # benchmark loop 2 + i += 1 + str = "foo#{x}bar#{y}baz" +end diff --git a/benchmark/vm_dstr_obj.rb b/benchmark/vm_dstr_obj.rb new file mode 100644 index 0000000000..fb78637ead --- /dev/null +++ b/benchmark/vm_dstr_obj.rb @@ -0,0 +1,6 @@ +i = 0 +x = y = Object.new +while i<6_000_000 # benchmark loop 2 + i += 1 + str = "foo#{x}bar#{y}baz" +end diff --git a/benchmark/vm_dstr_obj_def.rb b/benchmark/vm_dstr_obj_def.rb new file mode 100644 index 0000000000..99ff7b98fb --- /dev/null +++ b/benchmark/vm_dstr_obj_def.rb @@ -0,0 +1,8 @@ +i = 0 +o = Object.new +def o.to_s; -""; end +x = y = o +while i<6_000_000 # benchmark loop 2 + i += 1 + str = "foo#{x}bar#{y}baz" +end diff --git a/benchmark/vm_dstr_str.rb b/benchmark/vm_dstr_str.rb new file mode 100644 index 0000000000..45fc107892 --- /dev/null +++ b/benchmark/vm_dstr_str.rb @@ -0,0 +1,6 @@ +i = 0 +x = y = "" +while i<6_000_000 # benchmark loop 2 + i += 1 + str = "foo#{x}bar#{y}baz" +end diff --git a/benchmark/vm_dstr_sym.rb b/benchmark/vm_dstr_sym.rb new file mode 100644 index 0000000000..484b8f8150 --- /dev/null +++ b/benchmark/vm_dstr_sym.rb @@ -0,0 +1,6 @@ +i = 0 +x = y = :z +while i<6_000_000 # benchmark loop 2 + i += 1 + str = "foo#{x}bar#{y}baz" +end diff --git a/benchmark/vm1_ensure.yml b/benchmark/vm_ensure.yml index afbbe38bec..4ea62f30de 100644 --- a/benchmark/vm1_ensure.yml +++ b/benchmark/vm_ensure.yml @@ -1,6 +1,6 @@ # Not utilizing loop_count since using it for this is too unstable for now benchmark: - vm1_ensure: | + vm_ensure: | i = 0 while i<30_000_000 i += 1 diff --git a/benchmark/vm2_eval.yml b/benchmark/vm_eval.yml index d506a9c079..7ba1a8d1de 100644 --- a/benchmark/vm2_eval.yml +++ b/benchmark/vm_eval.yml @@ -1,4 +1,4 @@ benchmark: - vm2_eval: | + vm_eval: | eval("1") loop_count: 6000000 diff --git a/benchmark/vm2_fiber_allocate.yml b/benchmark/vm_fiber_allocate.yml index f29705f694..b5a54e1ddf 100644 --- a/benchmark/vm2_fiber_allocate.yml +++ b/benchmark/vm_fiber_allocate.yml @@ -2,7 +2,7 @@ prelude: | # Disable GC to see raw throughput: GC.disable benchmark: - vm2_fiber_allocate: | + vm_fiber_allocate: | fiber = Fiber.new{Fiber.yield} fiber.resume loop_count: 100000 diff --git a/benchmark/vm2_fiber_count.yml b/benchmark/vm_fiber_count.yml index 3ecf6bdcb2..b83d3152d4 100644 --- a/benchmark/vm2_fiber_count.yml +++ b/benchmark/vm_fiber_count.yml @@ -3,7 +3,7 @@ prelude: | fibers = [] benchmark: - vm2_fiber_count: | + vm_fiber_count: | fiber = Fiber.new{Fiber.yield} fibers << fiber fiber.resume diff --git a/benchmark/vm2_fiber_reuse.yml b/benchmark/vm_fiber_reuse.yml index 0170650638..4ca41085b1 100644 --- a/benchmark/vm2_fiber_reuse.yml +++ b/benchmark/vm_fiber_reuse.yml @@ -2,7 +2,7 @@ prelude: | GC.disable fibers = [] benchmark: - vm2_fiber_reuse: | + vm_fiber_reuse: | 1024.times do fiber = Fiber.new{Fiber.yield} fibers << fiber diff --git a/benchmark/vm2_fiber_reuse_gc.yml b/benchmark/vm_fiber_reuse_gc.yml index 8fb91a84eb..892622f121 100644 --- a/benchmark/vm2_fiber_reuse_gc.yml +++ b/benchmark/vm_fiber_reuse_gc.yml @@ -2,7 +2,7 @@ prelude: | fibers = [] benchmark: - vm2_fiber_reuse_gc: | + vm_fiber_reuse_gc: | 2000.times do fiber = Fiber.new{Fiber.yield} fibers << fiber diff --git a/benchmark/vm2_fiber_switch.yml b/benchmark/vm_fiber_switch.yml index fbf7283c29..3de36b66eb 100644 --- a/benchmark/vm2_fiber_switch.yml +++ b/benchmark/vm_fiber_switch.yml @@ -4,6 +4,6 @@ prelude: | loop { Fiber.yield } end benchmark: - vm2_fiber_switch: | + vm_fiber_switch: | fib.resume loop_count: 20000000 diff --git a/benchmark/vm1_float_simple.yml b/benchmark/vm_float_simple.yml index 4e9ad1852b..92f5fd52ab 100644 --- a/benchmark/vm1_float_simple.yml +++ b/benchmark/vm_float_simple.yml @@ -1,7 +1,7 @@ prelude: | f = 0.0 benchmark: - vm1_float_simple: | + vm_float_simple: | f += 0.1; f -= 0.1 f += 0.1; f -= 0.1 f += 0.1; f -= 0.1 diff --git a/benchmark/vm_freezeobj.yml b/benchmark/vm_freezeobj.yml new file mode 100644 index 0000000000..69a795a354 --- /dev/null +++ b/benchmark/vm_freezeobj.yml @@ -0,0 +1,6 @@ +prelude: | + objs = 100000.times.map { Object.new } +benchmark: + vm_freeze_obj: | + objs.map(&:freeze) +loop_count: 600 diff --git a/benchmark/vm2_freezestring.yml b/benchmark/vm_freezestring.yml index b78af91a20..facc9aa043 100644 --- a/benchmark/vm2_freezestring.yml +++ b/benchmark/vm_freezestring.yml @@ -5,6 +5,6 @@ prelude: | end end benchmark: - vm2_freezestring: | + vm_freezestring: | "tXnL1BP5T1WPXMjuFNLQtallEtRcay1t2lHtJSrlVsDgvunlbtfpr/DGdH0NGYE9".freeze loop_count: 6000000 diff --git a/benchmark/vm3_gc.rb b/benchmark/vm_gc.rb index e668026915..e668026915 100644 --- a/benchmark/vm3_gc.rb +++ b/benchmark/vm_gc.rb diff --git a/benchmark/vm3_gc_old_full.rb b/benchmark/vm_gc_old_full.rb index cfdfc8c5a5..cfdfc8c5a5 100644 --- a/benchmark/vm3_gc_old_full.rb +++ b/benchmark/vm_gc_old_full.rb diff --git a/benchmark/vm3_gc_old_immediate.rb b/benchmark/vm_gc_old_immediate.rb index ad22feb655..ad22feb655 100644 --- a/benchmark/vm3_gc_old_immediate.rb +++ b/benchmark/vm_gc_old_immediate.rb diff --git a/benchmark/vm3_gc_old_lazy.rb b/benchmark/vm_gc_old_lazy.rb index b74d44baf1..b74d44baf1 100644 --- a/benchmark/vm3_gc_old_lazy.rb +++ b/benchmark/vm_gc_old_lazy.rb diff --git a/benchmark/vm1_gc_short_lived.yml b/benchmark/vm_gc_short_lived.yml index 8fdcb7371d..29c803fee3 100644 --- a/benchmark/vm1_gc_short_lived.yml +++ b/benchmark/vm_gc_short_lived.yml @@ -1,5 +1,5 @@ benchmark: - vm1_gc_short_lived: | + vm_gc_short_lived: | a = '' # short-lived String b = '' c = '' diff --git a/benchmark/vm1_gc_short_with_complex_long.yml b/benchmark/vm_gc_short_with_complex_long.yml index c22ea74a60..4b6c3ed7b9 100644 --- a/benchmark/vm1_gc_short_with_complex_long.yml +++ b/benchmark/vm_gc_short_with_complex_long.yml @@ -15,7 +15,7 @@ prelude: | GC.start GC.start benchmark: - vm1_gc_short_with_complex_long: | + vm_gc_short_with_complex_long: | a = '' # short-lived String b = '' c = '' diff --git a/benchmark/vm1_gc_short_with_long.yml b/benchmark/vm_gc_short_with_long.yml index c731aae548..03ba0f95a9 100644 --- a/benchmark/vm1_gc_short_with_long.yml +++ b/benchmark/vm_gc_short_with_long.yml @@ -3,7 +3,7 @@ prelude: | GC.start GC.start benchmark: - vm1_gc_short_with_long: | + vm_gc_short_with_long: | a = '' # short-lived String b = '' c = '' diff --git a/benchmark/vm1_gc_short_with_symbol.yml b/benchmark/vm_gc_short_with_symbol.yml index 7fc1abedd8..129b8bf4ed 100644 --- a/benchmark/vm1_gc_short_with_symbol.yml +++ b/benchmark/vm_gc_short_with_symbol.yml @@ -3,7 +3,7 @@ prelude: | GC.start GC.start benchmark: - vm1_gc_short_with_symbol: | + vm_gc_short_with_symbol: | a = '' # short-lived String b = '' c = '' diff --git a/benchmark/vm1_gc_wb_ary.yml b/benchmark/vm_gc_wb_ary.yml index 50fb4b6f84..e3293e72d0 100644 --- a/benchmark/vm1_gc_wb_ary.yml +++ b/benchmark/vm_gc_wb_ary.yml @@ -7,6 +7,6 @@ prelude: | short_lived = '' benchmark: - vm1_gc_wb_ary: | + vm_gc_wb_ary: | short_lived_ary[0] = short_lived # write barrier loop_count: 30000000 diff --git a/benchmark/vm1_gc_wb_ary_promoted.yml b/benchmark/vm_gc_wb_ary_promoted.yml index cf9b5de005..003995945b 100644 --- a/benchmark/vm1_gc_wb_ary_promoted.yml +++ b/benchmark/vm_gc_wb_ary_promoted.yml @@ -10,6 +10,6 @@ prelude: | short_lived = '' benchmark: - vm1_gc_wb_ary_promoted: | + vm_gc_wb_ary_promoted: | long_lived[0] = short_lived # write barrier loop_count: 30000000 diff --git a/benchmark/vm1_gc_wb_obj.yml b/benchmark/vm_gc_wb_obj.yml index 9dc08e7e1a..a2a2ce2d18 100644 --- a/benchmark/vm1_gc_wb_obj.yml +++ b/benchmark/vm_gc_wb_obj.yml @@ -10,6 +10,6 @@ prelude: | short_lived = '' benchmark: - vm1_gc_wb_obj: | + vm_gc_wb_obj: | short_lived_obj.foo = short_lived # write barrier loop_count: 30000000 diff --git a/benchmark/vm1_gc_wb_obj_promoted.yml b/benchmark/vm_gc_wb_obj_promoted.yml index 26859d2a52..00a454ba72 100644 --- a/benchmark/vm1_gc_wb_obj_promoted.yml +++ b/benchmark/vm_gc_wb_obj_promoted.yml @@ -12,6 +12,6 @@ prelude: | short_lived = '' benchmark: - vm1_gc_wb_obj_promoted: | + vm_gc_wb_obj_promoted: | long_lived.foo = short_lived # write barrier loop_count: 30000000 diff --git a/benchmark/vm_iclass_super.yml b/benchmark/vm_iclass_super.yml new file mode 100644 index 0000000000..21bb7db247 --- /dev/null +++ b/benchmark/vm_iclass_super.yml @@ -0,0 +1,20 @@ +prelude: | + class C + def m + 1 + end + + ("A".."M").each do |module_name| + eval <<-EOM + module #{module_name} + def m; super; end + end + prepend #{module_name} + EOM + end + end + + obj = C.new +benchmark: + vm_iclass_super: obj.m +loop_count: 6000000 diff --git a/benchmark/vm1_ivar.yml b/benchmark/vm_ivar.yml index 7aa6fac729..119531d5ef 100644 --- a/benchmark/vm1_ivar.yml +++ b/benchmark/vm_ivar.yml @@ -1,6 +1,6 @@ prelude: "@a = 1\n" benchmark: - vm1_ivar: | + vm_ivar: | j = @a k = @a loop_count: 30000000 diff --git a/benchmark/vm_ivar_embedded_obj_init.yml b/benchmark/vm_ivar_embedded_obj_init.yml new file mode 100644 index 0000000000..74fe20a630 --- /dev/null +++ b/benchmark/vm_ivar_embedded_obj_init.yml @@ -0,0 +1,14 @@ +prelude: | + class C + def set_ivars + @a = nil + @b = nil + @c = nil + end + end + + c = C.new +benchmark: + vm_ivar_embedded_obj_init: | + c.set_ivars +loop_count: 30000000 diff --git a/benchmark/vm_ivar_extended_obj_init.yml b/benchmark/vm_ivar_extended_obj_init.yml new file mode 100644 index 0000000000..f054bab282 --- /dev/null +++ b/benchmark/vm_ivar_extended_obj_init.yml @@ -0,0 +1,16 @@ +prelude: | + class C + def set_ivars + @a = nil + @b = nil + @c = nil + @d = nil + @e = nil + end + end + + c = C.new +benchmark: + vm_ivar_extended_obj_init: | + c.set_ivars +loop_count: 30000000 diff --git a/benchmark/vm_ivar_generic_get.yml b/benchmark/vm_ivar_generic_get.yml new file mode 100644 index 0000000000..dae2d37671 --- /dev/null +++ b/benchmark/vm_ivar_generic_get.yml @@ -0,0 +1,17 @@ +prelude: | + class C < Array + attr_reader :a, :b, :c + def initialize + @a = nil + @b = nil + @c = nil + end + end + + c = C.new +benchmark: + vm_ivar_generic_get: | + c.a + c.b + c.c +loop_count: 30000000 diff --git a/benchmark/vm_ivar_generic_set.yml b/benchmark/vm_ivar_generic_set.yml new file mode 100644 index 0000000000..102a6577fb --- /dev/null +++ b/benchmark/vm_ivar_generic_set.yml @@ -0,0 +1,14 @@ +prelude: | + class C < Array + def set_ivars + @a = nil + @b = nil + @c = nil + end + end + + c = C.new +benchmark: + vm_ivar_generic_set: | + c.set_ivars +loop_count: 30000000 diff --git a/benchmark/vm_ivar_get.yml b/benchmark/vm_ivar_get.yml new file mode 100644 index 0000000000..1e0dad665f --- /dev/null +++ b/benchmark/vm_ivar_get.yml @@ -0,0 +1,100 @@ +prelude: | + class Example + def initialize + @levar = 1 + @v0 = 1 + @v1 = 2 + @v3 = 3 + end + + def get_value_loop + sum = 0 + + i = 0 + while i < 100_000 + # 10 times to de-emphasize loop overhead + sum += @levar + sum += @levar + sum += @levar + sum += @levar + sum += @levar + sum += @levar + sum += @levar + sum += @levar + sum += @levar + sum += @levar + i += 1 + end + + return sum + end + + @levar = 1 + @v0 = 1 + @v1 = 2 + @v3 = 3 + + def self.get_value_loop + sum = 0 + + i = 0 + while i < 100_000 + # 10 times to de-emphasize loop overhead + sum += @levar + sum += @levar + sum += @levar + sum += @levar + sum += @levar + sum += @levar + sum += @levar + sum += @levar + sum += @levar + sum += @levar + i += 1 + end + + return sum + end + end + + class GenExample < Time + def initialize + @levar = 1 + @v0 = 1 + @v1 = 2 + @v3 = 3 + end + + def get_value_loop + sum = 0 + + i = 0 + while i < 100_000 + # 10 times to de-emphasize loop overhead + sum += @levar + sum += @levar + sum += @levar + sum += @levar + sum += @levar + sum += @levar + sum += @levar + sum += @levar + sum += @levar + sum += @levar + i += 1 + end + + return sum + end + end + + obj = Example.new + gen = GenExample.new +benchmark: + vm_ivar_get_on_obj: | + obj.get_value_loop + vm_ivar_get_on_class: | + Example.get_value_loop + vm_ivar_get_on_generic: | + gen.get_value_loop +loop_count: 100 diff --git a/benchmark/vm_ivar_get_unintialized.yml b/benchmark/vm_ivar_get_unintialized.yml new file mode 100644 index 0000000000..a1ccfb06ce --- /dev/null +++ b/benchmark/vm_ivar_get_unintialized.yml @@ -0,0 +1,12 @@ +prelude: | + class Example + def read + @uninitialized + end + end + + obj = Example.new +benchmark: + vm_ivar_get_uninitialized: | + obj.read +loop_count: 30000000 diff --git a/benchmark/vm_ivar_ic_miss.yml b/benchmark/vm_ivar_ic_miss.yml new file mode 100644 index 0000000000..944fb1a9e6 --- /dev/null +++ b/benchmark/vm_ivar_ic_miss.yml @@ -0,0 +1,20 @@ +prelude: | + class Foo + def initialize diverge + if diverge + @a = 1 + end + + @a0 = @a1 = @a2 = @a3 = @a4 = @a5 = @a6 = @a7 = @a8 = @a9 = @a10 = @a11 = @a12 = @a13 = @a14 = @a15 = @a16 = @a17 = @a18 = @a19 = @a20 = @a21 = @a22 = @a23 = @a24 = @a25 = @a26 = @a27 = @a28 = @a29 = @a30 = @a31 = @a32 = @a33 = @a34 = @a35 = @a36 = @a37 = @a38 = @a39 = @a40 = @a41 = @a42 = @a43 = @a44 = @a45 = @a46 = @a47 = @a48 = @a49 = @a50 = @a51 = @a52 = @a53 = @a54 = @a55 = @a56 = @a57 = @a58 = @a59 = @a60 = @a61 = @a62 = @a63 = @a64 = @a65 = @a66 = @a67 = @a68 = @a69 = @a70 = @a71 = @a72 = @a73 = @a74 = @b = 1 + end + + def b; @b; end + end + + a = Foo.new false + b = Foo.new true +benchmark: + vm_ivar_ic_miss: | + a.b + b.b +loop_count: 30000000 diff --git a/benchmark/vm_ivar_lazy_set.yml b/benchmark/vm_ivar_lazy_set.yml new file mode 100644 index 0000000000..7372ffcfbc --- /dev/null +++ b/benchmark/vm_ivar_lazy_set.yml @@ -0,0 +1,12 @@ +prelude: | + class Example + def lazy_set + @uninitialized ||= 123 + end + end + + objs = 10000000.times.map { Example.new } +benchmark: + vm_ivar_lazy_set: | + objs.each(&:lazy_set) +loop_count: 1 diff --git a/benchmark/vm_ivar_memoize.yml b/benchmark/vm_ivar_memoize.yml new file mode 100644 index 0000000000..90f6b07f05 --- /dev/null +++ b/benchmark/vm_ivar_memoize.yml @@ -0,0 +1,85 @@ +prelude: | + IVARS = 60 + class Record + def initialize(offset = false) + @offset = 1 if offset + @first = 0 + IVARS.times do |i| + instance_variable_set("@ivar_#{i}", i) + end + end + + def first + @first + end + + def lazy_set + @lazy_set ||= 123 + end + + def undef + @undef + end + end + + Record.new # Need one alloc to right size + + BASE = Record.new + LAZY = Record.new + LAZY.lazy_set + + class Miss < Record + @first = 0 + IVARS.times do |i| + instance_variable_set("@i_#{i}", i) + end + end + + Miss.new # Need one alloc to right size + MISS = Miss.new + + DIVERGENT = Record.new(true) + +benchmark: + vm_ivar_stable_shape: | + BASE.first + BASE.first + BASE.first + BASE.first + BASE.first + BASE.first + vm_ivar_memoize_unstable_shape: | + BASE.first + LAZY.first + BASE.first + LAZY.first + BASE.first + LAZY.first + vm_ivar_memoize_unstable_shape_miss: | + BASE.first + MISS.first + BASE.first + MISS.first + BASE.first + MISS.first + vm_ivar_unstable_undef: | + BASE.undef + LAZY.undef + BASE.undef + LAZY.undef + BASE.undef + LAZY.undef + vm_ivar_divergent_shape: | + BASE.first + DIVERGENT.first + BASE.first + DIVERGENT.first + BASE.first + DIVERGENT.first + vm_ivar_divergent_shape_imbalanced: | + BASE.first + DIVERGENT.first + DIVERGENT.first + DIVERGENT.first + DIVERGENT.first + DIVERGENT.first diff --git a/benchmark/vm_ivar_of_class.yml b/benchmark/vm_ivar_of_class.yml new file mode 100644 index 0000000000..172e28b2fd --- /dev/null +++ b/benchmark/vm_ivar_of_class.yml @@ -0,0 +1,12 @@ +prelude: | + class C + @a = 1 + def self.a + _a = @a; _a = @a; _a = @a; _a = @a; _a = @a; + _a = @a; _a = @a; _a = @a; _a = @a; _a = @a; + end + end +benchmark: + vm_ivar_of_class: | + a = C.a +loop_count: 30000000 diff --git a/benchmark/vm_ivar_of_class_set.yml b/benchmark/vm_ivar_of_class_set.yml new file mode 100644 index 0000000000..2ea5199423 --- /dev/null +++ b/benchmark/vm_ivar_of_class_set.yml @@ -0,0 +1,11 @@ +prelude: | + class C + @a = 1 + def self.a o + @a = o; @a = o; @a = o; @a = o; @a = o; @a = o; + end + end +benchmark: + vm_ivar_of_class_set: | + a = C.a(nil) +loop_count: 30000000 diff --git a/benchmark/vm1_ivar_set.yml b/benchmark/vm_ivar_set.yml index 6f19412d16..8bbb60043b 100644 --- a/benchmark/vm1_ivar_set.yml +++ b/benchmark/vm_ivar_set.yml @@ -1,5 +1,5 @@ benchmark: - vm1_ivar_set: | + vm_ivar_set: | @a = 1 @b = 2 loop_count: 30000000 diff --git a/benchmark/vm_ivar_set_on_instance.yml b/benchmark/vm_ivar_set_on_instance.yml new file mode 100644 index 0000000000..6ce53a86ec --- /dev/null +++ b/benchmark/vm_ivar_set_on_instance.yml @@ -0,0 +1,94 @@ +prelude: | + class TheClass + def initialize + @levar = 1 + @v0 = 1 + @v1 = 2 + @v3 = 3 + end + + def set_value_loop + # 100k + i = 0 + while i < 100_000 + # 10 times to de-emphasize loop overhead + @levar = i + @levar = i + @levar = i + @levar = i + @levar = i + @levar = i + @levar = i + @levar = i + @levar = i + @levar = i + i += 1 + end + end + end + + class Generic < Time + def initialize + @levar = 1 + @v0 = 1 + @v1 = 2 + @v3 = 3 + end + + def set_value_loop + # 100k + i = 0 + while i < 100_000 + # 10 times to de-emphasize loop overhead + @levar = i + @levar = i + @levar = i + @levar = i + @levar = i + @levar = i + @levar = i + @levar = i + @levar = i + @levar = i + i += 1 + end + end + end + + obj = TheClass.new + gen_obj = Generic.new + + class SomeClass + @levar = 1 + @v0 = 1 + @v1 = 2 + @v3 = 3 + + def self.set_value_loop + # 100k + i = 0 + while i < 100_000 + # 10 times to de-emphasize loop overhead + @levar = i + @levar = i + @levar = i + @levar = i + @levar = i + @levar = i + @levar = i + @levar = i + @levar = i + @levar = i + i += 1 + end + end + end + +benchmark: + vm_ivar_set_on_instance: | + obj.set_value_loop + vm_ivar_set_on_generic: | + gen_obj.set_value_loop + vm_ivar_set_on_class: | + SomeClass.set_value_loop +loop_count: 100 diff --git a/benchmark/vm_ivar_set_subclass.yml b/benchmark/vm_ivar_set_subclass.yml new file mode 100644 index 0000000000..bc8bf5bf6b --- /dev/null +++ b/benchmark/vm_ivar_set_subclass.yml @@ -0,0 +1,20 @@ +prelude: | + class A + def set_ivars + @a = nil + @b = nil + @c = nil + @d = nil + @e = nil + end + end + class B < A; end + class C < A; end + + b = B.new + c = C.new +benchmark: + vm_ivar_init_subclass: | + b.set_ivars + c.set_ivars +loop_count: 3000000 diff --git a/benchmark/vm1_length.yml b/benchmark/vm_length.yml index a18e2ca2e6..5fd94e7d86 100644 --- a/benchmark/vm1_length.yml +++ b/benchmark/vm_length.yml @@ -2,7 +2,7 @@ prelude: | a = 'abc' b = [1, 2, 3] benchmark: - vm1_length: | + vm_length: | a.length b.length loop_count: 30000000 diff --git a/benchmark/vm_lvar_cond_set.yml b/benchmark/vm_lvar_cond_set.yml new file mode 100644 index 0000000000..1845f9d12e --- /dev/null +++ b/benchmark/vm_lvar_cond_set.yml @@ -0,0 +1,8 @@ +benchmark: + vm_lvar_cond_set: | + a ||= 1 + b ||= 1 + c ||= 1 + d ||= 1 + nil +loop_count: 30000000 diff --git a/benchmark/vm1_lvar_init.yml b/benchmark/vm_lvar_init.yml index 10e2becef9..70a9b1c0ca 100644 --- a/benchmark/vm1_lvar_init.yml +++ b/benchmark/vm_lvar_init.yml @@ -1,6 +1,6 @@ # while loop cost is not removed because `i` is used in the script benchmark: - vm1_lvar_init: | + vm_lvar_init: | def m v unless v # unreachable code diff --git a/benchmark/vm1_lvar_set.yml b/benchmark/vm_lvar_set.yml index df8f6b6ea4..f29f763d81 100644 --- a/benchmark/vm1_lvar_set.yml +++ b/benchmark/vm_lvar_set.yml @@ -1,4 +1,4 @@ benchmark: - vm1_lvar_set: | + vm_lvar_set: | a = b = c = d = e = f = g = h = j = k = l = m = n = o = p = q = r = 1 loop_count: 30000000 diff --git a/benchmark/vm2_method.yml b/benchmark/vm_method.yml index cc7b9b28ff..d45e4ec572 100644 --- a/benchmark/vm2_method.yml +++ b/benchmark/vm_method.yml @@ -3,6 +3,6 @@ prelude: | nil end benchmark: - vm2_method: | + vm_method: | m; m; m; m; m; m; m; m; loop_count: 6000000 diff --git a/benchmark/vm2_method_missing.yml b/benchmark/vm_method_missing.yml index cbfb794b25..3da456c0bb 100644 --- a/benchmark/vm2_method_missing.yml +++ b/benchmark/vm_method_missing.yml @@ -6,6 +6,6 @@ prelude: | obj = C.new benchmark: - vm2_method_missing: | + vm_method_missing: | obj.m; obj.m; obj.m; obj.m; obj.m; obj.m; obj.m; obj.m; loop_count: 6000000 diff --git a/benchmark/vm_method_splat_calls.yml b/benchmark/vm_method_splat_calls.yml new file mode 100644 index 0000000000..f2f366e99c --- /dev/null +++ b/benchmark/vm_method_splat_calls.yml @@ -0,0 +1,13 @@ +prelude: | + def f(x=0, y: 0) end + a = [1] + ea = [] + kw = {y: 1} + b = lambda{} +benchmark: + arg_splat: "f(1, *ea)" + arg_splat_block: "f(1, *ea, &b)" + splat_kw_splat: "f(*a, **kw)" + splat_kw_splat_block: "f(*a, **kw, &b)" + splat_kw: "f(*a, y: 1)" + splat_kw_block: "f(*a, y: 1, &b)" diff --git a/benchmark/vm_method_splat_calls2.yml b/benchmark/vm_method_splat_calls2.yml new file mode 100644 index 0000000000..d33dcd7e8b --- /dev/null +++ b/benchmark/vm_method_splat_calls2.yml @@ -0,0 +1,27 @@ +prelude: | + def named_arg_splat(*a) end + def named_arg_kw_splat(*a, **kw) end + def anon_arg_splat(*) end + def anon_kw_splat(**) end + def anon_arg_kw_splat(*, **) end + def anon_fw_to_named(*, **) named_arg_kw_splat(*, **) end + def fw_to_named(...) named_arg_kw_splat(...) end + def fw_to_anon_to_named(...) anon_fw_to_named(...) end + def fw_no_kw(...) named_arg_splat(...) end + a = [1] + kw = {y: 1} +benchmark: + named_multi_arg_splat: "named_arg_splat(*a, *a)" + named_post_splat: "named_arg_splat(*a, a)" + anon_arg_splat: "anon_arg_splat(*a)" + anon_arg_kw_splat: "anon_arg_kw_splat(*a, **kw)" + anon_multi_arg_splat: "anon_arg_splat(*a, *a)" + anon_post_splat: "anon_arg_splat(*a, a)" + anon_kw_splat: "anon_kw_splat(**kw)" + anon_fw_to_named_splat: "anon_fw_to_named(*a, **kw)" + anon_fw_to_named_no_splat: "anon_fw_to_named(1, y: 1)" + fw_to_named_splat: "fw_to_named(*a, **kw)" + fw_to_named_no_splat: "fw_to_named(1, y: 1)" + fw_to_anon_to_named_splat: "fw_to_anon_to_named(*a, **kw)" + fw_to_anon_to_named_no_splat: "fw_to_anon_to_named(1, y: 1)" + fw_no_kw: "fw_no_kw(1, 2)" diff --git a/benchmark/vm2_method_with_block.yml b/benchmark/vm_method_with_block.yml index 6e522adccc..281a481394 100644 --- a/benchmark/vm2_method_with_block.yml +++ b/benchmark/vm_method_with_block.yml @@ -3,6 +3,6 @@ prelude: | nil end benchmark: - vm2_method_with_block: | + vm_method_with_block: | m{}; m{}; m{}; m{}; m{}; m{}; m{}; m{}; loop_count: 6000000 diff --git a/benchmark/vm2_module_ann_const_set.yml b/benchmark/vm_module_ann_const_set.yml index b0becd9d3d..243229ba4a 100644 --- a/benchmark/vm2_module_ann_const_set.yml +++ b/benchmark/vm_module_ann_const_set.yml @@ -1,4 +1,4 @@ benchmark: - vm2_module_ann_const_set: | + vm_module_ann_const_set: | Module.new.const_set(:X, Module.new) loop_count: 6000000 diff --git a/benchmark/vm2_module_const_set.yml b/benchmark/vm_module_const_set.yml index 05a640069c..e5a24181a9 100644 --- a/benchmark/vm2_module_const_set.yml +++ b/benchmark/vm_module_const_set.yml @@ -3,6 +3,6 @@ prelude: | end $VERBOSE = nil benchmark: - vm2_module_const_set: | + vm_module_const_set: | M.const_set(:X, Module.new) loop_count: 6000000 diff --git a/benchmark/vm2_mutex.yml b/benchmark/vm_mutex.yml index c40a90444a..abcf1e28ce 100644 --- a/benchmark/vm2_mutex.yml +++ b/benchmark/vm_mutex.yml @@ -3,6 +3,6 @@ prelude: | m = Thread::Mutex.new benchmark: - vm2_mutex: | + vm_mutex: | m.synchronize{} loop_count: 6000000 diff --git a/benchmark/vm1_neq.yml b/benchmark/vm_neq.yml index 65a8128dda..fb04d15ae8 100644 --- a/benchmark/vm1_neq.yml +++ b/benchmark/vm_neq.yml @@ -2,6 +2,6 @@ prelude: | obj1 = Object.new obj2 = Object.new benchmark: - vm1_neq: | + vm_neq: | obj1 != obj2 loop_count: 30000000 diff --git a/benchmark/vm2_newlambda.yml b/benchmark/vm_newlambda.yml index 93133f9f30..0b9787d91a 100644 --- a/benchmark/vm2_newlambda.yml +++ b/benchmark/vm_newlambda.yml @@ -1,4 +1,4 @@ benchmark: - vm2_newlambda: | + vm_newlambda: | lambda {} loop_count: 6000000 diff --git a/benchmark/vm1_not.yml b/benchmark/vm_not.yml index 0fb7b282a9..c68dde3c50 100644 --- a/benchmark/vm1_not.yml +++ b/benchmark/vm_not.yml @@ -1,6 +1,6 @@ prelude: | obj = Object.new benchmark: - vm1_not: | + vm_not: | !obj loop_count: 30000000 diff --git a/benchmark/vm2_poly_method.yml b/benchmark/vm_poly_method.yml index 0104bdfb66..dd2f4e71de 100644 --- a/benchmark/vm2_poly_method.yml +++ b/benchmark/vm_poly_method.yml @@ -1,6 +1,6 @@ # loop_count is not utilized since `i` is involved in the script benchmark: - vm2_poly_method: | + vm_poly_method: | class C1 def m 1 diff --git a/benchmark/vm2_poly_method_ov.yml b/benchmark/vm_poly_method_ov.yml index 3748073ba2..bca1b62729 100644 --- a/benchmark/vm2_poly_method_ov.yml +++ b/benchmark/vm_poly_method_ov.yml @@ -1,6 +1,6 @@ # loop_count is not utilized since `i` is involved in the script benchmark: - vm2_poly_method_ov: | + vm_poly_method_ov: | class C1 def m 1 diff --git a/benchmark/vm_poly_same_method.yml b/benchmark/vm_poly_same_method.yml new file mode 100644 index 0000000000..6c5404ac84 --- /dev/null +++ b/benchmark/vm_poly_same_method.yml @@ -0,0 +1,25 @@ +prelude: | + module AR; end + class AR::Base + def create_or_update + nil + end + def save + create_or_update + end + end + class Foo < AR::Base; end + class Bar < AR::Base; end + o1 = Foo.new + o2 = Bar.new +benchmark: + vm_poly_same_method: | + o1.save; o2.save; + o1.save; o2.save; + o1.save; o2.save; + o1.save; o2.save; + o1.save; o2.save; + o1.save; o2.save; + o1.save; o2.save; + o1.save; o2.save; +loop_count: 6000000 diff --git a/benchmark/vm2_poly_singleton.yml b/benchmark/vm_poly_singleton.yml index e58d7bfb37..c7923160fb 100644 --- a/benchmark/vm2_poly_singleton.yml +++ b/benchmark/vm_poly_singleton.yml @@ -1,6 +1,6 @@ # loop_count is not utilized since `i` is involved in the script benchmark: - vm2_poly_singleton: | + vm_poly_singleton: | class C1 def m; 1; end end diff --git a/benchmark/vm2_proc.yml b/benchmark/vm_proc.yml index 5c36e936d9..2f8de6c272 100644 --- a/benchmark/vm2_proc.yml +++ b/benchmark/vm_proc.yml @@ -7,6 +7,6 @@ prelude: | a = 1 } benchmark: - vm2_proc: | + vm_proc: | pr.call loop_count: 6000000 diff --git a/benchmark/vm2_raise1.yml b/benchmark/vm_raise1.yml index f6eb308968..247d9f70ee 100644 --- a/benchmark/vm2_raise1.yml +++ b/benchmark/vm_raise1.yml @@ -7,7 +7,7 @@ prelude: | end end benchmark: - vm2_raise1: | + vm_raise1: | begin rec 1 rescue diff --git a/benchmark/vm2_raise2.yml b/benchmark/vm_raise2.yml index 7d51b1b314..f0fa047b3c 100644 --- a/benchmark/vm2_raise2.yml +++ b/benchmark/vm_raise2.yml @@ -7,7 +7,7 @@ prelude: | end end benchmark: - vm2_raise2: | + vm_raise2: | begin rec 10 rescue diff --git a/benchmark/vm2_regexp.yml b/benchmark/vm_regexp.yml index 0f3968a99b..2aa3d94dbd 100644 --- a/benchmark/vm2_regexp.yml +++ b/benchmark/vm_regexp.yml @@ -1,6 +1,8 @@ prelude: | str = 'xxxhogexxx' benchmark: - vm2_regexp: | + vm_regexp: | /hoge/ =~ str + vm_regexp_invert: | + str =~ /hoge/ loop_count: 6000000 diff --git a/benchmark/vm1_rescue.yml b/benchmark/vm_rescue.yml index a175b823af..b4a0af521f 100644 --- a/benchmark/vm1_rescue.yml +++ b/benchmark/vm_rescue.yml @@ -1,5 +1,5 @@ benchmark: - vm1_rescue: | + vm_rescue: | begin rescue end diff --git a/benchmark/vm2_send.yml b/benchmark/vm_send.yml index 44a12a27d9..f31bc7ac89 100644 --- a/benchmark/vm2_send.yml +++ b/benchmark/vm_send.yml @@ -5,7 +5,10 @@ prelude: | end o = C.new + m = :m benchmark: - vm2_send: | + vm_send: | o.__send__ :m + vm_send_var: | + o.__send__ m loop_count: 6000000 diff --git a/benchmark/vm_send_cfunc.yml b/benchmark/vm_send_cfunc.yml new file mode 100644 index 0000000000..6f12b65176 --- /dev/null +++ b/benchmark/vm_send_cfunc.yml @@ -0,0 +1,14 @@ +prelude: | + ary = [] + kw = {a: 1} + empty_kw = {} + kw_ary = [Hash.ruby2_keywords_hash(a: 1)] + empty_kw_ary = [Hash.ruby2_keywords_hash({})] +benchmark: + vm_send_cfunc: itself + vm_send_cfunc_splat: itself(*ary) + vm_send_cfunc_splat_kw_hash: equal?(*kw_ary) + vm_send_cfunc_splat_empty_kw_hash: itself(*empty_kw_ary) + vm_send_cfunc_splat_kw: equal?(*ary, **kw) + vm_send_cfunc_splat_empty_kw: itself(*ary, **empty_kw) +loop_count: 20000000 diff --git a/benchmark/vm1_simplereturn.yml b/benchmark/vm_simplereturn.yml index 3564aac7e2..c9829cff0b 100644 --- a/benchmark/vm1_simplereturn.yml +++ b/benchmark/vm_simplereturn.yml @@ -3,5 +3,5 @@ prelude: | return 1 end benchmark: - vm1_simplereturn: m + vm_simplereturn: m loop_count: 30000000 diff --git a/benchmark/vm2_string_literal.yml b/benchmark/vm_string_literal.yml index 54b0aec1fe..64439c7980 100644 --- a/benchmark/vm2_string_literal.yml +++ b/benchmark/vm_string_literal.yml @@ -1,4 +1,4 @@ benchmark: - vm2_string_literal: | + vm_string_literal: | x = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" loop_count: 6000000 diff --git a/benchmark/vm2_struct_big_aref_hi.yml b/benchmark/vm_struct_big_aref_hi.yml index eed1846d28..4cf78970cb 100644 --- a/benchmark/vm2_struct_big_aref_hi.yml +++ b/benchmark/vm_struct_big_aref_hi.yml @@ -2,6 +2,6 @@ prelude: | s = Struct.new(*('a'..'z').map { |x| x.to_sym }) x = s.new benchmark: - vm2_struct_big_aref_hi: | + vm_struct_big_aref_hi: | x.z # x[25] loop_count: 6000000 diff --git a/benchmark/vm2_struct_big_aref_lo.yml b/benchmark/vm_struct_big_aref_lo.yml index 0915435b76..c91af27fa5 100644 --- a/benchmark/vm2_struct_big_aref_lo.yml +++ b/benchmark/vm_struct_big_aref_lo.yml @@ -2,6 +2,6 @@ prelude: | s = Struct.new(*('a'..'z').map { |x| x.to_sym }) x = s.new benchmark: - vm2_struct_big_aref_lo: | + vm_struct_big_aref_lo: | x.k # x[10] loop_count: 6000000 diff --git a/benchmark/vm2_struct_big_aset.yml b/benchmark/vm_struct_big_aset.yml index 6af50103d3..69550d14ea 100644 --- a/benchmark/vm2_struct_big_aset.yml +++ b/benchmark/vm_struct_big_aset.yml @@ -1,6 +1,6 @@ # loop_count is not utilized since `i` is involved in the script benchmark: - vm2_struct_big_aset: | + vm_struct_big_aset: | s = Struct.new(*('a'..'z').map { |x| x.to_sym }) x = s.new i = 0 diff --git a/benchmark/vm2_struct_big_href_hi.yml b/benchmark/vm_struct_big_href_hi.yml index 60aa7fddf3..09b764dd13 100644 --- a/benchmark/vm2_struct_big_href_hi.yml +++ b/benchmark/vm_struct_big_href_hi.yml @@ -2,6 +2,6 @@ prelude: | s = Struct.new(*('a'..'z').map { |x| x.to_sym }) x = s.new benchmark: - vm2_struct_big_href_hi: | + vm_struct_big_href_hi: | x[:z] loop_count: 6000000 diff --git a/benchmark/vm2_struct_big_href_lo.yml b/benchmark/vm_struct_big_href_lo.yml index c55c0bd16c..d2f00b220f 100644 --- a/benchmark/vm2_struct_big_href_lo.yml +++ b/benchmark/vm_struct_big_href_lo.yml @@ -2,6 +2,6 @@ prelude: | s = Struct.new(*('a'..'z').map { |x| x.to_sym }) x = s.new benchmark: - vm2_struct_big_href_lo: | + vm_struct_big_href_lo: | x[:k] loop_count: 6000000 diff --git a/benchmark/vm2_struct_big_hset.yml b/benchmark/vm_struct_big_hset.yml index d199c5bd47..fc45cbee9c 100644 --- a/benchmark/vm2_struct_big_hset.yml +++ b/benchmark/vm_struct_big_hset.yml @@ -1,6 +1,6 @@ # loop_count is not utilized since `i` is involved in the script benchmark: - vm2_struct_big_hset: | + vm_struct_big_hset: | s = Struct.new(*('a'..'z').map { |x| x.to_sym }) x = s.new i = 0 diff --git a/benchmark/vm2_struct_small_aref.yml b/benchmark/vm_struct_small_aref.yml index 83381bed3a..5a83251d1e 100644 --- a/benchmark/vm2_struct_small_aref.yml +++ b/benchmark/vm_struct_small_aref.yml @@ -2,6 +2,6 @@ prelude: | s = Struct.new(:a, :b, :c) x = s.new benchmark: - vm2_struct_small_aref: | + vm_struct_small_aref: | x.a loop_count: 6000000 diff --git a/benchmark/vm2_struct_small_aset.yml b/benchmark/vm_struct_small_aset.yml index 3e84a61dd0..74f435f126 100644 --- a/benchmark/vm2_struct_small_aset.yml +++ b/benchmark/vm_struct_small_aset.yml @@ -1,6 +1,6 @@ # loop_count is not utilized since `i` is involved in the script benchmark: - vm2_struct_small_aset: | + vm_struct_small_aset: | s = Struct.new(:a, :b, :c) x = s.new i = 0 diff --git a/benchmark/vm2_struct_small_href.yml b/benchmark/vm_struct_small_href.yml index b744f070d1..6b7d7f39e7 100644 --- a/benchmark/vm2_struct_small_href.yml +++ b/benchmark/vm_struct_small_href.yml @@ -2,6 +2,6 @@ prelude: | s = Struct.new(:a, :b, :c) x = s.new benchmark: - vm2_struct_small_href: | + vm_struct_small_href: | x[:a] loop_count: 6000000 diff --git a/benchmark/vm2_struct_small_hset.yml b/benchmark/vm_struct_small_hset.yml index d43845d6e0..5d43b150de 100644 --- a/benchmark/vm2_struct_small_hset.yml +++ b/benchmark/vm_struct_small_hset.yml @@ -2,6 +2,6 @@ prelude: | s = Struct.new(:a, :b, :c) x = s.new benchmark: - vm2_struct_small_hset: | + vm_struct_small_hset: | x[:a] = 1 loop_count: 6000000 diff --git a/benchmark/vm2_super.yml b/benchmark/vm_super.yml index 674743762a..0d1e965c6e 100644 --- a/benchmark/vm2_super.yml +++ b/benchmark/vm_super.yml @@ -13,5 +13,5 @@ prelude: | obj = CC.new benchmark: - vm2_super: obj.m + vm_super: obj.m loop_count: 6000000 diff --git a/benchmark/vm_super_splat_calls.yml b/benchmark/vm_super_splat_calls.yml new file mode 100644 index 0000000000..795e44e4da --- /dev/null +++ b/benchmark/vm_super_splat_calls.yml @@ -0,0 +1,25 @@ +prelude: | + @a = [1].freeze + @ea = [].freeze + @kw = {y: 1}.freeze + @b = lambda{} + extend(Module.new{def arg_splat(x=0, y: 0) end}) + extend(Module.new{def arg_splat_block(x=0, y: 0) end}) + extend(Module.new{def splat_kw_splat(x=0, y: 0) end}) + extend(Module.new{def splat_kw_splat_block(x=0, y: 0) end}) + extend(Module.new{def splat_kw(x=0, y: 0) end}) + extend(Module.new{def splat_kw_block(x=0, y: 0) end}) + + extend(Module.new{def arg_splat; super(1, *@ea) end}) + extend(Module.new{def arg_splat_block; super(1, *@ea, &@b) end}) + extend(Module.new{def splat_kw_splat; super(*@a, **@kw) end}) + extend(Module.new{def splat_kw_splat_block; super(*@a, **@kw, &@b) end}) + extend(Module.new{def splat_kw; super(*@a, y: 1) end}) + extend(Module.new{def splat_kw_block; super(*@a, y: 1, &@b) end}) +benchmark: + arg_splat: "arg_splat" + arg_splat_block: "arg_splat_block" + splat_kw_splat: "splat_kw_splat" + splat_kw_splat_block: "splat_kw_splat_block" + splat_kw: "splat_kw" + splat_kw_block: "splat_kw_block" diff --git a/benchmark/vm1_swap.yml b/benchmark/vm_swap.yml index fed87ccd62..e824a65e0a 100644 --- a/benchmark/vm1_swap.yml +++ b/benchmark/vm_swap.yml @@ -2,6 +2,6 @@ prelude: | a = 1 b = 2 benchmark: - vm1_swap: | + vm_swap: | a, b = b, a loop_count: 30000000 diff --git a/benchmark/vm_thread_condvar1.rb b/benchmark/vm_thread_condvar1.rb index cf5706b23e..feed27c3ad 100644 --- a/benchmark/vm_thread_condvar1.rb +++ b/benchmark/vm_thread_condvar1.rb @@ -1,9 +1,9 @@ # two threads, two mutex, two condvar ping-pong require 'thread' -m1 = Mutex.new -m2 = Mutex.new -cv1 = ConditionVariable.new -cv2 = ConditionVariable.new +m1 = Thread::Mutex.new +m2 = Thread::Mutex.new +cv1 = Thread::ConditionVariable.new +cv2 = Thread::ConditionVariable.new max = 100000 i = 0 wait = nil diff --git a/benchmark/vm_thread_condvar2.rb b/benchmark/vm_thread_condvar2.rb index 7c8dc19481..6590c4134b 100644 --- a/benchmark/vm_thread_condvar2.rb +++ b/benchmark/vm_thread_condvar2.rb @@ -1,16 +1,16 @@ # many threads, one mutex, many condvars require 'thread' -m = Mutex.new -cv1 = ConditionVariable.new -cv2 = ConditionVariable.new +m = Thread::Mutex.new +cv1 = Thread::ConditionVariable.new +cv2 = Thread::ConditionVariable.new max = 1000 n = 100 waiting = 0 scvs = [] waiters = n.times.map do |i| - start_cv = ConditionVariable.new + start_cv = Thread::ConditionVariable.new scvs << start_cv - start_mtx = Mutex.new + start_mtx = Thread::Mutex.new start_mtx.synchronize do th = Thread.new(start_mtx, start_cv) do |sm, scv| m.synchronize do diff --git a/benchmark/vm_thread_pass.rb b/benchmark/vm_thread_pass.rb index e5f2352610..438bd08d45 100644 --- a/benchmark/vm_thread_pass.rb +++ b/benchmark/vm_thread_pass.rb @@ -1,4 +1,4 @@ -# Plenty Thtread.pass +# Plenty Thread.pass # A performance may depend on GVL implementation. tmax = (ARGV.shift || 8).to_i diff --git a/benchmark/vm2_unif1.yml b/benchmark/vm_unif1.yml index caef13279f..04187bb0e2 100644 --- a/benchmark/vm2_unif1.yml +++ b/benchmark/vm_unif1.yml @@ -2,6 +2,6 @@ prelude: | def m a, b end benchmark: - vm2_unif1: | + vm_unif1: | m 100, 200 loop_count: 6000000 diff --git a/benchmark/vm1_yield.yml b/benchmark/vm_yield.yml index ae1f9316f9..230be3d84f 100644 --- a/benchmark/vm1_yield.yml +++ b/benchmark/vm_yield.yml @@ -1,6 +1,6 @@ # while loop cost is not removed due to benchmark_driver.gem's limitation benchmark: - vm1_yield: | + vm_yield: | def m i = 0 while i<30_000_000 diff --git a/benchmark/vm2_zsuper.yml b/benchmark/vm_zsuper.yml index f760cfd48e..bfb5837578 100644 --- a/benchmark/vm2_zsuper.yml +++ b/benchmark/vm_zsuper.yml @@ -13,6 +13,6 @@ prelude: | obj = CC.new benchmark: - vm2_zsuper: | + vm_zsuper: | obj.m 10 loop_count: 6000000 diff --git a/benchmark/vm_zsuper_splat_calls.yml b/benchmark/vm_zsuper_splat_calls.yml new file mode 100644 index 0000000000..82dc22349d --- /dev/null +++ b/benchmark/vm_zsuper_splat_calls.yml @@ -0,0 +1,28 @@ +prelude: | + a = [1].freeze + ea = [].freeze + kw = {y: 1}.freeze + b = lambda{} + extend(Module.new{def arg_splat(x=0, y: 0) end}) + extend(Module.new{def arg_splat_block(x=0, y: 0) end}) + extend(Module.new{def arg_splat_post(x=0, y: 0) end}) + extend(Module.new{def splat_kw_splat(x=0, y: 0) end}) + extend(Module.new{def splat_kw_splat_block(x=0, y: 0) end}) + extend(Module.new{def splat_kw(x=0, y: 0) end}) + extend(Module.new{def splat_kw_block(x=0, y: 0) end}) + + extend(Module.new{def arg_splat(x, *a) super end}) + extend(Module.new{def arg_splat_block(x, *a, &b) super end}) + extend(Module.new{def arg_splat_post(*a, x) super end}) + extend(Module.new{def splat_kw_splat(*a, **kw) super end}) + extend(Module.new{def splat_kw_splat_block(*a, **kw, &b) super end}) + extend(Module.new{def splat_kw(*a, y: 1) super end}) + extend(Module.new{def splat_kw_block(*a, y: 1, &b) super end}) +benchmark: + arg_splat: "arg_splat(1, *ea)" + arg_splat_block: "arg_splat_block(1, *ea, &b)" + arg_splat_post: "arg_splat_post(1, *ea, &b)" + splat_kw_splat: "splat_kw_splat(*a, **kw)" + splat_kw_splat_block: "splat_kw_splat_block(*a, **kw, &b)" + splat_kw: "splat_kw(*a, y: 1)" + splat_kw_block: "splat_kw_block(*a, y: 1, &b)" |
