Skip to content

Adopt five open benchmark PRs - #244

Merged
JuanVqz merged 5 commits into
mainfrom
feature/adopt-open-prs
Sep 29, 2026
Merged

JuanVqz merged 5 commits into
mainfrom
feature/adopt-open-prs

Conversation

@JuanVqz

@JuanVqz JuanVqz commented Sep 29, 2026 •

Copy link
Copy Markdown
Member

Summary

  • Lands five open benchmark PRs, one commit each, with every contributor credited as co-author, so each contribution can be read (and rejected) on its own.
  • Each one is brought up to today's rules: winner named by rank methods and listed first, runs on every Ruby in CI, same work in every report.
  • README entries keep the contributor's own text and sample output, and add a run on Ruby 4.0.7 below it.

Changes

Step 1: Hash#values_at vs Array#map { Hash#[] } (#174 by @kewlar)

  • The file as written, without the spaces padding one report label.
  • Local runs: values_at wins on Ruby 2.1, 3.4, 4.0, head and JRuby head (1.52x to 2.10x). On TruffleRuby head map was 1.06x ahead in one run, so no comment until CI confirms it.

Step 2: method vs forwarded method vs delegated method (#182 by @yogeshjain999)

  • The delegated report called pop(1) while the other two push, so it measured different work. It now calls << 1, which SimpleDelegator passes to the array, and all three return [1].
  • slowest becomes slower, so the rank names do not skip a step.
  • The PR's Ruby 2.2 sample is kept, with a note that it ran the pop version.

Step 3: Array#sum vs Array#inject(:+) (#140 by @jrmhaig)

  • Wrapped in if RUBY_VERSION >= '2.4.0', as suggested on the PR, so it skips Rubies without Array#sum instead of crashing.
  • Drops require "rubygems" and the .travis.yml change (main no longer has Travis). Labels Array#sum and Array#inject(:+).
  • A comment that the two only agree for Integers: for Floats, sum compensates for rounding errors.
  • The PR had no README entry, so this adds one next to the inject entry.

Step 4: array subset check (#237 by @etagwerker, from #125 by @gabteles)

  • Rank-named methods instead of minus_empty, all_include and so on. (a1 - a2).empty? is the winner, as the PR found on 3.3, 3.4 and 4.0.
  • A comment on where the winner changes: all? + include? wins on JRuby and TruffleRuby, and ties on Ruby 2.1.

Step 5: non-nil hash values, values.compact vs select (#236 by @etagwerker, from #124 by @sFrenkie)

  • No more Random.rand in the data, so the number of nils is the same on every run: every other value is nil.
  • The two select reports keep values with !v.nil? instead of by truthiness, so like compact they drop only nil and keep false (from the PR's Copilot review). With { a: false, b: nil, c: 1 } all three now return [false, 1]; the old select { |v| v } returned [1]. The README text's two snippets change the same way.
  • Rank-named methods, and the sanity check compares results without sorting (also from the Copilot review).
  • On ruby_4.0.7 values.compact is now 21.05x faster (13.78x before !v.nil?, which is a little more work than v). The PR's ruby_4.0.0 sample, which ran the truthiness version, is kept.

Test plan

  • The lint passes all 73 files, and RuboCop's quote check passes on the five new files.
  • Steps 1, 2, 4 and 5 ran on Ruby 2.1, 3.4, 4.0, head, JRuby head and TruffleRuby head (Docker, one run each). Step 5's six-Ruby run was before its data and !v.nil? changes; after them, it ran on 4.0.7.
  • Step 3 skips cleanly on Ruby 2.1, 2.3 and JRuby 9.1, and runs on 2.4, 4.0 and TruffleRuby 22.
  • Each file's sanity check (or a direct check) confirms its reports return the same result.
  • CI runs only the five new files, on all 26 jobs.

After this merges, each contributor PR gets a comment saying where it landed, and is closed.

JuanVqz and others added 5 commits September 28, 2026 14:51
From #174 by @kewlar: picking values by keys, when some keys may be
missing and their default values matter. values_at is the fast one.

Lands the file as the PR wrote it, without the spaces padding one report
label, on today's main. The README entry keeps the PR's sample (Ruby 3.2,
1.75x) and adds one from ruby_4.0 (2.05x).
Local runs agree on ruby_2.1, 3.4, 4.0, head and jruby_head (1.52x to
2.10x); truffleruby_head had map 1.06x ahead in one run.

Co-authored-by: Mindaugas Pelionis <1241866+kewlar@users.noreply.github.com>
From #182 by @yogeshjain999: when to define a method, forward it with
def_delegator, or let SimpleDelegator handle it. The plain method is the
fast one.

Two changes to the PR's file:
- The delegated report called pop(1) while the others push, so it
  measured different work. It now calls << 1, which SimpleDelegator
  passes to the array, and all three return [1].
- slowest becomes slower, so the rank names do not skip a step.

The README entry keeps the PR's sample (Ruby 2.2, measured the pop
version) and adds one from ruby_4.0 on the current code: forwarded 1.24x,
delegated 2.55x slower. Local runs keep that order on ruby_2.1, 3.4, head
and jruby_head; on truffleruby_head all three tie, the work optimized
away.

Co-authored-by: Yogesh Khater <6301525+yogeshjain999@users.noreply.github.com>
From #140 by @jrmhaig: how the Array#sum added in Ruby 2.4 compares with
the usual inject(:+). sum is the fast one.

Changes to the PR's file:
- Wrapped in if RUBY_VERSION >= '2.4.0', as suggested on the PR, so it
  skips Rubies without Array#sum instead of crashing (checked on
  ruby_2.1, 2.3 and jruby_9.1; runs on 2.4 and truffleruby_22).
- Drops require "rubygems", which no Ruby in CI needs.
- Labels Array#sum and Array#inject(:+).
- A comment that the two only agree for Integers: for Floats, sum
  compensates for rounding errors.

The PR's .travis.yml change is left out: main no longer has Travis. The
PR had no README entry; the new one, next to the inject entry, is from
ruby_4.0 (sum 1.56x faster).

Co-authored-by: Joseph Haig <4415912+jrmhaig@users.noreply.github.com>
From #237 by @etagwerker, which revisits #125 by @gabteles and fixes its
reversed Set#subset? arguments: five ways to check that every element of
one array is in another. (a1 - a2).empty? is the fast one, as the PR
found on Ruby 3.3, 3.4 and 4.0.

Changes to the PR's file:
- Rank-named methods instead of minus_empty, all_include and so on:
  faster (a1 - a2).empty?, fast all? + include?, then slow, slower and
  slowest for (a1 & a2).size, (a1 & a2) == a1 and Set#subset?.
- A comment on where the winner changes: all? + include? wins on JRuby
  and TruffleRuby, and ties on Ruby 2.1.
- The PR's header comment on one line per sentence.

The README entry keeps the PR's text and its 3.3, 3.4 and 4.0 runs, and
adds one from ruby_4.0.7.

Co-authored-by: Ernesto Tagwerker <17584+etagwerker@users.noreply.github.com>
Co-authored-by: Gabriel Teles <3189895+gabteles@users.noreply.github.com>
…124)

From #236 by @etagwerker, which revisits #124 by @sFrenkie and fixes its
data (it had no nil values, so compact did less work): three ways to
collect the non-nil values of a hash. values.compact is the fast one.

Changes to the PR's file:
- The data no longer uses Random.rand, so the number of nils does not
  change from run to run: every other value is nil (500 of 1000).
- The two select reports keep values with !v.nil? instead of by
  truthiness, so like compact they drop only nil and keep false (from the
  PR's Copilot review). The two snippets in the README text change the
  same way.
- Rank-named methods: fast values.compact, slow values.select, slower
  select.values, the order on every CRuby and JRuby run.
- The sanity check compares the results as they are, without sorting,
  since all three keep the hash's order (from the PR's Copilot review).
- Single quotes, as RuboCop asks.

The README entry keeps the PR's ruby_4.0.0 sample, which ran the
truthiness version, and adds one from ruby_4.0.7 on the current code
(21.05x).

Co-authored-by: Ernesto Tagwerker <17584+etagwerker@users.noreply.github.com>
Co-authored-by: sFrenkie <20856072+sFrenkie@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant