mirror of
https://github.com/denoland/deno.git
synced 2024-11-30 16:40:57 -05:00
fix(bench): run warmup benchmark to break JIT bias (#19844)
Closes https://github.com/denoland/deno/issues/15277 This commit adds a single "warmup" run of empty function when running `deno bench`. This change will break so-called "JIT bias" which makes V8 optimize the first function and then bail out of optimization on second function. In essence the "warmup" function is getting optimized and then all user benches are bailed out of optimization.
This commit is contained in:
parent
bbaab3b21c
commit
d267eaa3b9
3 changed files with 34 additions and 0 deletions
|
@ -685,6 +685,8 @@ function test(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let registeredWarmupBench = false;
|
||||||
|
|
||||||
// Main bench function provided by Deno.
|
// Main bench function provided by Deno.
|
||||||
function bench(
|
function bench(
|
||||||
nameOrFnOrOptions,
|
nameOrFnOrOptions,
|
||||||
|
@ -695,6 +697,25 @@ function bench(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!registeredWarmupBench) {
|
||||||
|
registeredWarmupBench = true;
|
||||||
|
const warmupBenchDesc = {
|
||||||
|
name: "<warmup>",
|
||||||
|
fn: function warmup() {},
|
||||||
|
async: false,
|
||||||
|
ignore: false,
|
||||||
|
baseline: false,
|
||||||
|
only: false,
|
||||||
|
sanitizeExit: true,
|
||||||
|
permissions: null,
|
||||||
|
warmup: true,
|
||||||
|
};
|
||||||
|
warmupBenchDesc.fn = wrapBenchmark(warmupBenchDesc);
|
||||||
|
const { id, origin } = ops.op_register_bench(warmupBenchDesc);
|
||||||
|
warmupBenchDesc.id = id;
|
||||||
|
warmupBenchDesc.origin = origin;
|
||||||
|
}
|
||||||
|
|
||||||
let benchDesc;
|
let benchDesc;
|
||||||
const defaults = {
|
const defaults = {
|
||||||
ignore: false,
|
ignore: false,
|
||||||
|
@ -777,6 +798,7 @@ function bench(
|
||||||
const AsyncFunction = (async () => {}).constructor;
|
const AsyncFunction = (async () => {}).constructor;
|
||||||
benchDesc.async = AsyncFunction === benchDesc.fn.constructor;
|
benchDesc.async = AsyncFunction === benchDesc.fn.constructor;
|
||||||
benchDesc.fn = wrapBenchmark(benchDesc);
|
benchDesc.fn = wrapBenchmark(benchDesc);
|
||||||
|
benchDesc.warmup = false;
|
||||||
|
|
||||||
const { id, origin } = ops.op_register_bench(benchDesc);
|
const { id, origin } = ops.op_register_bench(benchDesc);
|
||||||
benchDesc.id = id;
|
benchDesc.id = id;
|
||||||
|
|
|
@ -101,6 +101,8 @@ struct BenchInfo<'s> {
|
||||||
group: Option<String>,
|
group: Option<String>,
|
||||||
ignore: bool,
|
ignore: bool,
|
||||||
only: bool,
|
only: bool,
|
||||||
|
#[serde(default)]
|
||||||
|
warmup: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
|
@ -128,6 +130,7 @@ fn op_register_bench<'a>(
|
||||||
group: info.group,
|
group: info.group,
|
||||||
ignore: info.ignore,
|
ignore: info.ignore,
|
||||||
only: info.only,
|
only: info.only,
|
||||||
|
warmup: info.warmup,
|
||||||
};
|
};
|
||||||
let function: v8::Local<v8::Function> = info.function.v8_value.try_into()?;
|
let function: v8::Local<v8::Function> = info.function.v8_value.try_into()?;
|
||||||
let function = v8::Global::new(scope, function);
|
let function = v8::Global::new(scope, function);
|
||||||
|
|
|
@ -95,6 +95,7 @@ pub struct BenchDescription {
|
||||||
pub group: Option<String>,
|
pub group: Option<String>,
|
||||||
pub ignore: bool,
|
pub ignore: bool,
|
||||||
pub only: bool,
|
pub only: bool,
|
||||||
|
pub warmup: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
@ -194,6 +195,10 @@ impl BenchReporter for JsonReporter {
|
||||||
fn report_output(&mut self, _output: &str) {}
|
fn report_output(&mut self, _output: &str) {}
|
||||||
|
|
||||||
fn report_result(&mut self, desc: &BenchDescription, result: &BenchResult) {
|
fn report_result(&mut self, desc: &BenchDescription, result: &BenchResult) {
|
||||||
|
if desc.warmup {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let maybe_bench = self.0.benches.iter_mut().find(|bench| {
|
let maybe_bench = self.0.benches.iter_mut().find(|bench| {
|
||||||
bench.origin == desc.origin
|
bench.origin == desc.origin
|
||||||
&& bench.group == desc.group
|
&& bench.group == desc.group
|
||||||
|
@ -326,6 +331,10 @@ impl BenchReporter for ConsoleReporter {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn report_result(&mut self, desc: &BenchDescription, result: &BenchResult) {
|
fn report_result(&mut self, desc: &BenchDescription, result: &BenchResult) {
|
||||||
|
if desc.warmup {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let options = self.options.as_ref().unwrap();
|
let options = self.options.as_ref().unwrap();
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
|
|
Loading…
Reference in a new issue