Skip to content

Commit dbb1c49

Browse files
authored
perf: add script loading benchmark (#411)
# Summary Adds benchmarks for the `CreateOrUpdate` script loading command. The benchmarks run 50% updates to 50% initial loads ratios
1 parent 1077d48 commit dbb1c49

File tree

5 files changed

+107
-254
lines changed

5 files changed

+107
-254
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
function on_script_loaded()
2+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
fn on_script_loaded(){
2+
3+
}

benches/benchmarks.rs

+31-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ use criterion::{BatchSize, BenchmarkFilter};
1111
use regex::Regex;
1212
use script_integration_test_harness::test_functions::rand::Rng;
1313
use script_integration_test_harness::{
14-
perform_benchmark_with_generator, run_lua_benchmark, run_rhai_benchmark,
14+
make_test_lua_plugin, make_test_rhai_plugin, perform_benchmark_with_generator,
15+
run_lua_benchmark, run_plugin_script_load_benchmark, run_rhai_benchmark,
1516
};
1617
use std::collections::HashMap;
1718
use std::{path::PathBuf, sync::LazyLock, time::Duration};
@@ -241,6 +242,34 @@ fn conversion_benchmarks(criterion: &mut Criterion) {
241242
);
242243
}
243244

245+
fn script_load_benchmarks(criterion: &mut Criterion) {
246+
let mut group = criterion.benchmark_group("loading");
247+
let reload_probability = 0.5;
248+
// lua
249+
let plugin = make_test_lua_plugin();
250+
let content = include_str!("../assets/macro_benchmarks/loading/empty.lua");
251+
run_plugin_script_load_benchmark(
252+
plugin,
253+
"empty Lua",
254+
content,
255+
&mut group,
256+
|rand| format!("{rand}.lua"),
257+
reload_probability,
258+
);
259+
260+
// rhai
261+
let plugin = make_test_rhai_plugin();
262+
let content = include_str!("../assets/macro_benchmarks/loading/empty.rhai");
263+
run_plugin_script_load_benchmark(
264+
plugin,
265+
"empty Rhai",
266+
content,
267+
&mut group,
268+
|rand| format!("{rand}.rhai"),
269+
reload_probability,
270+
);
271+
}
272+
244273
pub fn benches() {
245274
maybe_with_profiler(|_profiler| {
246275
let mut criterion: criterion::Criterion<_> = (criterion::Criterion::default())
@@ -265,6 +294,7 @@ pub fn benches() {
265294

266295
script_benchmarks(&mut criterion, filter);
267296
conversion_benchmarks(&mut criterion);
297+
script_load_benchmarks(&mut criterion);
268298
});
269299
}
270300
criterion_main!(benches);

crates/testing_crates/script_integration_test_harness/src/lib.rs

+71-16
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,12 @@ use bevy::{
1414
event::{Event, Events},
1515
schedule::{IntoSystemConfigs, SystemConfigs},
1616
system::{IntoSystem, Local, Res, Resource, SystemState},
17-
world::{FromWorld, Mut},
17+
world::{Command, FromWorld, Mut},
1818
},
19+
log::Level,
1920
prelude::{Entity, World},
2021
reflect::{Reflect, TypeRegistry},
22+
utils::tracing,
2123
};
2224
use bevy_mod_scripting_core::{
2325
asset::ScriptAsset,
@@ -26,6 +28,7 @@ use bevy_mod_scripting_core::{
2628
ReflectAccessId, WorldAccessGuard, WorldGuard,
2729
},
2830
callback_labels,
31+
commands::CreateOrUpdateScript,
2932
error::{InteropError, ScriptError},
3033
event::{IntoCallbackLabel, ScriptErrorEvent},
3134
extractors::{HandlerContext, WithWorldGuard},
@@ -68,6 +71,22 @@ impl<L: IntoCallbackLabel, P: IntoScriptPluginParams> TestCallbackBuilder<P, L>
6871
}
6972
}
7073

