This module allows for introspection of YJIT, CRuby’s just-in-time compiler. Everything in the module is highly implementation specific and the API might be less stable compared to the standard library.
This module may not exist if YJIT does not support the particular platform for which CRuby is built.
# File tmp/rubies/ruby-3.3.0/yjit.rb, line 220
def self.code_gc
Primitive.rb_yjit_code_gc
end
Discard existing compiled code to reclaim memory and allow for recompilations in the future.
# File tmp/rubies/ruby-3.3.0/yjit.rb, line 144
def self.dump_exit_locations(filename)
unless trace_exit_locations_enabled?
raise ArgumentError, "--yjit-trace-exits must be enabled to use dump_exit_locations."
end
File.binwrite(filename, Marshal.dump(RubyVM::YJIT.exit_locations))
end
Marshal
dumps exit locations to the given filename.
Usage:
If --yjit-exit-locations
is passed, a file named “yjit_exit_locations.dump” will automatically be generated.
If you want to collect traces manually, call dump_exit_locations
directly.
Note that calling this in a script will generate stats after the dump is created, so the stats data may include exits from the dump itself.
In a script call:
at_exit do RubyVM::YJIT.dump_exit_locations("my_file.dump") end
Then run the file with the following options:
ruby --yjit --yjit-trace-exits test.rb
Once the code is done running, use Stackprof to read the dump file. See Stackprof documentation for options.
# File tmp/rubies/ruby-3.3.0/yjit.rb, line 32
def self.enable(stats: false)
return false if enabled?
at_exit { print_and_dump_stats } if stats
Primitive.rb_yjit_enable(stats, stats != :quiet)
end
Enable YJIT compilation.
# File tmp/rubies/ruby-3.3.0/yjit.rb, line 12
def self.enabled?
Primitive.cexpr! 'RBOOL(rb_yjit_enabled_p)'
end
Check if YJIT is enabled.
# File tmp/rubies/ruby-3.3.0/yjit.rb, line 476
def format_number(pad, number)
s = number.to_s
i = s.index('.') || s.size
s.insert(i -= 3, ',') while i > 3
s.rjust(pad, ' ')
end
Format large numbers with comma separators for readability
# File tmp/rubies/ruby-3.3.0/yjit.rb, line 484
def format_number_pct(pad, number, total)
padded_count = format_number(pad, number)
percentage = number.fdiv(total) * 100
formatted_pct = "%4.1f%%" % percentage
"#{padded_count} (#{formatted_pct})"
end
Format a number along with a percentage over a total value
# File tmp/rubies/ruby-3.3.0/yjit.rb, line 237
def print_and_dump_stats
if Primitive.rb_yjit_print_stats_p
_print_stats
end
_dump_locations
end
Print stats and dump exit locations
# File tmp/rubies/ruby-3.3.0/yjit.rb, line 27
def self.reset_stats!
Primitive.rb_yjit_reset_stats_bang
end
Discard statistics collected for --yjit-stats
.
# File tmp/rubies/ruby-3.3.0/yjit.rb, line 154
def self.runtime_stats(context: false)
stats = Primitive.rb_yjit_get_stats(context)
return stats if stats.nil?
stats[:object_shape_count] = Primitive.object_shape_count
return stats unless Primitive.rb_yjit_stats_enabled_p
side_exits = total_exit_count(stats)
total_exits = side_exits + stats[:leave_interp_return]
# Number of instructions that finish executing in YJIT.
# See :count-placement: about the subtraction.
retired_in_yjit = stats[:yjit_insns_count] - side_exits
# Average length of instruction sequences executed by YJIT
avg_len_in_yjit = total_exits > 0 ? retired_in_yjit.to_f / total_exits : 0
# Proportion of instructions that retire in YJIT
total_insns_count = retired_in_yjit + stats[:vm_insns_count]
yjit_ratio_pct = 100.0 * retired_in_yjit.to_f / total_insns_count
stats[:total_insns_count] = total_insns_count
stats[:ratio_in_yjit] = yjit_ratio_pct
# Make those stats available in RubyVM::YJIT.runtime_stats as well
stats[:side_exit_count] = side_exits
stats[:total_exit_count] = total_exits
stats[:avg_len_in_yjit] = avg_len_in_yjit
stats
end
Return a hash for statistics generated for the --yjit-stats
command line option. Return nil
when option is not passed or unavailable.
# File tmp/rubies/ruby-3.3.0/yjit.rb, line 17
def self.stats_enabled?
Primitive.rb_yjit_stats_enabled_p
end
Check if --yjit-stats
is used.
# File tmp/rubies/ruby-3.3.0/yjit.rb, line 187
def self.stats_string
# Lazily require StringIO to avoid breaking miniruby
require 'stringio'
strio = StringIO.new
_print_stats(out: strio)
strio.string
end
Format and print out counters as a String
. This returns a non-empty content only when --yjit-stats
is enabled.