模块 RubyVM::YJIT

此模块允许检查 YJIT,CRuby 的即时编译器。模块中的所有内容都是高度实现特定的,并且 API 与标准库相比可能不太稳定。

如果 YJIT 不支持构建 CRuby 的特定平台,则此模块可能不存在。

公共类方法

code_gc() 点击切换源代码

丢弃现有的编译代码以回收内存并允许将来重新编译。

# File yjit.rb, line 224
def self.code_gc
  Primitive.rb_yjit_code_gc
end
dump_exit_locations(filename) 点击切换源代码

Marshal 将退出位置转储到给定的文件名。

用法

如果传递了 --yjit-exit-locations,则会自动生成一个名为“yjit_exit_locations.dump”的文件。

如果您想手动收集跟踪,请直接调用 dump_exit_locations

请注意,在脚本中调用此方法将在创建转储后生成统计信息,因此统计信息数据可能包括转储本身的退出。

在脚本调用中

at_exit do
  RubyVM::YJIT.dump_exit_locations("my_file.dump")
end

然后使用以下选项运行文件

ruby --yjit --yjit-trace-exits test.rb

代码运行完毕后,使用 Stackprof 读取转储文件。有关选项,请参阅 Stackprof 文档。

# File yjit.rb, line 148
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
enable(stats: false) 点击切换源代码

启用 YJIT 编译。stats 选项决定是否启用 YJIT 统计信息。

  • false: 禁用统计信息。

  • true: 启用统计信息。在退出时打印统计信息。

  • :quiet: 启用统计信息。在退出时不打印统计信息。

# File yjit.rb, line 36
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
enabled?() 点击切换源代码

检查 YJIT 是否已启用。

# File yjit.rb, line 12
def self.enabled?
  Primitive.cexpr! 'RBOOL(rb_yjit_enabled_p)'
end
reset_stats!() 点击切换源代码

丢弃为 --yjit-stats 收集的统计信息。

# File yjit.rb, line 27
def self.reset_stats!
  Primitive.rb_yjit_reset_stats_bang
end
runtime_stats(context: false) 点击切换源代码

返回为 --yjit-stats 命令行选项生成的统计信息的哈希值。当选项未传递或不可用时,返回 nil

# File yjit.rb, line 158
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
stats_enabled?() 点击切换源代码

检查是否使用了 --yjit-stats

# File yjit.rb, line 17
def self.stats_enabled?
  Primitive.rb_yjit_stats_enabled_p
end
stats_string() 点击切换源代码

格式化并打印计数器作为 String。仅当启用 --yjit-stats 时,此方法才会返回非空内容。

# File yjit.rb, line 191
def self.stats_string
  # Lazily require StringIO to avoid breaking miniruby
  require 'stringio'
  strio = StringIO.new
  _print_stats(out: strio)
  strio.string
end

私有类方法

format_number(pad, number) 点击切换源代码

使用逗号分隔符格式化大数字,以提高可读性。

# File yjit.rb, line 480
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_number_pct(pad, number, total) 点击切换源代码

格式化数字以及相对于总值的百分比。

# File yjit.rb, line 488
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
print_and_dump_stats() 点击切换源代码

打印统计信息并转储退出位置。