summaryrefslogtreecommitdiff
path: root/yjit
diff options
context:
space:
mode:
authorMaxime Chevalier-Boisvert <maxime.chevalierboisvert@shopify.com>2023-11-03 17:07:13 -0400
committerGitHub <noreply@github.com>2023-11-03 21:07:13 +0000
commit6e38076b1689af98ab1164af9119b9304e54829a (patch)
treee043396c843dce64271d31975bcc667f4a2890e9 /yjit
parent38bdb9d0da1647a9b91463183a9b61330243d908 (diff)
YJIT: implement two-step call threshold (#8839)
* YJIT: implement two-step call threshold Automatically switch call threshold to a larger value for larger, production-sized apps, while still allowing smaller apps and command-line programs to start with a lower threshold. * Update yjit/src/options.rs Co-authored-by: Alan Wu <XrXr@users.noreply.github.com> * Make the new variables constants * Check that a custom call threshold was not specified --------- Co-authored-by: Alan Wu <XrXr@users.noreply.github.com>
Diffstat (limited to 'yjit')
-rw-r--r--yjit/src/options.rs15
-rw-r--r--yjit/src/yjit.rs8
2 files changed, 20 insertions, 3 deletions
diff --git a/yjit/src/options.rs b/yjit/src/options.rs
index fe0a7ec9cc..98c0548677 100644
--- a/yjit/src/options.rs
+++ b/yjit/src/options.rs
@@ -2,17 +2,26 @@ use std::{ffi::{CStr, CString}, ptr::null};
use crate::backend::current::TEMP_REGS;
use std::os::raw::{c_char, c_int, c_uint};
+// Call threshold for small deployments and command-line apps
+pub static SMALL_CALL_THRESHOLD: u64 = 30;
+
+// Call threshold for larger deployments and production-sized applications
+pub static LARGE_CALL_THRESHOLD: u64 = 120;
+
+// Number of live ISEQs after which we consider an app to be large
+pub static LARGE_ISEQ_COUNT: u64 = 40_000;
+
// This option is exposed to the C side a a global variable for performance, see vm.c
// Number of method calls after which to start generating code
// Threshold==1 means compile on first execution
#[no_mangle]
-static mut rb_yjit_call_threshold: u64 = 30;
+pub static mut rb_yjit_call_threshold: u64 = SMALL_CALL_THRESHOLD;
// This option is exposed to the C side a a global variable for performance, see vm.c
// Number of execution requests after which a method is no longer
// considered hot. Raising this results in more generated code.
#[no_mangle]
-static mut rb_yjit_cold_threshold: u64 = 200_000;
+pub static mut rb_yjit_cold_threshold: u64 = 200_000;
// Command-line options
#[derive(Clone, PartialEq, Eq, Debug)]
@@ -92,7 +101,7 @@ static YJIT_OPTIONS: [(&str, &str); 8] = [
("--yjit-trace-exits", "Record Ruby source location when exiting from generated code"),
("--yjit-trace-exits-sample-rate", "Trace exit locations only every Nth occurrence"),
("--yjit-exec-mem-size=num", "Size of executable memory block in MiB (default: 128)"),
- ("--yjit-call-threshold=num", "Number of calls to trigger JIT (default: 30)"),
+ ("--yjit-call-threshold=num", "Number of calls to trigger JIT"),
("--yjit-cold-threshold=num", "Global call after which ISEQs not compiled (default: 200K)"),
("--yjit-max-versions=num", "Maximum number of versions per basic block (default: 4)"),
("--yjit-perf", "Enable frame pointers and perf profiling"),
diff --git a/yjit/src/yjit.rs b/yjit/src/yjit.rs
index 1e7e01a834..8431168763 100644
--- a/yjit/src/yjit.rs
+++ b/yjit/src/yjit.rs
@@ -134,6 +134,14 @@ pub extern "C" fn rb_yjit_iseq_gen_entry_point(iseq: IseqPtr, ec: EcPtr, jit_exc
return std::ptr::null();
}
+ // If a custom call threshold was not specified on the command-line and
+ // this is a large application (has very many ISEQs), switch to
+ // using the call threshold for large applications after this entry point
+ use crate::stats::rb_yjit_live_iseq_count;
+ if unsafe { rb_yjit_call_threshold } == SMALL_CALL_THRESHOLD && unsafe { rb_yjit_live_iseq_count } > LARGE_ISEQ_COUNT {
+ unsafe { rb_yjit_call_threshold = LARGE_CALL_THRESHOLD; };
+ }
+
let maybe_code_ptr = with_compile_time(|| { gen_entry_point(iseq, ec, jit_exception) });
match maybe_code_ptr {