Skip to content

Commit d3ce8da

Browse files
k0kubunmaximecb
andauthored
Add an option to monitor YJIT stats (#330)
* Add an option to monitor YJIT stats * Update README.md --------- Co-authored-by: Maxime Chevalier-Boisvert <[email protected]>
1 parent 89ce789 commit d3ce8da

File tree

4 files changed

+52
-10
lines changed

4 files changed

+52
-10
lines changed

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,15 @@ PERF=record ruby --yjit-perf=map -Iharness-perf benchmarks/railsbench/benchmark.
210210

211211
This is the only harness that uses `run_benchmark`'s argument, `num_itrs_hint`.
212212

213+
### Printing YJIT stats
214+
215+
The `--yjit-stats` option of `./run_benchmarks.rb` allows you to print the diff of YJIT stats counters
216+
after each iteration with the default harness.
217+
218+
```
219+
./run_benchmarks.rb --yjit-stats=code_region_size,yjit_alloc_size
220+
```
221+
213222
## Measuring memory usage
214223

215224
`--rss` option of `run_benchmarks.rb` allows you to measure RSS after benchmark iterations.

harness/harness-common.rb

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,7 @@ def return_results(warmup_iterations, bench_iterations)
9191
# Collect our own peak mem usage as soon as reasonable after finishing the last iteration.
9292
rss = get_rss
9393
yjit_bench_results["rss"] = rss
94-
puts "RSS: %.1fMiB" % (rss / 1024.0 / 1024.0)
95-
9694
if maxrss = get_maxrss
97-
puts "MAXRSS: %.1fMiB" % (maxrss / 1024.0 / 1024.0)
9895
yjit_bench_results["maxrss"] = maxrss
9996
end
10097

@@ -103,15 +100,29 @@ def return_results(warmup_iterations, bench_iterations)
103100
yjit_bench_results["yjit_stats"] = yjit_stats
104101

105102
formatted_stats = proc { |key| "%10s" % yjit_stats[key].to_s.reverse.scan(/\d{1,3}/).join(",").reverse }
106-
puts "inline_code_size: #{formatted_stats[:inline_code_size]}"
107-
puts "outlined_code_size: #{formatted_stats[:outlined_code_size]}"
108-
puts "code_region_size: #{formatted_stats[:code_region_size]}"
109-
puts "yjit_alloc_size: #{formatted_stats[:yjit_alloc_size]}"
110-
if yjit_stats.key?(:compile_time_ns)
111-
puts "yjit_compile_time: %.2fms" % (yjit_stats[:compile_time_ns] / 1_000_000.0).round(2)
103+
yjit_stats_keys = [
104+
*ENV.fetch("YJIT_BENCH_STATS", "").split(",").map(&:to_sym),
105+
:inline_code_size,
106+
:outlined_code_size,
107+
:code_region_size,
108+
:yjit_alloc_size,
109+
:compile_time_ns,
110+
].uniq
111+
yjit_stats_pads = yjit_stats_keys.map(&:size).max + 1
112+
yjit_stats_keys.each do |key|
113+
if key == :compile_time_ns
114+
puts "#{"yjit_compile_time:".ljust(yjit_stats_pads)} %8.2fms" % (yjit_stats[:compile_time_ns] / 1_000_000.0).round(2)
115+
else
116+
puts "#{"#{key}:".ljust(yjit_stats_pads)} #{formatted_stats[key]}"
117+
end
112118
end
113119
end
114120

121+
puts "RSS: %.1fMiB" % (rss / 1024.0 / 1024.0)
122+
if maxrss
123+
puts "MAXRSS: %.1fMiB" % (maxrss / 1024.0 / 1024.0)
124+
end
125+
115126
write_json_file(yjit_bench_results)
116127
end
117128

harness/harness.rb

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,33 @@ def run_benchmark(_num_itrs_hint, &block)
3636
times = []
3737
total_time = 0
3838
num_itrs = 0
39+
header = "itr: time"
3940

41+
# If $YJIT_BENCH_STATS is given, print the diff of these stats at each iteration.
42+
if ENV["YJIT_BENCH_STATS"]
43+
yjit_stats = ENV["YJIT_BENCH_STATS"].split(",").map { |key| [key.to_sym, nil] }.to_h
44+
yjit_stats.each_key { |key| header << " #{key}" }
45+
end
46+
47+
puts header
4048
begin
49+
yjit_stats&.each_key { |key| yjit_stats[key] = RubyVM::YJIT.runtime_stats(key) }
50+
4151
time = realtime(&block)
4252
num_itrs += 1
4353

4454
# NOTE: we may want to avoid this as it could trigger GC?
4555
time_ms = (1000 * time).to_i
46-
puts "itr \##{num_itrs}: #{time_ms}ms"
56+
itr_str = "%4s %6s" % ["##{num_itrs}:", "#{time_ms}ms"]
57+
58+
yjit_stats&.each do |key, old_value|
59+
new_value = RubyVM::YJIT.runtime_stats(key)
60+
diff = (new_value - old_value).to_s.reverse.scan(/\d{1,3}/).join(",").reverse
61+
itr_str << " %#{key.size}s" % diff
62+
yjit_stats[key] = new_value
63+
end
4764

65+
puts itr_str
4866
# NOTE: we may want to preallocate an array and avoid append
4967
# We internally save the time in seconds to avoid loss of precision
5068
times << time

run_benchmarks.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,10 @@ def run_benchmarks(ruby:, ruby_description:, categories:, name_filters:, out_pat
390390
ENV["MIN_BENCH_TIME"] = "0"
391391
end
392392

393+
opts.on("--yjit-stats=STATS", "print YJIT stats at each iteration for the default harness") do |str|
394+
ENV["YJIT_BENCH_STATS"] = str
395+
end
396+
393397
opts.on("--yjit_opts=OPT_STRING", "string of command-line options to run YJIT with (ignored if you use -e)") do |str|
394398
args.yjit_opts=str
395399
end

0 commit comments

Comments
 (0)