Skip to content

Commit 8cafa5b

Browse files
tenderloverwstauner
andcommitted
Only count VM instructions in YJIT stats builds
The instruction counter is slowing multi-Ractor applications. I had changed it to use a thread local, but using a thread local is slowing single threaded applications. This commit only enables the instruction counter in YJIT stats builds until we can figure out a way to gather the information with lower overhead. Co-authored-by: Randy Stauner <[email protected]>
1 parent c1ce3d7 commit 8cafa5b

File tree

9 files changed

+21
-21
lines changed

9 files changed

+21
-21
lines changed

internal/vm.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ struct vm_ifunc *rb_current_ifunc(void);
8181

8282
#if USE_YJIT
8383
/* vm_exec.c */
84-
extern RB_THREAD_LOCAL_SPECIFIER uint64_t rb_vm_insns_count;
84+
extern uint64_t rb_vm_insns_count;
8585
#endif
8686

8787
extern bool rb_free_at_exit;

test/ruby/test_yjit.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1637,7 +1637,7 @@ def test = :ok
16371637
16381638
[
16391639
stats[:object_shape_count].is_a?(Integer),
1640-
stats[:ratio_in_yjit].is_a?(Float),
1640+
stats[:ratio_in_yjit].nil? || stats[:ratio_in_yjit].is_a?(Float),
16411641
].all?
16421642
RUBY
16431643
end
@@ -1648,7 +1648,7 @@ def test = :ok
16481648
3.times { test }
16491649
16501650
# Collect single stat.
1651-
stat = RubyVM::YJIT.runtime_stats(:ratio_in_yjit)
1651+
stat = RubyVM::YJIT.runtime_stats(:yjit_alloc_size)
16521652
16531653
# Ensure this invocation had stats.
16541654
return true unless RubyVM::YJIT.runtime_stats[:all_stats]

vm_exec.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
#if USE_YJIT
1515
// The number of instructions executed on vm_exec_core. --yjit-stats uses this.
16-
RB_THREAD_LOCAL_SPECIFIER uint64_t rb_vm_insns_count = 0;
16+
uint64_t rb_vm_insns_count = 0;
1717
#endif
1818

1919
#if VM_COLLECT_USAGE_DETAILS

vm_insnhelper.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ RUBY_EXTERN rb_serial_t ruby_vm_constant_cache_invalidations;
1616
RUBY_EXTERN rb_serial_t ruby_vm_constant_cache_misses;
1717
RUBY_EXTERN rb_serial_t ruby_vm_global_cvar_state;
1818

19-
#if USE_YJIT // We want vm_insns_count on any JIT-enabled build.
19+
#if USE_YJIT && YJIT_STATS // We want vm_insns_count only on stats builds.
2020
// Increment vm_insns_count for --yjit-stats. We increment this even when
2121
// --yjit or --yjit-stats is not used because branching to skip it is slower.
2222
// We also don't use ATOMIC_INC for performance, allowing inaccuracy on Ractors.

yjit.c

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
#include "internal/fixnum.h"
1717
#include "internal/numeric.h"
1818
#include "internal/gc.h"
19-
#include "internal/vm.h"
2019
#include "vm_core.h"
2120
#include "vm_callinfo.h"
2221
#include "builtin.h"
@@ -96,11 +95,6 @@ rb_yjit_mark_executable(void *mem_block, uint32_t mem_size)
9695
}
9796
}
9897

99-
uint64_t
100-
rb_yjit_vm_insns_count(void) {
101-
return rb_vm_insns_count;
102-
}
103-
10498
// Free the specified memory block.
10599
bool
106100
rb_yjit_mark_unused(void *mem_block, uint32_t mem_size)

yjit.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -422,10 +422,10 @@ def _print_stats(out: $stderr) # :nodoc:
422422
out.puts "object_shape_count: " + format_number(13, stats[:object_shape_count])
423423
out.puts "side_exit_count: " + format_number(13, stats[:side_exit_count])
424424
out.puts "total_exit_count: " + format_number(13, stats[:total_exit_count])
425-
out.puts "total_insns_count: " + format_number(13, stats[:total_insns_count])
426-
out.puts "vm_insns_count: " + format_number(13, stats[:vm_insns_count])
425+
out.puts "total_insns_count: " + format_number(13, stats[:total_insns_count]) if stats[:total_insns_count]
426+
out.puts "vm_insns_count: " + format_number(13, stats[:vm_insns_count]) if stats[:vm_insns_count]
427427
out.puts "yjit_insns_count: " + format_number(13, stats[:yjit_insns_count])
428-
out.puts "ratio_in_yjit: " + ("%12.1f" % stats[:ratio_in_yjit]) + "%"
428+
out.puts "ratio_in_yjit: " + ("%12.1f" % stats[:ratio_in_yjit]) + "%" if stats[:ratio_in_yjit]
429429
out.puts "avg_len_in_yjit: " + ("%13.1f" % stats[:avg_len_in_yjit])
430430

