One Engine
Instance Per Call
-
A system where scripts are called a lot, in tight loops or in parallel.
-
Keeping a global
Engine
instance is sub-optimal due to contention and locking. -
Scripts need to be executed independently from each other, perhaps concurrently.
-
Scripts are used to create Rust closures that are stored and may be called at any time, perhaps concurrently. In this case, the
Engine
instance is usually moved into the closure itself.
Procedure
-
Gather up all common custom functions into a custom package.
-
This custom package should also include standard packages needed. For example, to duplicate
Engine::new
, use aStandardPackage
. -
Packages are sharable, so using a custom package is much cheaper than registering all the functions one by one.
-
-
Always use
Engine::new_raw
to create a rawEngine
, instead ofEngine::new
which is much more expensive. A rawEngine
is extremely cheap to create. -
Register the custom package with the raw
Engine
viaPackage::register_into_engine
.
Examples
use rhai::def_package;
use rhai::packages::{Package, StandardPackage};
// Define the custom package 'MyCustomPackage'.
//
// Aggregate other base packages simply by listing them after the colon.
def_package! {
/// My own personal super-duper custom package
pub MyCustomPackage(module) : StandardPackage {
// Register additional Rust functions using 'Module::set_native_fn'.
let hash = module.set_native_fn("foo", |s: ImmutableString| {
Ok(foo(s.into_owned()))
});
// Remember to update the parameter names/types and return type metadata
// when using the 'metadata' feature.
// 'Module::set_native_fn' by default does not set function metadata.
module.update_fn_metadata(hash, &["s: ImmutableString", "i64"]);
}
}
let ast = /* ... some AST ... */;
let custom_pkg = MyCustomPackage::new();
// The following loop creates 10,000 Engine instances!
for x in 0..10_000 {
// Create a raw Engine - extremely cheap
let mut engine = Engine::new_raw();
// Register custom package - cheap
custom_pkg.register_into_engine(&mut engine);
// Evaluate script
engine.run_ast(&ast)?;
}