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>
This commit is contained in:
parent
38bdb9d0da
commit
6e38076b16
@ -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"),
|
||||
|
@ -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 {
|
||||
|
Loading…
x
Reference in New Issue
Block a user