431431
print_sorted_exit_counts(stats, out: out, prefix: "exit_")

yjit/bindgen/src/main.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,6 @@ fn main() {
317317
.allowlist_function("rb_yjit_get_page_size")
318318
.allowlist_function("rb_yjit_iseq_builtin_attrs")
319319
.allowlist_function("rb_yjit_iseq_inspect")
320-
.allowlist_function("rb_yjit_vm_insns_count")
321320
.allowlist_function("rb_yjit_builtin_function")
322321
.allowlist_function("rb_set_cfp_(pc|sp)")
323322
.allowlist_function("rb_yjit_multi_ractor_p")
@@ -381,6 +380,9 @@ fn main() {
381380
.allowlist_function("rb_ivar_get")
382381
.allowlist_function("rb_mod_name")
383382

383+
// From internal/vm.h
384+
.allowlist_var("rb_vm_insns_count")
385+
384386
// From include/ruby/internal/intern/vm.h
385387
.allowlist_function("rb_get_alloc_func")
386388

yjit/src/cruby_bindings.inc.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1060,6 +1060,7 @@ extern "C" {
10601060
elts: *const VALUE,
10611061
) -> VALUE;
10621062
pub fn rb_vm_top_self() -> VALUE;
1063+
pub static mut rb_vm_insns_count: u64;
10631064
pub fn rb_method_entry_at(obj: VALUE, id: ID) -> *const rb_method_entry_t;
10641065
pub fn rb_callable_method_entry(klass: VALUE, id: ID) -> *const rb_callable_method_entry_t;
10651066
pub fn rb_callable_method_entry_or_negative(
@@ -1139,7 +1140,6 @@ extern "C" {
11391140
pub fn rb_jit_cont_each_iseq(callback: rb_iseq_callback, data: *mut ::std::os::raw::c_void);
11401141
pub fn rb_yjit_mark_writable(mem_block: *mut ::std::os::raw::c_void, mem_size: u32) -> bool;
11411142
pub fn rb_yjit_mark_executable(mem_block: *mut ::std::os::raw::c_void, mem_size: u32);
1142-
pub fn rb_yjit_vm_insns_count() -> u64;
11431143
pub fn rb_yjit_mark_unused(mem_block: *mut ::std::os::raw::c_void, mem_size: u32) -> bool;
11441144
pub fn rb_yjit_array_len(a: VALUE) -> ::std::os::raw::c_long;
11451145
pub fn rb_yjit_icache_invalidate(

yjit/src/stats.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -789,7 +789,9 @@ fn rb_yjit_gen_stats_dict(key: VALUE) -> VALUE {
789789
set_stat_usize!(hash, "context_cache_bytes", crate::core::CTX_ENCODE_CACHE_BYTES + crate::core::CTX_DECODE_CACHE_BYTES);
790790

791791
// VM instructions count
792-
set_stat_usize!(hash, "vm_insns_count", rb_yjit_vm_insns_count() as usize);
792+
if rb_vm_insns_count > 0 {
793+
set_stat_usize!(hash, "vm_insns_count", rb_vm_insns_count as usize);
794+
}
793795

794796
set_stat_usize!(hash, "live_iseq_count", rb_yjit_live_iseq_count as usize);
795797
set_stat_usize!(hash, "iseq_alloc_count", rb_yjit_iseq_alloc_count as usize);
@@ -859,11 +861,13 @@ fn rb_yjit_gen_stats_dict(key: VALUE) -> VALUE {
859861
set_stat_double!(hash, "avg_len_in_yjit", avg_len_in_yjit);
860862

861863
// Proportion of instructions that retire in YJIT
862-
let total_insns_count = retired_in_yjit + rb_yjit_vm_insns_count();
863-
set_stat_usize!(hash, "total_insns_count", total_insns_count as usize);
864+
if rb_vm_insns_count > 0 {
865+
let total_insns_count = retired_in_yjit + rb_vm_insns_count;
866+
set_stat_usize!(hash, "total_insns_count", total_insns_count as usize);
864867

865-
let ratio_in_yjit: f64 = 100.0 * retired_in_yjit as f64 / total_insns_count as f64;
866-
set_stat_double!(hash, "ratio_in_yjit", ratio_in_yjit);
868+
let ratio_in_yjit: f64 = 100.0 * retired_in_yjit as f64 / total_insns_count as f64;
869+
set_stat_double!(hash, "ratio_in_yjit", ratio_in_yjit);
870+
}
867871

868872
// Set method call counts in a Ruby dict
869873
fn set_call_counts(

0 commit comments

Comments
 (0)