summaryrefslogtreecommitdiff
path: root/yjit
diff options
context:
space:
mode:
authorAdam Hess <HParker@github.com>2023-04-13 07:07:07 -0700
committerGitHub <noreply@github.com>2023-04-13 10:07:07 -0400
commit854baee2c936006d7f38ebb27ee577c00afc6249 (patch)
treec5bb8bf804adccc29a1af4065c62365dba9445c4 /yjit
parent02a7e12b80823919fb614ad3ea6241d5115d14fe (diff)
downloadruby-854baee2c936006d7f38ebb27ee577c00afc6249.tar.gz
YJIT: Add a sampling option to exit tracing (#7693)
Add a sampling option to trace exits Running YJIT with trace exits enabled can make very large metrics files. This allows us to configure a sample rate to make tracing exits possible on larger tests. This also updates the documented YJIT options. Co-authored-by: Alan Wu <XrXr@users.noreply.github.com> Co-authored-by: John Hawthorn <john@hawthorn.email> Co-authored-by: Maxime Chevalier-Boisvert <maximechevalierb@gmail.com>
Diffstat (limited to 'yjit')
-rw-r--r--yjit/src/options.rs20
-rw-r--r--yjit/src/stats.rs21
2 files changed, 38 insertions, 3 deletions
diff --git a/yjit/src/options.rs b/yjit/src/options.rs
index 03acc7bbe0..78a507ce11 100644
--- a/yjit/src/options.rs
+++ b/yjit/src/options.rs
@@ -32,6 +32,9 @@ pub struct Options {
// Trace locations of exits
pub gen_trace_exits: bool,
+ // how often to sample exit trace data
+ pub trace_exits_sample_rate: usize,
+
// Whether to start YJIT in paused state (initialize YJIT but don't
// compile anything)
pub pause: bool,
@@ -59,6 +62,7 @@ pub static mut OPTIONS: Options = Options {
num_temp_regs: 5,
gen_stats: false,
gen_trace_exits: false,
+ trace_exits_sample_rate: 0,
pause: false,
dump_insns: false,
dump_disasm: None,
@@ -173,7 +177,8 @@ pub fn parse_option(str_ptr: *const std::os::raw::c_char) -> Option<()> {
("greedy-versioning", "") => unsafe { OPTIONS.greedy_versioning = true },
("no-type-prop", "") => unsafe { OPTIONS.no_type_prop = true },
("stats", "") => unsafe { OPTIONS.gen_stats = true },
- ("trace-exits", "") => unsafe { OPTIONS.gen_trace_exits = true; OPTIONS.gen_stats = true },
+ ("trace-exits", "") => unsafe { OPTIONS.gen_trace_exits = true; OPTIONS.gen_stats = true; OPTIONS.trace_exits_sample_rate = 0 },
+ ("trace-exits-sample-rate", sample_rate) => unsafe { OPTIONS.gen_trace_exits = true; OPTIONS.gen_stats = true; OPTIONS.trace_exits_sample_rate = sample_rate.parse().unwrap(); },
("dump-insns", "") => unsafe { OPTIONS.dump_insns = true },
("verify-ctx", "") => unsafe { OPTIONS.verify_ctx = true },
@@ -183,6 +188,19 @@ pub fn parse_option(str_ptr: *const std::os::raw::c_char) -> Option<()> {
}
}
+ // before we continue, check that sample_rate is either 0 or a prime number
+ let trace_sample_rate = unsafe { OPTIONS.trace_exits_sample_rate };
+ if trace_sample_rate > 1 {
+ let mut i = 2;
+ while i*i <= trace_sample_rate {
+ if trace_sample_rate % i == 0 {
+ println!("Warning: using a non-prime number as your sampling rate can result in less accurate sampling data");
+ return Some(());
+ }
+ i += 1;
+ }
+ }
+
// dbg!(unsafe {OPTIONS});
// Option successfully parsed
diff --git a/yjit/src/stats.rs b/yjit/src/stats.rs
index f937c6e625..42b7de7a59 100644
--- a/yjit/src/stats.rs
+++ b/yjit/src/stats.rs
@@ -26,7 +26,9 @@ pub struct YjitExitLocations {
raw_samples: Vec<VALUE>,
/// Vec to hold line_samples which represent line numbers of
/// the iseq caller.
- line_samples: Vec<i32>
+ line_samples: Vec<i32>,
+ /// Number of samples skipped when sampling
+ skipped_samples: usize
}
/// Private singleton instance of yjit exit locations
@@ -47,7 +49,8 @@ impl YjitExitLocations {
let yjit_exit_locations = YjitExitLocations {
raw_samples: Vec::new(),
- line_samples: Vec::new()
+ line_samples: Vec::new(),
+ skipped_samples: 0
};
// Initialize the yjit exit locations instance
@@ -71,6 +74,11 @@ impl YjitExitLocations {
&mut YjitExitLocations::get_instance().line_samples
}
+ /// Get the number of samples skipped
+ pub fn get_skipped_samples() -> &'static mut usize {
+ &mut YjitExitLocations::get_instance().skipped_samples
+ }
+
/// Mark the data stored in YjitExitLocations::get_raw_samples that needs to be used by
/// rb_yjit_add_frame. YjitExitLocations::get_raw_samples are an array of
/// VALUE pointers, exit instruction, and number of times we've seen this stack row
@@ -573,6 +581,15 @@ pub extern "C" fn rb_yjit_record_exit_stack(exit_pc: *const VALUE)
return;
}
+ if get_option!(trace_exits_sample_rate) > 0 {
+ if get_option!(trace_exits_sample_rate) <= *YjitExitLocations::get_skipped_samples() {
+ YjitExitLocations::get_instance().skipped_samples = 0;
+ } else {
+ YjitExitLocations::get_instance().skipped_samples += 1;
+ return;
+ }
+ }
+
// rb_vm_insn_addr2opcode won't work in cargo test --all-features
// because it's a C function. Without insn call, this function is useless
// so wrap the whole thing in a not test check.