summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakashi Kokubun <takashi.kokubun@shopify.com>2025-09-30 20:50:08 -0700
committerGitHub <noreply@github.com>2025-09-30 20:50:08 -0700
commit56f777cedf1b9acc2fe74bda3d5dde351ba31951 (patch)
treef956ad497379f6fc62b4b427006c4daac2b3838d
parent400e150f00ebbd71b14c9c4a885b1eb23be4b4b2 (diff)
ZJIT: Add more *_send_count stats (#14689)
-rw-r--r--zjit.rb21
-rw-r--r--zjit/src/codegen.rs5
-rw-r--r--zjit/src/stats.rs29
3 files changed, 51 insertions, 4 deletions
diff --git a/zjit.rb b/zjit.rb
index 2ff4cf2a5b..ab5bae719a 100644
--- a/zjit.rb
+++ b/zjit.rb
@@ -162,9 +162,16 @@ class << RubyVM::ZJIT
print_counters_with_prefix(prefix: 'compile_error_', prompt: 'compile error reasons', buf:, stats:, limit: 20)
print_counters_with_prefix(prefix: 'exit_', prompt: 'side exit reasons', buf:, stats:, limit: 20)
- # Show the most important stats ratio_in_zjit at the end
+ # Show no-prefix counters, having the most important stat `ratio_in_zjit` at the end
print_counters([
+ :send_count,
:dynamic_send_count,
+ :optimized_send_count,
+ :iseq_optimized_send_count,
+ :inline_cfunc_optimized_send_count,
+ :variadic_cfunc_optimized_send_count,
+ ], buf:, stats:, right_align: true, base: :send_count)
+ print_counters([
:dynamic_getivar_count,
:dynamic_setivar_count,
@@ -202,12 +209,18 @@ class << RubyVM::ZJIT
# :stopdoc:
private
- def print_counters(keys, buf:, stats:)
- left_pad = keys.map { |key| key.to_s.sub(/_time_ns\z/, '_time').size }.max + 1
+ def print_counters(keys, buf:, stats:, right_align: false, base: nil)
+ key_pad = keys.map { |key| key.to_s.sub(/_time_ns\z/, '_time').size }.max + 1
+ key_align = '-' unless right_align
+ value_pad = keys.filter_map { |key| stats[key] }.map { |value| number_with_delimiter(value).size }.max
+
keys.each do |key|
# Some stats like vm_insn_count and ratio_in_zjit are not supported on the release build
next unless stats.key?(key)
value = stats[key]
+ if base && key != base
+ ratio = " (%4.1f%%)" % (100.0 * value / stats[base])
+ end
case key
when :ratio_in_zjit
@@ -219,7 +232,7 @@ class << RubyVM::ZJIT
value = number_with_delimiter(value)
end
- buf << "#{"%-#{left_pad}s" % "#{key}:"} #{value}\n"
+ buf << "%#{key_align}*s %*s%s\n" % [key_pad, "#{key}:", value_pad, value, ratio]
end
end
diff --git a/zjit/src/codegen.rs b/zjit/src/codegen.rs
index b8d527fb8d..23631ae6ba 100644
--- a/zjit/src/codegen.rs
+++ b/zjit/src/codegen.rs
@@ -661,6 +661,7 @@ fn gen_patch_point(jit: &mut JITState, asm: &mut Assembler, invariant: &Invarian
/// Lowering for [`Insn::CCall`]. This is a low-level raw call that doesn't know
/// anything about the callee, so handling for e.g. GC safety is dealt with elsewhere.
fn gen_ccall(asm: &mut Assembler, cfun: *const u8, args: Vec<Opnd>) -> lir::Opnd {
+ gen_incr_counter(asm, Counter::inline_cfunc_optimized_send_count);
asm.ccall(cfun, args)
}
@@ -675,6 +676,8 @@ fn gen_ccall_variadic(
cme: *const rb_callable_method_entry_t,
state: &FrameState,
) -> lir::Opnd {
+ gen_incr_counter(asm, Counter::variadic_cfunc_optimized_send_count);
+
gen_prepare_non_leaf_call(jit, asm, state);
let stack_growth = state.stack_size();
@@ -1051,6 +1054,8 @@ fn gen_send_without_block_direct(
args: Vec<Opnd>,
state: &FrameState,
) -> lir::Opnd {
+ gen_incr_counter(asm, Counter::iseq_optimized_send_count);
+
let local_size = unsafe { get_iseq_body_local_table_size(iseq) }.as_usize();
let stack_growth = state.stack_size() + local_size + unsafe { get_iseq_body_stack_max(iseq) }.as_usize();
gen_stack_overflow_check(jit, asm, state, stack_growth);
diff --git a/zjit/src/stats.rs b/zjit/src/stats.rs
index a9cf1bde7c..5c8333d01d 100644
--- a/zjit/src/stats.rs
+++ b/zjit/src/stats.rs
@@ -21,6 +21,9 @@ macro_rules! make_counters {
dynamic_send {
$($dynamic_send_counter_name:ident,)+
}
+ optimized_send {
+ $($optimized_send_counter_name:ident,)+
+ }
$($counter_name:ident,)+
) => {
/// Struct containing the counter values
@@ -29,6 +32,7 @@ macro_rules! make_counters {
$(pub $default_counter_name: u64,)+
$(pub $exit_counter_name: u64,)+
$(pub $dynamic_send_counter_name: u64,)+
+ $(pub $optimized_send_counter_name: u64,)+
$(pub $counter_name: u64,)+
}
@@ -39,6 +43,7 @@ macro_rules! make_counters {
$($default_counter_name,)+
$($exit_counter_name,)+
$($dynamic_send_counter_name,)+
+ $($optimized_send_counter_name,)+
$($counter_name,)+
}
@@ -48,6 +53,7 @@ macro_rules! make_counters {
$( Counter::$default_counter_name => stringify!($default_counter_name).to_string(), )+
$( Counter::$exit_counter_name => stringify!($exit_counter_name).to_string(), )+
$( Counter::$dynamic_send_counter_name => stringify!($dynamic_send_counter_name).to_string(), )+
+ $( Counter::$optimized_send_counter_name => stringify!($optimized_send_counter_name).to_string(), )+
$( Counter::$counter_name => stringify!($counter_name).to_string(), )+
}
}
@@ -60,6 +66,7 @@ macro_rules! make_counters {
$( Counter::$default_counter_name => std::ptr::addr_of_mut!(counters.$default_counter_name), )+
$( Counter::$exit_counter_name => std::ptr::addr_of_mut!(counters.$exit_counter_name), )+
$( Counter::$dynamic_send_counter_name => std::ptr::addr_of_mut!(counters.$dynamic_send_counter_name), )+
+ $( Counter::$optimized_send_counter_name => std::ptr::addr_of_mut!(counters.$optimized_send_counter_name), )+
$( Counter::$counter_name => std::ptr::addr_of_mut!(counters.$counter_name), )+
}
}
@@ -80,6 +87,11 @@ macro_rules! make_counters {
$( Counter::$dynamic_send_counter_name, )+
];
+ /// List of other counters that are summed as optimized_send_count.
+ pub const OPTIMIZED_SEND_COUNTERS: &'static [Counter] = &[
+ $( Counter::$optimized_send_counter_name, )+
+ ];
+
/// List of other counters that are available only for --zjit-stats.
pub const OTHER_COUNTERS: &'static [Counter] = &[
$( Counter::$counter_name, )+
@@ -140,6 +152,13 @@ make_counters! {
send_fallback_not_optimized_instruction,
}
+ // Optimized send counters that are summed as optimized_send_count
+ optimized_send {
+ iseq_optimized_send_count,
+ inline_cfunc_optimized_send_count,
+ variadic_cfunc_optimized_send_count,
+ }
+
// compile_error_: Compile error reasons
compile_error_iseq_stack_too_large,
compile_error_exception_handler,
@@ -421,6 +440,16 @@ pub extern "C" fn rb_zjit_stats(_ec: EcPtr, _self: VALUE, target_key: VALUE) ->
}
set_stat_usize!(hash, "dynamic_send_count", dynamic_send_count);
+ // Set optimized send counters
+ let mut optimized_send_count = 0;
+ for &counter in OPTIMIZED_SEND_COUNTERS {
+ let count = unsafe { *counter_ptr(counter) };
+ optimized_send_count += count;
+ set_stat_usize!(hash, &counter.name(), count);
+ }
+ set_stat_usize!(hash, "optimized_send_count", optimized_send_count);
+ set_stat_usize!(hash, "send_count", dynamic_send_count + optimized_send_count);
+
// Set send fallback counters for NotOptimizedInstruction
let send_fallback_counters = ZJITState::get_send_fallback_counters();
for (op_idx, count) in send_fallback_counters.iter().enumerate().take(VM_INSTRUCTION_SIZE as usize) {