diff options
Diffstat (limited to 'benchmark')
433 files changed, 6611 insertions, 1409 deletions
diff --git a/benchmark/README.md b/benchmark/README.md new file mode 100644 index 0000000000..9f9192685e --- /dev/null +++ b/benchmark/README.md @@ -0,0 +1,75 @@ +# ruby/benchmark + +This directory has benchmark definitions to be run with +[benchmark\_driver.gem](https://github.com/benchmark-driver/benchmark-driver). + +## Normal usage + +Execute `gem install benchmark_driver` and run a command like: + +```bash +# Run a benchmark script with the ruby in the $PATH +benchmark-driver benchmark/app_fib.rb + +# Run benchmark scripts with multiple Ruby executables or options +benchmark-driver benchmark/*.rb -e /path/to/ruby -e '/path/to/ruby --jit' + +# Or compare Ruby versions managed by rbenv +benchmark-driver benchmark/*.rb --rbenv '2.5.1;2.6.0-preview2 --jit' + +# You can collect many metrics in many ways +benchmark-driver benchmark/*.rb --runner memory --output markdown + +# Some are defined with YAML for complex setup or accurate measurement +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, 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) + --timeout SECONDS Timeout ruby command execution with timeout(1) + -v, --verbose Verbose mode. Multiple -v options increase visibility (max: 2) +``` + +## make benchmark + +Using `make benchmark`, `make update-benchmark-driver` automatically downloads +the supported version of benchmark\_driver, and it runs benchmarks with the downloaded +benchmark\_driver. + +```bash +# Run all benchmarks with the ruby in the $PATH and the built ruby +make benchmark + +# Or compare with specific ruby binary +make benchmark COMPARE_RUBY="/path/to/ruby --jit" + +# Run vm benchmarks +make benchmark ITEM=vm + +# Run some limited benchmarks in ITEM-matched files +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 + +# 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=vm_bigarray OPTS="-r peak" +``` diff --git a/benchmark/bm_app_answer.rb b/benchmark/app_answer.rb index 3cd8a8fd37..3cd8a8fd37 100644 --- a/benchmark/bm_app_answer.rb +++ b/benchmark/app_answer.rb diff --git a/benchmark/app_aobench.rb b/benchmark/app_aobench.rb new file mode 100644 index 0000000000..c1546e08ab --- /dev/null +++ b/benchmark/app_aobench.rb @@ -0,0 +1,297 @@ +# coding: US-ASCII + +# AO render benchmark +# Original program (C) Syoyo Fujita in Javascript (and other languages) +# https://code.google.com/p/aobench/ +# Ruby(yarv2llvm) version by Hideki Miura +# + +IMAGE_WIDTH = 256 +IMAGE_HEIGHT = 256 +NSUBSAMPLES = 2 +NAO_SAMPLES = 8 + +srand(0) + +class Vec + def initialize(x, y, z) + @x = x + @y = y + @z = z + end + + attr_accessor :x, :y, :z + + def vadd(b) + Vec.new(@x + b.x, @y + b.y, @z + b.z) + end + + def vsub(b) + Vec.new(@x - b.x, @y - b.y, @z - b.z) + end + + def vcross(b) + Vec.new(@y * b.z - @z * b.y, + @z * b.x - @x * b.z, + @x * b.y - @y * b.x) + end + + def vdot(b) + @x * b.x + @y * b.y + @z * b.z + end + + def vlength + Math.sqrt(@x * @x + @y * @y + @z * @z) + end + + def vnormalize + len = vlength + v = Vec.new(@x, @y, @z) + if len > 1.0e-17 then + v.x = v.x / len + v.y = v.y / len + v.z = v.z / len + end + v + end +end + + +class Sphere + def initialize(center, radius) + @center = center + @radius = radius + end + + attr_reader :center, :radius + + def intersect(ray, isect) + rs = ray.org.vsub(@center) + b = rs.vdot(ray.dir) + c = rs.vdot(rs) - (@radius * @radius) + d = b * b - c + if d > 0.0 then + t = - b - Math.sqrt(d) + + if t > 0.0 and t < isect.t then + isect.t = t + isect.hit = true + isect.pl = Vec.new(ray.org.x + ray.dir.x * t, + ray.org.y + ray.dir.y * t, + ray.org.z + ray.dir.z * t) + n = isect.pl.vsub(@center) + isect.n = n.vnormalize + else + 0.0 + end + end + nil + end +end + +class Plane + def initialize(p, n) + @p = p + @n = n + end + + def intersect(ray, isect) + d = -@p.vdot(@n) + v = ray.dir.vdot(@n) + v0 = v + if v < 0.0 then + v0 = -v + end + if v0 < 1.0e-17 then + return + end + + t = -(ray.org.vdot(@n) + d) / v + + if t > 0.0 and t < isect.t then + isect.hit = true + isect.t = t + isect.n = @n + isect.pl = Vec.new(ray.org.x + t * ray.dir.x, + ray.org.y + t * ray.dir.y, + ray.org.z + t * ray.dir.z) + end + nil + end +end + +class Ray + def initialize(org, dir) + @org = org + @dir = dir + end + + attr_accessor :org, :dir +end + +class Isect + def initialize + @t = 10000000.0 + @hit = false + @pl = Vec.new(0.0, 0.0, 0.0) + @n = Vec.new(0.0, 0.0, 0.0) + end + + attr_accessor :t, :hit, :pl, :n +end + +def clamp(f) + i = f * 255.5 + if i > 255.0 then + i = 255.0 + end + if i < 0.0 then + i = 0.0 + end + i.to_i +end + +def orthoBasis(basis, n) + basis[2] = Vec.new(n.x, n.y, n.z) + basis[1] = Vec.new(0.0, 0.0, 0.0) + + if n.x < 0.6 and n.x > -0.6 then + basis[1].x = 1.0 + elsif n.y < 0.6 and n.y > -0.6 then + basis[1].y = 1.0 + elsif n.z < 0.6 and n.z > -0.6 then + basis[1].z = 1.0 + else + basis[1].x = 1.0 + end + + basis[0] = basis[1].vcross(basis[2]) + basis[0] = basis[0].vnormalize + + basis[1] = basis[2].vcross(basis[0]) + basis[1] = basis[1].vnormalize +end + +class Scene + def initialize + @spheres = Array.new + @spheres[0] = Sphere.new(Vec.new(-2.0, 0.0, -3.5), 0.5) + @spheres[1] = Sphere.new(Vec.new(-0.5, 0.0, -3.0), 0.5) + @spheres[2] = Sphere.new(Vec.new(1.0, 0.0, -2.2), 0.5) + @plane = Plane.new(Vec.new(0.0, -0.5, 0.0), Vec.new(0.0, 1.0, 0.0)) + end + + def ambient_occlusion(isect) + basis = Array.new + orthoBasis(basis, isect.n) + + ntheta = NAO_SAMPLES + nphi = NAO_SAMPLES + eps = 0.0001 + occlusion = 0.0 + + p0 = Vec.new(isect.pl.x + eps * isect.n.x, + isect.pl.y + eps * isect.n.y, + isect.pl.z + eps * isect.n.z) + nphi.times do |j| + ntheta.times do |i| + r = rand + phi = 2.0 * 3.14159265 * rand + x = Math.cos(phi) * Math.sqrt(1.0 - r) + y = Math.sin(phi) * Math.sqrt(1.0 - r) + z = Math.sqrt(r) + + rx = x * basis[0].x + y * basis[1].x + z * basis[2].x + ry = x * basis[0].y + y * basis[1].y + z * basis[2].y + rz = x * basis[0].z + y * basis[1].z + z * basis[2].z + + raydir = Vec.new(rx, ry, rz) + ray = Ray.new(p0, raydir) + + occisect = Isect.new + @spheres[0].intersect(ray, occisect) + @spheres[1].intersect(ray, occisect) + @spheres[2].intersect(ray, occisect) + @plane.intersect(ray, occisect) + if occisect.hit then + occlusion = occlusion + 1.0 + else + 0.0 + end + end + end + + occlusion = (ntheta.to_f * nphi.to_f - occlusion) / (ntheta.to_f * nphi.to_f) + + Vec.new(occlusion, occlusion, occlusion) + end + + def render(w, h, nsubsamples) + cnt = 0 + nsf = nsubsamples.to_f + h.times do |y| + w.times do |x| + rad = Vec.new(0.0, 0.0, 0.0) + + # Subsampling + nsubsamples.times do |v| + nsubsamples.times do |u| + + cnt = cnt + 1 + wf = w.to_f + hf = h.to_f + xf = x.to_f + yf = y.to_f + uf = u.to_f + vf = v.to_f + + px = (xf + (uf / nsf) - (wf / 2.0)) / (wf / 2.0) + py = -(yf + (vf / nsf) - (hf / 2.0)) / (hf / 2.0) + + eye = Vec.new(px, py, -1.0).vnormalize + + ray = Ray.new(Vec.new(0.0, 0.0, 0.0), eye) + + isect = Isect.new + @spheres[0].intersect(ray, isect) + @spheres[1].intersect(ray, isect) + @spheres[2].intersect(ray, isect) + @plane.intersect(ray, isect) + if isect.hit then + col = ambient_occlusion(isect) + rad.x = rad.x + col.x + rad.y = rad.y + col.y + rad.z = rad.z + col.z + end + end + end + + r = rad.x / (nsf * nsf) + g = rad.y / (nsf * nsf) + b = rad.z / (nsf * nsf) + printf("%c", clamp(r)) + printf("%c", clamp(g)) + printf("%c", clamp(b)) + end + nil + end + + nil + end +end + +alias printf_orig printf +def printf *args + # $fp.printf(*args) +end + +# File.open("ao.ppm", "w") do |fp| + # $fp = fp + printf("P6\n") + printf("%d %d\n", IMAGE_WIDTH, IMAGE_HEIGHT) + printf("255\n") + Scene.new.render(IMAGE_WIDTH, IMAGE_HEIGHT, NSUBSAMPLES) +# end + +undef printf +alias printf printf_orig diff --git a/benchmark/app_erb.yml b/benchmark/app_erb.yml new file mode 100644 index 0000000000..31e29b7644 --- /dev/null +++ b/benchmark/app_erb.yml @@ -0,0 +1,23 @@ +# +# Create many HTML strings with ERB. +# +prelude: | + require 'erb' + + data = <<erb + <html> + <head> <%= title %> </head> + <body> + <h1> <%= title %> </h1> + <p> + <%= content %> + </p> + </body> + </html> + erb + + title = "hello world!" + content = "hello world!\n" * 10 +benchmark: + app_erb: ERB.new(data).result(binding) +loop_count: 15000 diff --git a/benchmark/bm_app_factorial.rb b/benchmark/app_factorial.rb index 45f471dfdb..45f471dfdb 100644 --- a/benchmark/bm_app_factorial.rb +++ b/benchmark/app_factorial.rb diff --git a/benchmark/bm_app_fib.rb b/benchmark/app_fib.rb index 34a7b2e725..e61bc8aa32 100644 --- a/benchmark/bm_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/app_lc_fizzbuzz.rb b/benchmark/app_lc_fizzbuzz.rb new file mode 100644 index 0000000000..f09574bbeb --- /dev/null +++ b/benchmark/app_lc_fizzbuzz.rb @@ -0,0 +1,52 @@ +# +# FizzBuzz program using only lambda calculus +# +# This program is quoted from +# "Understanding Computation" by Tom Stuart +# http://computationbook.com/ +# +# You can understand why this program works fine by reading this book. +# + +solution = -> k { -> f { -> f { -> x { f[-> y { x[x][y] }] }[-> x { f[-> y { x[x][y] }] }] }[-> f { -> l { -> x { -> g { -> b { b }[-> p { p[-> x { -> y { x } }] }[l]][x][-> y { g[f[-> l { -> p { p[-> x { -> y { y } }] }[-> p { p[-> x { -> y { y } }] }[l]] }[l]][x][g]][-> l { -> p { p[-> x { -> y { x } }] }[-> p { p[-> x { -> y { y } }] }[l]] }[l]][y] }] } } } }][k][-> x { -> y { -> f { f[x][y] } } }[-> x { -> y { x } }][-> x { -> y { x } }]][-> l { -> x { -> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[l][f[x]] } }] } }[-> f { -> x { f[-> y { x[x][y] }] }[-> x { f[-> y { x[x][y] }] }] }[-> f { -> m { -> n { -> b { b }[-> m { -> n { -> n { n[-> x { -> x { -> y { y } } }][-> x { -> y { x } }] }[-> m { -> n { n[-> n { -> p { p[-> x { -> y { x } }] }[n[-> p { -> x { -> y { -> f { f[x][y] } } }[-> p { p[-> x { -> y { y } }] }[p]][-> n { -> p { -> x { p[n[p][x]] } } }[-> p { p[-> x { -> y { y } }] }[p]]] }][-> x { -> y { -> f { f[x][y] } } }[-> p { -> x { x } }][-> p { -> x { x } }]]] }][m] } }[m][n]] } }[m][n]][-> x { -> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[f[-> n { -> p { -> x { p[n[p][x]] } } }[m]][n]][m][x] }][-> x { -> y { -> f { f[x][y] } } }[-> x { -> y { x } }][-> x { -> y { x } }]] } } }][-> p { -> x { p[x] } }][-> p { -> x { p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[x]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] } }]][-> n { -> b { b }[-> n { n[-> x { -> x { -> y { y } } }][-> x { -> y { x } }] }[-> f { -> x { f[-> y { x[x][y] }] }[-> x { f[-> y { x[x][y] }] }] }[-> f { -> m { -> n { -> b { b }[-> m { -> n { -> n { n[-> x { -> x { -> y { y } } }][-> x { -> y { x } }] }[-> m { -> n { n[-> n { -> p { p[-> x { -> y { x } }] }[n[-> p { -> x { -> y { -> f { f[x][y] } } }[-> p { p[-> x { -> y { y } }] }[p]][-> n { -> p { -> x { p[n[p][x]] } } }[-> p { p[-> x { -> y { y } }] }[p]]] }][-> x { -> y { -> f { f[x][y] } } }[-> p { -> x { x } }][-> p { -> x { x } }]]] }][m] } }[m][n]] } }[n][m]][-> x { f[-> m { -> n { n[-> n { -> p { p[-> x { -> y { x } }] }[n[-> p { -> x { -> y { -> f { f[x][y] } } }[-> p { p[-> x { -> y { y } }] }[p]][-> n { -> p { -> x { p[n[p][x]] } } }[-> p { p[-> x { -> y { y } }] }[p]]] }][-> x { -> y { -> f { f[x][y] } } }[-> p { -> x { x } }][-> p { -> x { x } }]]] }][m] } }[m][n]][n][x] }][m] } } }][n][-> p { -> x { p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[x]]]]]]]]]]]]]]] } }]]][-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> x { -> y { -> f { f[x][y] } } }[-> x { -> y { x } }][-> x { -> y { x } }]][-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]]]]][-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]]]]][-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]]]][-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]][-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]]]]][-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]]]]][-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]]][-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]][-> b { b }[-> n { n[-> x { -> x { -> y { y } } }][-> x { -> y { x } }] }[-> f { -> x { f[-> y { x[x][y] }] }[-> x { f[-> y { x[x][y] }] }] }[-> f { -> m { -> n { -> b { b }[-> m { -> n { -> n { n[-> x { -> x { -> y { y } } }][-> x { -> y { x } }] }[-> m { -> n { n[-> n { -> p { p[-> x { -> y { x } }] }[n[-> p { -> x { -> y { -> f { f[x][y] } } }[-> p { p[-> x { -> y { y } }] }[p]][-> n { -> p { -> x { p[n[p][x]] } } }[-> p { p[-> x { -> y { y } }] }[p]]] }][-> x { -> y { -> f { f[x][y] } } }[-> p { -> x { x } }][-> p { -> x { x } }]]] }][m] } }[m][n]] } }[n][m]][-> x { f[-> m { -> n { n[-> n { -> p { p[-> x { -> y { x } }] }[n[-> p { -> x { -> y { -> f { f[x][y] } } }[-> p { p[-> x { -> y { y } }] }[p]][-> n { -> p { -> x { p[n[p][x]] } } }[-> p { p[-> x { -> y { y } }] }[p]]] }][-> x { -> y { -> f { f[x][y] } } }[-> p { -> x { x } }][-> p { -> x { x } }]]] }][m] } }[m][n]][n][x] }][m] } } }][n][-> p { -> x { p[p[p[x]]] } }]]][-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> x { -> y { -> f { f[x][y] } } }[-> x { -> y { x } }][-> x { -> y { x } }]][-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]]]]][-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]]]]][-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]]][-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]][-> b { b }[-> n { n[-> x { -> x { -> y { y } } }][-> x { -> y { x } }] }[-> f { -> x { f[-> y { x[x][y] }] }[-> x { f[-> y { x[x][y] }] }] }[-> f { -> m { -> n { -> b { b }[-> m { -> n { -> n { n[-> x { -> x { -> y { y } } }][-> x { -> y { x } }] }[-> m { -> n { n[-> n { -> p { p[-> x { -> y { x } }] }[n[-> p { -> x { -> y { -> f { f[x][y] } } }[-> p { p[-> x { -> y { y } }] }[p]][-> n { -> p { -> x { p[n[p][x]] } } }[-> p { p[-> x { -> y { y } }] }[p]]] }][-> x { -> y { -> f { f[x][y] } } }[-> p { -> x { x } }][-> p { -> x { x } }]]] }][m] } }[m][n]] } }[n][m]][-> x { f[-> m { -> n { n[-> n { -> p { p[-> x { -> y { x } }] }[n[-> p { -> x { -> y { -> f { f[x][y] } } }[-> p { p[-> x { -> y { y } }] }[p]][-> n { -> p { -> x { p[n[p][x]] } } }[-> p { p[-> x { -> y { y } }] }[p]]] }][-> x { -> y { -> f { f[x][y] } } }[-> p { -> x { x } }][-> p { -> x { x } }]]] }][m] } }[m][n]][n][x] }][m] } } }][n][-> p { -> x { p[p[p[p[p[x]]]]] } }]]][-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> x { -> y { -> f { f[x][y] } } }[-> x { -> y { x } }][-> x { -> y { x } }]][-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]]]]][-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]]]]][-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]]]][-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]][-> f { -> x { f[-> y { x[x][y] }] }[-> x { f[-> y { x[x][y] }] }] }[-> f { -> n { -> l { -> x { -> f { -> x { f[-> y { x[x][y] }] }[-> x { f[-> y { x[x][y] }] }] }[-> f { -> l { -> x { -> g { -> b { b }[-> p { p[-> x { -> y { x } }] }[l]][x][-> y { g[f[-> l { -> p { p[-> x { -> y { y } }] }[-> p { p[-> x { -> y { y } }] }[l]] }[l]][x][g]][-> l { -> p { p[-> x { -> y { x } }] }[-> p { p[-> x { -> y { y } }] }[l]] }[l]][y] }] } } } }][l][-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> x { -> y { -> f { f[x][y] } } }[-> x { -> y { x } }][-> x { -> y { x } }]][x]][-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }] } }[-> b { b }[-> m { -> n { -> n { n[-> x { -> x { -> y { y } } }][-> x { -> y { x } }] }[-> m { -> n { n[-> n { -> p { p[-> x { -> y { x } }] }[n[-> p { -> x { -> y { -> f { f[x][y] } } }[-> p { p[-> x { -> y { y } }] }[p]][-> n { -> p { -> x { p[n[p][x]] } } }[-> p { p[-> x { -> y { y } }] }[p]]] }][-> x { -> y { -> f { f[x][y] } } }[-> p { -> x { x } }][-> p { -> x { x } }]]] }][m] } }[m][n]] } }[n][-> n { -> p { p[-> x { -> y { x } }] }[n[-> p { -> x { -> y { -> f { f[x][y] } } }[-> p { p[-> x { -> y { y } }] }[p]][-> n { -> p { -> x { p[n[p][x]] } } }[-> p { p[-> x { -> y { y } }] }[p]]] }][-> x { -> y { -> f { f[x][y] } } }[-> p { -> x { x } }][-> p { -> x { x } }]]] }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]][-> x { -> y { -> f { f[x][y] } } }[-> x { -> y { x } }][-> x { -> y { x } }]][-> x { f[-> f { -> x { f[-> y { x[x][y] }] }[-> x { f[-> y { x[x][y] }] }] }[-> f { -> m { -> n { -> b { b }[-> m { -> n { -> n { n[-> x { -> x { -> y { y } } }][-> x { -> y { x } }] }[-> m { -> n { n[-> n { -> p { p[-> x { -> y { x } }] }[n[-> p { -> x { -> y { -> f { f[x][y] } } }[-> p { p[-> x { -> y { y } }] }[p]][-> n { -> p { -> x { p[n[p][x]] } } }[-> p { p[-> x { -> y { y } }] }[p]]] }][-> x { -> y { -> f { f[x][y] } } }[-> p { -> x { x } }][-> p { -> x { x } }]]] }][m] } }[m][n]] } }[n][m]][-> x { -> n { -> p { -> x { p[n[p][x]] } } }[f[-> m { -> n { n[-> n { -> p { p[-> x { -> y { x } }] }[n[-> p { -> x { -> y { -> f { f[x][y] } } }[-> p { p[-> x { -> y { y } }] }[p]][-> n { -> p { -> x { p[n[p][x]] } } }[-> p { p[-> x { -> y { y } }] }[p]]] }][-> x { -> y { -> f { f[x][y] } } }[-> p { -> x { x } }][-> p { -> x { x } }]]] }][m] } }[m][n]][n]][x] }][-> p { -> x { x } }] } } }][n][-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]][x] }]][-> f { -> x { f[-> y { x[x][y] }] }[-> x { f[-> y { x[x][y] }] }] }[-> f { -> m { -> n { -> b { b }[-> m { -> n { -> n { n[-> x { -> x { -> y { y } } }][-> x { -> y { x } }] }[-> m { -> n { n[-> n { -> p { p[-> x { -> y { x } }] }[n[-> p { -> x { -> y { -> f { f[x][y] } } }[-> p { p[-> x { -> y { y } }] }[p]][-> n { -> p { -> x { p[n[p][x]] } } }[-> p { p[-> x { -> y { y } }] }[p]]] }][-> x { -> y { -> f { f[x][y] } } }[-> p { -> x { x } }][-> p { -> x { x } }]]] }][m] } }[m][n]] } }[n][m]][-> x { f[-> m { -> n { n[-> n { -> p { p[-> x { -> y { x } }] }[n[-> p { -> x { -> y { -> f { f[x][y] } } }[-> p { p[-> x { -> y { y } }] }[p]][-> n { -> p { -> x { p[n[p][x]] } } }[-> p { p[-> x { -> y { y } }] }[p]]] }][-> x { -> y { -> f { f[x][y] } } }[-> p { -> x { x } }][-> p { -> x { x } }]]] }][m] } }[m][n]][n][x] }][m] } } }][n][-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]] } }][n]]]] }] + +FIRST = -> l { LEFT[RIGHT[l]] } +IF = -> b { b } +LEFT = -> p { p[-> x { -> y { x } } ] } +RIGHT = -> p { p[-> x { -> y { y } } ] } +IS_EMPTY = LEFT +REST = -> l { RIGHT[RIGHT[l]] } + +def to_integer(proc) + proc[-> n { n + 1 }][0] +end + +def to_boolean(proc) + IF[proc][true][false] +end + +def to_array(proc) + array = [] + + until to_boolean(IS_EMPTY[proc]) + array.push(FIRST[proc]) + proc = REST[proc] + end + + array +end + +def to_char(c) + '0123456789BFiuz'.slice(to_integer(c)) +end + +def to_string(s) + to_array(s).map { |c| to_char(c) }.join +end + +answer = to_array(solution).map do |p| + to_string(p) +end + +answer_ary = answer.to_a +# puts answer_ary diff --git a/benchmark/bm_app_mandelbrot.rb b/benchmark/app_mandelbrot.rb index 801b75e8e2..801b75e8e2 100644 --- a/benchmark/bm_app_mandelbrot.rb +++ b/benchmark/app_mandelbrot.rb diff --git a/benchmark/bm_app_pentomino.rb b/benchmark/app_pentomino.rb index 59c63f358e..47be7b203f 100644 --- a/benchmark/bm_app_pentomino.rb +++ b/benchmark/app_pentomino.rb @@ -128,132 +128,3 @@ mkboard $p[4] = [$p[4][0]] $pnum = (0...$p.length).to_a setpiece([],0) - - -__END__ - -# original - -NP = 5 -ROW = 8 + NP -COL = 8 - -$p = [] -$b = [] -$no = 0 - -def piece(n,a,nb) - for x in nb - a[n] = x - if n == NP-1 - $p << [a.sort] - else - nbc=nb.dup - for d in [-ROW, -1, 1, ROW] - if x+d > 0 and not a.include?(x+d) and not nbc.include?(x+d) - nbc << x+d - end - end - nbc.delete x - piece(n+1,a[0..n],nbc) - end - end -end - -def kikaku(a) - a.collect {|x| x - a[0]} -end -def ud(a) - kikaku(a.collect {|x| ((x+NP)%ROW)-ROW*((x+NP)/ROW) }.sort) -end -def rl(a) - kikaku(a.collect {|x| ROW*((x+NP)/ROW)+ROW-((x+NP)%ROW)}.sort) -end -def xy(a) - kikaku(a.collect {|x| ROW*((x+NP)%ROW) + (x+NP)/ROW }.sort) -end - -def mkpieces - piece(0,[],[0]) - $p.each do |a| - a0 = a[0] - a[1] = ud(a0) - a[2] = rl(a0) - a[3] = ud(rl(a0)) - a[4] = xy(a0) - a[5] = ud(xy(a0)) - a[6] = rl(xy(a0)) - a[7] = ud(rl(xy(a0))) - a.sort! - a.uniq! - end - $p.uniq!.sort! {|x,y| x[0] <=> y[0] } -end - -def mkboard - for i in 0...ROW*COL - if i % ROW >= ROW-NP - $b[i] = -2 - else - $b[i] = -1 - end - $b[3*ROW+3]=$b[3*ROW+4]=$b[4*ROW+3]=$b[4*ROW+4]=-2 - end -end - -def pboard - print "No. #$no\n" - for i in 0...COL - print "|" - for j in 0...ROW-NP - x = $b[i*ROW+j] - if x < 0 - print "..|" - else - printf "%2d|",x+1 - end - end - print "\n" - end - print "\n" -end - -$pnum=[] -def setpiece(a,pos) - if a.length == $p.length then - $no += 1 - pboard - return - end - while $b[pos] != -1 - pos += 1 - end - ($pnum - a).each do |i| - $p[i].each do |x| - f = 0 - for s in x do - if $b[pos+s] != -1 - f=1 - break - end - end - if f == 0 then - for s in x do - $b[pos+s] = i - end - a << i - setpiece(a.dup, pos) - a.pop - for s in x do - $b[pos+s] = -1 - end - end - end - end -end - -mkpieces -mkboard -$p[4] = [$p[4][0]] -$pnum = (0...$p.length).to_a -setpiece([],0) diff --git a/benchmark/bm_app_raise.rb b/benchmark/app_raise.rb index 5db8f95d50..5db8f95d50 100644 --- a/benchmark/bm_app_raise.rb +++ b/benchmark/app_raise.rb diff --git a/benchmark/bm_app_strconcat.rb b/benchmark/app_strconcat.rb index 7eed7c1aed..7eed7c1aed 100644 --- a/benchmark/bm_app_strconcat.rb +++ b/benchmark/app_strconcat.rb diff --git a/benchmark/bm_app_tak.rb b/benchmark/app_tak.rb index efe5380f4e..efe5380f4e 100644 --- a/benchmark/bm_app_tak.rb +++ b/benchmark/app_tak.rb diff --git a/benchmark/bm_app_tarai.rb b/benchmark/app_tarai.rb index 4c146f5ccf..4c146f5ccf 100644 --- a/benchmark/bm_app_tarai.rb +++ b/benchmark/app_tarai.rb diff --git a/benchmark/bm_app_uri.rb b/benchmark/app_uri.rb index 586edfd5dc..586edfd5dc 100644 --- a/benchmark/bm_app_uri.rb +++ b/benchmark/app_uri.rb 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_sample_100k_10.rb b/benchmark/array_sample_100k_10.rb new file mode 100644 index 0000000000..5f41ecc32b --- /dev/null +++ b/benchmark/array_sample_100k_10.rb @@ -0,0 +1,2 @@ +arr = [*0...100000] +10_000.times {arr.sample 10} diff --git a/benchmark/array_sample_100k_11.rb b/benchmark/array_sample_100k_11.rb new file mode 100644 index 0000000000..18b1715319 --- /dev/null +++ b/benchmark/array_sample_100k_11.rb @@ -0,0 +1,2 @@ +arr = [*0...100000] +10_000.times {arr.sample 11} diff --git a/benchmark/array_sample_100k__100.rb b/benchmark/array_sample_100k__100.rb new file mode 100644 index 0000000000..22863afe89 --- /dev/null +++ b/benchmark/array_sample_100k__100.rb @@ -0,0 +1,2 @@ +arr = [*0...100000] +10_000.times {arr.sample 100} diff --git a/benchmark/array_sample_100k__1k.rb b/benchmark/array_sample_100k__1k.rb new file mode 100644 index 0000000000..4cd79e6c67 --- /dev/null +++ b/benchmark/array_sample_100k__1k.rb @@ -0,0 +1,2 @@ +arr = [*0...100000] +10_000.times {arr.sample 1000} diff --git a/benchmark/array_sample_100k__6k.rb b/benchmark/array_sample_100k__6k.rb new file mode 100644 index 0000000000..b3d264249e --- /dev/null +++ b/benchmark/array_sample_100k__6k.rb @@ -0,0 +1,2 @@ +arr = [*0...100000] +10_000.times {arr.sample 6000} diff --git a/benchmark/array_sample_100k___10k.rb b/benchmark/array_sample_100k___10k.rb new file mode 100644 index 0000000000..5dd55ec058 --- /dev/null +++ b/benchmark/array_sample_100k___10k.rb @@ -0,0 +1,2 @@ +arr = [*0...100000] +10_000.times {arr.sample 10_000} diff --git a/benchmark/array_sample_100k___50k.rb b/benchmark/array_sample_100k___50k.rb new file mode 100644 index 0000000000..1506732c3c --- /dev/null +++ b/benchmark/array_sample_100k___50k.rb @@ -0,0 +1,2 @@ +arr = [*0...100000] +10_000.times {arr.sample 50_000} diff --git a/benchmark/array_shift.rb b/benchmark/array_shift.rb new file mode 100644 index 0000000000..798bb9e3f4 --- /dev/null +++ b/benchmark/array_shift.rb @@ -0,0 +1,14 @@ +require 'benchmark' + +Benchmark.bm do |x| + [10_000,1_000_000,100_000_000].each do |n| + ary = Array.new(n,0) + GC.start + x.report("#{n}:shift"){ ary.shift } + (0..4).each do |i| + ary = Array.new(n,0) + GC.start + x.report("#{n}:shift(#{i})"){ ary.shift(i) } + end + end +end diff --git a/benchmark/array_small_and.rb b/benchmark/array_small_and.rb new file mode 100644 index 0000000000..e53a6edae6 --- /dev/null +++ b/benchmark/array_small_and.rb @@ -0,0 +1,17 @@ +MIN_SIZE = ENV.fetch('SMALL_ARRAY_MIN', 0).to_i +MAX_SIZE = ENV.fetch('SMALL_ARRAY_MAX', 16).to_i +ITERATIONS = ENV.fetch('SMALL_ARRAY_ITERATIONS', 100).to_i + +ARRAYS = (MIN_SIZE..MAX_SIZE).map do |size1| + (MIN_SIZE..MAX_SIZE).map do |size2| + [Array.new(size1) { rand(MAX_SIZE) }, Array.new(size2) { rand(MAX_SIZE) }] + end +end + +ITERATIONS.times do + ARRAYS.each do |group| + group.each do |arr1, arr2| + arr1 & arr2 + end + end +end diff --git a/benchmark/array_small_diff.rb b/benchmark/array_small_diff.rb new file mode 100644 index 0000000000..9661ee48db --- /dev/null +++ b/benchmark/array_small_diff.rb @@ -0,0 +1,17 @@ +MIN_SIZE = ENV.fetch('SMALL_ARRAY_MIN', 0).to_i +MAX_SIZE = ENV.fetch('SMALL_ARRAY_MAX', 16).to_i +ITERATIONS = ENV.fetch('SMALL_ARRAY_ITERATIONS', 100).to_i + +ARRAYS = (MIN_SIZE..MAX_SIZE).map do |size1| + (MIN_SIZE..MAX_SIZE).map do |size2| + [Array.new(size1) { rand(MAX_SIZE) }, Array.new(size2) { rand(MAX_SIZE) }] + end +end + +ITERATIONS.times do + ARRAYS.each do |group| + group.each do |arr1, arr2| + arr1 - arr2 + end + end +end diff --git a/benchmark/array_small_or.rb b/benchmark/array_small_or.rb new file mode 100644 index 0000000000..c58b5fd1ff --- /dev/null +++ b/benchmark/array_small_or.rb @@ -0,0 +1,17 @@ +MIN_SIZE = ENV.fetch('SMALL_ARRAY_MIN', 0).to_i +MAX_SIZE = ENV.fetch('SMALL_ARRAY_MAX', 16).to_i +ITERATIONS = ENV.fetch('SMALL_ARRAY_ITERATIONS', 100).to_i + +ARRAYS = (MIN_SIZE..MAX_SIZE).map do |size1| + (MIN_SIZE..MAX_SIZE).map do |size2| + [Array.new(size1) { rand(MAX_SIZE) }, Array.new(size2) { rand(MAX_SIZE) }] + end +end + +ITERATIONS.times do + ARRAYS.each do |group| + group.each do |arr1, arr2| + arr1 | arr2 + end + end +end diff --git a/benchmark/array_sort_block.rb b/benchmark/array_sort_block.rb new file mode 100644 index 0000000000..3579786056 --- /dev/null +++ b/benchmark/array_sort_block.rb @@ -0,0 +1,2 @@ +ary = Array.new(1000) { rand(1000) } +10000.times { ary.sort { |a, b| a <=> b } } diff --git a/benchmark/array_sort_float.rb b/benchmark/array_sort_float.rb new file mode 100644 index 0000000000..9a6e2f8bd2 --- /dev/null +++ b/benchmark/array_sort_float.rb @@ -0,0 +1,2 @@ +arr = Array.new(1000) { rand } +10000.times { arr.sort } 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/array_values_at_int.rb b/benchmark/array_values_at_int.rb new file mode 100644 index 0000000000..6cb394cb9f --- /dev/null +++ b/benchmark/array_values_at_int.rb @@ -0,0 +1,2 @@ +ary = Array.new(10000) {|i| i} +100000.times { ary.values_at(500) } diff --git a/benchmark/array_values_at_range.rb b/benchmark/array_values_at_range.rb new file mode 100644 index 0000000000..5b53806d1c --- /dev/null +++ b/benchmark/array_values_at_range.rb @@ -0,0 +1,2 @@ +ary = Array.new(10000) {|i| i} +100000.times { ary.values_at(1..2000) } 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/bighash.rb b/benchmark/bighash.rb new file mode 100644 index 0000000000..e2ad5a5c94 --- /dev/null +++ b/benchmark/bighash.rb @@ -0,0 +1 @@ +h = {}; 5000000.times {|n| h[n] = n } diff --git a/benchmark/bm_app_erb.rb b/benchmark/bm_app_erb.rb deleted file mode 100644 index 77c66a7949..0000000000 --- a/benchmark/bm_app_erb.rb +++ /dev/null @@ -1,26 +0,0 @@ -# -# Create many HTML strings with ERB. -# - -require 'erb' - -data = DATA.read -max = 15_000 -title = "hello world!" -content = "hello world!\n" * 10 - -max.times{ - ERB.new(data).result(binding) -} - -__END__ - -<html> - <head> <%= title %> </head> - <body> - <h1> <%= title %> </h1> - <p> - <%= content %> - </p> - </body> -</html> diff --git a/benchmark/bm_so_count_words.rb b/benchmark/bm_so_count_words.rb deleted file mode 100644 index 65f6337a4a..0000000000 --- a/benchmark/bm_so_count_words.rb +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/ruby -# -*- mode: ruby -*- -# $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 -end -# STDERR.puts "#{nl} #{nw} #{nc}" - diff --git a/benchmark/bm_so_k_nucleotide.rb b/benchmark/bm_so_k_nucleotide.rb deleted file mode 100644 index dadab3e79c..0000000000 --- a/benchmark/bm_so_k_nucleotide.rb +++ /dev/null @@ -1,48 +0,0 @@ -# The Computer Language Shootout -# http://shootout.alioth.debian.org -# -# contributed by jose fco. gonzalez -# modified by Sokolov Yura - -seq = String.new - -def frecuency( seq,length ) - n, table = seq.length - length + 1, Hash.new(0) - f, i = nil, nil - (0 ... length).each do |f| - (f ... n).step(length) do |i| - table[seq[i,length]] += 1 - end - end - [n,table] - -end - -def sort_by_freq( seq,length ) - n,table = frecuency( seq,length ) - a, b, v = nil, nil, nil - table.sort{|a,b| b[1] <=> a[1]}.each do |v| - puts "%s %.3f" % [v[0].upcase,((v[1]*100).to_f/n)] - end - puts -end - -def find_seq( seq,s ) - n,table = frecuency( seq,s.length ) - puts "#{table[s].to_s}\t#{s.upcase}" -end - -input = open(File.join(File.dirname($0), 'fasta.output.100000'), 'rb') - -line = input.gets while line !~ /^>THREE/ -line = input.gets - -while (line !~ /^>/) & line do - seq << line.chomp - line = input.gets -end - -[1,2].each {|i| sort_by_freq( seq,i ) } - -%w(ggt ggta ggtatt ggtattttaatt ggtattttaatttatagt).each{|s| find_seq( seq,s) } - diff --git a/benchmark/bm_so_reverse_complement.rb b/benchmark/bm_so_reverse_complement.rb deleted file mode 100644 index 82ea666994..0000000000 --- a/benchmark/bm_so_reverse_complement.rb +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/ruby -# The Great Computer Language Shootout -# http://shootout.alioth.debian.org/ -# -# Contributed by Peter Bjarke Olsen -# Modified by Doug King - -seq=Array.new - -def revcomp(seq) - seq.reverse!.tr!('wsatugcyrkmbdhvnATUGCYRKMBDHVN','WSTAACGRYMKVHDBNTAACGRYMKVHDBN') - stringlen=seq.length - 0.step(stringlen-1,60) {|x| print seq.slice(x,60) , "\n"} -end - -input = open(File.join(File.dirname($0), 'fasta.output.2500000'), 'rb') - -while input.gets - if $_ =~ />/ - if seq.length != 0 - revcomp(seq.join) - seq=Array.new - end - puts $_ - else - $_.sub(/\n/,'') - seq.push $_ - end -end -revcomp(seq.join) diff --git a/benchmark/bm_vm1_attr_ivar.rb b/benchmark/bm_vm1_attr_ivar.rb deleted file mode 100644 index 16906f3605..0000000000 --- a/benchmark/bm_vm1_attr_ivar.rb +++ /dev/null @@ -1,14 +0,0 @@ -class C - attr_reader :a, :b - def initialize - @a = nil - @b = nil - end -end -obj = C.new -i = 0 -while i<30_000_000 # while loop 1 - i += 1 - j = obj.a - k = obj.b -end diff --git a/benchmark/bm_vm1_attr_ivar_set.rb b/benchmark/bm_vm1_attr_ivar_set.rb deleted file mode 100644 index 7e7a6b48c0..0000000000 --- a/benchmark/bm_vm1_attr_ivar_set.rb +++ /dev/null @@ -1,14 +0,0 @@ -class C - attr_accessor :a, :b - def initialize - @a = nil - @b = nil - end -end -obj = C.new -i = 0 -while i<30_000_000 # while loop 1 - i += 1 - obj.a = 1 - obj.b = 2 -end diff --git a/benchmark/bm_vm1_block.rb b/benchmark/bm_vm1_block.rb deleted file mode 100644 index a9f56b15ea..0000000000 --- a/benchmark/bm_vm1_block.rb +++ /dev/null @@ -1,10 +0,0 @@ -def m - yield -end - -i = 0 -while i<30_000_000 # while loop 1 - i += 1 - m{ - } -end diff --git a/benchmark/bm_vm1_const.rb b/benchmark/bm_vm1_const.rb deleted file mode 100644 index ac59ebccf1..0000000000 --- a/benchmark/bm_vm1_const.rb +++ /dev/null @@ -1,8 +0,0 @@ -Const = 1 - -i = 0 -while i<30_000_000 # while loop 1 - i += 1 - j = Const - k = Const -end diff --git a/benchmark/bm_vm1_ensure.rb b/benchmark/bm_vm1_ensure.rb deleted file mode 100644 index a1596145f2..0000000000 --- a/benchmark/bm_vm1_ensure.rb +++ /dev/null @@ -1,11 +0,0 @@ -i = 0 -while i<30_000_000 # benchmark loop 1 - i += 1 - begin - begin - ensure - end - ensure - end -end - diff --git a/benchmark/bm_vm1_float_simple.rb b/benchmark/bm_vm1_float_simple.rb deleted file mode 100644 index d4581439ff..0000000000 --- a/benchmark/bm_vm1_float_simple.rb +++ /dev/null @@ -1,7 +0,0 @@ -i = 0.0; f = 0.0 -while i<30_000_000 - i += 1 - f += 0.1; f -= 0.1 - f += 0.1; f -= 0.1 - f += 0.1; f -= 0.1 -end diff --git a/benchmark/bm_vm1_ivar.rb b/benchmark/bm_vm1_ivar.rb deleted file mode 100644 index 68a73cf92f..0000000000 --- a/benchmark/bm_vm1_ivar.rb +++ /dev/null @@ -1,8 +0,0 @@ -@a = 1 - -i = 0 -while i<30_000_000 # while loop 1 - i += 1 - j = @a - k = @a -end diff --git a/benchmark/bm_vm1_ivar_set.rb b/benchmark/bm_vm1_ivar_set.rb deleted file mode 100644 index bd81b06c34..0000000000 --- a/benchmark/bm_vm1_ivar_set.rb +++ /dev/null @@ -1,6 +0,0 @@ -i = 0 -while i<30_000_000 # while loop 1 - i += 1 - @a = 1 - @b = 2 -end diff --git a/benchmark/bm_vm1_length.rb b/benchmark/bm_vm1_length.rb deleted file mode 100644 index 353de3ab0e..0000000000 --- a/benchmark/bm_vm1_length.rb +++ /dev/null @@ -1,9 +0,0 @@ -a = 'abc' -b = [1, 2, 3] -i = 0 -while i<30_000_000 # while loop 1 - i += 1 - a.length - b.length -end - diff --git a/benchmark/bm_vm1_lvar_init.rb b/benchmark/bm_vm1_lvar_init.rb deleted file mode 100644 index 36f2068811..0000000000 --- a/benchmark/bm_vm1_lvar_init.rb +++ /dev/null @@ -1,18 +0,0 @@ -def m v - unless v - # unreachable code - v1 = v2 = v3 = v4 = v5 = v6 = v7 = v8 = v9 = v10 = - v11 = v12 = v13 = v14 = v15 = v16 = v17 = v18 = v19 = v20 = - v21 = v22 = v23 = v24 = v25 = v26 = v27 = v28 = v29 = v30 = - v31 = v32 = v33 = v34 = v35 = v36 = v37 = v38 = v39 = v40 = - v41 = v42 = v43 = v44 = v45 = v46 = v47 = v48 = v49 = v50 = 1 - end -end - -i = 0 - -while i<30_000_000 # while loop 1 - i += 1 - m i -end - diff --git a/benchmark/bm_vm1_lvar_set.rb b/benchmark/bm_vm1_lvar_set.rb deleted file mode 100644 index 222e864134..0000000000 --- a/benchmark/bm_vm1_lvar_set.rb +++ /dev/null @@ -1,5 +0,0 @@ -i = 0 -while i<30_000_000 # while loop 1 - i += 1 - a = b = c = d = e = f = g = h = j = k = l = m = n = o = p = q = r = 1 -end diff --git a/benchmark/bm_vm1_neq.rb b/benchmark/bm_vm1_neq.rb deleted file mode 100644 index bbb4ae07a4..0000000000 --- a/benchmark/bm_vm1_neq.rb +++ /dev/null @@ -1,8 +0,0 @@ -i = 0 -obj1 = Object.new -obj2 = Object.new - -while i<30_000_000 # while loop 1 - i += 1 - obj1 != obj2 -end diff --git a/benchmark/bm_vm1_not.rb b/benchmark/bm_vm1_not.rb deleted file mode 100644 index b09ecdcc21..0000000000 --- a/benchmark/bm_vm1_not.rb +++ /dev/null @@ -1,7 +0,0 @@ -i = 0 -obj = Object.new - -while i<30_000_000 # while loop 1 - i += 1 - !obj -end diff --git a/benchmark/bm_vm1_rescue.rb b/benchmark/bm_vm1_rescue.rb deleted file mode 100644 index b0d3e2bdfa..0000000000 --- a/benchmark/bm_vm1_rescue.rb +++ /dev/null @@ -1,7 +0,0 @@ -i = 0 -while i<30_000_000 # while loop 1 - i += 1 - begin - rescue - end -end diff --git a/benchmark/bm_vm1_simplereturn.rb b/benchmark/bm_vm1_simplereturn.rb deleted file mode 100644 index 63f9f21675..0000000000 --- a/benchmark/bm_vm1_simplereturn.rb +++ /dev/null @@ -1,9 +0,0 @@ -def m - return 1 -end -i = 0 -while i<30_000_000 # while loop 1 - i += 1 - m -end - diff --git a/benchmark/bm_vm1_swap.rb b/benchmark/bm_vm1_swap.rb deleted file mode 100644 index 918f8b2112..0000000000 --- a/benchmark/bm_vm1_swap.rb +++ /dev/null @@ -1,8 +0,0 @@ -a = 1 -b = 2 -i = 0 -while i<30_000_000 # while loop 1 - i += 1 - a, b = b, a -end - diff --git a/benchmark/bm_vm1_yield.rb b/benchmark/bm_vm1_yield.rb deleted file mode 100644 index 775597cea6..0000000000 --- a/benchmark/bm_vm1_yield.rb +++ /dev/null @@ -1,10 +0,0 @@ -def m - i = 0 - while i<30_000_000 # while loop 1 - i += 1 - yield - end -end - -m{} - diff --git a/benchmark/bm_vm2_bigarray.rb b/benchmark/bm_vm2_bigarray.rb deleted file mode 100644 index b02509d6a2..0000000000 --- a/benchmark/bm_vm2_bigarray.rb +++ /dev/null @@ -1,106 +0,0 @@ -i = 0 -while i<6_000_000 # benchmark loop 2 - i += 1 - a = [ - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - 1,2,3,4,5,6,7,8,9,10, - ] -end diff --git a/benchmark/bm_vm2_bighash.rb b/benchmark/bm_vm2_bighash.rb deleted file mode 100644 index 5e3f437bb8..0000000000 --- a/benchmark/bm_vm2_bighash.rb +++ /dev/null @@ -1,5 +0,0 @@ -i = 0 -while i<60_000 # benchmark loop 2 - i += 1 - 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,} -end diff --git a/benchmark/bm_vm2_case.rb b/benchmark/bm_vm2_case.rb deleted file mode 100644 index adc6e4df0a..0000000000 --- a/benchmark/bm_vm2_case.rb +++ /dev/null @@ -1,14 +0,0 @@ -i = 0 -while i<6_000_000 # while loop 2 - case :foo - when :bar - raise - when :baz - raise - when :boo - raise - when :foo - i += 1 - end -end - diff --git a/benchmark/bm_vm2_defined_method.rb b/benchmark/bm_vm2_defined_method.rb deleted file mode 100644 index 053ed6c912..0000000000 --- a/benchmark/bm_vm2_defined_method.rb +++ /dev/null @@ -1,9 +0,0 @@ -class Object - define_method(:m){} -end - -i = 0 -while i<6_000_000 # benchmark loop 2 - i += 1 - m; m; m; m; m; m; m; m; -end diff --git a/benchmark/bm_vm2_method_missing.rb b/benchmark/bm_vm2_method_missing.rb deleted file mode 100644 index 2badc73101..0000000000 --- a/benchmark/bm_vm2_method_missing.rb +++ /dev/null @@ -1,12 +0,0 @@ -class C - def method_missing mid - end -end - -obj = C.new - -i = 0 -while i<6_000_000 # benchmark loop 2 - i += 1 - obj.m; obj.m; obj.m; obj.m; obj.m; obj.m; obj.m; obj.m; -end diff --git a/benchmark/bm_vm2_method_with_block.rb b/benchmark/bm_vm2_method_with_block.rb deleted file mode 100644 index b4efb4f520..0000000000 --- a/benchmark/bm_vm2_method_with_block.rb +++ /dev/null @@ -1,9 +0,0 @@ -def m - nil -end - -i = 0 -while i<6_000_000 # benchmark loop 2 - i += 1 - m{}; m{}; m{}; m{}; m{}; m{}; m{}; m{}; -end diff --git a/benchmark/bm_vm2_mutex.rb b/benchmark/bm_vm2_mutex.rb deleted file mode 100644 index 7362f738c5..0000000000 --- a/benchmark/bm_vm2_mutex.rb +++ /dev/null @@ -1,9 +0,0 @@ -require 'thread' - -m = Mutex.new - -i = 0 -while i<6_000_000 # benchmark loop 2 - i += 1 - m.synchronize{} -end diff --git a/benchmark/bm_vm2_poly_method.rb b/benchmark/bm_vm2_poly_method.rb deleted file mode 100644 index c82c0e4bce..0000000000 --- a/benchmark/bm_vm2_poly_method.rb +++ /dev/null @@ -1,20 +0,0 @@ -class C1 - def m - 1 - end -end -class C2 - def m - 2 - end -end - -o1 = C1.new -o2 = C2.new - -i = 0 -while i<6_000_000 # benchmark loop 2 - o = (i % 2 == 0) ? o1 : o2 - o.m; o.m; o.m; o.m; o.m; o.m; o.m; o.m - i += 1 -end diff --git a/benchmark/bm_vm2_poly_method_ov.rb b/benchmark/bm_vm2_poly_method_ov.rb deleted file mode 100644 index aa5fd1dd38..0000000000 --- a/benchmark/bm_vm2_poly_method_ov.rb +++ /dev/null @@ -1,20 +0,0 @@ -class C1 - def m - 1 - end -end -class C2 - def m - 2 - end -end - -o1 = C1.new -o2 = C2.new - -i = 0 -while i<6_000_000 # benchmark loop 2 - o = (i % 2 == 0) ? o1 : o2 -# o.m; o.m; o.m; o.m; o.m; o.m; o.m; o.m - i += 1 -end diff --git a/benchmark/bm_vm2_proc.rb b/benchmark/bm_vm2_proc.rb deleted file mode 100644 index 65e5217371..0000000000 --- a/benchmark/bm_vm2_proc.rb +++ /dev/null @@ -1,14 +0,0 @@ -def m &b - b -end - -pr = m{ - a = 1 -} - -i = 0 -while i<6_000_000 # benchmark loop 2 - i += 1 - pr.call -end - diff --git a/benchmark/bm_vm2_raise1.rb b/benchmark/bm_vm2_raise1.rb deleted file mode 100644 index aa5387987f..0000000000 --- a/benchmark/bm_vm2_raise1.rb +++ /dev/null @@ -1,18 +0,0 @@ -def rec n - if n > 0 - rec n-1 - else - raise - end -end - -i = 0 -while i<6_000_000 # benchmark loop 2 - i += 1 - - begin - rec 1 - rescue - # ignore - end -end diff --git a/benchmark/bm_vm2_raise2.rb b/benchmark/bm_vm2_raise2.rb deleted file mode 100644 index 1f61c63157..0000000000 --- a/benchmark/bm_vm2_raise2.rb +++ /dev/null @@ -1,18 +0,0 @@ -def rec n - if n > 0 - rec n-1 - else - raise - end -end - -i = 0 -while i<6_000_000 # benchmark loop 2 - i += 1 - - begin - rec 10 - rescue - # ignore - end -end diff --git a/benchmark/bm_vm2_send.rb b/benchmark/bm_vm2_send.rb deleted file mode 100644 index 6a3ab6fdab..0000000000 --- a/benchmark/bm_vm2_send.rb +++ /dev/null @@ -1,12 +0,0 @@ -class C - def m - end -end - -o = C.new - -i = 0 -while i<6_000_000 # benchmark loop 2 - i += 1 - o.__send__ :m -end diff --git a/benchmark/bm_vm2_super.rb b/benchmark/bm_vm2_super.rb deleted file mode 100644 index afd8579e7b..0000000000 --- a/benchmark/bm_vm2_super.rb +++ /dev/null @@ -1,20 +0,0 @@ - -class C - def m - 1 - end -end - -class CC < C - def m - super() - end -end - -obj = CC.new - -i = 0 -while i<6_000_000 # benchmark loop 2 - obj.m - i += 1 -end diff --git a/benchmark/bm_vm2_unif1.rb b/benchmark/bm_vm2_unif1.rb deleted file mode 100644 index 1774625942..0000000000 --- a/benchmark/bm_vm2_unif1.rb +++ /dev/null @@ -1,8 +0,0 @@ -i = 0 -def m a, b -end - -while i<6_000_000 # benchmark loop 2 - i += 1 - m 100, 200 -end diff --git a/benchmark/bm_vm2_zsuper.rb b/benchmark/bm_vm2_zsuper.rb deleted file mode 100644 index 2a43e62217..0000000000 --- a/benchmark/bm_vm2_zsuper.rb +++ /dev/null @@ -1,20 +0,0 @@ -i = 0 - -class C - def m a - 1 - end -end - -class CC < C - def m a - super - end -end - -obj = CC.new - -while i<6_000_000 # benchmark loop 2 - obj.m 10 - i += 1 -end diff --git a/benchmark/bm_vm_thread_alive_check1.rb b/benchmark/bm_vm_thread_alive_check1.rb deleted file mode 100644 index c993accdda..0000000000 --- a/benchmark/bm_vm_thread_alive_check1.rb +++ /dev/null @@ -1,6 +0,0 @@ -5_000.times{ - t = Thread.new{} - while t.alive? - Thread.pass - end -} diff --git a/benchmark/bm_vm_thread_pass_flood.rb b/benchmark/bm_vm_thread_pass_flood.rb deleted file mode 100644 index 27157d1a6f..0000000000 --- a/benchmark/bm_vm_thread_pass_flood.rb +++ /dev/null @@ -1,8 +0,0 @@ -1000.times{ - Thread.new{loop{Thread.pass}} -} - -i = 0 -while i<10000 - i += 1 -end 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 new file mode 100644 index 0000000000..655be9d7d8 --- /dev/null +++ b/benchmark/cgi_escape_html.yml @@ -0,0 +1,31 @@ +prelude: | + # frozen_string_literal: true + require 'cgi/escape' +benchmark: + - script: CGI.escapeHTML("") + loop_count: 20000000 + - script: CGI.escapeHTML("abcde") + loop_count: 20000000 + - script: CGI.escapeHTML("abcd<") + loop_count: 20000000 + - script: CGI.escapeHTML("'&\"<>") + loop_count: 5000000 + - prelude: long_no_escape = "abcde" * 300 + script: CGI.escapeHTML(long_no_escape) + loop_count: 1000000 + - prelude: long_all_escape = "'&\"<>" * 10 + script: CGI.escapeHTML(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: 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/complex_float_add.yml b/benchmark/complex_float_add.yml new file mode 100644 index 0000000000..d0150c5e5b --- /dev/null +++ b/benchmark/complex_float_add.yml @@ -0,0 +1,7 @@ +prelude: | + max, min = 1000.0, -1000.0 + a = Complex(rand(max)+min, rand(max)+min) + b = Complex(rand(max)+min, rand(max)+min) +benchmark: + complex_float_add: c = a + b +loop_count: 1000000 diff --git a/benchmark/complex_float_div.yml b/benchmark/complex_float_div.yml new file mode 100644 index 0000000000..b9f5e1d51c --- /dev/null +++ b/benchmark/complex_float_div.yml @@ -0,0 +1,7 @@ +prelude: | + max, min = 1000.0, -1000.0 + a = Complex(rand(max)+min, rand(max)+min) + b = Complex(rand(max)+min, rand(max)+min) +benchmark: + complex_float_div: c = a / b +loop_count: 1000000 diff --git a/benchmark/complex_float_mul.yml b/benchmark/complex_float_mul.yml new file mode 100644 index 0000000000..59b096a6dc --- /dev/null +++ b/benchmark/complex_float_mul.yml @@ -0,0 +1,7 @@ +prelude: | + max, min = 1000.0, -1000.0 + a = Complex(rand(max)+min, rand(max)+min) + b = Complex(rand(max)+min, rand(max)+min) +benchmark: + complex_float_mul: c = a * b +loop_count: 1000000 diff --git a/benchmark/complex_float_new.yml b/benchmark/complex_float_new.yml new file mode 100644 index 0000000000..6fcde3125b --- /dev/null +++ b/benchmark/complex_float_new.yml @@ -0,0 +1,7 @@ +prelude: | + max, min = 1000.0, -1000.0 + a = Complex(rand(max)+min, rand(max)+min) + b = Complex(rand(max)+min, rand(max)+min) +benchmark: + complex_float_new: c = Complex(a, b) +loop_count: 1000000 diff --git a/benchmark/complex_float_power.yml b/benchmark/complex_float_power.yml new file mode 100644 index 0000000000..c40a31ab55 --- /dev/null +++ b/benchmark/complex_float_power.yml @@ -0,0 +1,7 @@ +prelude: | + max, min = 1000.0, -1000.0 + a = Complex(rand(max)+min, rand(max)+min) + b = Complex(rand(max)+min, rand(max)+min) +benchmark: + complex_float_power: c = a ** b +loop_count: 1000000 diff --git a/benchmark/complex_float_sub.yml b/benchmark/complex_float_sub.yml new file mode 100644 index 0000000000..3fafe7cdbe --- /dev/null +++ b/benchmark/complex_float_sub.yml @@ -0,0 +1,7 @@ +prelude: | + max, min = 1000.0, -1000.0 + a = Complex(rand(max)+min, rand(max)+min) + b = Complex(rand(max)+min, rand(max)+min) +benchmark: + complex_float_sub: c = a - b +loop_count: 1000000 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/dir_empty_p.rb b/benchmark/dir_empty_p.rb new file mode 100644 index 0000000000..8329c757cf --- /dev/null +++ b/benchmark/dir_empty_p.rb @@ -0,0 +1,5 @@ +require 'tmpdir' +max = 100_000 +Dir.mktmpdir('bm_dir_empty_p') do |dir| + max.times { Dir.empty?(dir) } +end diff --git a/benchmark/driver.rb b/benchmark/driver.rb deleted file mode 100644 index cbc72cf604..0000000000 --- a/benchmark/driver.rb +++ /dev/null @@ -1,301 +0,0 @@ -# -# Ruby Benchmark driver -# - -first = true - -begin - require 'optparse' -rescue LoadError - if first - first = false - $:.unshift File.join(File.dirname(__FILE__), '../lib') - retry - else - raise - end -end - -require 'benchmark' -require 'pp' - -class BenchmarkDriver - def self.benchmark(opt) - driver = self.new(opt[:execs], opt[:dir], opt) - begin - driver.run - ensure - driver.show_results - end - end - - def output *args - puts(*args) - @output and @output.puts(*args) - end - - def message *args - output(*args) if @verbose - end - - def message_print *args - if @verbose - print(*args) - STDOUT.flush - @output and @output.print(*args) - end - end - - def progress_message *args - unless STDOUT.tty? - STDERR.print(*args) - STDERR.flush - end - end - - def initialize execs, dir, opt = {} - @execs = execs.map{|e| - e.strip! - next if e.empty? - - if /(.+)::(.+)/ =~ e - # ex) ruby-a::/path/to/ruby-a - label = $1.strip - path = $2 - version = `#{path} -v`.chomp - else - path = e - version = label = `#{path} -v`.chomp - end - [path, label, version] - }.compact - - @dir = dir - @repeat = opt[:repeat] || 1 - @repeat = 1 if @repeat < 1 - @pattern = opt[:pattern] || nil - @exclude = opt[:exclude] || nil - @verbose = opt[:quiet] ? false : (opt[:verbose] || false) - @output = opt[:output] ? open(opt[:output], 'w') : nil - @loop_wl1 = @loop_wl2 = nil - @ruby_arg = opt[:ruby_arg] || nil - @opt = opt - - # [[name, [[r-1-1, r-1-2, ...], [r-2-1, r-2-2, ...]]], ...] - @results = [] - - if @verbose - @start_time = Time.now - message @start_time - @execs.each_with_index{|(path, label, version), i| - message "target #{i}: " + (label == version ? "#{label}" : "#{label} (#{version})") + " at \"#{path}\"" - } - end - end - - def adjusted_results name, results - s = nil - results.each_with_index{|e, i| - r = e.min - case name - when /^vm1_/ - if @loop_wl1 - r -= @loop_wl1[i] - r = 0 if r < 0 - s = '*' - end - when /^vm2_/ - if @loop_wl2 - r -= @loop_wl2[i] - r = 0 if r < 0 - s = '*' - end - end - yield r - } - s - end - - def show_results - output - - if @verbose - message '-----------------------------------------------------------' - message 'raw data:' - message - message PP.pp(@results, "", 79) - message - message "Elapsed time: #{Time.now - @start_time} (sec)" - end - - output '-----------------------------------------------------------' - output 'benchmark results:' - - if @verbose and @repeat > 1 - output "minimum results in each #{@repeat} measurements." - end - - output "Execution time (sec)" - output "name\t#{@execs.map{|(_, v)| v}.join("\t")}" - @results.each{|v, result| - rets = [] - s = adjusted_results(v, result){|r| - rets << sprintf("%.3f", r) - } - output "#{v}#{s}\t#{rets.join("\t")}" - } - - if @execs.size > 1 - output - output "Speedup ratio: compare with the result of `#{@execs[0][1]}' (greater is better)" - output "name\t#{@execs[1..-1].map{|(_, v)| v}.join("\t")}" - @results.each{|v, result| - rets = [] - first_value = nil - s = adjusted_results(v, result){|r| - if first_value - if r == 0 - rets << "Error" - else - rets << sprintf("%.3f", first_value/r) - end - else - first_value = r - end - } - output "#{v}#{s}\t#{rets.join("\t")}" - } - end - - if @opt[:output] - output - output "Log file: #{@opt[:output]}" - end - end - - def files - flag = {} - @files = Dir.glob(File.join(@dir, 'bm*.rb')).map{|file| - next if @pattern && /#{@pattern}/ !~ File.basename(file) - next if @exclude && /#{@exclude}/ =~ File.basename(file) - case file - when /bm_(vm[12])_/, /bm_loop_(whileloop2?).rb/ - flag[$1] = true - end - file - }.compact - - if flag['vm1'] && !flag['whileloop'] - @files << File.join(@dir, 'bm_loop_whileloop.rb') - elsif flag['vm2'] && !flag['whileloop2'] - @files << File.join(@dir, 'bm_loop_whileloop2.rb') - end - - @files.sort! - progress_message "total: #{@files.size * @repeat} trial(s) (#{@repeat} trial(s) for #{@files.size} benchmark(s))\n" - @files - end - - def run - files.each_with_index{|file, i| - @i = i - r = measure_file(file) - - if /bm_loop_whileloop.rb/ =~ file - @loop_wl1 = r[1].map{|e| e.min} - elsif /bm_loop_whileloop2.rb/ =~ file - @loop_wl2 = r[1].map{|e| e.min} - end - } - end - - def measure_file file - name = File.basename(file, '.rb').sub(/^bm_/, '') - prepare_file = File.join(File.dirname(file), "prepare_#{name}.rb") - load prepare_file if FileTest.exist?(prepare_file) - - if @verbose - output - output '-----------------------------------------------------------' - output name - output - output File.read(file) - output - end - - result = [name] - result << @execs.map{|(e, v)| - (0...@repeat).map{ - message_print "#{v}\t" - progress_message '.' - - m = measure(e, file) - message "#{m}" - m - } - } - @results << result - result - end - - def measure executable, file - cmd = "#{executable} #{@ruby_arg} #{file}" - - m = Benchmark.measure{ - system(cmd, out: File::NULL) - } - - if $? != 0 - output "\`#{cmd}\' exited with abnormal status (#{$?})" - 0 - else - m.real - end - end -end - -if __FILE__ == $0 - opt = { - :execs => [], - :dir => File.dirname(__FILE__), - :repeat => 1, - :output => "bmlog-#{Time.now.strftime('%Y%m%d-%H%M%S')}.#{$$}", - } - - parser = OptionParser.new{|o| - o.on('-e', '--executables [EXECS]', - "Specify benchmark one or more targets (e1::path1; e2::path2; e3::path3;...)"){|e| - e.split(/;/).each{|path| - opt[:execs] << path - } - } - o.on('-d', '--directory [DIRECTORY]', "Benchmark suites directory"){|d| - opt[:dir] = d - } - o.on('-p', '--pattern [PATTERN]', "Benchmark name pattern"){|p| - opt[:pattern] = p - } - o.on('-x', '--exclude [PATTERN]', "Benchmark exclude pattern"){|e| - opt[:exclude] = e - } - o.on('-r', '--repeat-count [NUM]', "Repeat count"){|n| - opt[:repeat] = n.to_i - } - o.on('-o', '--output-file [FILE]', "Output file"){|f| - opt[:output] = f - } - o.on('--ruby-arg [ARG]', "Optional argument for ruby"){|a| - opt[:ruby_arg] = a - } - o.on('-q', '--quiet', "Run without notify information except result table."){|q| - opt[:quiet] = q - } - o.on('-v', '--verbose'){|v| - opt[:verbose] = v - } - } - - parser.parse!(ARGV) - BenchmarkDriver.benchmark(opt) -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_grep_v_100.rb b/benchmark/enum_lazy_grep_v_100.rb new file mode 100644 index 0000000000..8832392e65 --- /dev/null +++ b/benchmark/enum_lazy_grep_v_100.rb @@ -0,0 +1,4 @@ +grep_data = (1..10).to_a * 1000 +N = 100 +enum = grep_data.lazy.grep_v(->(i){i == 0}).grep_v(->(i){i == 0}) +N.times {enum.each {}} diff --git a/benchmark/enum_lazy_grep_v_20.rb b/benchmark/enum_lazy_grep_v_20.rb new file mode 100644 index 0000000000..329509fa8f --- /dev/null +++ b/benchmark/enum_lazy_grep_v_20.rb @@ -0,0 +1,4 @@ +grep_data = (1..10).to_a * 1000 +N = 100 +enum = grep_data.lazy.grep_v(->(i){i > 2}).grep_v(->(i){i > 2}) +N.times {enum.each {}} diff --git a/benchmark/enum_lazy_grep_v_50.rb b/benchmark/enum_lazy_grep_v_50.rb new file mode 100644 index 0000000000..02ea4d4e71 --- /dev/null +++ b/benchmark/enum_lazy_grep_v_50.rb @@ -0,0 +1,4 @@ +grep_data = (1..10).to_a * 1000 +N = 100 +enum = grep_data.lazy.grep_v(->(i){i > 5}).grep_v(->(i){i > 5}) +N.times {enum.each {}} diff --git a/benchmark/enum_lazy_uniq_100.rb b/benchmark/enum_lazy_uniq_100.rb new file mode 100644 index 0000000000..2e6434d9c4 --- /dev/null +++ b/benchmark/enum_lazy_uniq_100.rb @@ -0,0 +1,4 @@ +uniq_data = (1..10_000).to_a +N = 100 +enum = uniq_data.lazy.uniq {|i| i % 10000}.uniq {|i| i % 10000} +N.times {enum.each {}} diff --git a/benchmark/enum_lazy_uniq_20.rb b/benchmark/enum_lazy_uniq_20.rb new file mode 100644 index 0000000000..75e6398fee --- /dev/null +++ b/benchmark/enum_lazy_uniq_20.rb @@ -0,0 +1,4 @@ +uniq_data = (1..10_000).to_a +N = 100 +enum = uniq_data.lazy.uniq {|i| i % 2000}.uniq {|i| i % 2000} +N.times {enum.each {}} diff --git a/benchmark/enum_lazy_uniq_50.rb b/benchmark/enum_lazy_uniq_50.rb new file mode 100644 index 0000000000..59a39b78ff --- /dev/null +++ b/benchmark/enum_lazy_uniq_50.rb @@ -0,0 +1,4 @@ +uniq_data = (1..10_000).to_a +N = 100 +enum = uniq_data.lazy.uniq {|i| i % 5000}.uniq {|i| i % 5000} +N.times {enum.each {}} 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/erb_render.yml b/benchmark/erb_render.yml new file mode 100644 index 0000000000..15f6c3880b --- /dev/null +++ b/benchmark/erb_render.yml @@ -0,0 +1,24 @@ +prelude: | + require 'erb' + + data = <<erb + <html> + <head> <%= title %> </head> + <body> + <h1> <%= title %> </h1> + <p> + <%= content %> + </p> + </body> + </html> + erb + + title = "hello world!" + content = "hello world!\n" * 10 + + src = "def self.render(title, content); #{ERB.new(data).src}; end" + mod = Module.new + mod.instance_eval(src, "(ERB)") +benchmark: + erb_render: mod.render(title, content) +loop_count: 1500000 diff --git a/benchmark/fiber_chain.yml b/benchmark/fiber_chain.yml new file mode 100644 index 0000000000..a36c759f8e --- /dev/null +++ b/benchmark/fiber_chain.yml @@ -0,0 +1,36 @@ +prelude: | + def make_link(previous) + Fiber.new do + while message = previous.resume + Fiber.yield(message) + end + end + end + + def make_chain(length = 1000, &block) + chain = Fiber.new(&block) + + (length - 1).times do + chain = make_link(chain) + end + + return chain + end + + message = "Hello World!" + + chain = make_chain do + while true + Fiber.yield(message) + end + end +benchmark: + make_chain: | + make_chain(100) do + while true + Fiber.yield(message) + end + end + resume_chain: | + chain.resume +loop_count: 5000 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_chmod.rb b/benchmark/file_chmod.rb new file mode 100644 index 0000000000..1cd4760c9d --- /dev/null +++ b/benchmark/file_chmod.rb @@ -0,0 +1,9 @@ +# chmod file +require 'tempfile' +max = 200_000 +tmp = Tempfile.new('chmod') +path = tmp.path +max.times do + File.chmod(0777, path) +end +tmp.close! diff --git a/benchmark/file_dirname.yml b/benchmark/file_dirname.yml new file mode 100644 index 0000000000..43a81c9371 --- /dev/null +++ b/benchmark/file_dirname.yml @@ -0,0 +1,6 @@ +prelude: | + # frozen_string_literal: true +benchmark: + long: File.dirname("/Users/george/src/github.com/ruby/ruby/benchmark/file_dirname.yml") + short: File.dirname("foo/bar") + n_4: File.dirname("/Users/george/src/github.com/ruby/ruby/benchmark/file_dirname.yml", 4) diff --git a/benchmark/file_extname.yml b/benchmark/file_extname.yml new file mode 100644 index 0000000000..fb16e55840 --- /dev/null +++ b/benchmark/file_extname.yml @@ -0,0 +1,6 @@ +prelude: | + # frozen_string_literal: true +benchmark: + long: File.extname("/Users/george/src/github.com/ruby/ruby/benchmark/file_dirname.yml") + long_name: File.extname("Users_george_src_github.com_ruby_ruby_benchmark_file_dirname.yml") + short: File.extname("foo/bar") 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/file_rename.rb b/benchmark/file_rename.rb new file mode 100644 index 0000000000..bbb44aebac --- /dev/null +++ b/benchmark/file_rename.rb @@ -0,0 +1,11 @@ +# rename file +require 'tempfile' + +max = 100_000 +tmp = [ Tempfile.new('rename-a'), Tempfile.new('rename-b') ] +a, b = tmp.map { |x| x.path } +tmp.each { |t| t.close } # Windows can't rename files without closing them +max.times do + File.rename(a, b) + File.rename(b, a) +end 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/gc/aobench.rb b/benchmark/gc/aobench.rb new file mode 100644 index 0000000000..275f58b924 --- /dev/null +++ b/benchmark/gc/aobench.rb @@ -0,0 +1 @@ +require_relative '../app_aobench' diff --git a/benchmark/gc/binary_trees.rb b/benchmark/gc/binary_trees.rb new file mode 100644 index 0000000000..83347cdd20 --- /dev/null +++ b/benchmark/gc/binary_trees.rb @@ -0,0 +1 @@ +require_relative '../so_binary_trees' diff --git a/benchmark/gc/gcbench.rb b/benchmark/gc/gcbench.rb new file mode 100644 index 0000000000..23d0b91c6c --- /dev/null +++ b/benchmark/gc/gcbench.rb @@ -0,0 +1,57 @@ +require 'benchmark' +require 'pp' +require 'optparse' + +$list = true +$gcprof = false + +opt = OptionParser.new +opt.on('-q'){$list = false} +opt.on('-d'){$gcprof = false} +opt.on('-p'){$gcprof = true} +opt.parse!(ARGV) + +script = File.join(File.dirname(__FILE__), ARGV.shift) +script += '.rb' unless FileTest.exist?(script) +raise "#{script} not found" unless FileTest.exist?(script) + +puts "Script: #{script}" + +if $gcprof + GC::Profiler.enable +end + +tms = Benchmark.measure{|x| + load script +} + +gc_time = 0 + +if $gcprof + gc_time = GC::Profiler.total_time + GC::Profiler.report if $list and RUBY_VERSION >= '2.0.0' # before 1.9.3, report() may run infinite loop + GC::Profiler.disable +end + +pp GC.stat + +puts "#{RUBY_DESCRIPTION} #{GC::OPTS.inspect}" if defined?(GC::OPTS) + +desc = "#{RUBY_VERSION}#{RUBY_PATCHLEVEL >= 0 ? "p#{RUBY_PATCHLEVEL}" : "dev"}" +name = File.basename(script, '.rb') + +puts +puts script +puts Benchmark::CAPTION +puts tms +puts "GC total time (sec): #{gc_time}" + +# show High-Water Mark on Linux +if File.exist?('/proc/self/status') && /VmHWM:\s*(\d+.+)/ =~ File.read('/proc/self/status') + puts + puts "VmHWM: #{$1.chomp}" +end + +puts +puts "Summary of #{name} on #{desc}\t#{tms.real}\t#{gc_time}\t#{GC.count}" +puts " (real time in sec, GC time in sec, GC count)" diff --git a/benchmark/gc/hash1.rb b/benchmark/gc/hash1.rb new file mode 100644 index 0000000000..cb030d458d --- /dev/null +++ b/benchmark/gc/hash1.rb @@ -0,0 +1,11 @@ +value = 0.01 +h = {} +n = 50_000 + +1.upto(n){|i| + h["%020d" % i] = "v-#{i}" +} + +(n * 1_000).times{ + '' +} diff --git a/benchmark/gc/hash2.rb b/benchmark/gc/hash2.rb new file mode 100644 index 0000000000..e8c943fb21 --- /dev/null +++ b/benchmark/gc/hash2.rb @@ -0,0 +1,7 @@ +value = 0.01 +h = {} +n = 4*(10**6) + +1.upto(n){|i| + h["%020d" % i] = value * i +} diff --git a/benchmark/gc/null.rb b/benchmark/gc/null.rb new file mode 100644 index 0000000000..c05a79f561 --- /dev/null +++ b/benchmark/gc/null.rb @@ -0,0 +1 @@ +# null diff --git a/benchmark/gc/pentomino.rb b/benchmark/gc/pentomino.rb new file mode 100644 index 0000000000..8ebdff7d1d --- /dev/null +++ b/benchmark/gc/pentomino.rb @@ -0,0 +1 @@ +require_relative '../app_pentomino' diff --git a/benchmark/gc/rdoc.rb b/benchmark/gc/rdoc.rb new file mode 100644 index 0000000000..14c89f5611 --- /dev/null +++ b/benchmark/gc/rdoc.rb @@ -0,0 +1,13 @@ +require 'rdoc/rdoc' +require 'tmpdir' + +srcdir = File.expand_path('../..', __dir__) + +Dir.mktmpdir('rdocbench-'){|d| + dir = File.join(d, 'rdocbench') + args = %W(--root #{srcdir} --page-dir #{srcdir}/doc --encoding=UTF-8 --no-force-update --all --ri --debug --quiet #{srcdir}) + args << '--op' << dir + + r = RDoc::RDoc.new + r.document args +} diff --git a/benchmark/gc/redblack.rb b/benchmark/gc/redblack.rb new file mode 100644 index 0000000000..c66290140a --- /dev/null +++ b/benchmark/gc/redblack.rb @@ -0,0 +1,366 @@ +# This benchmark is imported from https://github.com/jruby/rubybench/blob/master/time/bench_red_black.rb +# License is License is Apache-2 + +require 'benchmark' + +# Algorithm based on "Introduction to Algorithms" by Cormen and others +class RedBlackTree + class Node + attr_accessor :color + attr_accessor :key + attr_accessor :left + attr_accessor :right + attr_accessor :parent + + RED = :red + BLACK = :black + COLORS = [RED, BLACK].freeze + + def initialize(key, color = RED) + raise ArgumentError, "Bad value for color parameter" unless COLORS.include?(color) + @color = color + @key = key + @left = @right = @parent = NilNode.instance + end + + def black? + return color == BLACK + end + + def red? + return color == RED + end + end + + class NilNode < Node + class << self + private :new + + # it's not thread safe + def instance + @instance ||= begin + def instance + return @instance + end + + new + end + end + end + + def initialize + self.color = BLACK + self.key = 0 + self.left = nil + self.right = nil + self.parent = nil + end + + def nil? + return true + end + end + + include Enumerable + + attr_accessor :root + attr_accessor :size + + def initialize + self.root = NilNode.instance + self.size = 0 + end + + def add(key) + insert(Node.new(key)) + end + + def insert(x) + insert_helper(x) + + x.color = Node::RED + while x != root && x.parent.color == Node::RED + if x.parent == x.parent.parent.left + y = x.parent.parent.right + if !y.nil? && y.color == Node::RED + x.parent.color = Node::BLACK + y.color = Node::BLACK + x.parent.parent.color = Node::RED + x = x.parent.parent + else + if x == x.parent.right + x = x.parent + left_rotate(x) + end + x.parent.color = Node::BLACK + x.parent.parent.color = Node::RED + right_rotate(x.parent.parent) + end + else + y = x.parent.parent.left + if !y.nil? && y.color == Node::RED + x.parent.color = Node::BLACK + y.color = Node::BLACK + x.parent.parent.color = Node::RED + x = x.parent.parent + else + if x == x.parent.left + x = x.parent + right_rotate(x) + end + x.parent.color = Node::BLACK + x.parent.parent.color = Node::RED + left_rotate(x.parent.parent) + end + end + end + root.color = Node::BLACK + end + + alias << insert + + def delete(z) + y = (z.left.nil? || z.right.nil?) ? z : successor(z) + x = y.left.nil? ? y.right : y.left + x.parent = y.parent + + if y.parent.nil? + self.root = x + else + if y == y.parent.left + y.parent.left = x + else + y.parent.right = x + end + end + + z.key = y.key if y != z + + if y.color == Node::BLACK + delete_fixup(x) + end + + self.size -= 1 + return y + end + + def minimum(x = root) + while !x.left.nil? + x = x.left + end + return x + end + + def maximum(x = root) + while !x.right.nil? + x = x.right + end + return x + end + + def successor(x) + if !x.right.nil? + return minimum(x.right) + end + y = x.parent + while !y.nil? && x == y.right + x = y + y = y.parent + end + return y + end + + def predecessor(x) + if !x.left.nil? + return maximum(x.left) + end + y = x.parent + while !y.nil? && x == y.left + x = y + y = y.parent + end + return y + end + + def inorder_walk(x = root) + x = self.minimum + while !x.nil? + yield x.key + x = successor(x) + end + end + + alias each inorder_walk + + def reverse_inorder_walk(x = root) + x = self.maximum + while !x.nil? + yield x.key + x = predecessor(x) + end + end + + alias reverse_each reverse_inorder_walk + + def search(key, x = root) + while !x.nil? && x.key != key + key < x.key ? x = x.left : x = x.right + end + return x + end + + def empty? + return self.root.nil? + end + + def black_height(x = root) + height = 0 + while !x.nil? + x = x.left + height +=1 if x.nil? || x.black? + end + return height + end + +private + + def left_rotate(x) + raise "x.right is nil!" if x.right.nil? + y = x.right + x.right = y.left + y.left.parent = x if !y.left.nil? + y.parent = x.parent + if x.parent.nil? + self.root = y + else + if x == x.parent.left + x.parent.left = y + else + x.parent.right = y + end + end + y.left = x + x.parent = y + end + + def right_rotate(x) + raise "x.left is nil!" if x.left.nil? + y = x.left + x.left = y.right + y.right.parent = x if !y.right.nil? + y.parent = x.parent + if x.parent.nil? + self.root = y + else + if x == x.parent.left + x.parent.left = y + else + x.parent.right = y + end + end + y.right = x + x.parent = y + end + + def insert_helper(z) + y = NilNode.instance + x = root + while !x.nil? + y = x + z.key < x.key ? x = x.left : x = x.right + end + z.parent = y + if y.nil? + self.root = z + else + z.key < y.key ? y.left = z : y.right = z + end + self.size += 1 + end + + def delete_fixup(x) + while x != root && x.color == Node::BLACK + if x == x.parent.left + w = x.parent.right + if w.color == Node::RED + w.color = Node::BLACK + x.parent.color = Node::RED + left_rotate(x.parent) + w = x.parent.right + end + if w.left.color == Node::BLACK && w.right.color == Node::BLACK + w.color = Node::RED + x = x.parent + else + if w.right.color == Node::BLACK + w.left.color = Node::BLACK + w.color = Node::RED + right_rotate(w) + w = x.parent.right + end + w.color = x.parent.color + x.parent.color = Node::BLACK + w.right.color = Node::BLACK + left_rotate(x.parent) + x = root + end + else + w = x.parent.left + if w.color == Node::RED + w.color = Node::BLACK + x.parent.color = Node::RED + right_rotate(x.parent) + w = x.parent.left + end + if w.right.color == Node::BLACK && w.left.color == Node::BLACK + w.color = Node::RED + x = x.parent + else + if w.left.color == Node::BLACK + w.right.color = Node::BLACK + w.color = Node::RED + left_rotate(w) + w = x.parent.left + end + w.color = x.parent.color + x.parent.color = Node::BLACK + w.left.color = Node::BLACK + right_rotate(x.parent) + x = root + end + end + end + x.color = Node::BLACK + end +end + +def rbt_bm + n = 100_000 + a1 = []; n.times { a1 << rand(999_999) } + a2 = []; n.times { a2 << rand(999_999) } + + start = Time.now + + tree = RedBlackTree.new + + n.times {|i| tree.add(i) } + n.times { tree.delete(tree.root) } + + tree = RedBlackTree.new + a1.each {|e| tree.add(e) } + a2.each {|e| tree.search(e) } + tree.inorder_walk {|key| key + 1 } + tree.reverse_inorder_walk {|key| key + 1 } + n.times { tree.minimum } + n.times { tree.maximum } + + return Time.now - start +end + +N = (ARGV[0] || 10).to_i + +N.times do + # puts rbt_bm.to_f + rbt_bm.to_f + # puts "GC.count = #{GC.count}" if GC.respond_to?(:count) +end diff --git a/benchmark/gc/ring.rb b/benchmark/gc/ring.rb new file mode 100644 index 0000000000..be2c7b7250 --- /dev/null +++ b/benchmark/gc/ring.rb @@ -0,0 +1,29 @@ +# create many old objects + +max = 30_000_000 + +class Ring + attr_reader :next_ring + def initialize n = nil + @next_ring = n + end + + + def size + s = 1 + ring = self + while ring.next_ring + s += 1 + ring = ring.next_ring + end + s + end +end + +ring = Ring.new + +max.times{ + ring = Ring.new(ring) +} + +# p ring.size 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_dsym.rb b/benchmark/hash_aref_dsym.rb new file mode 100644 index 0000000000..af4f8c36d4 --- /dev/null +++ b/benchmark/hash_aref_dsym.rb @@ -0,0 +1,4 @@ +h = {} +syms = ('a'..'z').map { |s| s.to_sym } +syms.each { |s| h[s] = 1 } +200_000.times { syms.each { |s| h[s] } } diff --git a/benchmark/hash_aref_dsym_long.rb b/benchmark/hash_aref_dsym_long.rb new file mode 100644 index 0000000000..9d7759379e --- /dev/null +++ b/benchmark/hash_aref_dsym_long.rb @@ -0,0 +1,21 @@ +# [ruby-core:70129] [Bug #11396] +collection_size = 200000 +sample_size = 10000 + +values = (1..collection_size).to_a.map do |x| + "THIS IS A LONGER STRING THAT IS ALSO UNIQUE #{x}" +end + +symbol_hash = {} + +values.each do |x| + symbol_hash[x.to_sym] = 1 +end + +# use the same samples each time to minimize deviations +rng = Random.new(0) +symbol_sample_array = values.sample(sample_size, random: rng).map(&:to_sym) + +3000.times do + symbol_sample_array.each { |x| symbol_hash[x] } +end diff --git a/benchmark/hash_aref_fix.rb b/benchmark/hash_aref_fix.rb new file mode 100644 index 0000000000..1346890582 --- /dev/null +++ b/benchmark/hash_aref_fix.rb @@ -0,0 +1,4 @@ +h = {} +nums = (1..26).to_a +nums.each { |i| h[i] = i } +200_000.times { nums.each { |s| h[s] } } diff --git a/benchmark/hash_aref_flo.rb b/benchmark/hash_aref_flo.rb new file mode 100644 index 0000000000..2217274c82 --- /dev/null +++ b/benchmark/hash_aref_flo.rb @@ -0,0 +1,4 @@ +h = {} +strs = [*1..10000].map! {|i| i.fdiv(10)} +strs.each { |s| h[s] = s } +50.times { strs.each { |s| h[s] } } diff --git a/benchmark/hash_aref_miss.rb b/benchmark/hash_aref_miss.rb new file mode 100644 index 0000000000..b0913dd4bb --- /dev/null +++ b/benchmark/hash_aref_miss.rb @@ -0,0 +1,5 @@ +h = {} +strs = ('a'..'z').to_a.map!(&:freeze) +strs.each { |s| h[s] = s } +strs = ('A'..'Z').to_a +200_000.times { strs.each { |s| h[s] } } diff --git a/benchmark/hash_aref_str.rb b/benchmark/hash_aref_str.rb new file mode 100644 index 0000000000..19439b061b --- /dev/null +++ b/benchmark/hash_aref_str.rb @@ -0,0 +1,4 @@ +h = {} +strs = ('a'..'z').to_a.map!(&:freeze) +strs.each { |s| h[s] = s } +200_000.times { strs.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_aref_sym.rb b/benchmark/hash_aref_sym.rb new file mode 100644 index 0000000000..f75d163fe6 --- /dev/null +++ b/benchmark/hash_aref_sym.rb @@ -0,0 +1,9 @@ +h = {} +syms = ('a'..'z').to_a +begin + syms = eval("%i[#{syms.join(' ')}]") +rescue SyntaxError # <= 1.9.3 + syms.map!(&:to_sym) +end +syms.each { |s| h[s] = s } +200_000.times { syms.each { |s| h[s] } } diff --git a/benchmark/hash_aref_sym_long.rb b/benchmark/hash_aref_sym_long.rb new file mode 100644 index 0000000000..9dab8df7be --- /dev/null +++ b/benchmark/hash_aref_sym_long.rb @@ -0,0 +1,13 @@ +h = {} +syms = %w[puts warn syswrite write stat bacon lettuce tomato +some symbols in this array may already be interned others should not be +hash browns make good breakfast but not cooked using prime numbers +shift for division entries delete_if keys exist? +] +begin + syms = eval("%i[#{syms.join(' ')}]") +rescue SyntaxError # <= 1.9.3 + syms.map!(&:to_sym) +end +syms.each { |s| h[s] = s } +200_000.times { syms.each { |s| h[s] } } 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_flatten.rb b/benchmark/hash_flatten.rb new file mode 100644 index 0000000000..e944aae9f2 --- /dev/null +++ b/benchmark/hash_flatten.rb @@ -0,0 +1,9 @@ +h = {} + +10000.times do |i| + h[i] = nil +end + +1000.times do + h.flatten +end diff --git a/benchmark/hash_ident_flo.rb b/benchmark/hash_ident_flo.rb new file mode 100644 index 0000000000..0c7edfed3e --- /dev/null +++ b/benchmark/hash_ident_flo.rb @@ -0,0 +1,4 @@ +h = {}.compare_by_identity +strs = (1..10000).to_a.map!(&:to_f) +strs.each { |s| h[s] = s } +50.times { strs.each { |s| h[s] } } diff --git a/benchmark/hash_ident_num.rb b/benchmark/hash_ident_num.rb new file mode 100644 index 0000000000..b226736c6f --- /dev/null +++ b/benchmark/hash_ident_num.rb @@ -0,0 +1,4 @@ +h = {}.compare_by_identity +nums = (1..26).to_a +nums.each { |n| h[n] = n } +200_000.times { nums.each { |n| h[n] } } diff --git a/benchmark/hash_ident_obj.rb b/benchmark/hash_ident_obj.rb new file mode 100644 index 0000000000..4b3b58edec --- /dev/null +++ b/benchmark/hash_ident_obj.rb @@ -0,0 +1,4 @@ +h = {}.compare_by_identity +objs = 26.times.map { Object.new } +objs.each { |o| h[o] = o } +200_000.times { objs.each { |o| h[o] } } diff --git a/benchmark/hash_ident_str.rb b/benchmark/hash_ident_str.rb new file mode 100644 index 0000000000..8582b38e31 --- /dev/null +++ b/benchmark/hash_ident_str.rb @@ -0,0 +1,4 @@ +h = {}.compare_by_identity +strs = ('a'..'z').to_a +strs.each { |s| h[s] = s } +200_000.times { strs.each { |s| h[s] } } diff --git a/benchmark/hash_ident_sym.rb b/benchmark/hash_ident_sym.rb new file mode 100644 index 0000000000..4c81e3d28e --- /dev/null +++ b/benchmark/hash_ident_sym.rb @@ -0,0 +1,4 @@ +h = {}.compare_by_identity +syms = ('a'..'z').to_a.map(&:to_sym) +syms.each { |s| h[s] = s } +200_000.times { syms.each { |s| h[s] } } 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_keys.rb b/benchmark/hash_keys.rb new file mode 100644 index 0000000000..6863cd01f9 --- /dev/null +++ b/benchmark/hash_keys.rb @@ -0,0 +1,9 @@ +h = {} + +10000.times do |i| + h[i] = nil +end + +5000.times do + h.keys +end diff --git a/benchmark/hash_literal_small2.rb b/benchmark/hash_literal_small2.rb new file mode 100644 index 0000000000..c188529260 --- /dev/null +++ b/benchmark/hash_literal_small2.rb @@ -0,0 +1,3 @@ +# frozen_string_literal: true + +1_000_000.times.map { { "foo" => "bar", "bar" => "baz" } } diff --git a/benchmark/hash_literal_small4.rb b/benchmark/hash_literal_small4.rb new file mode 100644 index 0000000000..739f71b5b0 --- /dev/null +++ b/benchmark/hash_literal_small4.rb @@ -0,0 +1,3 @@ +# frozen_string_literal: true + +1_000_000.times.map { { "foo" => "bar", "bar" => "baz", "baz" => "lol", "lol" => "lgtm" } } diff --git a/benchmark/hash_literal_small8.rb b/benchmark/hash_literal_small8.rb new file mode 100644 index 0000000000..53d80af535 --- /dev/null +++ b/benchmark/hash_literal_small8.rb @@ -0,0 +1,3 @@ +# frozen_string_literal: true + +1_000_000.times.map { { "foo" => "bar", "bar" => "baz", "baz" => "lol", "lol" => "lgtm", "lgtm" => "nope", "nope" => "ok", "ok" => "again", "again" => "wait" } } diff --git a/benchmark/hash_long.rb b/benchmark/hash_long.rb new file mode 100644 index 0000000000..03d9109602 --- /dev/null +++ b/benchmark/hash_long.rb @@ -0,0 +1,4 @@ +k1 = "Ping Pong Ping Pong Ping Pong Ping Pong Ping Pong Ping Pong Ping Pong Ping Pong Ping Pong Ping Pong"; +k2 = "Pong Ping Pong Ping Pong Ping Pong Ping Pong Ping Pong Ping Pong Ping Pong Ping Pong Ping Pong Ping"; +h = {k1 => 0, k2 => 0}; +3000000.times{|i| k = i % 2 ? k2 : k1; h [k] = h[k] + 1} 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/hash_shift.rb b/benchmark/hash_shift.rb new file mode 100644 index 0000000000..a645671a5b --- /dev/null +++ b/benchmark/hash_shift.rb @@ -0,0 +1,10 @@ +h = {} + +10000.times do |i| + h[i] = nil +end + +50000.times do + k, v = h.shift + h[k] = v +end diff --git a/benchmark/hash_shift_u16.rb b/benchmark/hash_shift_u16.rb new file mode 100644 index 0000000000..ec800d0342 --- /dev/null +++ b/benchmark/hash_shift_u16.rb @@ -0,0 +1,10 @@ +h = {} + +(16384..65536).each do |i| + h[i] = nil +end + +300000.times do + k, v = h.shift + h[k] = v +end diff --git a/benchmark/hash_shift_u24.rb b/benchmark/hash_shift_u24.rb new file mode 100644 index 0000000000..de4e0fa696 --- /dev/null +++ b/benchmark/hash_shift_u24.rb @@ -0,0 +1,10 @@ +h = {} + +(0xff4000..0xffffff).each do |i| + h[i] = nil +end + +300000.times do + k, v = h.shift + h[k] = v +end diff --git a/benchmark/hash_shift_u32.rb b/benchmark/hash_shift_u32.rb new file mode 100644 index 0000000000..656aa55583 --- /dev/null +++ b/benchmark/hash_shift_u32.rb @@ -0,0 +1,10 @@ +h = {} + +(0xffff4000..0xffffffff).each do |i| + h[i] = nil +end + +300000.times do + k, v = h.shift + h[k] = v +end diff --git a/benchmark/hash_small2.rb b/benchmark/hash_small2.rb new file mode 100644 index 0000000000..45485d9c71 --- /dev/null +++ b/benchmark/hash_small2.rb @@ -0,0 +1 @@ +1000000.times.map{|i| a={}; 2.times{|j| a[j]=j}; a} diff --git a/benchmark/hash_small4.rb b/benchmark/hash_small4.rb new file mode 100644 index 0000000000..acd4084334 --- /dev/null +++ b/benchmark/hash_small4.rb @@ -0,0 +1 @@ +1000000.times.map{|i| a={}; 4.times{|j| a[j]=j}; a} diff --git a/benchmark/hash_small8.rb b/benchmark/hash_small8.rb new file mode 100644 index 0000000000..9cffcc91b6 --- /dev/null +++ b/benchmark/hash_small8.rb @@ -0,0 +1 @@ +1000000.times.map{|i| a={}; 8.times{|j| a[j]=j}; a} diff --git a/benchmark/hash_to_proc.rb b/benchmark/hash_to_proc.rb new file mode 100644 index 0000000000..2b675bf509 --- /dev/null +++ b/benchmark/hash_to_proc.rb @@ -0,0 +1,9 @@ +h = {} + +10000.times do |i| + h[i] = nil +end + +5000.times do |i| + [i].map(&h) +end diff --git a/benchmark/hash_values.rb b/benchmark/hash_values.rb new file mode 100644 index 0000000000..069441302f --- /dev/null +++ b/benchmark/hash_values.rb @@ -0,0 +1,9 @@ +h = {} + +10000.times do |i| + h[i] = nil +end + +5000.times do + h.values +end diff --git a/benchmark/int_quo.rb b/benchmark/int_quo.rb new file mode 100644 index 0000000000..e22a3f8c30 --- /dev/null +++ b/benchmark/int_quo.rb @@ -0,0 +1 @@ +5000000.times { 42.quo(3) } 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_copy_stream_write.rb b/benchmark/io_copy_stream_write.rb new file mode 100644 index 0000000000..3fd87250a4 --- /dev/null +++ b/benchmark/io_copy_stream_write.rb @@ -0,0 +1,24 @@ +# The goal of this is to use a synthetic (non-IO) reader +# to trigger the read/write loop of IO.copy_stream, +# bypassing in-kernel mechanisms like sendfile for zero copy, +# so we wrap the /dev/zero IO object: + +class Zero + def initialize + @n = 100000 + @in = File.open('/dev/zero', 'rb') + end + + def read(len, buf) + return if (@n -= 1) == 0 + @in.read(len, buf) + end +end + +begin + src = Zero.new + dst = File.open(IO::NULL, 'wb') + n = IO.copy_stream(src, dst) +rescue Errno::ENOENT + # not *nix +end if IO.respond_to?(:copy_stream) && IO.const_defined?(:NULL) diff --git a/benchmark/io_copy_stream_write_socket.rb b/benchmark/io_copy_stream_write_socket.rb new file mode 100644 index 0000000000..11f369bd0d --- /dev/null +++ b/benchmark/io_copy_stream_write_socket.rb @@ -0,0 +1,35 @@ +# The goal of this is to use a synthetic (non-IO) reader +# to trigger the read/write loop of IO.copy_stream, +# bypassing in-kernel mechanisms like sendfile for zero copy, +# so we wrap the /dev/zero IO object: +class Zero + def initialize + @n = 100000 + @in = File.open('/dev/zero', 'rb') + end + + def read(len, buf) + return if (@n -= 1) == 0 + @in.read(len, buf) + end +end + +begin + require 'socket' + src = Zero.new + rd, wr = UNIXSocket.pair + pid = fork do + wr.close + buf = String.new + while rd.read(16384, buf) + end + end + rd.close + IO.copy_stream(src, wr) +rescue Errno::ENOENT, NotImplementedError, NameError + # not *nix: missing /dev/zero, fork, or UNIXSocket +rescue LoadError # no socket? +ensure + wr.close if wr + Process.waitpid(pid) if pid +end if IO.respond_to?(:copy_stream) diff --git a/benchmark/bm_io_file_create.rb b/benchmark/io_file_create.rb index 2f205c1333..2f205c1333 100644 --- a/benchmark/bm_io_file_create.rb +++ b/benchmark/io_file_create.rb diff --git a/benchmark/bm_io_file_read.rb b/benchmark/io_file_read.rb index b9e796ed30..b9e796ed30 100644 --- a/benchmark/bm_io_file_read.rb +++ b/benchmark/io_file_read.rb diff --git a/benchmark/bm_io_file_write.rb b/benchmark/io_file_write.rb index aa1be0e5fe..aa1be0e5fe 100644 --- a/benchmark/bm_io_file_write.rb +++ b/benchmark/io_file_write.rb diff --git a/benchmark/io_nonblock_noex.rb b/benchmark/io_nonblock_noex.rb new file mode 100644 index 0000000000..da9357fdc6 --- /dev/null +++ b/benchmark/io_nonblock_noex.rb @@ -0,0 +1,22 @@ +nr = 1_000_000 +i = 0 +msg = '.' +buf = '.' +noex = { exception: false } +begin + r, w = IO.pipe + while i < nr + i += 1 + w.write_nonblock(msg, noex) + r.read_nonblock(1, buf, noex) + end +rescue ArgumentError # old Rubies + while i < nr + i += 1 + w.write_nonblock(msg) + r.read_nonblock(1, buf) + end +ensure + r.close + w.close +end diff --git a/benchmark/io_nonblock_noex2.rb b/benchmark/io_nonblock_noex2.rb new file mode 100644 index 0000000000..56819d049b --- /dev/null +++ b/benchmark/io_nonblock_noex2.rb @@ -0,0 +1,21 @@ +nr = 1_000_000 +i = 0 +msg = '.' +buf = '.' +begin + r, w = IO.pipe + while i < nr + i += 1 + w.write_nonblock(msg, exception: false) + r.read_nonblock(1, buf, exception: false) + end +rescue ArgumentError # old Rubies + while i < nr + i += 1 + w.write_nonblock(msg) + r.read_nonblock(1, buf) + end +ensure + r.close + w.close +end diff --git a/benchmark/io_pipe_rw.rb b/benchmark/io_pipe_rw.rb new file mode 100644 index 0000000000..6862a8ae61 --- /dev/null +++ b/benchmark/io_pipe_rw.rb @@ -0,0 +1,13 @@ +# Measure uncontended GVL performance via read/write with 1:1 threading +# If we switch to M:N threading, this will benchmark something else... +r, w = IO.pipe +src = '0'.freeze +dst = String.new +i = 0 +while i < 1_000_000 + i += 1 + w.write(src) + r.read(1, dst) +end +w.close +r.close diff --git a/benchmark/bm_io_select.rb b/benchmark/io_select.rb index 19248daeb1..19248daeb1 100644 --- a/benchmark/bm_io_select.rb +++ b/benchmark/io_select.rb diff --git a/benchmark/bm_io_select2.rb b/benchmark/io_select2.rb index 10e37d71b2..10e37d71b2 100644 --- a/benchmark/bm_io_select2.rb +++ b/benchmark/io_select2.rb diff --git a/benchmark/bm_io_select3.rb b/benchmark/io_select3.rb index 7d0ba1f092..7d0ba1f092 100644 --- a/benchmark/bm_io_select3.rb +++ b/benchmark/io_select3.rb 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/irb_color.yml b/benchmark/irb_color.yml new file mode 100644 index 0000000000..ebdc8d7e8b --- /dev/null +++ b/benchmark/irb_color.yml @@ -0,0 +1,13 @@ +prelude: | + require 'irb/color' + code = <<~'CODE' + def self.foo # bar + :"erb #{ERB.new("<%= self %>", trim_mode: ?-).result}" + end + CODE +benchmark: + irb_color_complete: | + IRB::Color.colorize_code(code, complete: true) + irb_color_incomplete: | + IRB::Color.colorize_code(code, complete: false) +loop_count: 2000000 diff --git a/benchmark/irb_exec.yml b/benchmark/irb_exec.yml new file mode 100644 index 0000000000..28933f8b38 --- /dev/null +++ b/benchmark/irb_exec.yml @@ -0,0 +1,10 @@ +prelude: | + # frozen_string_literal: true + require 'rbconfig' + irb_f = [File.join(File.dirname(RbConfig.ruby), 'irb'), '-f'] +benchmark: + irb_exec: | + IO.popen(irb_f, 'w') do |io| + io.write('exit') + end +loop_count: 30 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/output/driver.rb b/benchmark/lib/benchmark_driver/output/driver.rb new file mode 100644 index 0000000000..d22236e9fb --- /dev/null +++ b/benchmark/lib/benchmark_driver/output/driver.rb @@ -0,0 +1,36 @@ +require 'benchmark_driver/output/simple' + +# This replicates the legacy benchmark/driver.rb behavior. +class BenchmarkDriver::Output::Driver < BenchmarkDriver::Output::Simple + def initialize(*) + super + @stdout = $stdout + @strio = StringIO.new + $stdout = IOMultiplexer.new(@stdout, @strio) + end + + def with_benchmark(*) + super + ensure + logfile = "bmlog-#{Time.now.strftime('%Y%m%d-%H%M%S')}.#{$$}.log" + puts "\nLog file: #{logfile}" + + $stdout = @stdout + File.write(logfile, @strio.tap(&:rewind).read) + end + + class IOMultiplexer + def initialize(io1, io2) + @io1 = io1 + @io2 = io2 + end + + [:write, :sync, :sync=, :puts, :print, :flush].each do |method| + define_method(method) do |*args| + @io1.send(method, *args) + @io2.send(method, *args) + end + end + end + private_constant :IOMultiplexer +end diff --git a/benchmark/lib/benchmark_driver/runner/cstime.rb b/benchmark/lib/benchmark_driver/runner/cstime.rb new file mode 100644 index 0000000000..3c3453e527 --- /dev/null +++ b/benchmark/lib/benchmark_driver/runner/cstime.rb @@ -0,0 +1,22 @@ +require 'benchmark_driver/runner/total' + +class BenchmarkDriver::Runner::Cstime < BenchmarkDriver::Runner::Total + METRIC = BenchmarkDriver::Metric.new(name: 'cstime', unit: 's', larger_better: false) + + # JobParser returns this, `BenchmarkDriver::Runner.runner_for` searches "*::Job" + Job = Class.new(BenchmarkDriver::DefaultJob) + # Dynamically fetched and used by `BenchmarkDriver::JobParser.parse` + JobParser = BenchmarkDriver::DefaultJobParser.for(klass: Job, metrics: [METRIC]) + + private + + # Overriding BenchmarkDriver::Runner::Total#metric + def metric + METRIC + end + + # Overriding BenchmarkDriver::Runner::Total#target + def target + :cstime + end +end diff --git a/benchmark/lib/benchmark_driver/runner/cutime.rb b/benchmark/lib/benchmark_driver/runner/cutime.rb new file mode 100644 index 0000000000..e139962ef2 --- /dev/null +++ b/benchmark/lib/benchmark_driver/runner/cutime.rb @@ -0,0 +1,22 @@ +require 'benchmark_driver/runner/total' + +class BenchmarkDriver::Runner::Cutime < BenchmarkDriver::Runner::Total + METRIC = BenchmarkDriver::Metric.new(name: 'cutime', unit: 's', larger_better: false) + + # JobParser returns this, `BenchmarkDriver::Runner.runner_for` searches "*::Job" + Job = Class.new(BenchmarkDriver::DefaultJob) + # Dynamically fetched and used by `BenchmarkDriver::JobParser.parse` + JobParser = BenchmarkDriver::DefaultJobParser.for(klass: Job, metrics: [METRIC]) + + private + + # Overriding BenchmarkDriver::Runner::Total#metric + def metric + METRIC + end + + # Overriding BenchmarkDriver::Runner::Total#target + def target + :cutime + end +end diff --git a/benchmark/lib/benchmark_driver/runner/peak.rb b/benchmark/lib/benchmark_driver/runner/peak.rb new file mode 100644 index 0000000000..d04f2e51ff --- /dev/null +++ b/benchmark/lib/benchmark_driver/runner/peak.rb @@ -0,0 +1,151 @@ +require 'benchmark_driver/struct' +require 'benchmark_driver/metric' +require 'benchmark_driver/default_job' +require 'benchmark_driver/default_job_parser' +require 'tempfile' + +class BenchmarkDriver::Runner::Peak + METRIC = BenchmarkDriver::Metric.new( + name: 'Peak memory usage', unit: 'bytes', larger_better: false, worse_word: 'larger', + ) + + # JobParser returns this, `BenchmarkDriver::Runner.runner_for` searches "*::Job" + Job = Class.new(BenchmarkDriver::DefaultJob) + # Dynamically fetched and used by `BenchmarkDriver::JobParser.parse` + JobParser = BenchmarkDriver::DefaultJobParser.for(klass: Job, metrics: [METRIC]) + + # @param [BenchmarkDriver::Config::RunnerConfig] config + # @param [BenchmarkDriver::Output] output + # @param [BenchmarkDriver::Context] contexts + def initialize(config:, output:, contexts:) + @config = config + @output = output + @contexts = contexts + end + + # This method is dynamically called by `BenchmarkDriver::JobRunner.run` + # @param [Array<BenchmarkDriver::Runner::Peak::Job>] jobs + def run(jobs) + if jobs.any? { |job| job.loop_count.nil? } + jobs = jobs.map do |job| + job.loop_count ? job : Job.new(job.to_h.merge(loop_count: 1)) + end + end + + @output.with_benchmark do + jobs.each do |job| + @output.with_job(name: job.name) do + job.runnable_contexts(@contexts).each do |context| + value = BenchmarkDriver::Repeater.with_repeat(config: @config, larger_better: false) do + run_benchmark(job, context: context) + end + @output.with_context(name: context.name, executable: context.executable, gems: context.gems, prelude: context.prelude) do + @output.report(values: { metric => value }, loop_count: job.loop_count) + end + end + end + end + end + end + + private + + # @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, + ) + + memory_status = File.expand_path('../../../../tool/lib/memory_status', __dir__) + Tempfile.open(['benchmark_driver-', '.rb']) do |f| + with_script(benchmark.render) do |path| + output = IO.popen([*context.executable.command, path, f.path, target, memory_status], &:read) + if $?.success? + Integer(f.read) + else + $stdout.print(output) + BenchmarkDriver::Result::ERROR + end + end + end + end + + # Overridden by BenchmarkDriver::Runner::Size + def target + 'peak' + end + + # Overridden by BenchmarkDriver::Runner::Size + def metric + METRIC + end + + def with_script(script) + if @config.verbose >= 2 + sep = '-' * 30 + $stdout.puts "\n\n#{sep}[Script begin]#{sep}\n#{script}#{sep}[Script end]#{sep}\n\n" + end + + Tempfile.open(['benchmark_driver-', '.rb']) do |f| + f.puts script + f.close + return yield(f.path) + end + end + + # @param [String] prelude + # @param [String] script + # @param [String] teardown + # @param [Integer] loop_count + BenchmarkScript = ::BenchmarkDriver::Struct.new(:preludes, :script, :teardown, :loop_count) do + def render + prelude = preludes.reject(&:nil?).reject(&:empty?).join("\n") + <<-RUBY +#{prelude} +#{while_loop(script, loop_count)} +#{teardown} + +result_file, target, memory_status = ARGV +require_relative memory_status + +ms = Memory::Status.new +case target.to_sym +when :peak + key = ms.respond_to?(:hwm) ? :hwm : :peak +when :size + key = ms.respond_to?(:rss) ? :rss : :size +else + raise('unexpected target: ' + target) +end + +File.write(result_file, ms[key]) + RUBY + end + + private + + def while_loop(content, times) + if !times.is_a?(Integer) || times <= 0 + raise ArgumentError.new("Unexpected times: #{times.inspect}") + end + + if times > 1 + <<-RUBY +__bmdv_i = 0 +while __bmdv_i < #{times} + #{content} + __bmdv_i += 1 +end + RUBY + else + content + end + end + end + private_constant :BenchmarkScript +end 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/benchmark_driver/runner/size.rb b/benchmark/lib/benchmark_driver/runner/size.rb new file mode 100644 index 0000000000..1b31f901c7 --- /dev/null +++ b/benchmark/lib/benchmark_driver/runner/size.rb @@ -0,0 +1,25 @@ +require 'benchmark_driver/runner/peak' + +# Actually the same as BenchmarkDriver::Runner::Memory +class BenchmarkDriver::Runner::Size < BenchmarkDriver::Runner::Peak + METRIC = BenchmarkDriver::Metric.new( + name: 'Max resident set size', unit: 'bytes', larger_better: false, worse_word: 'larger', + ) + + # JobParser returns this, `BenchmarkDriver::Runner.runner_for` searches "*::Job" + Job = Class.new(BenchmarkDriver::DefaultJob) + # Dynamically fetched and used by `BenchmarkDriver::JobParser.parse` + JobParser = BenchmarkDriver::DefaultJobParser.for(klass: Job, metrics: [METRIC]) + + private + + # Overriding BenchmarkDriver::Runner::Peak#metric + def metric + METRIC + end + + # Overriding BenchmarkDriver::Runner::Peak#target + def target + 'size' + end +end diff --git a/benchmark/lib/benchmark_driver/runner/stime.rb b/benchmark/lib/benchmark_driver/runner/stime.rb new file mode 100644 index 0000000000..4577fb0bf8 --- /dev/null +++ b/benchmark/lib/benchmark_driver/runner/stime.rb @@ -0,0 +1,22 @@ +require 'benchmark_driver/runner/total' + +class BenchmarkDriver::Runner::Stime < BenchmarkDriver::Runner::Total + METRIC = BenchmarkDriver::Metric.new(name: 'stime', unit: 's', larger_better: false) + + # JobParser returns this, `BenchmarkDriver::Runner.runner_for` searches "*::Job" + Job = Class.new(BenchmarkDriver::DefaultJob) + # Dynamically fetched and used by `BenchmarkDriver::JobParser.parse` + JobParser = BenchmarkDriver::DefaultJobParser.for(klass: Job, metrics: [METRIC]) + + private + + # Overriding BenchmarkDriver::Runner::Total#metric + def metric + METRIC + end + + # Overriding BenchmarkDriver::Runner::Total#target + def target + :stime + end +end diff --git a/benchmark/lib/benchmark_driver/runner/total.rb b/benchmark/lib/benchmark_driver/runner/total.rb new file mode 100644 index 0000000000..64dc14f84e --- /dev/null +++ b/benchmark/lib/benchmark_driver/runner/total.rb @@ -0,0 +1,137 @@ +require 'benchmark_driver/struct' +require 'benchmark_driver/metric' +require 'benchmark_driver/default_job' +require 'benchmark_driver/default_job_parser' +require 'tempfile' + +class BenchmarkDriver::Runner::Total + METRIC = BenchmarkDriver::Metric.new(name: 'Total time', unit: 's', larger_better: false) + + # JobParser returns this, `BenchmarkDriver::Runner.runner_for` searches "*::Job" + Job = Class.new(BenchmarkDriver::DefaultJob) + # Dynamically fetched and used by `BenchmarkDriver::JobParser.parse` + JobParser = BenchmarkDriver::DefaultJobParser.for(klass: Job, metrics: [METRIC]) + + # @param [BenchmarkDriver::Config::RunnerConfig] config + # @param [BenchmarkDriver::Output] output + # @param [BenchmarkDriver::Context] contexts + def initialize(config:, output:, contexts:) + @config = config + @output = output + @contexts = contexts + end + + # This method is dynamically called by `BenchmarkDriver::JobRunner.run` + # @param [Array<BenchmarkDriver::Runner::Total::Job>] jobs + def run(jobs) + if jobs.any? { |job| job.loop_count.nil? } + raise 'missing loop_count is not supported in Ruby repository' + end + + @output.with_benchmark do + jobs.each do |job| + @output.with_job(name: job.name) do + job.runnable_contexts(@contexts).each do |context| + duration = BenchmarkDriver::Repeater.with_repeat(config: @config, larger_better: false) do + run_benchmark(job, context: context) + end + @output.with_context(name: context.name, executable: context.executable, gems: context.gems, prelude: context.prelude) do + @output.report(values: { metric => duration }, duration: duration, loop_count: job.loop_count) + end + end + end + end + end + end + + private + + # @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, + ) + + Tempfile.open(['benchmark_driver-', '.rb']) do |f| + with_script(benchmark.render(result: f.path, target: target)) do |path| + IO.popen([*context.executable.command, path], &:read) # TODO: print stdout if verbose=2 + if $?.success? + Float(f.read) + else + BenchmarkDriver::Result::ERROR + end + end + end + end + + # This method is overridden by some subclasses + def metric + METRIC + end + + # This method is overridden by some subclasses + def target + :total + end + + def with_script(script) + if @config.verbose >= 2 + sep = '-' * 30 + $stdout.puts "\n\n#{sep}[Script begin]#{sep}\n#{script}#{sep}[Script end]#{sep}\n\n" + end + + Tempfile.open(['benchmark_driver-', '.rb']) do |f| + f.puts script + f.close + return yield(f.path) + end + 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(result:, target:) + prelude = preludes.reject(&:nil?).reject(&:empty?).join("\n") + <<-RUBY +#{prelude} + +require 'benchmark' +__bmdv_result = Benchmark.measure { + #{while_loop(script, loop_count)} +} + +#{teardown} + +File.write(#{result.dump}, __bmdv_result.#{target}) + RUBY + end + + private + + def while_loop(content, times) + 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 = 0 +while __bmdv_i < #{times} + #{content} + __bmdv_i += 1 +end + RUBY + end + end + private_constant :BenchmarkScript +end diff --git a/benchmark/lib/benchmark_driver/runner/utime.rb b/benchmark/lib/benchmark_driver/runner/utime.rb new file mode 100644 index 0000000000..b61d83a188 --- /dev/null +++ b/benchmark/lib/benchmark_driver/runner/utime.rb @@ -0,0 +1,22 @@ +require 'benchmark_driver/runner/total' + +class BenchmarkDriver::Runner::Utime < BenchmarkDriver::Runner::Total + METRIC = BenchmarkDriver::Metric.new(name: 'utime', unit: 's', larger_better: false) + + # JobParser returns this, `BenchmarkDriver::Runner.runner_for` searches "*::Job" + Job = Class.new(BenchmarkDriver::DefaultJob) + # Dynamically fetched and used by `BenchmarkDriver::JobParser.parse` + JobParser = BenchmarkDriver::DefaultJobParser.for(klass: Job, metrics: [METRIC]) + + private + + # Overriding BenchmarkDriver::Runner::Total#metric + def metric + METRIC + end + + # Overriding BenchmarkDriver::Runner::Total#target + def target + :utime + end +end diff --git a/benchmark/lib/load.rb b/benchmark/lib/load.rb new file mode 100644 index 0000000000..31b770c484 --- /dev/null +++ b/benchmark/lib/load.rb @@ -0,0 +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/bm_loop_for.rb b/benchmark/loop_for.rb index 0fc4cc1511..0fc4cc1511 100644 --- a/benchmark/bm_loop_for.rb +++ b/benchmark/loop_for.rb diff --git a/benchmark/bm_loop_generator.rb b/benchmark/loop_generator.rb index d3375c744c..6a3194b670 100644 --- a/benchmark/bm_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/bm_loop_times.rb b/benchmark/loop_times.rb index 521f72ad1a..521f72ad1a 100644 --- a/benchmark/bm_loop_times.rb +++ b/benchmark/loop_times.rb 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/bm_loop_whileloop.rb b/benchmark/loop_whileloop.rb index 0072822c06..0072822c06 100644 --- a/benchmark/bm_loop_whileloop.rb +++ b/benchmark/loop_whileloop.rb diff --git a/benchmark/bm_loop_whileloop2.rb b/benchmark/loop_whileloop2.rb index 47d02dffc4..47d02dffc4 100644 --- a/benchmark/bm_loop_whileloop2.rb +++ b/benchmark/loop_whileloop2.rb diff --git a/benchmark/make_fasta_output.rb b/benchmark/make_fasta_output.rb deleted file mode 100644 index b6d787ae27..0000000000 --- a/benchmark/make_fasta_output.rb +++ /dev/null @@ -1,19 +0,0 @@ -# prepare 'fasta.output' - -def prepare_fasta_output n - filebase = File.join(File.dirname($0), 'fasta.output') - script = File.join(File.dirname($0), 'bm_so_fasta.rb') - file = "#{filebase}.#{n}" - - unless FileTest.exist?(file) - STDERR.puts "preparing #{file}" - - open(file, 'w'){|f| - ARGV[0] = n - $stdout = f - load script - $stdout = STDOUT - } - end -end - diff --git a/benchmark/marshal_dump_flo.rb b/benchmark/marshal_dump_flo.rb new file mode 100644 index 0000000000..9b8d0c6afb --- /dev/null +++ b/benchmark/marshal_dump_flo.rb @@ -0,0 +1,2 @@ +bug10761 = 10000.times.map { |x| x.to_f } +100.times { Marshal.dump(bug10761) } diff --git a/benchmark/marshal_dump_load_geniv.rb b/benchmark/marshal_dump_load_geniv.rb new file mode 100644 index 0000000000..8252ad90fa --- /dev/null +++ b/benchmark/marshal_dump_load_geniv.rb @@ -0,0 +1,10 @@ +a = '' +a.instance_eval do + @a = :a + @b = :b + @c = :c +end +100000.times do + a = Marshal.load(Marshal.dump(a)) +end +#p(a.instance_eval { @a == :a && @b == :b && @c == :c }) 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/marshal_dump_load_time.rb b/benchmark/marshal_dump_load_time.rb new file mode 100644 index 0000000000..e29743b791 --- /dev/null +++ b/benchmark/marshal_dump_load_time.rb @@ -0,0 +1 @@ +100000.times { Marshal.load(Marshal.dump(Time.now)) } 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/match_gt4.rb b/benchmark/match_gt4.rb new file mode 100644 index 0000000000..ffda109912 --- /dev/null +++ b/benchmark/match_gt4.rb @@ -0,0 +1 @@ +1000000.times { /(.)(.)(\d+)(\d)/.match("THX1138.") } diff --git a/benchmark/match_small.rb b/benchmark/match_small.rb new file mode 100644 index 0000000000..3b743d484a --- /dev/null +++ b/benchmark/match_small.rb @@ -0,0 +1 @@ +1000000.times { 'haystack'.match(/hay/) } 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/prepare_so_count_words.rb b/benchmark/prepare_so_count_words.rb deleted file mode 100644 index ee2138cdb2..0000000000 --- a/benchmark/prepare_so_count_words.rb +++ /dev/null @@ -1,15 +0,0 @@ -# prepare 'wc.input' - -def prepare_wc_input - wcinput = File.join(File.dirname($0), 'wc.input') - wcbase = File.join(File.dirname($0), 'wc.input.base') - unless FileTest.exist?(wcinput) - data = File.read(wcbase) - 13.times{ - data << data - } - open(wcinput, 'w'){|f| f.write data} - end -end - -prepare_wc_input diff --git a/benchmark/prepare_so_k_nucleotide.rb b/benchmark/prepare_so_k_nucleotide.rb deleted file mode 100644 index f28f4460a1..0000000000 --- a/benchmark/prepare_so_k_nucleotide.rb +++ /dev/null @@ -1,2 +0,0 @@ -require File.join(File.dirname(__FILE__), 'make_fasta_output') -prepare_fasta_output(100_000) diff --git a/benchmark/prepare_so_reverse_complement.rb b/benchmark/prepare_so_reverse_complement.rb deleted file mode 100644 index 7f089109de..0000000000 --- a/benchmark/prepare_so_reverse_complement.rb +++ /dev/null @@ -1,2 +0,0 @@ -require File.join(File.dirname(__FILE__), 'make_fasta_output') -prepare_fasta_output(2_500_000) 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_last.yml b/benchmark/range_last.yml new file mode 100644 index 0000000000..a6674f82ee --- /dev/null +++ b/benchmark/range_last.yml @@ -0,0 +1,4 @@ +benchmark: + - (1..1_000_000).last(100) + - (1..1_000_000).last(1000) + - (1..1_000_000).last(10000) 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 new file mode 100644 index 0000000000..6b6a4836b0 --- /dev/null +++ b/benchmark/realpath.yml @@ -0,0 +1,33 @@ +prelude: | + f = File + pwd = Dir.pwd + Dir.mkdir('b') unless f.directory?('b') + f.write('b/a', '') unless f.file?('b/a') + + relative = 'b/a' + absolute = File.join(pwd, relative) + dir = 'b' + file = 'a' + + 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)" + relative_relative: "f.realpath(file, dir)" + absolute_relative: "f.realpath(absolute, dir)" + relative_absolute: "f.realpath(relative, pwd)" + relative_nil_dir: "f.realdirpath(relative_dir, nil)" + absolute_nil_dir: "f.realdirpath(absolute_dir, nil)" + relative_relative_dir: "f.realdirpath(file_dir, dir)" + absolute_relative_dir: "f.realdirpath(absolute_dir, dir)" + relative_absolute_dir: "f.realdirpath(relative_dir, pwd)" + relative_nil_notexist: "f.realpath(relative_dir, nil) rescue nil" + absolute_nil_notexist: "f.realpath(absolute_dir, nil) rescue nil" + relative_relative_notexist: "f.realpath(file_dir, dir) rescue nil" + absolute_relative_notexist: "f.realpath(absolute_dir, dir) rescue nil" + relative_absolute_notexist: "f.realpath(relative_dir, pwd) rescue 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/report.rb b/benchmark/report.rb deleted file mode 100644 index d2dc56b1e1..0000000000 --- a/benchmark/report.rb +++ /dev/null @@ -1,79 +0,0 @@ -# -# YARV benchmark driver -# - -require 'yarvutil' -require 'benchmark' -require 'rbconfig' - -def exec_command type, file, w - <<-EOP - $DRIVER_PATH = '#{File.dirname($0)}' - $LOAD_PATH.replace $LOAD_PATH | #{$LOAD_PATH.inspect} - require 'benchmark' - require 'yarvutil' -# print '#{type}' - begin - puts Benchmark.measure{ - #{w}('#{file}') - }.utime - rescue Exception => exec_command_error_variable - puts "\t" + exec_command_error_variable.message - end - EOP -end - -def benchmark cmd - rubybin = ENV['RUBY'] || RbConfig.ruby - - IO.popen(rubybin, 'r+'){|io| - io.write cmd - io.close_write - return io.gets - } -end - -def ruby_exec file - prog = exec_command 'ruby', file, 'load' - benchmark prog -end - -def yarv_exec file - prog = exec_command 'yarv', file, 'YARVUtil.load_bm' - benchmark prog -end - -$wr = $wy = nil - -def measure bench - file = File.dirname($0) + "/bm_#{bench}.rb" - r = ruby_exec(file).to_f - y = yarv_exec(file).to_f - puts "#{bench}\t#{r}\t#{y}" -end - -def measure2 - r = ruby_exec.to_f - y = yarv_exec.to_f - puts r/y -end - -if $0 == __FILE__ - %w{ - whileloop - whileloop2 - times - const - method - poly_method - block - rescue - rescue2 - }.each{|bench| - measure bench - } -end - - - - diff --git a/benchmark/require.yml b/benchmark/require.yml new file mode 100644 index 0000000000..09f218cf08 --- /dev/null +++ b/benchmark/require.yml @@ -0,0 +1,32 @@ +prelude: | + require "fileutils" + + def prepare + num_files = 10000 + + basename = File.dirname($0) + data_dir = File.join(basename, "bm_require.data") + + # skip if all of files exists + if File.exist?(File.join(data_dir, "c#{num_files}.rb")) + return + end + + FileUtils.mkdir_p(data_dir) + + 1.upto(num_files) do |i| + File.write("#{data_dir}/c#{i}.rb", "class C#{i}\n""end\n") + end + end + + prepare +benchmark: + require: | + $:.push File.join(File.dirname(__FILE__), "bm_require.data") + + 1.upto(10000) do |i| + require "c#{i}" + end + + $:.pop +loop_count: 1 diff --git a/benchmark/require_thread.yml b/benchmark/require_thread.yml new file mode 100644 index 0000000000..0c63257106 --- /dev/null +++ b/benchmark/require_thread.yml @@ -0,0 +1,40 @@ +prelude: | + require "fileutils" + + def prepare + num_files = 10000 + + basename = File.dirname($0) + data_dir = File.join(basename, "bm_require.data") + + # skip if all of files exists + if File.exist?(File.join(data_dir, "c#{num_files}.rb")) + return + end + + FileUtils.mkdir_p(data_dir) + + 1.upto(num_files) do |i| + File.write("#{data_dir}/c#{i}.rb", "class C#{i}\n""end\n") + end + end + + prepare +benchmark: + require_thread: | + $:.push File.join(File.dirname(__FILE__), "bm_require.data") + + i=0 + t = Thread.new do + while true + i = i+1 # dummy loop + end + end + + 1.upto(100) do |i| + require "c#{i}" + end + + $:.pop + t.kill +loop_count: 1 diff --git a/benchmark/run.rb b/benchmark/run.rb deleted file mode 100644 index 0cd2363849..0000000000 --- a/benchmark/run.rb +++ /dev/null @@ -1,127 +0,0 @@ -# -# Ruby benchmark driver -# - -require 'benchmark' -require 'rbconfig' - -$matzrubyonly = false -$rubyonly = false - -$results = [] - -# prepare 'wc.input' -def prepare_wc_input - wcinput = File.join(File.dirname($0), 'wc.input') - wcbase = File.join(File.dirname($0), 'wc.input.base') - unless FileTest.exist?(wcinput) - data = File.read(wcbase) - 13.times{ - data << data - } - open(wcinput, 'w'){|f| f.write data} - end -end - -prepare_wc_input - -def bm file - prog = File.readlines(file).map{|e| e.rstrip}.join("\n") - return if prog.empty? - - /[a-z]+_(.+)\.rb/ =~ file - bm_name = $1 - puts '-----------------------------------------------------------' unless $rubyonly || $matzrubyonly - puts "#{bm_name}: " - - -puts <<EOS unless $matzrubyonly || $rubyonly -#{prog} --- -EOS - begin - result = [bm_name] - result << matzruby_exec(file) unless $rubyonly - result << ruby_exec(file) unless $matzrubyonly - $results << result - - rescue Exception => e - puts - puts "** benchmark failure: #{e}" - puts e.backtrace - end -end - -def benchmark file, bin - m = Benchmark.measure{ - `#{bin} #{$opts} #{file}` - } - sec = '%.3f' % m.real - puts " #{sec}" - sec -end - -def ruby_exec file - print 'ruby' - benchmark file, $ruby_program -end - -def matzruby_exec file - print 'matz' - rubylib = ENV['RUBYLIB'] - ENV['RUBYLIB'] = '' - r = benchmark file, $matzruby_program - ENV['RUBYLIB'] = rubylib - r -end - -if $0 == __FILE__ - ARGV.each{|arg| - case arg - when /\A--ruby=(.+)/ - $ruby_program = $1 - when /\A--matzruby=(.+)/ - $matzruby_program = $1 - when /\A--opts=(.+)/ - $opts = $1 - when /\A(-r|--only-ruby)\z/ - $rubyonly = true - when /\A(-m|--only-matzruby)\z/ - $matzrubyonly = true - end - } - ARGV.delete_if{|arg| - /\A-/ =~ arg - } - - puts "MatzRuby:" - system("#{$matzruby_program} -v") - puts "Ruby:" - system("#{$ruby_program} -v") - puts - - if ARGV.empty? - Dir.glob(File.dirname(__FILE__) + '/bm_*.rb').sort.each{|file| - bm file - } - else - ARGV.each{|file| - Dir.glob(File.join(File.dirname(__FILE__), file + '*')){|ef| - # file = "#{File.dirname(__FILE__)}/#{file}.rb" - bm ef - } - } - end - - puts - puts "-- benchmark summary ---------------------------" - $results.each{|res| - print res.shift, "\t" - (res||[]).each{|result| - /([\d\.]+)/ =~ result - print $1 + "\t" if $1 - } - puts - } -end - diff --git a/benchmark/runc.rb b/benchmark/runc.rb deleted file mode 100644 index 97c5cef045..0000000000 --- a/benchmark/runc.rb +++ /dev/null @@ -1,27 +0,0 @@ -# -# -# - -require 'benchmark' -require 'rbconfig' - -$rubybin = ENV['RUBY'] || RbConfig.ruby - -def runfile file - puts file - file = File.join(File.dirname($0), 'contrib', file) - Benchmark.bm{|x| - x.report('ruby'){ - system("#{$rubybin} #{file}") - } - x.report('yarv'){ - system("#{$rubybin} -rite -I.. #{file}") - } - } -end - -ARGV.each{|file| - runfile file -} - - 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/securerandom.rb b/benchmark/securerandom.rb new file mode 100644 index 0000000000..a082ea6d5b --- /dev/null +++ b/benchmark/securerandom.rb @@ -0,0 +1,5 @@ +require "securerandom" + +20_0000.times do + SecureRandom.random_number(100) +end 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/bm_so_ackermann.rb b/benchmark/so_ackermann.rb index 7db5be9050..4effa1ecaf 100644 --- a/benchmark/bm_so_ackermann.rb +++ b/benchmark/so_ackermann.rb @@ -1,5 +1,5 @@ #!/usr/bin/ruby -# -*- mode: ruby -*- +# -*- Ruby -*- # $Id: ackermann-ruby.code,v 1.4 2004/11/13 07:40:41 bfulgham Exp $ # http://www.bagley.org/~doug/shootout/ diff --git a/benchmark/bm_so_array.rb b/benchmark/so_array.rb index 2b8fce8f99..767e03db5f 100644 --- a/benchmark/bm_so_array.rb +++ b/benchmark/so_array.rb @@ -1,5 +1,5 @@ #!/usr/bin/ruby -# -*- mode: ruby -*- +# -*- Ruby -*- # $Id: ary-ruby.code,v 1.4 2004/11/13 07:41:27 bfulgham Exp $ # http://www.bagley.org/~doug/shootout/ # with help from Paul Brannan and Mark Hubbart diff --git a/benchmark/bm_so_binary_trees.rb b/benchmark/so_binary_trees.rb index 6a26465578..b1693e4109 100644 --- a/benchmark/bm_so_binary_trees.rb +++ b/benchmark/so_binary_trees.rb @@ -4,7 +4,9 @@ # contributed by Jesse Millikan # disable output -def STDOUT.write_ *args +alias puts_orig puts +def puts str + # disable puts end def item_check(tree) @@ -25,7 +27,7 @@ def bottom_up_tree(item, depth) end end -max_depth = 12 # 16 # ARGV[0].to_i +max_depth = 16 # ARGV[0].to_i min_depth = 4 max_depth = min_depth + 2 if min_depth + 2 > max_depth @@ -55,3 +57,6 @@ min_depth.step(max_depth + 1, 2) do |depth| end puts "long lived tree of depth #{max_depth}\t check: #{item_check(long_lived_tree)}" + +undef puts +alias puts puts_orig diff --git a/benchmark/bm_so_concatenate.rb b/benchmark/so_concatenate.rb index 873214de7c..4468e20ac8 100644 --- a/benchmark/bm_so_concatenate.rb +++ b/benchmark/so_concatenate.rb @@ -1,5 +1,5 @@ #!/usr/bin/ruby -# -*- mode: ruby -*- +# -*- Ruby -*- # $Id: strcat-ruby.code,v 1.4 2004/11/13 07:43:28 bfulgham Exp $ # http://www.bagley.org/~doug/shootout/ # based on code from Aristarkh A Zagorodnikov and Dat Nguyen diff --git a/benchmark/wc.input.base b/benchmark/so_count_words.yml index 41143fbac0..f7322a8541 100644 --- a/benchmark/wc.input.base +++ b/benchmark/so_count_words.yml @@ -1,25 +1,66 @@ -Subject: Re: Who was Izchak Miller? -From: "Jane D. Anonymous" <nobody@yale.edu> -Date: 1996/04/28 -Message-Id: <4lv7bc$oh@news.ycc.yale.edu> -References: <317C405E.5DFA@panix.com> <4lk6vl$gde@ns.oar.net> -To: 75176.2330@compuserve.com -Content-Type: text/plain; charset=us-ascii -Organization: Yale University -X-Url: news:4lk6vl$gde@ns.oar.net -Mime-Version: 1.0 -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 :-). - Tamar Miller - -The following is a really long word of 5000 characters: - -wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww +prelude: | + #!/usr/bin/ruby + + wc_input_base = <<EOS + Subject: Re: Who was Izchak Miller? + From: "Jane D. Anonymous" <nobody@yale.edu> + Date: 1996/04/28 + Message-Id: <4lv7bc$oh@news.ycc.yale.edu> + References: <317C405E.5DFA@panix.com> <4lk6vl$gde@ns.oar.net> + To: 75176.2330@compuserve.com + Content-Type: text/plain; charset=us-ascii + Organization: Yale University + X-Url: news:4lk6vl$gde@ns.oar.net + Mime-Version: 1.0 + 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 :-). + Tamar Miller + + The following is a really long word of 5000 characters: + + wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww + EOS + + # prepare 'wc.input' + + def prepare_wc_input(wcbase) + wcinput = File.join(File.dirname($0), 'wc.input') + unless FileTest.exist?(wcinput) + data = wcbase.dup + 13.times{ + data << data + } + File.write(wcinput, data) + end + at_exit {File.unlink(wcinput) rescue nil} + end + + prepare_wc_input(wc_input_base) + +benchmark: + so_count_words: | + # $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 + + nl = nw = nc = 0 + 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}" + +loop_count: 1 diff --git a/benchmark/bm_so_exception.rb b/benchmark/so_exception.rb index deb003a594..eb205b4df1 100644 --- a/benchmark/bm_so_exception.rb +++ b/benchmark/so_exception.rb @@ -1,5 +1,5 @@ #!/usr/bin/ruby -# -*- mode: ruby -*- +# -*- Ruby -*- # $Id: except-ruby.code,v 1.4 2004/11/13 07:41:33 bfulgham Exp $ # http://www.bagley.org/~doug/shootout/ diff --git a/benchmark/bm_so_fannkuch.rb b/benchmark/so_fannkuch.rb index bac5ecd44c..bac5ecd44c 100644 --- a/benchmark/bm_so_fannkuch.rb +++ b/benchmark/so_fannkuch.rb diff --git a/benchmark/bm_so_fasta.rb b/benchmark/so_fasta.rb index 3f759ba7ae..dcc6b39507 100644 --- a/benchmark/bm_so_fasta.rb +++ b/benchmark/so_fasta.rb @@ -3,7 +3,7 @@ # Contributed by Sokolov Yura $last = 42.0 -def gen_random (max,im=139968,ia=3877,ic=29573) +def gen_random(max, im=139968, ia=3877, ic=29573) (max * ($last = ($last * ia + ic) % im)) / im end diff --git a/benchmark/so_k_nucleotide.yml b/benchmark/so_k_nucleotide.yml new file mode 100644 index 0000000000..d7df086c39 --- /dev/null +++ b/benchmark/so_k_nucleotide.yml @@ -0,0 +1,155 @@ +prelude: | + bm_so_fasta = <<'EOS' + # The Computer Language Shootout + # http://shootout.alioth.debian.org/ + # Contributed by Sokolov Yura + + $last = 42.0 + def gen_random(max, im=139968, ia=3877, ic=29573) + (max * ($last = ($last * ia + ic) % im)) / im + end + + alu = + "GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG"+ + "GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA"+ + "CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT"+ + "ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA"+ + "GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG"+ + "AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC"+ + "AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA" + + iub = [ + ["a", 0.27], + ["c", 0.12], + ["g", 0.12], + ["t", 0.27], + + ["B", 0.02], + ["D", 0.02], + ["H", 0.02], + ["K", 0.02], + ["M", 0.02], + ["N", 0.02], + ["R", 0.02], + ["S", 0.02], + ["V", 0.02], + ["W", 0.02], + ["Y", 0.02], + ] + homosapiens = [ + ["a", 0.3029549426680], + ["c", 0.1979883004921], + ["g", 0.1975473066391], + ["t", 0.3015094502008], + ] + + def make_repeat_fasta(id, desc, src, n) + puts ">#{id} #{desc}" + v = nil + width = 60 + l = src.length + s = src * ((n / l) + 1) + s.slice!(n, l) + puts(s.scan(/.{1,#{width}}/).join("\n")) + end + + def make_random_fasta(id, desc, table, n) + puts ">#{id} #{desc}" + rand, v = nil,nil + width = 60 + chunk = 1 * width + prob = 0.0 + table.each{|v| v[1]= (prob += v[1])} + for i in 1..(n/width) + puts((1..width).collect{ + rand = gen_random(1.0) + table.find{|v| v[1]>rand}[0] + }.join) + end + if n%width != 0 + puts((1..(n%width)).collect{ + rand = gen_random(1.0) + table.find{|v| v[1]>rand}[0] + }.join) + end + end + + + n = (ARGV[0] or 250_000).to_i + + make_repeat_fasta('ONE', 'Homo sapiens alu', alu, n*2) + make_random_fasta('TWO', 'IUB ambiguity codes', iub, n*3) + make_random_fasta('THREE', 'Homo sapiens frequency', homosapiens, n*5) + EOS +benchmark: + - name: so_k_nucleotide + prelude: | + script = File.join(File.dirname($0), 'bm_so_fasta.rb') + File.write(script, bm_so_fasta) + + def prepare_fasta_output n + filebase = File.join(File.dirname($0), 'fasta.output') + script = File.join(File.dirname($0), 'bm_so_fasta.rb') + file = "#{filebase}.#{n}" + + unless FileTest.exist?(file) + STDERR.puts "preparing #{file}" + + open(file, 'w'){|f| + ARGV[0] = n + $stdout = f + load script + $stdout = STDOUT + } + end + end + prepare_fasta_output(100_000) + script: | + # The Computer Language Shootout + # http://shootout.alioth.debian.org + # + # contributed by jose fco. gonzalez + # modified by Sokolov Yura + + seq = String.new + + def frecuency( seq,length ) + n, table = seq.length - length + 1, Hash.new(0) + f, i = nil, nil + (0 ... length).each do |f| + (f ... n).step(length) do |i| + table[seq[i,length]] += 1 + end + end + [n,table] + + end + + def sort_by_freq( seq,length ) + n,table = frecuency( seq,length ) + a, b, v = nil, nil, nil + table.sort{|a,b| b[1] <=> a[1]}.each do |v| + puts "%s %.3f" % [v[0].upcase,((v[1]*100).to_f/n)] + end + puts + end + + def find_seq( seq,s ) + n,table = frecuency( seq,s.length ) + puts "#{table[s].to_s}\t#{s.upcase}" + end + + input = open(File.join(File.dirname($0), 'fasta.output.100000'), 'rb') + + line = input.gets while line !~ /^>THREE/ + line = input.gets + + while (line !~ /^>/) & line do + seq << line.chomp + line = input.gets + end + + [1,2].each {|i| sort_by_freq( seq,i ) } + + %w(ggt ggta ggtatt ggtattttaatt ggtattttaatttatagt).each{|s| find_seq( seq,s) } + loop_count: 1 diff --git a/benchmark/bm_so_lists.rb b/benchmark/so_lists.rb index e8f4a2a5f7..e8f4a2a5f7 100644 --- a/benchmark/bm_so_lists.rb +++ b/benchmark/so_lists.rb diff --git a/benchmark/bm_so_mandelbrot.rb b/benchmark/so_mandelbrot.rb index 76331c64b8..76331c64b8 100644 --- a/benchmark/bm_so_mandelbrot.rb +++ b/benchmark/so_mandelbrot.rb diff --git a/benchmark/bm_so_matrix.rb b/benchmark/so_matrix.rb index e2c5c8e559..2d1e72bda9 100644 --- a/benchmark/bm_so_matrix.rb +++ b/benchmark/so_matrix.rb @@ -1,5 +1,5 @@ #!/usr/bin/ruby -# -*- mode: ruby -*- +# -*- Ruby -*- # $Id: matrix-ruby.code,v 1.4 2004/11/13 07:42:14 bfulgham Exp $ # http://www.bagley.org/~doug/shootout/ diff --git a/benchmark/bm_so_meteor_contest.rb b/benchmark/so_meteor_contest.rb index 99cf6a91cc..d8c8e3ab9c 100644 --- a/benchmark/bm_so_meteor_contest.rb +++ b/benchmark/so_meteor_contest.rb @@ -32,7 +32,7 @@ class Rotation @start_masks = Array.new(60) # create the rotational masks by placing the base mask at the location and seeing if - # 1) it overlaps the boundries and 2) it produces a prunable board. if either of these + # 1) it overlaps the boundaries and 2) it produces a prunable board. if either of these # is true the piece cannot be placed 0.upto(59) do | offset | mask = is_even(offset) ? (@even_mask << offset) : (@odd_mask << offset) @@ -155,7 +155,7 @@ class Rotation # given a set of directions places the piece (as defined by a set of directions) on the board at # a location that will not take it off the edge - def get_values ( directions ) + def get_values( directions ) start = start_adjust(directions) values = [ start ] directions.each do | direction | @@ -260,7 +260,7 @@ end # support function that create three utility maps: # $converter -- for each row an array that maps a five bit row (via array mapping) -# to the a a five bit representation of the bits below it +# to the a five bit representation of the bits below it # $bit_count -- maps a five bit row (via array mapping) to the number of 1s in the row # @@new_regions -- maps a five bit row (via array mapping) to an array of "region" arrays # a region array has three values the first is a mask of bits in the region, @@ -326,9 +326,9 @@ end # The exact procedure is described in-code def prunable( board, location, slotting = false) collectors = [] - # loop accross the rows + # loop across the rows (location / 6).to_i.upto(9) do | row_on | - # obtain a set of regions representing the bits of the curent row. + # obtain a set of regions representing the bits of the current row. regions = $regions[(board >> (row_on * 6)) & 0b11111] converter = $converter[row_on] @@ -370,7 +370,7 @@ def prunable( board, location, slotting = false) end # check the existing collectors, if any collector overlapped no bits in the region its [2] value will - # be zero. The size of any such reaason is tested if it is not a muliple of five true is returned since + # be zero. The size of any such reaason is tested if it is not a multiple of five true is returned since # the board is prunable. if it is a multiple of five it is removed. # Collector that are still active have a new adjacent value [0] set based n the matched bits # and have [2] cleared out for the next cycle. @@ -382,7 +382,7 @@ def prunable( board, location, slotting = false) collectors[collector_num] = nil else # if a collector matches all bits in the row then we can return unprunable early for the - # follwing reasons: + # following reasons: # 1) there can be no more unavailable bits bince we fill from the top left downward # 2) all previous regions have been closed or joined so only this region can fail # 3) this region must be good since there can never be only 1 region that is nuot @@ -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) @@ -467,7 +467,7 @@ def find_top( rotation_skip) end # the normail find routine, iterates through the available pieces, checks all rotations at the current location -# and adds any boards found. depth is acheived via recursion. the overall approach is described +# and adds any boards found. depth is achieved via recursion. the overall approach is described # here: http://www-128.ibm.com/developerworks/java/library/j-javaopt/ # parameters: # start_location -- where to start looking for place for the next piece at @@ -526,7 +526,7 @@ def save( board_string) @boards_found += 1 # the exit motif is a time saver. Ideally the function should return, but those tests - # take noticable time (performance). + # take noticeable time (performance). if (@boards_found == @stop_count) then print_results exit(0) @@ -561,4 +561,3 @@ create_collector_support @boards_found = 0 find_all ######## DO IT!!! - diff --git a/benchmark/bm_so_nbody.rb b/benchmark/so_nbody.rb index d6c5bb9e61..9884fc4edc 100644 --- a/benchmark/bm_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/bm_so_nested_loop.rb b/benchmark/so_nested_loop.rb index a0513f8c47..766fcf7b84 100644 --- a/benchmark/bm_so_nested_loop.rb +++ b/benchmark/so_nested_loop.rb @@ -1,5 +1,5 @@ #!/usr/bin/ruby -# -*- mode: ruby -*- +# -*- Ruby -*- # $Id: nestedloop-ruby.code,v 1.4 2004/11/13 07:42:22 bfulgham Exp $ # http://www.bagley.org/~doug/shootout/ # from Avi Bryant diff --git a/benchmark/bm_so_nsieve.rb b/benchmark/so_nsieve.rb index a65cc78233..a65cc78233 100644 --- a/benchmark/bm_so_nsieve.rb +++ b/benchmark/so_nsieve.rb diff --git a/benchmark/bm_so_nsieve_bits.rb b/benchmark/so_nsieve_bits.rb index 6f958ee44e..6f958ee44e 100644 --- a/benchmark/bm_so_nsieve_bits.rb +++ b/benchmark/so_nsieve_bits.rb diff --git a/benchmark/bm_so_object.rb b/benchmark/so_object.rb index e8607c7199..131f44624c 100644 --- a/benchmark/bm_so_object.rb +++ b/benchmark/so_object.rb @@ -1,5 +1,5 @@ #!/usr/bin/ruby -# -*- mode: ruby -*- +# -*- Ruby -*- # $Id: objinst-ruby.code,v 1.4 2004/11/13 07:42:25 bfulgham Exp $ # http://www.bagley.org/~doug/shootout/ # with help from Aristarkh Zagorodnikov diff --git a/benchmark/bm_so_partial_sums.rb b/benchmark/so_partial_sums.rb index 630b45cb8d..630b45cb8d 100644 --- a/benchmark/bm_so_partial_sums.rb +++ b/benchmark/so_partial_sums.rb diff --git a/benchmark/bm_so_pidigits.rb b/benchmark/so_pidigits.rb index c7d6fbfb4d..9a537b2d1c 100644 --- a/benchmark/bm_so_pidigits.rb +++ b/benchmark/so_pidigits.rb @@ -38,7 +38,7 @@ end class Transformation attr_reader :q, :r, :s, :t - def initialize (q, r, s, t) + def initialize(q, r, s, t) @q,@r,@s,@t,@k = q,r,s,t,0 end diff --git a/benchmark/bm_so_random.rb b/benchmark/so_random.rb index a66b9e8e63..a66b9e8e63 100644 --- a/benchmark/bm_so_random.rb +++ b/benchmark/so_random.rb diff --git a/benchmark/so_reverse_complement.yml b/benchmark/so_reverse_complement.yml new file mode 100644 index 0000000000..de05eedfc4 --- /dev/null +++ b/benchmark/so_reverse_complement.yml @@ -0,0 +1,137 @@ +prelude: | + bm_so_fasta = <<'EOS' + # The Computer Language Shootout + # http://shootout.alioth.debian.org/ + # Contributed by Sokolov Yura + + $last = 42.0 + def gen_random(max, im=139968, ia=3877, ic=29573) + (max * ($last = ($last * ia + ic) % im)) / im + end + + alu = + "GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG"+ + "GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA"+ + "CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT"+ + "ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA"+ + "GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG"+ + "AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC"+ + "AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA" + + iub = [ + ["a", 0.27], + ["c", 0.12], + ["g", 0.12], + ["t", 0.27], + + ["B", 0.02], + ["D", 0.02], + ["H", 0.02], + ["K", 0.02], + ["M", 0.02], + ["N", 0.02], + ["R", 0.02], + ["S", 0.02], + ["V", 0.02], + ["W", 0.02], + ["Y", 0.02], + ] + homosapiens = [ + ["a", 0.3029549426680], + ["c", 0.1979883004921], + ["g", 0.1975473066391], + ["t", 0.3015094502008], + ] + + def make_repeat_fasta(id, desc, src, n) + puts ">#{id} #{desc}" + v = nil + width = 60 + l = src.length + s = src * ((n / l) + 1) + s.slice!(n, l) + puts(s.scan(/.{1,#{width}}/).join("\n")) + end + + def make_random_fasta(id, desc, table, n) + puts ">#{id} #{desc}" + rand, v = nil,nil + width = 60 + chunk = 1 * width + prob = 0.0 + table.each{|v| v[1]= (prob += v[1])} + for i in 1..(n/width) + puts((1..width).collect{ + rand = gen_random(1.0) + table.find{|v| v[1]>rand}[0] + }.join) + end + if n%width != 0 + puts((1..(n%width)).collect{ + rand = gen_random(1.0) + table.find{|v| v[1]>rand}[0] + }.join) + end + end + + + n = (ARGV[0] or 250_000).to_i + + make_repeat_fasta('ONE', 'Homo sapiens alu', alu, n*2) + make_random_fasta('TWO', 'IUB ambiguity codes', iub, n*3) + make_random_fasta('THREE', 'Homo sapiens frequency', homosapiens, n*5) + EOS +benchmark: + - name: so_reverse_complement + prelude: | + script = File.join(File.dirname($0), 'bm_so_fasta.rb') + File.write(script, bm_so_fasta) + + def prepare_fasta_output n + filebase = File.join(File.dirname($0), 'fasta.output') + script = File.join(File.dirname($0), 'bm_so_fasta.rb') + file = "#{filebase}.#{n}" + + unless FileTest.exist?(file) + STDERR.puts "preparing #{file}" + + open(file, 'w'){|f| + ARGV[0] = n + $stdout = f + load script + $stdout = STDOUT + } + end + end + prepare_fasta_output(2_500_000) + script: | + # The Great Computer Language Shootout + # http://shootout.alioth.debian.org/ + # + # Contributed by Peter Bjarke Olsen + # Modified by Doug King + + seq=Array.new + + def revcomp(seq) + seq.reverse!.tr!('wsatugcyrkmbdhvnATUGCYRKMBDHVN','WSTAACGRYMKVHDBNTAACGRYMKVHDBN') + stringlen=seq.length + 0.step(stringlen-1,60) {|x| print seq.slice(x,60) , "\n"} + end + + input = open(File.join(File.dirname($0), 'fasta.output.2500000'), 'rb') + + while input.gets + if $_ =~ />/ + if seq.length != 0 + revcomp(seq.join) + seq=Array.new + end + puts $_ + else + $_.sub(/\n/,'') + seq.push $_ + end + end + revcomp(seq.join) + loop_count: 1 diff --git a/benchmark/bm_so_sieve.rb b/benchmark/so_sieve.rb index 43dc302648..43dc302648 100644 --- a/benchmark/bm_so_sieve.rb +++ b/benchmark/so_sieve.rb diff --git a/benchmark/bm_so_spectralnorm.rb b/benchmark/so_spectralnorm.rb index 6b97206689..6b97206689 100644 --- a/benchmark/bm_so_spectralnorm.rb +++ b/benchmark/so_spectralnorm.rb diff --git a/benchmark/string_capitalize.yml b/benchmark/string_capitalize.yml new file mode 100644 index 0000000000..7d23fd3d35 --- /dev/null +++ b/benchmark/string_capitalize.yml @@ -0,0 +1,10 @@ +prelude: | + str1 = [*"a".."m",*"N".."Z",*"0".."9"].join("") + str10 = str1 * 10 + str100 = str10 * 10 + str1000 = str100 * 10 +benchmark: + capitalize-1: str1.capitalize + capitalize-10: str10.capitalize + capitalize-100: str100.capitalize + capitalize-1000: str1000.capitalize 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 new file mode 100644 index 0000000000..1fea6afbec --- /dev/null +++ b/benchmark/string_downcase.yml @@ -0,0 +1,18 @@ +prelude: | + str1 = [*"A".."Z",*"0".."9"].join("") + 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_index.rb b/benchmark/string_index.rb new file mode 100644 index 0000000000..7783111082 --- /dev/null +++ b/benchmark/string_index.rb @@ -0,0 +1,3 @@ +str1 = "あ" * 1024 + "い" # not single byte optimizable +str2 = "い" +100_000.times { str1.index(str2) } 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_scan_re.rb b/benchmark/string_scan_re.rb new file mode 100644 index 0000000000..b0d60201a9 --- /dev/null +++ b/benchmark/string_scan_re.rb @@ -0,0 +1,2 @@ +str = Array.new(1_000, 'abc').join(',') +1_000.times { str.scan(/abc/) } diff --git a/benchmark/string_scan_str.rb b/benchmark/string_scan_str.rb new file mode 100644 index 0000000000..42440bd948 --- /dev/null +++ b/benchmark/string_scan_str.rb @@ -0,0 +1,2 @@ +str = Array.new(1_000, 'abc').join(',') +1_000.times { str.scan('abc') } 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 new file mode 100644 index 0000000000..cc2c7d7855 --- /dev/null +++ b/benchmark/string_split.yml @@ -0,0 +1,22 @@ +prelude: | + str1 = [*0..5].join(" ") + " " + str10 = str1 * 10 + str100 = str10 * 10 + str1000 = str100 * 10 +benchmark: + 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 new file mode 100644 index 0000000000..eeb5928907 --- /dev/null +++ b/benchmark/string_swapcase.yml @@ -0,0 +1,18 @@ +prelude: | + str1 = [*"A".."M",*"n".."z",*"0".."9"].join("") + 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 new file mode 100644 index 0000000000..dab84bbde2 --- /dev/null +++ b/benchmark/string_upcase.yml @@ -0,0 +1,18 @@ +prelude: | + str1 = [*"a".."z",*"0".."9"].join("") + 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_strptime.yml b/benchmark/time_strptime.yml new file mode 100644 index 0000000000..8d89ebb7a7 --- /dev/null +++ b/benchmark/time_strptime.yml @@ -0,0 +1,13 @@ +prelude: | + require 'time' +benchmark: + - Time.strptime("28/Aug/2005:06:54:20 +0000", "%d/%b/%Y:%T %z") + - Time.strptime("1", "%s") + - Time.strptime("0 +0100", "%s %z") + - Time.strptime("0 UTC", "%s %z") + - Time.strptime("1.5", "%s.%N") + - Time.strptime("1.000000000001", "%s.%N") + - Time.strptime("20010203 -0200", "%Y%m%d %z") + - Time.strptime("20010203 UTC", "%Y%m%d %z") + - Time.strptime("2018-365", "%Y-%j") + - Time.strptime("2018-091", "%Y-%j") diff --git a/benchmark/time_subsec.rb b/benchmark/time_subsec.rb new file mode 100644 index 0000000000..505021c701 --- /dev/null +++ b/benchmark/time_subsec.rb @@ -0,0 +1,2 @@ +t = Time.now +4000000.times { t.subsec } 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/vm_array.yml b/benchmark/vm_array.yml new file mode 100644 index 0000000000..2a177237ef --- /dev/null +++ b/benchmark/vm_array.yml @@ -0,0 +1,4 @@ +benchmark: + vm_array: | + a = [1,2,3,4,5,6,7,8,9,10] +loop_count: 6000000 diff --git a/benchmark/vm_attr_ivar.yml b/benchmark/vm_attr_ivar.yml new file mode 100644 index 0000000000..75b803478e --- /dev/null +++ b/benchmark/vm_attr_ivar.yml @@ -0,0 +1,14 @@ +prelude: | + class C + attr_reader :a, :b + def initialize + @a = nil + @b = nil + end + end + obj = C.new +benchmark: + vm_attr_ivar: | + j = obj.a + k = obj.b +loop_count: 30000000 diff --git a/benchmark/vm_attr_ivar_set.yml b/benchmark/vm_attr_ivar_set.yml new file mode 100644 index 0000000000..a0d379b18a --- /dev/null +++ b/benchmark/vm_attr_ivar_set.yml @@ -0,0 +1,14 @@ +prelude: | + class C + attr_accessor :a, :b + def initialize + @a = nil + @b = nil + end + end + obj = C.new +benchmark: + vm_attr_ivar_set: | + obj.a = 1 + obj.b = 2 +loop_count: 30000000 diff --git a/benchmark/bm_vm3_backtrace.rb b/benchmark/vm_backtrace.rb index 0fbf73e1ca..0fbf73e1ca 100644 --- a/benchmark/bm_vm3_backtrace.rb +++ b/benchmark/vm_backtrace.rb diff --git a/benchmark/vm_bigarray.yml b/benchmark/vm_bigarray.yml new file mode 100644 index 0000000000..8b2d3f3443 --- /dev/null +++ b/benchmark/vm_bigarray.yml @@ -0,0 +1,105 @@ +benchmark: + vm_bigarray: | + a = [ + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + 1,2,3,4,5,6,7,8,9,10, + ] +loop_count: 6000000 diff --git a/benchmark/vm_bighash.yml b/benchmark/vm_bighash.yml new file mode 100644 index 0000000000..4dacfde793 --- /dev/null +++ b/benchmark/vm_bighash.yml @@ -0,0 +1,4 @@ +benchmark: + 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/vm_block.yml b/benchmark/vm_block.yml new file mode 100644 index 0000000000..68b3e40bf5 --- /dev/null +++ b/benchmark/vm_block.yml @@ -0,0 +1,9 @@ +prelude: | + def m + yield + end +benchmark: + 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/vm_blockparam.yml b/benchmark/vm_blockparam.yml new file mode 100644 index 0000000000..5e5a0170a2 --- /dev/null +++ b/benchmark/vm_blockparam.yml @@ -0,0 +1,7 @@ +prelude: | + def m &b + end +benchmark: + vm_blockparam: | + m{} +loop_count: 30000000 diff --git a/benchmark/vm_blockparam_call.yml b/benchmark/vm_blockparam_call.yml new file mode 100644 index 0000000000..a7d8d366ea --- /dev/null +++ b/benchmark/vm_blockparam_call.yml @@ -0,0 +1,8 @@ +prelude: | + def m &b + b.call + end +benchmark: + vm_blockparam_call: | + m{} +loop_count: 30000000 diff --git a/benchmark/vm_blockparam_pass.yml b/benchmark/vm_blockparam_pass.yml new file mode 100644 index 0000000000..841f5e7a63 --- /dev/null +++ b/benchmark/vm_blockparam_pass.yml @@ -0,0 +1,12 @@ +prelude: | + def bp_yield + yield + end + + def bp_pass &b + bp_yield &b + end +benchmark: + vm_blockparam_pass: | + bp_pass{} +loop_count: 30000000 diff --git a/benchmark/vm_blockparam_yield.yml b/benchmark/vm_blockparam_yield.yml new file mode 100644 index 0000000000..8ea9b46ed2 --- /dev/null +++ b/benchmark/vm_blockparam_yield.yml @@ -0,0 +1,8 @@ +prelude: | + def bp_yield &b + yield + end +benchmark: + 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/vm_case.yml b/benchmark/vm_case.yml new file mode 100644 index 0000000000..b26a491a15 --- /dev/null +++ b/benchmark/vm_case.yml @@ -0,0 +1,13 @@ +benchmark: + vm_case: | + case :foo + when :bar + raise + when :baz + raise + when :boo + raise + when :foo + # noop + end +loop_count: 6000000 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/vm_case_lit.yml b/benchmark/vm_case_lit.yml new file mode 100644 index 0000000000..9f91801544 --- /dev/null +++ b/benchmark/vm_case_lit.yml @@ -0,0 +1,23 @@ +# loop_count is not utilized since `i` is involved in the script +benchmark: + vm_case_lit: | + i = 0 + @ret = [ "foo", true, false, :sym, 6, nil, 0.1, 0xffffffffffffffff ] + def foo(i) + @ret[i % @ret.size] + end + + while i<6_000_000 + case foo(i) + when "foo" then :foo + when true then true + when false then false + when :sym then :sym + when 6 then :fix + when nil then nil + when 0.1 then :float + when 0xffffffffffffffff then :big + end + i += 1 + end +loop_count: 1 diff --git a/benchmark/bm_vm3_clearmethodcache.rb b/benchmark/vm_clearmethodcache.rb index 9661323cd2..9661323cd2 100644 --- a/benchmark/bm_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/vm_defined_method.yml b/benchmark/vm_defined_method.yml new file mode 100644 index 0000000000..347e0cfd33 --- /dev/null +++ b/benchmark/vm_defined_method.yml @@ -0,0 +1,8 @@ +prelude: | + class Object + define_method(:m){} + end +benchmark: + vm_defined_method: | + m; m; m; m; m; m; m; m; +loop_count: 6000000 diff --git a/benchmark/vm_dstr.yml b/benchmark/vm_dstr.yml new file mode 100644 index 0000000000..30c7a3193c --- /dev/null +++ b/benchmark/vm_dstr.yml @@ -0,0 +1,6 @@ +prelude: | + x = y = 'z' +benchmark: + vm_dstr: | + str = "foo#{x}bar#{y}baz" +loop_count: 6000000 diff --git a/benchmark/bm_vm2_dstr.rb b/benchmark/vm_dstr_ary.rb index 58c0f7bbc3..1d3aa3b97b 100644 --- a/benchmark/bm_vm2_dstr.rb +++ b/benchmark/vm_dstr_ary.rb @@ -1,5 +1,5 @@ i = 0 -x = y = 'z' +x = y = [] while i<6_000_000 # benchmark loop 2 i += 1 str = "foo#{x}bar#{y}baz" diff --git a/benchmark/bm_vm2_method.rb b/benchmark/vm_dstr_bool.rb index a8ccff7138..631ca54755 100644 --- a/benchmark/bm_vm2_method.rb +++ b/benchmark/vm_dstr_bool.rb @@ -1,9 +1,7 @@ -def m - nil -end - i = 0 +x = true +y = false while i<6_000_000 # benchmark loop 2 i += 1 - m; m; m; m; m; m; m; m; + 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/bm_vm2_eval.rb b/benchmark/vm_dstr_int.rb index 307cfc28ef..ed380d7595 100644 --- a/benchmark/bm_vm2_eval.rb +++ b/benchmark/vm_dstr_int.rb @@ -1,6 +1,5 @@ i = 0 while i<6_000_000 # benchmark loop 2 i += 1 - eval("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/bm_vm2_array.rb b/benchmark/vm_dstr_str.rb index df9037c83c..45fc107892 100644 --- a/benchmark/bm_vm2_array.rb +++ b/benchmark/vm_dstr_str.rb @@ -1,5 +1,6 @@ i = 0 +x = y = "" while i<6_000_000 # benchmark loop 2 i += 1 - a = [1,2,3,4,5,6,7,8,9,10] + str = "foo#{x}bar#{y}baz" end diff --git a/benchmark/bm_vm2_regexp.rb b/benchmark/vm_dstr_sym.rb index 55f9e957a3..484b8f8150 100644 --- a/benchmark/bm_vm2_regexp.rb +++ b/benchmark/vm_dstr_sym.rb @@ -1,6 +1,6 @@ i = 0 -str = 'xxxhogexxx' +x = y = :z while i<6_000_000 # benchmark loop 2 - /hoge/ =~ str i += 1 + str = "foo#{x}bar#{y}baz" end diff --git a/benchmark/vm_ensure.yml b/benchmark/vm_ensure.yml new file mode 100644 index 0000000000..4ea62f30de --- /dev/null +++ b/benchmark/vm_ensure.yml @@ -0,0 +1,14 @@ +# Not utilizing loop_count since using it for this is too unstable for now +benchmark: + vm_ensure: | + i = 0 + while i<30_000_000 + i += 1 + begin + begin + ensure + end + ensure + end + end +loop_count: 1 diff --git a/benchmark/vm_eval.yml b/benchmark/vm_eval.yml new file mode 100644 index 0000000000..7ba1a8d1de --- /dev/null +++ b/benchmark/vm_eval.yml @@ -0,0 +1,4 @@ +benchmark: + vm_eval: | + eval("1") +loop_count: 6000000 diff --git a/benchmark/vm_fiber_allocate.yml b/benchmark/vm_fiber_allocate.yml new file mode 100644 index 0000000000..b5a54e1ddf --- /dev/null +++ b/benchmark/vm_fiber_allocate.yml @@ -0,0 +1,8 @@ +prelude: | + # Disable GC to see raw throughput: + GC.disable +benchmark: + vm_fiber_allocate: | + fiber = Fiber.new{Fiber.yield} + fiber.resume +loop_count: 100000 diff --git a/benchmark/vm_fiber_count.yml b/benchmark/vm_fiber_count.yml new file mode 100644 index 0000000000..b83d3152d4 --- /dev/null +++ b/benchmark/vm_fiber_count.yml @@ -0,0 +1,10 @@ +# On Linux, you will need to increase the maximum number of memory maps: +# sudo sysctl -w vm.max_map_count=200000 +prelude: | + fibers = [] +benchmark: + vm_fiber_count: | + fiber = Fiber.new{Fiber.yield} + fibers << fiber + fiber.resume +loop_count: 100000 diff --git a/benchmark/vm_fiber_reuse.yml b/benchmark/vm_fiber_reuse.yml new file mode 100644 index 0000000000..4ca41085b1 --- /dev/null +++ b/benchmark/vm_fiber_reuse.yml @@ -0,0 +1,14 @@ +prelude: | + GC.disable + fibers = [] +benchmark: + vm_fiber_reuse: | + 1024.times do + fiber = Fiber.new{Fiber.yield} + fibers << fiber + fiber.resume + end + + fibers.clear + GC.start +loop_count: 200 diff --git a/benchmark/vm_fiber_reuse_gc.yml b/benchmark/vm_fiber_reuse_gc.yml new file mode 100644 index 0000000000..892622f121 --- /dev/null +++ b/benchmark/vm_fiber_reuse_gc.yml @@ -0,0 +1,12 @@ +# https://bugs.ruby-lang.org/issues/16009 +prelude: | + fibers = [] +benchmark: + vm_fiber_reuse_gc: | + 2000.times do + fiber = Fiber.new{Fiber.yield} + fibers << fiber + fiber.resume + end + fibers.clear +loop_count: 100 diff --git a/benchmark/vm_fiber_switch.yml b/benchmark/vm_fiber_switch.yml new file mode 100644 index 0000000000..3de36b66eb --- /dev/null +++ b/benchmark/vm_fiber_switch.yml @@ -0,0 +1,9 @@ +prelude: | + # based on benchmark for [ruby-core:65518] [Feature #10341] by Knut Franke + fib = Fiber.new do + loop { Fiber.yield } + end +benchmark: + vm_fiber_switch: | + fib.resume +loop_count: 20000000 diff --git a/benchmark/vm_float_simple.yml b/benchmark/vm_float_simple.yml new file mode 100644 index 0000000000..92f5fd52ab --- /dev/null +++ b/benchmark/vm_float_simple.yml @@ -0,0 +1,8 @@ +prelude: | + f = 0.0 +benchmark: + vm_float_simple: | + f += 0.1; f -= 0.1 + f += 0.1; f -= 0.1 + f += 0.1; f -= 0.1 +loop_count: 30000000 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/vm_freezestring.yml b/benchmark/vm_freezestring.yml new file mode 100644 index 0000000000..facc9aa043 --- /dev/null +++ b/benchmark/vm_freezestring.yml @@ -0,0 +1,10 @@ +prelude: | + class String + def freeze + -self + end + end +benchmark: + vm_freezestring: | + "tXnL1BP5T1WPXMjuFNLQtallEtRcay1t2lHtJSrlVsDgvunlbtfpr/DGdH0NGYE9".freeze +loop_count: 6000000 diff --git a/benchmark/bm_vm3_gc.rb b/benchmark/vm_gc.rb index 7db9829d44..e668026915 100755..100644 --- a/benchmark/bm_vm3_gc.rb +++ b/benchmark/vm_gc.rb @@ -1,4 +1,3 @@ -#! /usr/bin/ruby 5000.times do 100.times do {"xxxx"=>"yyyy"} diff --git a/benchmark/vm_gc_old_full.rb b/benchmark/vm_gc_old_full.rb new file mode 100644 index 0000000000..cfdfc8c5a5 --- /dev/null +++ b/benchmark/vm_gc_old_full.rb @@ -0,0 +1,4 @@ +old_object = Array.new(1_000_000){''} +100.times do + GC.start +end diff --git a/benchmark/vm_gc_old_immediate.rb b/benchmark/vm_gc_old_immediate.rb new file mode 100644 index 0000000000..ad22feb655 --- /dev/null +++ b/benchmark/vm_gc_old_immediate.rb @@ -0,0 +1,4 @@ +old_object = Array.new(1_000_000){''} +30_000.times do + GC.start(full_mark: false, immediate_sweep: true) +end diff --git a/benchmark/vm_gc_old_lazy.rb b/benchmark/vm_gc_old_lazy.rb new file mode 100644 index 0000000000..b74d44baf1 --- /dev/null +++ b/benchmark/vm_gc_old_lazy.rb @@ -0,0 +1,4 @@ +old_object = Array.new(1_000_000){''} +30_000.times do + GC.start(full_mark: false, immediate_sweep: false) +end diff --git a/benchmark/vm_gc_short_lived.yml b/benchmark/vm_gc_short_lived.yml new file mode 100644 index 0000000000..29c803fee3 --- /dev/null +++ b/benchmark/vm_gc_short_lived.yml @@ -0,0 +1,9 @@ +benchmark: + vm_gc_short_lived: | + a = '' # short-lived String + b = '' + c = '' + d = '' + e = '' + f = '' +loop_count: 30000000 diff --git a/benchmark/vm_gc_short_with_complex_long.yml b/benchmark/vm_gc_short_with_complex_long.yml new file mode 100644 index 0000000000..4b6c3ed7b9 --- /dev/null +++ b/benchmark/vm_gc_short_with_complex_long.yml @@ -0,0 +1,25 @@ +prelude: | + def nested_hash h, n + if n == 0 + '' + else + 10.times{ + h[Object.new] = nested_hash(h, n-1) + } + end + end + + long_lived = Hash.new + nested_hash long_lived, 6 + + GC.start + GC.start +benchmark: + vm_gc_short_with_complex_long: | + a = '' # short-lived String + b = '' + c = '' + d = '' + e = '' + f = '' +loop_count: 30000000 diff --git a/benchmark/vm_gc_short_with_long.yml b/benchmark/vm_gc_short_with_long.yml new file mode 100644 index 0000000000..03ba0f95a9 --- /dev/null +++ b/benchmark/vm_gc_short_with_long.yml @@ -0,0 +1,13 @@ +prelude: | + long_lived = Array.new(1_000_000){|i| "#{i}"} + GC.start + GC.start +benchmark: + vm_gc_short_with_long: | + a = '' # short-lived String + b = '' + c = '' + d = '' + e = '' + f = '' +loop_count: 30000000 diff --git a/benchmark/vm_gc_short_with_symbol.yml b/benchmark/vm_gc_short_with_symbol.yml new file mode 100644 index 0000000000..129b8bf4ed --- /dev/null +++ b/benchmark/vm_gc_short_with_symbol.yml @@ -0,0 +1,13 @@ +prelude: | + 50_000.times{|i| sym = "sym#{i}".to_sym} + GC.start + GC.start +benchmark: + vm_gc_short_with_symbol: | + a = '' # short-lived String + b = '' + c = '' + d = '' + e = '' + f = '' +loop_count: 30000000 diff --git a/benchmark/vm_gc_wb_ary.yml b/benchmark/vm_gc_wb_ary.yml new file mode 100644 index 0000000000..e3293e72d0 --- /dev/null +++ b/benchmark/vm_gc_wb_ary.yml @@ -0,0 +1,12 @@ +prelude: | + short_lived_ary = [] + + if RUBY_VERSION >= "2.2.0" + GC.start(full_mark: false, immediate_mark: true, immediate_sweep: true) + end + + short_lived = '' +benchmark: + vm_gc_wb_ary: | + short_lived_ary[0] = short_lived # write barrier +loop_count: 30000000 diff --git a/benchmark/vm_gc_wb_ary_promoted.yml b/benchmark/vm_gc_wb_ary_promoted.yml new file mode 100644 index 0000000000..003995945b --- /dev/null +++ b/benchmark/vm_gc_wb_ary_promoted.yml @@ -0,0 +1,15 @@ +prelude: | + long_lived = [] + + if RUBY_VERSION > "2.2.0" + 3.times{ GC.start(full_mark: false, immediate_mark: true, immediate_sweep: true) } + elsif + GC.start + end + + short_lived = '' + +benchmark: + vm_gc_wb_ary_promoted: | + long_lived[0] = short_lived # write barrier +loop_count: 30000000 diff --git a/benchmark/vm_gc_wb_obj.yml b/benchmark/vm_gc_wb_obj.yml new file mode 100644 index 0000000000..a2a2ce2d18 --- /dev/null +++ b/benchmark/vm_gc_wb_obj.yml @@ -0,0 +1,15 @@ +prelude: | + class C + attr_accessor :foo + end + short_lived_obj = C.new + + if RUBY_VERSION >= "2.2.0" + GC.start(full_mark: false, immediate_mark: true, immediate_sweep: true) + end + + short_lived = '' +benchmark: + vm_gc_wb_obj: | + short_lived_obj.foo = short_lived # write barrier +loop_count: 30000000 diff --git a/benchmark/vm_gc_wb_obj_promoted.yml b/benchmark/vm_gc_wb_obj_promoted.yml new file mode 100644 index 0000000000..00a454ba72 --- /dev/null +++ b/benchmark/vm_gc_wb_obj_promoted.yml @@ -0,0 +1,17 @@ +prelude: | + class C + attr_accessor :foo + end + long_lived = C.new + + if RUBY_VERSION >= "2.2.0" + 3.times{ GC.start(full_mark: false, immediate_mark: true, immediate_sweep: true) } + elsif + GC.start + end + + short_lived = '' +benchmark: + 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/vm_ivar.yml b/benchmark/vm_ivar.yml new file mode 100644 index 0000000000..119531d5ef --- /dev/null +++ b/benchmark/vm_ivar.yml @@ -0,0 +1,6 @@ +prelude: "@a = 1\n" +benchmark: + 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/vm_ivar_set.yml b/benchmark/vm_ivar_set.yml new file mode 100644 index 0000000000..8bbb60043b --- /dev/null +++ b/benchmark/vm_ivar_set.yml @@ -0,0 +1,5 @@ +benchmark: + 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/vm_length.yml b/benchmark/vm_length.yml new file mode 100644 index 0000000000..5fd94e7d86 --- /dev/null +++ b/benchmark/vm_length.yml @@ -0,0 +1,8 @@ +prelude: | + a = 'abc' + b = [1, 2, 3] +benchmark: + 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/vm_lvar_init.yml b/benchmark/vm_lvar_init.yml new file mode 100644 index 0000000000..70a9b1c0ca --- /dev/null +++ b/benchmark/vm_lvar_init.yml @@ -0,0 +1,21 @@ +# while loop cost is not removed because `i` is used in the script +benchmark: + vm_lvar_init: | + def m v + unless v + # unreachable code + v1 = v2 = v3 = v4 = v5 = v6 = v7 = v8 = v9 = v10 = + v11 = v12 = v13 = v14 = v15 = v16 = v17 = v18 = v19 = v20 = + v21 = v22 = v23 = v24 = v25 = v26 = v27 = v28 = v29 = v30 = + v31 = v32 = v33 = v34 = v35 = v36 = v37 = v38 = v39 = v40 = + v41 = v42 = v43 = v44 = v45 = v46 = v47 = v48 = v49 = v50 = 1 + end + end + + i = 0 + + while i<30_000_000 + i += 1 + m i + end +loop_count: 1 diff --git a/benchmark/vm_lvar_set.yml b/benchmark/vm_lvar_set.yml new file mode 100644 index 0000000000..f29f763d81 --- /dev/null +++ b/benchmark/vm_lvar_set.yml @@ -0,0 +1,4 @@ +benchmark: + 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/vm_method.yml b/benchmark/vm_method.yml new file mode 100644 index 0000000000..d45e4ec572 --- /dev/null +++ b/benchmark/vm_method.yml @@ -0,0 +1,8 @@ +prelude: | + def m + nil + end +benchmark: + vm_method: | + m; m; m; m; m; m; m; m; +loop_count: 6000000 diff --git a/benchmark/vm_method_missing.yml b/benchmark/vm_method_missing.yml new file mode 100644 index 0000000000..3da456c0bb --- /dev/null +++ b/benchmark/vm_method_missing.yml @@ -0,0 +1,11 @@ +prelude: | + class C + def method_missing mid + end + end + + obj = C.new +benchmark: + 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/vm_method_with_block.yml b/benchmark/vm_method_with_block.yml new file mode 100644 index 0000000000..281a481394 --- /dev/null +++ b/benchmark/vm_method_with_block.yml @@ -0,0 +1,8 @@ +prelude: | + def m + nil + end +benchmark: + vm_method_with_block: | + m{}; m{}; m{}; m{}; m{}; m{}; m{}; m{}; +loop_count: 6000000 diff --git a/benchmark/vm_module_ann_const_set.yml b/benchmark/vm_module_ann_const_set.yml new file mode 100644 index 0000000000..243229ba4a --- /dev/null +++ b/benchmark/vm_module_ann_const_set.yml @@ -0,0 +1,4 @@ +benchmark: + vm_module_ann_const_set: | + Module.new.const_set(:X, Module.new) +loop_count: 6000000 diff --git a/benchmark/vm_module_const_set.yml b/benchmark/vm_module_const_set.yml new file mode 100644 index 0000000000..e5a24181a9 --- /dev/null +++ b/benchmark/vm_module_const_set.yml @@ -0,0 +1,8 @@ +prelude: | + module M + end + $VERBOSE = nil +benchmark: + vm_module_const_set: | + M.const_set(:X, Module.new) +loop_count: 6000000 diff --git a/benchmark/vm_mutex.yml b/benchmark/vm_mutex.yml new file mode 100644 index 0000000000..abcf1e28ce --- /dev/null +++ b/benchmark/vm_mutex.yml @@ -0,0 +1,8 @@ +prelude: | + require 'thread' + + m = Thread::Mutex.new +benchmark: + vm_mutex: | + m.synchronize{} +loop_count: 6000000 diff --git a/benchmark/vm_neq.yml b/benchmark/vm_neq.yml new file mode 100644 index 0000000000..fb04d15ae8 --- /dev/null +++ b/benchmark/vm_neq.yml @@ -0,0 +1,7 @@ +prelude: | + obj1 = Object.new + obj2 = Object.new +benchmark: + vm_neq: | + obj1 != obj2 +loop_count: 30000000 diff --git a/benchmark/vm_newlambda.yml b/benchmark/vm_newlambda.yml new file mode 100644 index 0000000000..0b9787d91a --- /dev/null +++ b/benchmark/vm_newlambda.yml @@ -0,0 +1,4 @@ +benchmark: + vm_newlambda: | + lambda {} +loop_count: 6000000 diff --git a/benchmark/vm_not.yml b/benchmark/vm_not.yml new file mode 100644 index 0000000000..c68dde3c50 --- /dev/null +++ b/benchmark/vm_not.yml @@ -0,0 +1,6 @@ +prelude: | + obj = Object.new +benchmark: + vm_not: | + !obj +loop_count: 30000000 diff --git a/benchmark/vm_poly_method.yml b/benchmark/vm_poly_method.yml new file mode 100644 index 0000000000..dd2f4e71de --- /dev/null +++ b/benchmark/vm_poly_method.yml @@ -0,0 +1,24 @@ +# loop_count is not utilized since `i` is involved in the script +benchmark: + vm_poly_method: | + class C1 + def m + 1 + end + end + class C2 + def m + 2 + end + end + + o1 = C1.new + o2 = C2.new + + i = 0 + while i<6_000_000 + o = (i % 2 == 0) ? o1 : o2 + o.m; o.m; o.m; o.m; o.m; o.m; o.m; o.m + i += 1 + end +loop_count: 1 diff --git a/benchmark/vm_poly_method_ov.yml b/benchmark/vm_poly_method_ov.yml new file mode 100644 index 0000000000..bca1b62729 --- /dev/null +++ b/benchmark/vm_poly_method_ov.yml @@ -0,0 +1,24 @@ +# loop_count is not utilized since `i` is involved in the script +benchmark: + vm_poly_method_ov: | + class C1 + def m + 1 + end + end + class C2 + def m + 2 + end + end + + o1 = C1.new + o2 = C2.new + + i = 0 + while i<6_000_000 + o = (i % 2 == 0) ? o1 : o2 + # o.m; o.m; o.m; o.m; o.m; o.m; o.m; o.m + i += 1 + end +loop_count: 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/vm_poly_singleton.yml b/benchmark/vm_poly_singleton.yml new file mode 100644 index 0000000000..c7923160fb --- /dev/null +++ b/benchmark/vm_poly_singleton.yml @@ -0,0 +1,18 @@ +# loop_count is not utilized since `i` is involved in the script +benchmark: + vm_poly_singleton: | + class C1 + def m; 1; end + end + + o1 = C1.new + o2 = C1.new + o2.singleton_class + + i = 0 + while i<6_000_000 # benchmark loop 2 + o = (i % 2 == 0) ? o1 : o2 + o.m; o.m; o.m; o.m; o.m; o.m; o.m; o.m + i += 1 + end +loop_count: 1 diff --git a/benchmark/vm_proc.yml b/benchmark/vm_proc.yml new file mode 100644 index 0000000000..2f8de6c272 --- /dev/null +++ b/benchmark/vm_proc.yml @@ -0,0 +1,12 @@ +prelude: | + def m &b + b + end + + pr = m{ + a = 1 + } +benchmark: + vm_proc: | + pr.call +loop_count: 6000000 diff --git a/benchmark/vm_raise1.yml b/benchmark/vm_raise1.yml new file mode 100644 index 0000000000..247d9f70ee --- /dev/null +++ b/benchmark/vm_raise1.yml @@ -0,0 +1,16 @@ +prelude: | + def rec n + if n > 0 + rec n-1 + else + raise + end + end +benchmark: + vm_raise1: | + begin + rec 1 + rescue + # ignore + end +loop_count: 6000000 diff --git a/benchmark/vm_raise2.yml b/benchmark/vm_raise2.yml new file mode 100644 index 0000000000..f0fa047b3c --- /dev/null +++ b/benchmark/vm_raise2.yml @@ -0,0 +1,16 @@ +prelude: | + def rec n + if n > 0 + rec n-1 + else + raise + end + end +benchmark: + vm_raise2: | + begin + rec 10 + rescue + # ignore + end +loop_count: 6000000 diff --git a/benchmark/vm_regexp.yml b/benchmark/vm_regexp.yml new file mode 100644 index 0000000000..2aa3d94dbd --- /dev/null +++ b/benchmark/vm_regexp.yml @@ -0,0 +1,8 @@ +prelude: | + str = 'xxxhogexxx' +benchmark: + vm_regexp: | + /hoge/ =~ str + vm_regexp_invert: | + str =~ /hoge/ +loop_count: 6000000 diff --git a/benchmark/vm_rescue.yml b/benchmark/vm_rescue.yml new file mode 100644 index 0000000000..b4a0af521f --- /dev/null +++ b/benchmark/vm_rescue.yml @@ -0,0 +1,6 @@ +benchmark: + vm_rescue: | + begin + rescue + end +loop_count: 30000000 diff --git a/benchmark/vm_send.yml b/benchmark/vm_send.yml new file mode 100644 index 0000000000..f31bc7ac89 --- /dev/null +++ b/benchmark/vm_send.yml @@ -0,0 +1,14 @@ +prelude: | + class C + def m + end + end + + o = C.new + m = :m +benchmark: + 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/vm_simplereturn.yml b/benchmark/vm_simplereturn.yml new file mode 100644 index 0000000000..c9829cff0b --- /dev/null +++ b/benchmark/vm_simplereturn.yml @@ -0,0 +1,7 @@ +prelude: | + def m + return 1 + end +benchmark: + vm_simplereturn: m +loop_count: 30000000 diff --git a/benchmark/vm_string_literal.yml b/benchmark/vm_string_literal.yml new file mode 100644 index 0000000000..64439c7980 --- /dev/null +++ b/benchmark/vm_string_literal.yml @@ -0,0 +1,4 @@ +benchmark: + vm_string_literal: | + x = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +loop_count: 6000000 diff --git a/benchmark/vm_struct_big_aref_hi.yml b/benchmark/vm_struct_big_aref_hi.yml new file mode 100644 index 0000000000..4cf78970cb --- /dev/null +++ b/benchmark/vm_struct_big_aref_hi.yml @@ -0,0 +1,7 @@ +prelude: | + s = Struct.new(*('a'..'z').map { |x| x.to_sym }) + x = s.new +benchmark: + vm_struct_big_aref_hi: | + x.z # x[25] +loop_count: 6000000 diff --git a/benchmark/vm_struct_big_aref_lo.yml b/benchmark/vm_struct_big_aref_lo.yml new file mode 100644 index 0000000000..c91af27fa5 --- /dev/null +++ b/benchmark/vm_struct_big_aref_lo.yml @@ -0,0 +1,7 @@ +prelude: | + s = Struct.new(*('a'..'z').map { |x| x.to_sym }) + x = s.new +benchmark: + vm_struct_big_aref_lo: | + x.k # x[10] +loop_count: 6000000 diff --git a/benchmark/vm_struct_big_aset.yml b/benchmark/vm_struct_big_aset.yml new file mode 100644 index 0000000000..69550d14ea --- /dev/null +++ b/benchmark/vm_struct_big_aset.yml @@ -0,0 +1,11 @@ +# loop_count is not utilized since `i` is involved in the script +benchmark: + vm_struct_big_aset: | + s = Struct.new(*('a'..'z').map { |x| x.to_sym }) + x = s.new + i = 0 + while i<6_000_000 + i += 1 + x.k = i # x[10] = i + end +loop_count: 1 diff --git a/benchmark/vm_struct_big_href_hi.yml b/benchmark/vm_struct_big_href_hi.yml new file mode 100644 index 0000000000..09b764dd13 --- /dev/null +++ b/benchmark/vm_struct_big_href_hi.yml @@ -0,0 +1,7 @@ +prelude: | + s = Struct.new(*('a'..'z').map { |x| x.to_sym }) + x = s.new +benchmark: + vm_struct_big_href_hi: | + x[:z] +loop_count: 6000000 diff --git a/benchmark/vm_struct_big_href_lo.yml b/benchmark/vm_struct_big_href_lo.yml new file mode 100644 index 0000000000..d2f00b220f --- /dev/null +++ b/benchmark/vm_struct_big_href_lo.yml @@ -0,0 +1,7 @@ +prelude: | + s = Struct.new(*('a'..'z').map { |x| x.to_sym }) + x = s.new +benchmark: + vm_struct_big_href_lo: | + x[:k] +loop_count: 6000000 diff --git a/benchmark/vm_struct_big_hset.yml b/benchmark/vm_struct_big_hset.yml new file mode 100644 index 0000000000..fc45cbee9c --- /dev/null +++ b/benchmark/vm_struct_big_hset.yml @@ -0,0 +1,11 @@ +# loop_count is not utilized since `i` is involved in the script +benchmark: + vm_struct_big_hset: | + s = Struct.new(*('a'..'z').map { |x| x.to_sym }) + x = s.new + i = 0 + while i<6_000_000 + i += 1 + x[:k] = i + end +loop_count: 1 diff --git a/benchmark/vm_struct_small_aref.yml b/benchmark/vm_struct_small_aref.yml new file mode 100644 index 0000000000..5a83251d1e --- /dev/null +++ b/benchmark/vm_struct_small_aref.yml @@ -0,0 +1,7 @@ +prelude: | + s = Struct.new(:a, :b, :c) + x = s.new +benchmark: + vm_struct_small_aref: | + x.a +loop_count: 6000000 diff --git a/benchmark/vm_struct_small_aset.yml b/benchmark/vm_struct_small_aset.yml new file mode 100644 index 0000000000..74f435f126 --- /dev/null +++ b/benchmark/vm_struct_small_aset.yml @@ -0,0 +1,11 @@ +# loop_count is not utilized since `i` is involved in the script +benchmark: + vm_struct_small_aset: | + s = Struct.new(:a, :b, :c) + x = s.new + i = 0 + while i<6_000_000 + i += 1 + x.a = i + end +loop_count: 1 diff --git a/benchmark/vm_struct_small_href.yml b/benchmark/vm_struct_small_href.yml new file mode 100644 index 0000000000..6b7d7f39e7 --- /dev/null +++ b/benchmark/vm_struct_small_href.yml @@ -0,0 +1,7 @@ +prelude: | + s = Struct.new(:a, :b, :c) + x = s.new +benchmark: + vm_struct_small_href: | + x[:a] +loop_count: 6000000 diff --git a/benchmark/vm_struct_small_hset.yml b/benchmark/vm_struct_small_hset.yml new file mode 100644 index 0000000000..5d43b150de --- /dev/null +++ b/benchmark/vm_struct_small_hset.yml @@ -0,0 +1,7 @@ +prelude: | + s = Struct.new(:a, :b, :c) + x = s.new +benchmark: + vm_struct_small_hset: | + x[:a] = 1 +loop_count: 6000000 diff --git a/benchmark/vm_super.yml b/benchmark/vm_super.yml new file mode 100644 index 0000000000..0d1e965c6e --- /dev/null +++ b/benchmark/vm_super.yml @@ -0,0 +1,17 @@ +prelude: | + class C + def m + 1 + end + end + + class CC < C + def m + super() + end + end + + obj = CC.new +benchmark: + 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/vm_swap.yml b/benchmark/vm_swap.yml new file mode 100644 index 0000000000..e824a65e0a --- /dev/null +++ b/benchmark/vm_swap.yml @@ -0,0 +1,7 @@ +prelude: | + a = 1 + b = 2 +benchmark: + vm_swap: | + a, b = b, a +loop_count: 30000000 diff --git a/benchmark/vm_symbol_block_pass.rb b/benchmark/vm_symbol_block_pass.rb new file mode 100644 index 0000000000..1d433353e1 --- /dev/null +++ b/benchmark/vm_symbol_block_pass.rb @@ -0,0 +1,13 @@ +class C + 1000.times {|i| + eval("def i#{i};end") + } +end + +c = C.new +m = C.instance_methods(false) +5_000.times do + m.each do |n| + c.tap(&n) + end +end diff --git a/benchmark/vm_thread_alive_check.yml b/benchmark/vm_thread_alive_check.yml new file mode 100644 index 0000000000..d21737d3e8 --- /dev/null +++ b/benchmark/vm_thread_alive_check.yml @@ -0,0 +1,8 @@ +benchmark: + vm_thread_alive_check: | + t = Thread.new{} + while t.alive? + Thread.pass + end +loop_count: 50_000 + diff --git a/benchmark/vm_thread_close.rb b/benchmark/vm_thread_close.rb new file mode 100644 index 0000000000..3e9a265ce8 --- /dev/null +++ b/benchmark/vm_thread_close.rb @@ -0,0 +1,6 @@ +1000.times { Thread.new { sleep } } +i = 0 +while i<100_000 # benchmark loop 3 + i += 1 + IO.pipe.each(&:close) +end diff --git a/benchmark/vm_thread_condvar1.rb b/benchmark/vm_thread_condvar1.rb new file mode 100644 index 0000000000..feed27c3ad --- /dev/null +++ b/benchmark/vm_thread_condvar1.rb @@ -0,0 +1,28 @@ +# two threads, two mutex, two condvar ping-pong +require 'thread' +m1 = Thread::Mutex.new +m2 = Thread::Mutex.new +cv1 = Thread::ConditionVariable.new +cv2 = Thread::ConditionVariable.new +max = 100000 +i = 0 +wait = nil +m2.synchronize do + wait = Thread.new do + m1.synchronize do + m2.synchronize { cv2.signal } + while (i += 1) < max + cv1.wait(m1) + cv2.signal + end + end + end + cv2.wait(m2) +end +m1.synchronize do + while i < max + cv1.signal + cv2.wait(m1) + end +end +wait.join diff --git a/benchmark/vm_thread_condvar2.rb b/benchmark/vm_thread_condvar2.rb new file mode 100644 index 0000000000..6590c4134b --- /dev/null +++ b/benchmark/vm_thread_condvar2.rb @@ -0,0 +1,35 @@ +# many threads, one mutex, many condvars +require 'thread' +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 = Thread::ConditionVariable.new + scvs << start_cv + start_mtx = Thread::Mutex.new + start_mtx.synchronize do + th = Thread.new(start_mtx, start_cv) do |sm, scv| + m.synchronize do + sm.synchronize { scv.signal } + max.times do + cv2.signal if (waiting += 1) == n + cv1.wait(m) + end + end + end + start_cv.wait(start_mtx) + th + end +end +m.synchronize do + max.times do + cv2.wait(m) until waiting == n + waiting = 0 + cv1.broadcast + end +end +waiters.each(&:join) diff --git a/benchmark/bm_vm_thread_create_join.rb b/benchmark/vm_thread_create_join.rb index 393cd45df9..393cd45df9 100644 --- a/benchmark/bm_vm_thread_create_join.rb +++ b/benchmark/vm_thread_create_join.rb diff --git a/benchmark/bm_vm_thread_mutex1.rb b/benchmark/vm_thread_mutex1.rb index 5c9f85dfb7..66e42c85e1 100644 --- a/benchmark/bm_vm_thread_mutex1.rb +++ b/benchmark/vm_thread_mutex1.rb @@ -1,7 +1,7 @@ # one thread, one mutex (no contention) require 'thread' -m = Mutex.new +m = Thread::Mutex.new r = 0 max = 2000 lmax = max * max diff --git a/benchmark/bm_vm_thread_mutex2.rb b/benchmark/vm_thread_mutex2.rb index 10de59054f..6e6c804c31 100644 --- a/benchmark/bm_vm_thread_mutex2.rb +++ b/benchmark/vm_thread_mutex2.rb @@ -1,7 +1,7 @@ # two threads, one mutex require 'thread' -m = Mutex.new +m = Thread::Mutex.new r = 0 max = 2000 lmax = (max * max)/2 diff --git a/benchmark/bm_vm_thread_mutex3.rb b/benchmark/vm_thread_mutex3.rb index 7f9a44b39d..c750dc542a 100644 --- a/benchmark/bm_vm_thread_mutex3.rb +++ b/benchmark/vm_thread_mutex3.rb @@ -1,7 +1,7 @@ # 1000 threads, one mutex require 'thread' -m = Mutex.new +m = Thread::Mutex.new r = 0 max = 2000 (1..max).map{ diff --git a/benchmark/bm_vm_thread_pass.rb b/benchmark/vm_thread_pass.rb index b5b3c0bc85..438bd08d45 100644 --- a/benchmark/bm_vm_thread_pass.rb +++ b/benchmark/vm_thread_pass.rb @@ -1,8 +1,8 @@ -# Plenty Thtread.pass +# Plenty Thread.pass # A performance may depend on GVL implementation. -tmax = (ARGV.shift || 2).to_i -lmax = 200_000 / tmax +tmax = (ARGV.shift || 8).to_i +lmax = 400_000 / tmax (1..tmax).map{ Thread.new{ diff --git a/benchmark/vm_thread_pass_flood.rb b/benchmark/vm_thread_pass_flood.rb new file mode 100644 index 0000000000..65df8e6154 --- /dev/null +++ b/benchmark/vm_thread_pass_flood.rb @@ -0,0 +1,10 @@ +# n.b. this is a good test for GVL when pinned to a single CPU + +5_000.times{ + Thread.new{loop{Thread.pass}} +} + +i = 0 +while i<10_000 + i += 1 +end diff --git a/benchmark/bm_vm_thread_pipe.rb b/benchmark/vm_thread_pipe.rb index 272d231eba..112a621905 100644 --- a/benchmark/bm_vm_thread_pipe.rb +++ b/benchmark/vm_thread_pipe.rb @@ -1,4 +1,4 @@ -# Mesure small and plenty pipe read/write. +# Measure small and plenty pipe read/write. # A performance may depend on GVL implementation. lmax = 100_000 diff --git a/benchmark/vm_thread_queue.rb b/benchmark/vm_thread_queue.rb new file mode 100644 index 0000000000..1dd3696a3c --- /dev/null +++ b/benchmark/vm_thread_queue.rb @@ -0,0 +1,18 @@ +require 'thread' + +n = 10_000_000 +q = Thread::Queue.new +consumer = Thread.new{ + while q.pop + # consuming + end +} + +producer = Thread.new{ + n.times{ + q.push true + } + q.push nil +} + +consumer.join diff --git a/benchmark/vm_thread_sized_queue.rb b/benchmark/vm_thread_sized_queue.rb new file mode 100644 index 0000000000..7b9af5482b --- /dev/null +++ b/benchmark/vm_thread_sized_queue.rb @@ -0,0 +1,20 @@ +require 'thread' +# on producer, one consumer + +n = 1_000_000 +q = Thread::SizedQueue.new(100) +consumer = Thread.new{ + while q.pop + # consuming + end +} + +producer = Thread.new{ + while n > 0 + q.push true + n -= 1 + end + q.push nil +} + +consumer.join diff --git a/benchmark/vm_thread_sized_queue2.rb b/benchmark/vm_thread_sized_queue2.rb new file mode 100644 index 0000000000..de9f55e978 --- /dev/null +++ b/benchmark/vm_thread_sized_queue2.rb @@ -0,0 +1,23 @@ +require 'thread' +# one producer, many consumers +n = 1_000_000 +m = 10 +q = Thread::SizedQueue.new(100) +consumers = m.times.map do + Thread.new do + while q.pop + # consuming + end + end +end + +producer = Thread.new do + while n > 0 + q.push true + n -= 1 + end + m.times { q.push nil } +end + +producer.join +consumers.each(&:join) diff --git a/benchmark/vm_thread_sized_queue3.rb b/benchmark/vm_thread_sized_queue3.rb new file mode 100644 index 0000000000..ce5f1796d8 --- /dev/null +++ b/benchmark/vm_thread_sized_queue3.rb @@ -0,0 +1,22 @@ +require 'thread' +# many producers, one consumer +n = 1_000_000 +m = 10 +q = Thread::SizedQueue.new(100) +consumer = Thread.new do + while q.pop + # consuming + end +end + +producers = m.times.map do + Thread.new do + while n > 0 + q.push true + n -= 1 + end + end +end +producers.each(&:join) +q.push nil +consumer.join diff --git a/benchmark/vm_thread_sized_queue4.rb b/benchmark/vm_thread_sized_queue4.rb new file mode 100644 index 0000000000..a9b7d80ec0 --- /dev/null +++ b/benchmark/vm_thread_sized_queue4.rb @@ -0,0 +1,26 @@ +require 'thread' +# many producers, many consumers +nr = 1_000_000 +n = 10 +m = 10 +q = Thread::SizedQueue.new(100) +consumers = n.times.map do + Thread.new do + while q.pop + # consuming + end + end +end + +producers = m.times.map do + Thread.new do + while nr > 0 + q.push true + nr -= 1 + end + end +end + +producers.each(&:join) +n.times { q.push nil } +consumers.each(&:join) diff --git a/benchmark/vm_thread_sleep.yml b/benchmark/vm_thread_sleep.yml new file mode 100644 index 0000000000..96901d8466 --- /dev/null +++ b/benchmark/vm_thread_sleep.yml @@ -0,0 +1,4 @@ +benchmark: + vm_thread_sleep: | + Thread.new { sleep } +loop_count: 10_000 diff --git a/benchmark/vm_unif1.yml b/benchmark/vm_unif1.yml new file mode 100644 index 0000000000..04187bb0e2 --- /dev/null +++ b/benchmark/vm_unif1.yml @@ -0,0 +1,7 @@ +prelude: | + def m a, b + end +benchmark: + vm_unif1: | + m 100, 200 +loop_count: 6000000 diff --git a/benchmark/vm_yield.yml b/benchmark/vm_yield.yml new file mode 100644 index 0000000000..230be3d84f --- /dev/null +++ b/benchmark/vm_yield.yml @@ -0,0 +1,13 @@ +# while loop cost is not removed due to benchmark_driver.gem's limitation +benchmark: + vm_yield: | + def m + i = 0 + while i<30_000_000 + i += 1 + yield + end + end + + m{} +loop_count: 1 diff --git a/benchmark/vm_zsuper.yml b/benchmark/vm_zsuper.yml new file mode 100644 index 0000000000..bfb5837578 --- /dev/null +++ b/benchmark/vm_zsuper.yml @@ -0,0 +1,18 @@ +prelude: | + class C + def m a + 1 + end + end + + class CC < C + def m a + super + end + end + + obj = CC.new +benchmark: + 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)" |
