модуль RubyVM::YJIT
Этот модуль позволяет получить доступ к данным о YJIT, инкрементальном компиляторе в процессе выполнения CRuby. Этот модуль предназначен только для разработки YJIT, поэтому все элементы модуля являются специфичными для реализации и не гарантируют стабильности API.
Этот модуль может отсутствовать, если YJIT не поддерживает платформу, для которой построен CRuby. Также не гарантируется стабильность API в ситуациях, когда этот модуль определён.
Методы публичного класса
# File yjit.rb, line 209 def self.code_gc Primitive.rb_yjit_code_gc end
Освобождает и перекомпилирует весь существующий JIT-код
# File yjit.rb, line 183
def self.disasm(iseq)
# If a method or proc is passed in, get its iseq
iseq = RubyVM::InstructionSequence.of(iseq)
if self.enabled?
# Produce the disassembly string
# Include the YARV iseq disasm in the string for additional context
iseq.disasm + "\n" + Primitive.rb_yjit_disasm_iseq(iseq)
else
iseq.disasm
end
end Производит дизассемблирование для iseq
# File yjit.rb, line 138
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 сохраняет местоположения выхода в указанный файл.
Использование:
Если передаётся `–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 13 def self.enabled? Primitive.cexpr! 'RBOOL(rb_yjit_enabled_p())' end
Проверяет, включён ли YJIT
# File yjit.rb, line 36
def self.exit_locations
return unless trace_exit_locations_enabled?
results = Primitive.rb_yjit_get_exit_locations
raw_samples = results[:raw].dup
line_samples = results[:lines].dup
frames = results[:frames].dup
samples_count = 0
# Loop through the instructions and set the frame hash with the data.
# We use nonexistent.def for the file name, otherwise insns.def will be displayed
# and that information isn't useful in this context.
RubyVM::INSTRUCTION_NAMES.each_with_index do |name, frame_id|
frame_hash = { samples: 0, total_samples: 0, edges: {}, name: name, file: "nonexistent.def", line: nil, lines: {} }
results[:frames][frame_id] = frame_hash
frames[frame_id] = frame_hash
end
# Loop through the raw_samples and build the hashes for StackProf.
# The loop is based off an example in the StackProf documentation and therefore
# this functionality can only work with that library.
#
# Raw Samples:
# [ length, frame1, frame2, frameN, ..., instruction, count
#
# Line Samples
# [ length, line_1, line_2, line_n, ..., dummy value, count
i = 0
while i < raw_samples.length
stack_length = raw_samples[i] + 1
i += 1 # consume the stack length
prev_frame_id = nil
stack_length.times do |idx|
idx += i
frame_id = raw_samples[idx]
if prev_frame_id
prev_frame = frames[prev_frame_id]
prev_frame[:edges][frame_id] ||= 0
prev_frame[:edges][frame_id] += 1
end
frame_info = frames[frame_id]
frame_info[:total_samples] += 1
frame_info[:lines][line_samples[idx]] ||= [0, 0]
frame_info[:lines][line_samples[idx]][0] += 1
prev_frame_id = frame_id
end
i += stack_length # consume the stack
top_frame_id = prev_frame_id
top_frame_line = 1
sample_count = raw_samples[i]
frames[top_frame_id][:samples] += sample_count
frames[top_frame_id][:lines] ||= {}
frames[top_frame_id][:lines][top_frame_line] ||= [0, 0]
frames[top_frame_id][:lines][top_frame_line][1] += sample_count
samples_count += sample_count
i += 1
end
results[:samples] = samples_count
# Set missed_samples and gc_samples to 0 as their values
# don't matter to us in this context.
results[:missed_samples] = 0
results[:gc_samples] = 0
results
end Если включено `–yjit-trace-exits`, парсит хеши из Primitive.rb_yjit_get_exit_locations в формат, читаемый Stackprof. Это позволит нам найти точное местоположение выхода в YJIT на основе инструкции, которая его производит.
# File yjit.rb, line 197
def self.insns_compiled(iseq)
# If a method or proc is passed in, get its iseq
iseq = RubyVM::InstructionSequence.of(iseq)
if self.enabled?
Primitive.rb_yjit_insns_compiled(iseq)
else
Qnil
end
end Возвращает список инструкций, скомпилированных YJIT для iseq
# File yjit.rb, line 28 def self.reset_stats! Primitive.rb_yjit_reset_stats_bang end
Удаляет статистику, собранную для `–yjit-stats`.
# File yjit.rb, line 148
def self.runtime_stats
stats = Primitive.rb_yjit_get_stats
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[:exec_instruction] - side_exits
# Average length of instruction sequences executed by YJIT
avg_len_in_yjit = retired_in_yjit.to_f / total_exits
# This only available on yjit stats builds
if stats.key?(:vm_insns_count)
# 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
end
# 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 Возвращает хеш статистики, сгенерированный для командной строки `–yjit-stats`. Возвращает nil, если опция не передана или недоступна.
# File yjit.rb, line 18 def self.stats_enabled? Primitive.rb_yjit_stats_enabled_p end
Проверяет использование `–yjit-stats`.
# File yjit.rb, line 23 def self.trace_exit_locations_enabled? Primitive.rb_yjit_trace_exit_locations_enabled_p end
Проверяет, включено ли `rb_yjit_trace_exit_locations_enabled_p`.
Ruby Core © 1993–2022 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.