Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,22 @@ jobs:
MIN_BENCH_TIME: '0'
continue-on-error: ${{ matrix.continue-on-error || false }}

- name: Test run_benchmarks.rb - Ractors
run: ./run_benchmarks.rb --category=ractor
env:
WARMUP_ITRS: '1'
MIN_BENCH_ITRS: '1'
MIN_BENCH_TIME: '0'
continue-on-error: ${{ matrix.continue-on-error || false }}

- name: Test run_benchmarks.rb - Ractor Only
run: ./run_benchmarks.rb --category=ractor-only
env:
WARMUP_ITRS: '1'
MIN_BENCH_ITRS: '1'
MIN_BENCH_TIME: '0'
continue-on-error: ${{ matrix.continue-on-error || false }}

- name: Test run_benchmarks.rb --graph
run: |
sudo apt-get update
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*.csv
*.dump
logs*
benchmarks/*/data/

__pycache__
/benchmarks/discourse
Expand Down
37 changes: 37 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,43 @@ It's also convenient for profiling, debugging, etc, especially since all benchma
ruby benchmarks/some_benchmark.rb
```

## Ractor Benchmarks

ruby-bench supports Ractor-specific benchmarking with dedicated categories and benchmark directories.

### Ractor Categories

There are two Ractor-related categories:

* **`--category ractor`** - Runs both regular benchmarks marked with `ractor:
true` in `benchmarks.yml` AND all benchmarks from the `benchmarks-ractor`
directory. The `harness-ractor` harness is used for both types of benchmark.

* **`--category ractor-only`** - Runs ONLY benchmarks from the
`benchmarks-ractor` directory, ignoring regular benchmarks even if they are
marked with `ractor: true`. This category also automatically uses the
`harness-ractor` harness.

### Directory Structure

The `benchmarks-ractor/` directory sits at the same level as the main
`benchmarks` directory, and contains Ractor-specific benchmark
implementations that are designed to test Ractor functionality. They are not
intended to be used with any harness except `harness-ractor`.

### Usage Examples

```bash
# Run all Ractor-capable benchmarks (both regular and Ractor-specific)
./run_benchmarks.rb --category ractor

# Run only dedicated Ractor benchmarks from benchmarks-ractor directory
./run_benchmarks.rb --category ractor-only
```

Note: The `harness-ractor` harness is automatically selected when using these
categories, so there's no need to specify `--harness` manually.

## Ruby options

By default, ruby-bench benchmarks the Ruby used for `run_benchmarks.rb`.
Expand Down
9 changes: 9 additions & 0 deletions benchmarks-ractor/gvl_release_acquire/benchmark.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
require_relative "../../harness/loader"

run_benchmark(5) do |num_rs, ractor_args|
output = File.open("/dev/null", "wb")
input = File.open("/dev/zero", "rb")
100_000.times do
output.write(input.read(10))
end
end
2 changes: 2 additions & 0 deletions benchmarks-ractor/json_parse_float/Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
source "https://rubygems.org"
gem "json", "2.13.2"
14 changes: 14 additions & 0 deletions benchmarks-ractor/json_parse_float/Gemfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
GEM
remote: https://rubygems.org/
specs:
json (2.13.2)

PLATFORMS
arm64-darwin-23
ruby

DEPENDENCIES
json (= 2.13.2)

BUNDLED WITH
2.7.0
39 changes: 39 additions & 0 deletions benchmarks-ractor/json_parse_float/benchmark.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
require_relative "../../harness/loader"

Dir.chdir(__dir__)
use_gemfile
require "json"
puts "json v#{JSON::VERSION}"

ELEMENTS = 100_000
list = ELEMENTS.times.map do
{
rand => rand,
rand => rand,
rand => rand,
rand => rand,
rand => rand,
rand => rand,
rand => rand,
rand => rand,
rand => rand,
rand => rand,
}.to_json
end
Ractor.make_shareable(list)

# Work is divided between ractors
run_benchmark(5, ractor_args: [list]) do |num_rs, list|
# num_rs: 1,list: 100_000
# num_rs: 2 list: 50_000
# num_rs: 4 list: 25_000
if num_rs.zero?
num = list.size
else
num = list.size / num_rs
end
list.each_with_index do |json, idx|
break if idx >= num
JSON.parse(json)
end
end
2 changes: 2 additions & 0 deletions benchmarks-ractor/json_parse_string/Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
source "https://rubygems.org"
gem "json", "2.13.2"
14 changes: 14 additions & 0 deletions benchmarks-ractor/json_parse_string/Gemfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
GEM
remote: https://rubygems.org/
specs:
json (2.13.2)

PLATFORMS
arm64-darwin-23
ruby

DEPENDENCIES
json (= 2.13.2)

BUNDLED WITH
2.7.0
49 changes: 49 additions & 0 deletions benchmarks-ractor/json_parse_string/benchmark.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
require_relative "../../harness/loader"

Dir.chdir(__dir__)
use_gemfile
require "json"
puts "json v#{JSON::VERSION}"

ELEMENTS = 300_000
list = ELEMENTS.times.map do |i|
{
"string #{i}" => "value #{i}",
"string #{i}" => "value #{i}",
"string #{i}" => "value #{i}",
"string #{i}" => "value #{i}",
"string #{i}" => "value #{i}",
"string #{i}" => "value #{i}",
"string #{i}" => "value #{i}",
"string #{i}" => "value #{i}",
"string #{i}" => "value #{i}",
"string #{i}" => "value #{i}",
"string #{i}" => "value #{i}",
"string #{i}" => "value #{i}",
"string #{i}" => "value #{i}",
"string #{i}" => "value #{i}",
"string #{i}" => "value #{i}",
"string #{i}" => "value #{i}",
"string #{i}" => "value #{i}",
"string #{i}" => "value #{i}",
"string #{i}" => "value #{i}",
"string #{i}" => "value #{i}",
}.to_json
end
Ractor.make_shareable(list)

# Work is divided between ractors
run_benchmark(5, ractor_args: [list]) do |num_rs, list|
# num_rs: 1,list: 100_000
# num_rs: 2 list: 50_000
# num_rs: 4 list: 25_000
if num_rs.zero?
num = list.size
else
num = list.size / num_rs
end
list.each_with_index do |json, idx|
break if idx >= num
JSON.parse(json)
end
end
66 changes: 66 additions & 0 deletions benchmarks-ractor/knucleotide/benchmark.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# The Computer Language Benchmarks Game
# https://salsa.debian.org/benchmarksgame-team/benchmarksgame/
#
# k-nucleotide benchmark - Ractor implementation
# Mirrors the Process.fork version structure as closely as possible

require_relative "../../harness/loader"

def frequency(seq, length)
frequencies = Hash.new(0)
last_index = seq.length - length

i = 0
while i <= last_index
frequencies[seq.byteslice(i, length)] += 1
i += 1
end

[seq.length - length + 1, frequencies]
end

def sort_by_freq(seq, length)
n, table = frequency(seq, length)

table.sort { |a, b|
cmp = b[1] <=> a[1]
cmp == 0 ? a[0] <=> b[0] : cmp
}.map! { |seq, count|
"#{seq} #{'%.3f' % ((count * 100.0) / n)}"
}.join("\n") << "\n\n"
end

def find_seq(seq, s)
_, table = frequency(seq, s.length)
"#{table[s] || 0}\t#{s}\n"
end

def generate_test_sequence(size)
alu = "GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCA" +
"GGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGG" +
"TGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTT" +
"GCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA"

sequence = ""
full_copies = size / alu.length
remainder = size % alu.length

full_copies.times { sequence << alu }
sequence << alu[0, remainder] if remainder > 0

sequence.upcase.freeze
end

# Make sequence shareable for Ractors
TEST_SEQUENCE = Ractor.make_shareable(generate_test_sequence(100_000))

run_benchmark(5) do |num_ractors, ractor_args|
freqs = [1, 2]
nucleos = %w(GGT GGTA GGTATT GGTATTTTAATT GGTATTTTAATTTATAGT)

# Sequential version - mirrors Process version but without Workers
results = []
freqs.each { |i| results << sort_by_freq(TEST_SEQUENCE, i) }
nucleos.each { |s| results << find_seq(TEST_SEQUENCE, s) }
results
end
23 changes: 23 additions & 0 deletions benchmarks-ractor/optcarrot/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
.bundle/
Gemfile.lock
coverage/
doc/
pkg/
vendor/
optcarrot-*.gem

.git
.dockerignore
.*.sw*
**/.*.sw*
tools/nes-test-roms
SDL2.dll
video.png
video.gif
audio.wav
stackprof-*.dump
perf.data
perf.data.old
benchmark/bm-*.csv
benchmark/Dockerfile.*
tmp
21 changes: 21 additions & 0 deletions benchmarks-ractor/optcarrot/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/.bundle/
/Gemfile.lock
/benchmark
/coverage/
/pkg/
/vendor/
optcarrot-*.gem

.*.sw*
/tools/nes-test-roms
video.png
video.gif
audio.wav
stackprof-*.dump
perf.data
perf.data.old
benchmark/bm-*.csv
ppu-core.rb
cpu-core.rb
benchmark/Dockerfile.*
benchmark/*-core-opt-*.rb
Loading
Loading