2024-01-01 19:58:21 +00:00
|
|
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
2021-04-18 12:51:48 +00:00
|
|
|
use bencher::Bencher;
|
|
|
|
use deno_core::v8;
|
2021-05-21 13:46:26 +00:00
|
|
|
use deno_core::Extension;
|
2021-04-18 12:51:48 +00:00
|
|
|
use deno_core::JsRuntime;
|
2023-12-13 15:07:26 +00:00
|
|
|
use deno_core::PollEventLoopOptions;
|
2021-05-21 13:46:26 +00:00
|
|
|
use deno_core::RuntimeOptions;
|
2021-04-18 12:51:48 +00:00
|
|
|
|
|
|
|
use crate::profiling::is_profiling;
|
|
|
|
|
2021-05-21 13:46:26 +00:00
|
|
|
pub fn create_js_runtime(setup: impl FnOnce() -> Vec<Extension>) -> JsRuntime {
|
|
|
|
JsRuntime::new(RuntimeOptions {
|
2023-03-10 00:22:27 +00:00
|
|
|
extensions: setup(),
|
2023-05-04 00:44:59 +00:00
|
|
|
module_loader: None,
|
2021-05-21 13:46:26 +00:00
|
|
|
..Default::default()
|
|
|
|
})
|
2021-04-18 12:51:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn loop_code(iters: u64, src: &str) -> String {
|
2023-01-27 15:43:16 +00:00
|
|
|
format!(r#"for(let i=0; i < {iters}; i++) {{ {src} }}"#,)
|
2021-04-18 12:51:48 +00:00
|
|
|
}
|
|
|
|
|
2022-02-23 17:51:13 +00:00
|
|
|
#[derive(Copy, Clone)]
|
|
|
|
pub struct BenchOptions {
|
|
|
|
pub benching_inner: u64,
|
|
|
|
pub profiling_inner: u64,
|
|
|
|
pub profiling_outer: u64,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for BenchOptions {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self {
|
|
|
|
benching_inner: 1_000,
|
|
|
|
profiling_inner: 1_000,
|
|
|
|
profiling_outer: 10_000,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-18 12:51:48 +00:00
|
|
|
pub fn bench_js_sync(
|
|
|
|
b: &mut Bencher,
|
|
|
|
src: &str,
|
2021-05-21 13:46:26 +00:00
|
|
|
setup: impl FnOnce() -> Vec<Extension>,
|
2022-02-23 17:51:13 +00:00
|
|
|
) {
|
|
|
|
bench_js_sync_with(b, src, setup, Default::default())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn bench_js_sync_with(
|
|
|
|
b: &mut Bencher,
|
|
|
|
src: &str,
|
|
|
|
setup: impl FnOnce() -> Vec<Extension>,
|
|
|
|
opts: BenchOptions,
|
2021-04-18 12:51:48 +00:00
|
|
|
) {
|
|
|
|
let mut runtime = create_js_runtime(setup);
|
2021-04-28 16:28:46 +00:00
|
|
|
let scope = &mut runtime.handle_scope();
|
2021-04-18 12:51:48 +00:00
|
|
|
|
|
|
|
// Increase JS iterations if profiling for nicer flamegraphs
|
2022-02-23 17:51:13 +00:00
|
|
|
let inner_iters = if is_profiling() {
|
|
|
|
opts.profiling_inner * opts.profiling_outer
|
|
|
|
} else {
|
|
|
|
opts.benching_inner
|
|
|
|
};
|
2021-04-18 12:51:48 +00:00
|
|
|
// Looped code
|
|
|
|
let looped_src = loop_code(inner_iters, src);
|
|
|
|
|
|
|
|
let code = v8::String::new(scope, looped_src.as_ref()).unwrap();
|
|
|
|
let script = v8::Script::compile(scope, code, None).unwrap();
|
|
|
|
// Run once if profiling, otherwise regular bench loop
|
|
|
|
if is_profiling() {
|
|
|
|
script.run(scope).unwrap();
|
|
|
|
} else {
|
|
|
|
b.iter(|| {
|
|
|
|
script.run(scope).unwrap();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn bench_js_async(
|
|
|
|
b: &mut Bencher,
|
|
|
|
src: &str,
|
2021-05-21 13:46:26 +00:00
|
|
|
setup: impl FnOnce() -> Vec<Extension>,
|
2022-02-23 17:51:13 +00:00
|
|
|
) {
|
|
|
|
bench_js_async_with(b, src, setup, Default::default())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn bench_js_async_with(
|
|
|
|
b: &mut Bencher,
|
|
|
|
src: &str,
|
|
|
|
setup: impl FnOnce() -> Vec<Extension>,
|
|
|
|
opts: BenchOptions,
|
2021-04-18 12:51:48 +00:00
|
|
|
) {
|
|
|
|
let mut runtime = create_js_runtime(setup);
|
|
|
|
let tokio_runtime = tokio::runtime::Builder::new_current_thread()
|
|
|
|
.enable_all()
|
|
|
|
.build()
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
// Looped code
|
2022-02-23 17:51:13 +00:00
|
|
|
let inner_iters = if is_profiling() {
|
|
|
|
opts.profiling_inner
|
|
|
|
} else {
|
|
|
|
opts.benching_inner
|
|
|
|
};
|
|
|
|
let looped = loop_code(inner_iters, src);
|
2023-03-21 22:33:12 +00:00
|
|
|
// Get a &'static str by leaking -- this is fine because it's benchmarking code
|
|
|
|
let src = Box::leak(looped.into_boxed_str());
|
2021-04-18 12:51:48 +00:00
|
|
|
if is_profiling() {
|
2022-02-23 17:51:13 +00:00
|
|
|
for _ in 0..opts.profiling_outer {
|
2021-05-21 13:42:17 +00:00
|
|
|
tokio_runtime.block_on(inner_async(src, &mut runtime));
|
2021-04-18 12:51:48 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
b.iter(|| {
|
2021-05-21 13:42:17 +00:00
|
|
|
tokio_runtime.block_on(inner_async(src, &mut runtime));
|
2021-04-18 12:51:48 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
2021-05-21 13:42:17 +00:00
|
|
|
|
2023-03-21 22:33:12 +00:00
|
|
|
async fn inner_async(src: &'static str, runtime: &mut JsRuntime) {
|
2024-03-05 01:17:39 +00:00
|
|
|
runtime.execute_script("inner_loop", src).unwrap();
|
2023-12-13 15:07:26 +00:00
|
|
|
runtime
|
|
|
|
.run_event_loop(PollEventLoopOptions::default())
|
|
|
|
.await
|
|
|
|
.unwrap();
|
2021-05-21 13:42:17 +00:00
|
|
|
}
|