Add opt-in Ractor-local GC metrics to the Ractor harness - #537
eightbitraptor wants to merge 6 commits into
Conversation
Add gc_total_time_warmup/bench in milliseconds and gc_global_count_warmup/bench (on Ruby versions with support for global_gc_count) to the JSON output, plus a global column in the per-iteration stdout table. Ignore this if the benchmarked Ruby doesn't support global gc counts (introduced during Ruby 4.1 dev cycle).
enable with RUBY_BENCH_RACTOR_GC=1 The mode requires Ruby 4.1 or newer (because of the Ractor-local GC.stat and per-Ractor GC.measure_total_time);
Passing --ractor-gc to run_benchmarks.rb now sets RUBY_BENCH_RACTOR_GC=1
|
I think having a miscount of |
|
@luke-gruber ruby/ruby#19147 I went a different way, by tracking the number of globals initiated by each Ractor. We can then subtract that from the major count to get the true local major count. It's difficult and I guess we could go one way or the other but I opted not to just discount globals as majors, because they do run a major GC. I'm not wedded to this decision though. |
|
I don't know, that seems kind of hacky. The fact that global GC does a pseudo-"major" GC on each objspace is an implementation detail that imo shouldn't leak out to Edit: to be honest, I don't really care how they're measured so if it's easier to do it that way I'm fine with it. What matters is getting good benchmarks and then fixing the GC issues. |
./run_benchmarks.rb --category ractor --ractor-gcsamplesGC.statand GC total time in every worker Ractor's own object space on each iteration, and also records process-wide GC counters observed by the main Ractor.We record all data in the JSON output as well as teh summary tables.
The target needs Ruby 4.1 or newer (specifically after this PR ruby/ruby#18976). Older versions raise
NotImplementedErrorinstead of producing misleading numbers.What it looks like
Per-iteration harness output:
Single-executable summary (absolute columns):
Comparison summary (ratios + base → comparison counts):
We've also added notes to the end of the run alongside the existing legend that explains some nuances in the numbers:
The global GC count shenanigans
The asterisks and the notes are needed because these numbers overlap in a way the counters cannot currently separate:
A stop-the-world global cycle is attributed to the Ractor that triggered it: the driving objspace's
major_gc_countincrements (gc/default/default.c), and bystanders' local counts do not move.GC.stat(:global_gc_count)is a process-wide counter mirrored into every Ractor's scopedGC.stat— a worker's global cycles move the main Ractor's scoped read too.So a worker's local counts already include the global cycles it triggered, counted as majors. A row reading
gc_count 41, major 10, global 4can contain those same 4 cycles inside the 41. The starred columns are a view of a subset so you can't add them togethercompact_countcounts "my object space was compacted" per object space, so one global compacting cycle increments it in every Ractor. It can never be worker-summed; we record the main Ractor's delta once per iteration.I am working on a small Ruby feature to add
triggered_global_gc_countto the Ractor's localGC.statoutput, which will allow us to calculate exact numbers.Feedback wanted
This is a draft mainly to get eyes on the presentation, in order to start gathering feedback while I work on the
triggered_global_gc_countchange:Column names.
(worker sum)suffixes,GC ms/worker, and the starredglobal GCs/iter*/global/iter ratio*/controller compacts/iter*. Does the*read as "see the notes" or is it noise? Better names or suggestions on how to present this better are very welcome.Do we even need the new CRuby counter to get a full picture or is it enough that the total gc count also contains the globals such that
major + minor + globaldoesn't equalgc_count?GC ms/workerdivides each iteration's worker-sum GC time by its sampled worker count, then takes the mean. Is mean good enough, or shall we have max/median instead.We've always tried to keep the table output narrower than the github comment box. Can we even do that anymore. Any suggestions for a better layout are very welcome here.