74+
pub fn install_test_plugin<P: IntoScriptPluginParams + Plugin>(
75+
app: &mut bevy::app::App,
76+
plugin: P,
77+
include_test_functions: bool,
78+
) {
79+
app.add_plugins((
80+
ScriptFunctionsPlugin,
81+
CoreScriptGlobalsPlugin::default(),
82+
BMSScriptingInfrastructurePlugin,
83+
plugin,
84+
));
85+
if include_test_functions {
86+
register_test_functions(app);
87+
}
88+
}
89+
7190
#[cfg(feature = "lua")]
7291
pub fn make_test_lua_plugin() -> bevy_mod_scripting_lua::LuaScriptingPlugin {
7392
use bevy_mod_scripting_core::{bindings::WorldContainer, ConfigureScriptPlugin};
@@ -203,14 +222,7 @@ pub fn execute_integration_test<
203222

204223
let mut app = setup_integration_test(init);
205224

206-
app.add_plugins((
207-
ScriptFunctionsPlugin,
208-
CoreScriptGlobalsPlugin::default(),
209-
BMSScriptingInfrastructurePlugin,
210-
plugin,
211-
));
212-
213-
register_test_functions(&mut app);
225+
install_test_plugin(&mut app, plugin, true);
214226

215227
app.add_event::<TestEventFinished>();
216228

@@ -411,13 +423,7 @@ where
411423

412424
let mut app = setup_integration_test(|_, _| {});
413425

414-
app.add_plugins((
415-
ScriptFunctionsPlugin,
416-
CoreScriptGlobalsPlugin::default(),
417-
BMSScriptingInfrastructurePlugin,
418-
plugin,
419-
));
420-
register_test_functions(&mut app);
426+
install_test_plugin(&mut app, plugin, true);
421427

422428
let script_id = script_id.to_owned();
423429
let script_id_clone = script_id.clone();
@@ -468,6 +474,55 @@ where
468474
}
469475
}
470476

477+
pub fn run_plugin_script_load_benchmark<
478+
P: IntoScriptPluginParams + Plugin + FromWorld,
479+
M: Measurement,
480+
>(
481+
plugin: P,
482+
benchmark_id: &str,
483+
content: &str,
484+
criterion: &mut criterion::BenchmarkGroup<M>,
485+
script_id_generator: impl Fn(u64) -> String,
486+
reload_probability: f32,
487+
) {
488+
let mut app = setup_integration_test(|_, _| {});
489+
install_test_plugin(&mut app, plugin, false);
490+
let mut rng_guard = RNG.lock().unwrap();
491+
*rng_guard = rand_chacha::ChaCha12Rng::from_seed([42u8; 32]);
492+
drop(rng_guard);
493+
criterion.bench_function(benchmark_id, |c| {
494+
c.iter_batched(
495+
|| {
496+
let mut rng = RNG.lock().unwrap();
497+
let is_reload = rng.random_range(0f32..=1f32) < reload_probability;
498+
let random_id = if is_reload { 0 } else { rng.random::<u64>() };
499+
500+
let random_script_id = script_id_generator(random_id);
501+
// we manually load the script inside a command
502+
let content = content.to_string().into_boxed_str();
503+
(
504+
CreateOrUpdateScript::<P>::new(
505+
random_script_id.into(),
506+
content.clone().into(),
507+
None,
508+
),
509+
is_reload,
510+
)
511+
},
512+
|(command, _is_reload)| {
513+
tracing::event!(
514+
Level::TRACE,
515+
"profiling_iter {} is reload?: {}",
516+
benchmark_id,
517+
_is_reload
518+
);
519+
command.apply(app.world_mut());
520+
},
521+
BatchSize::LargeInput,
522+
);
523+
});
524+
}
525+
471526
pub fn perform_benchmark_with_generator<
472527
M: Measurement,
473528
I,

0 commit comments

Comments
 (0)