Files
ruby/benchmark
Jean Boussier 37325e9f7a Array#flatten: optimize the common *args.flatten pattern
A common Ruby idiom for variadic methods is to flatten the argument
list so that it can be called with either variadic arguments or an
Array.

e.g. from the sqlite3 gem:

```ruby
def bind_params(*bind_vars)
  bind_vars.flatten.each do |var|
  # ...
```

However, as soon as `flatten` encounter another array, it has to
protect against recursion, which requires allocating an expensive
identity Hash.
So this pattern has a relatively high cost when called with
a single array argument (e.g. `bind_params [1, 2, 3]`).

We can specialize for that common case without noticeably
impacting other usages of `Array#flatten`:

|                              |compare-ruby|built-ruby|
|:-----------------------------|-----------:|---------:|
|small_flat_ary.flatten        |      7.547M|    7.974M|
|                              |           -|     1.06x|
|small_flat_ary.flatten!       |      6.031M|    6.105M|
|                              |           -|     1.01x|
|large_flat_ary.flatten        |    465.896k|  485.861k|
|                              |           -|     1.04x|
|large_flat_ary.flatten!       |    455.872k|  478.103k|
|                              |           -|     1.05x|
|small_pairs_ary.flatten       |      1.327M|    1.407M|
|                              |           -|     1.06x|
|small_pairs_ary.flatten!      |      1.165M|    1.153M|
|                              |       1.01x|         -|
|large_pairs_ary.flatten       |     96.612k|   96.976k|
|                              |           -|     1.00x|
|large_pairs_ary.flatten!      |     94.108k|   97.289k|
|                              |           -|     1.03x|
|mostly_flat_ary.flatten       |    399.648k|  417.327k|
|                              |           -|     1.04x|
|mostly_flat_ary.flatten!      |    378.315k|  395.946k|
|                              |           -|     1.05x|
|small_nested_ary.flatten      |      2.513M|    7.788M|
|                              |           -|     3.10x|
|small_nested_ary.flatten!     |      2.024M|    5.914M|
|                              |           -|     2.92x|
|large_nested_ary.flatten      |    341.635k|  485.319k|
|                              |           -|     1.42x|
|large_nested_ary.flatten!     |    329.837k|  475.014k|
|                              |           -|     1.44x|
|small_nested_ary.flatten(1)   |      9.497M|   61.350M|
|                              |           -|     6.46x|
|small_nested_ary.flatten!(1)  |      5.136M|   17.668M|
|                              |           -|     3.44x|
|large_nested_ary.flatten(1)   |      1.575M|   60.241M|
|                              |           -|    38.26x|
|large_nested_ary.flatten!(1)  |      1.369M|   16.835M|
|                              |           -|    12.30x|
2026-08-22 22:13:33 +02:00
..
2018-09-28 05:28:12 +00:00
2019-08-05 09:04:32 +09:00
2024-09-13 14:35:25 +09:00
2025-04-18 00:10:03 +00:00
2020-07-18 23:45:00 +09:00
2020-07-18 23:45:00 +09:00
2020-07-18 23:45:00 +09:00
2020-07-18 23:45:25 +09:00
2026-01-21 11:23:01 +01:00
2021-02-10 19:42:00 +09:00
2024-07-08 12:24:33 +02:00
2019-06-01 20:07:50 +09:00
2025-08-30 14:14:10 +02:00
2026-05-13 17:37:48 +09:00
2026-07-13 15:04:42 +09:00
2019-08-10 11:26:23 +09:00
2018-12-27 06:12:09 +00:00
2018-12-27 06:12:09 +00:00
2023-02-28 10:05:30 -08:00
2018-12-27 06:12:09 +00:00
2025-08-11 22:22:38 +09:00
2023-11-20 14:33:20 +01:00
2026-03-13 09:15:55 -04:00
2019-01-07 02:05:21 +00:00
2024-09-23 14:29:25 +09:00
2023-04-25 08:06:16 -07:00
2023-04-25 08:06:16 -07:00
2021-06-18 10:02:44 -07:00

ruby/benchmark

This directory has benchmark definitions to be run with benchmark_driver.gem.

Normal usage

Execute gem install benchmark_driver and run a command like:

# 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:

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.

# 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 exact filenames instead of matching ITEM:
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"