diff --git a/Cargo.lock b/Cargo.lock index a3e186aca428..e7ddb66e2918 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8035,6 +8035,7 @@ dependencies = [ "lazy_static", "libsecp256k1", "log 0.4.14", + "lru 0.6.6", "parity-scale-codec", "parking_lot 0.11.1", "paste 1.0.6", diff --git a/bin/node-template/node/src/service.rs b/bin/node-template/node/src/service.rs index 82b1c5625373..92bd059e528a 100644 --- a/bin/node-template/node/src/service.rs +++ b/bin/node-template/node/src/service.rs @@ -78,6 +78,7 @@ pub fn new_partial( config.wasm_method, config.default_heap_pages, config.max_runtime_instances, + config.runtime_cache_size, ); let (client, backend, keystore_container, task_manager) = diff --git a/bin/node/cli/benches/block_production.rs b/bin/node/cli/benches/block_production.rs index 5a520e7b6339..f2dbc1fff6be 100644 --- a/bin/node/cli/benches/block_production.rs +++ b/bin/node/cli/benches/block_production.rs @@ -104,6 +104,7 @@ fn new_node(tokio_handle: Handle) -> node_cli::service::NewFullBase { tracing_targets: None, tracing_receiver: Default::default(), max_runtime_instances: 8, + runtime_cache_size: 2, announce_block: true, base_path: Some(base_path), informant_output_format: Default::default(), diff --git a/bin/node/cli/benches/transaction_pool.rs b/bin/node/cli/benches/transaction_pool.rs index 4f5ccd6ea912..2965c6336f0f 100644 --- a/bin/node/cli/benches/transaction_pool.rs +++ b/bin/node/cli/benches/transaction_pool.rs @@ -96,6 +96,7 @@ fn new_node(tokio_handle: Handle) -> node_cli::service::NewFullBase { tracing_targets: None, tracing_receiver: Default::default(), max_runtime_instances: 8, + runtime_cache_size: 2, announce_block: true, base_path: Some(base_path), informant_output_format: Default::default(), diff --git a/bin/node/cli/src/service.rs b/bin/node/cli/src/service.rs index 1dfce9331b75..fbc91c5f7d2e 100644 --- a/bin/node/cli/src/service.rs +++ b/bin/node/cli/src/service.rs @@ -161,6 +161,7 @@ pub fn new_partial( config.wasm_method, config.default_heap_pages, config.max_runtime_instances, + config.runtime_cache_size, ); let (client, backend, keystore_container, task_manager) = diff --git a/bin/node/executor/benches/bench.rs b/bin/node/executor/benches/bench.rs index 03c3eb53e23f..aea37b68d55b 100644 --- a/bin/node/executor/benches/bench.rs +++ b/bin/node/executor/benches/bench.rs @@ -194,7 +194,7 @@ fn bench_execute_block(c: &mut Criterion) { ExecutionMethod::Wasm(wasm_method) => (false, wasm_method), }; - let executor = NativeElseWasmExecutor::new(wasm_method, None, 8); + let executor = NativeElseWasmExecutor::new(wasm_method, None, 8, 2); let runtime_code = RuntimeCode { code_fetcher: &sp_core::traits::WrappedRuntimeCode(compact_code_unwrap().into()), hash: vec![1, 2, 3], diff --git a/bin/node/executor/tests/common.rs b/bin/node/executor/tests/common.rs index 87506ba66a3e..84b5728a1a84 100644 --- a/bin/node/executor/tests/common.rs +++ b/bin/node/executor/tests/common.rs @@ -96,7 +96,7 @@ pub fn from_block_number(n: u32) -> Header { } pub fn executor() -> NativeElseWasmExecutor { - NativeElseWasmExecutor::new(WasmExecutionMethod::Interpreted, None, 8) + NativeElseWasmExecutor::new(WasmExecutionMethod::Interpreted, None, 8, 2) } pub fn executor_call< diff --git a/bin/node/inspect/src/command.rs b/bin/node/inspect/src/command.rs index 9bf69511689c..e20c91456515 100644 --- a/bin/node/inspect/src/command.rs +++ b/bin/node/inspect/src/command.rs @@ -41,6 +41,7 @@ impl InspectCmd { config.wasm_method, config.default_heap_pages, config.max_runtime_instances, + config.runtime_cache_size, ); let client = new_full_client::(&config, None, executor)?; diff --git a/bin/node/testing/src/bench.rs b/bin/node/testing/src/bench.rs index 3240497a9d62..6a5c4b80e1fe 100644 --- a/bin/node/testing/src/bench.rs +++ b/bin/node/testing/src/bench.rs @@ -400,7 +400,7 @@ impl BenchDb { let backend = sc_service::new_db_backend(db_config).expect("Should not fail"); let client = sc_service::new_client( backend.clone(), - NativeElseWasmExecutor::new(WasmExecutionMethod::Compiled, None, 8), + NativeElseWasmExecutor::new(WasmExecutionMethod::Compiled, None, 8, 2), &keyring.generate_genesis(), None, None, diff --git a/client/cli/src/commands/run_cmd.rs b/client/cli/src/commands/run_cmd.rs index ad2f04583c10..d0d4dc63c021 100644 --- a/client/cli/src/commands/run_cmd.rs +++ b/client/cli/src/commands/run_cmd.rs @@ -238,6 +238,10 @@ pub struct RunCmd { #[structopt(long)] pub max_runtime_instances: Option, + /// Maximum number of different runtimes that can be cached. + #[structopt(long, default_value = "2")] + pub runtime_cache_size: u8, + /// Run a temporary node. /// /// A temporary directory will be created to store the configuration and will be deleted @@ -450,6 +454,10 @@ impl CliConfiguration for RunCmd { Ok(self.max_runtime_instances.map(|x| x.min(256))) } + fn runtime_cache_size(&self) -> Result { + Ok(self.runtime_cache_size) + } + fn base_path(&self) -> Result> { Ok(if self.tmp { Some(BasePath::new_temp_dir()?) diff --git a/client/cli/src/config.rs b/client/cli/src/config.rs index 20e2bf0df5b2..1fda07d2571f 100644 --- a/client/cli/src/config.rs +++ b/client/cli/src/config.rs @@ -452,6 +452,13 @@ pub trait CliConfiguration: Sized { Ok(Default::default()) } + /// Get maximum different runtimes in cache + /// + /// By default this is `2`. + fn runtime_cache_size(&self) -> Result { + Ok(2) + } + /// Activate or not the automatic announcing of blocks after import /// /// By default this is `false`. @@ -482,6 +489,7 @@ pub trait CliConfiguration: Sized { let is_validator = role.is_authority(); let (keystore_remote, keystore) = self.keystore_config(&config_dir)?; let telemetry_endpoints = self.telemetry_endpoints(&chain_spec)?; + let runtime_cache_size = self.runtime_cache_size()?; let unsafe_pruning = self.import_params().map(|p| p.unsafe_pruning).unwrap_or(false); @@ -534,6 +542,7 @@ pub trait CliConfiguration: Sized { role, base_path: Some(base_path), informant_output_format: Default::default(), + runtime_cache_size, }) } diff --git a/client/executor/Cargo.toml b/client/executor/Cargo.toml index b3a393f9472a..dea8a26edde3 100644 --- a/client/executor/Cargo.toml +++ b/client/executor/Cargo.toml @@ -34,6 +34,7 @@ parking_lot = "0.11.1" log = "0.4.8" libsecp256k1 = "0.7" sp-core-hashing-proc-macro = { version = "4.0.0-dev", path = "../../primitives/core/hashing/proc-macro" } +lru = "0.6.6" [dev-dependencies] wat = "1.0" diff --git a/client/executor/src/integration_tests/mod.rs b/client/executor/src/integration_tests/mod.rs index 01c040687ddd..3ff0ecebd9ac 100644 --- a/client/executor/src/integration_tests/mod.rs +++ b/client/executor/src/integration_tests/mod.rs @@ -130,6 +130,7 @@ fn call_in_wasm( HostFunctions::host_functions(), 8, None, + 2, ); executor.uncached_call( RuntimeBlob::uncompress_if_needed(&wasm_binary_unwrap()[..]).unwrap(), @@ -480,6 +481,7 @@ fn should_trap_when_heap_exhausted(wasm_method: WasmExecutionMethod) { HostFunctions::host_functions(), 8, None, + 2, ); let err = executor @@ -593,6 +595,7 @@ fn parallel_execution(wasm_method: WasmExecutionMethod) { HostFunctions::host_functions(), 8, None, + 2, )); let threads: Vec<_> = (0..8) .map(|_| { diff --git a/client/executor/src/lib.rs b/client/executor/src/lib.rs index 041db87bc82a..9a4d8e3cf0b6 100644 --- a/client/executor/src/lib.rs +++ b/client/executor/src/lib.rs @@ -80,6 +80,7 @@ mod tests { sp_io::SubstrateHostFunctions::host_functions(), 8, None, + 2, ); let res = executor .uncached_call( diff --git a/client/executor/src/native_executor.rs b/client/executor/src/native_executor.rs index 62e76d559c0f..1c01520ac9c8 100644 --- a/client/executor/src/native_executor.rs +++ b/client/executor/src/native_executor.rs @@ -130,12 +130,17 @@ impl WasmExecutor { host_functions: Vec<&'static dyn Function>, max_runtime_instances: usize, cache_path: Option, + runtime_cache_size: u8, ) -> Self { WasmExecutor { method, default_heap_pages: default_heap_pages.unwrap_or(DEFAULT_HEAP_PAGES), host_functions: Arc::new(host_functions), - cache: Arc::new(RuntimeCache::new(max_runtime_instances, cache_path.clone())), + cache: Arc::new(RuntimeCache::new( + max_runtime_instances, + cache_path.clone(), + runtime_cache_size, + )), cache_path, } } @@ -330,6 +335,7 @@ impl NativeElseWasmExecutor { fallback_method: WasmExecutionMethod, default_heap_pages: Option, max_runtime_instances: usize, + runtime_cache_size: u8, ) -> Self { let extended = D::ExtendHostFunctions::host_functions(); let mut host_functions = sp_io::SubstrateHostFunctions::host_functions() @@ -351,6 +357,7 @@ impl NativeElseWasmExecutor { host_functions, max_runtime_instances, None, + runtime_cache_size, ); NativeElseWasmExecutor { @@ -636,6 +643,7 @@ mod tests { WasmExecutionMethod::Interpreted, None, 8, + 2, ); my_interface::HostFunctions::host_functions().iter().for_each(|function| { assert_eq!(executor.wasm.host_functions.iter().filter(|f| f == &function).count(), 2); diff --git a/client/executor/src/wasm_runtime.rs b/client/executor/src/wasm_runtime.rs index 88c033814ed6..44ed6eb32304 100644 --- a/client/executor/src/wasm_runtime.rs +++ b/client/executor/src/wasm_runtime.rs @@ -23,6 +23,7 @@ use crate::error::{Error, WasmError}; use codec::Decode; +use lru::LruCache; use parking_lot::Mutex; use sc_executor_common::{ runtime_blob::RuntimeBlob, @@ -54,20 +55,24 @@ impl Default for WasmExecutionMethod { } } -/// A Wasm runtime object along with its cached runtime version. -struct VersionedRuntime { +#[derive(Debug, PartialEq, Eq, Hash, Clone)] +struct VersionedRuntimeId { /// Runtime code hash. code_hash: Vec, /// Wasm runtime type. wasm_method: WasmExecutionMethod, - /// Shared runtime that can spawn instances. - module: Arc, /// The number of WebAssembly heap pages this instance was created with. heap_pages: u64, +} + +/// A Wasm runtime object along with its cached runtime version. +struct VersionedRuntime { + /// Shared runtime that can spawn instances. + module: Arc, /// Runtime version according to `Core_version` if any. version: Option, /// Cached instance pool. - instances: Vec>>>, + instances: Arc>>>>, } impl VersionedRuntime { @@ -137,8 +142,6 @@ impl VersionedRuntime { } } -const MAX_RUNTIMES: usize = 2; - /// Cache for the runtimes. /// /// When an instance is requested for the first time it is added to this cache. Metadata is kept @@ -149,12 +152,12 @@ const MAX_RUNTIMES: usize = 2; /// the memory reset to the initial memory. So, one runtime instance is reused for every fetch /// request. /// -/// The size of cache is equal to `MAX_RUNTIMES`. +/// The size of cache is configurable via the cli option `--runtime-cache-size`. pub struct RuntimeCache { /// A cache of runtimes along with metadata. /// /// Runtimes sorted by recent usage. The most recently used is at the front. - runtimes: Mutex<[Option>; MAX_RUNTIMES]>, + runtimes: Mutex>>, /// The size of the instances cache for each runtime. max_runtime_instances: usize, cache_path: Option, @@ -163,13 +166,24 @@ pub struct RuntimeCache { impl RuntimeCache { /// Creates a new instance of a runtimes cache. /// - /// `max_runtime_instances` specifies the number of runtime instances preserved in an in-memory - /// cache. + /// `max_runtime_instances` specifies the number of instances per runtime preserved in an + /// in-memory cache. /// /// `cache_path` allows to specify an optional directory where the executor can store files /// for caching. - pub fn new(max_runtime_instances: usize, cache_path: Option) -> RuntimeCache { - RuntimeCache { runtimes: Default::default(), max_runtime_instances, cache_path } + /// + /// `runtime_cache_size` specifies the number of different runtimes versions preserved in an + /// in-memory cache. + pub fn new( + max_runtime_instances: usize, + cache_path: Option, + runtime_cache_size: u8, + ) -> RuntimeCache { + RuntimeCache { + runtimes: Mutex::new(LruCache::new(runtime_cache_size.into())), + max_runtime_instances, + cache_path, + } } /// Prepares a WASM module instance and executes given function for it. @@ -221,71 +235,55 @@ impl RuntimeCache { let code_hash = &runtime_code.hash; let heap_pages = runtime_code.heap_pages.unwrap_or(default_heap_pages); + let versioned_runtime_id = + VersionedRuntimeId { code_hash: code_hash.clone(), heap_pages, wasm_method }; + let mut runtimes = self.runtimes.lock(); // this must be released prior to calling f - let pos = runtimes.iter().position(|r| { - r.as_ref().map_or(false, |r| { - r.wasm_method == wasm_method && - r.code_hash == *code_hash && - r.heap_pages == heap_pages - }) - }); + let versioned_runtime = if let Some(versioned_runtime) = runtimes.get(&versioned_runtime_id) + { + versioned_runtime.clone() + } else { + let code = runtime_code.fetch_runtime_code().ok_or(WasmError::CodeNotFound)?; + + let time = std::time::Instant::now(); + + let result = create_versioned_wasm_runtime( + &code, + ext, + wasm_method, + heap_pages, + host_functions.into(), + allow_missing_func_imports, + self.max_runtime_instances, + self.cache_path.as_deref(), + ); + + match result { + Ok(ref result) => { + log::debug!( + target: "wasm-runtime", + "Prepared new runtime version {:?} in {} ms.", + result.version, + time.elapsed().as_millis(), + ); + }, + Err(ref err) => { + log::warn!(target: "wasm-runtime", "Cannot create a runtime: {:?}", err); + }, + } - let runtime = match pos { - Some(n) => runtimes[n] - .clone() - .expect("`position` only returns `Some` for entries that are `Some`"), - None => { - let code = runtime_code.fetch_runtime_code().ok_or(WasmError::CodeNotFound)?; - - let time = std::time::Instant::now(); - - let result = create_versioned_wasm_runtime( - &code, - code_hash.clone(), - ext, - wasm_method, - heap_pages, - host_functions.into(), - allow_missing_func_imports, - self.max_runtime_instances, - self.cache_path.as_deref(), - ); - - match result { - Ok(ref result) => { - log::debug!( - target: "wasm-runtime", - "Prepared new runtime version {:?} in {} ms.", - result.version, - time.elapsed().as_millis(), - ); - }, - Err(ref err) => { - log::warn!(target: "wasm-runtime", "Cannot create a runtime: {:?}", err); - }, - } + let versioned_runtime = Arc::new(result?); - Arc::new(result?) - }, + // Save new versioned wasm runtime in cache + runtimes.put(versioned_runtime_id, versioned_runtime.clone()); + + versioned_runtime }; - // Rearrange runtimes by last recently used. - match pos { - Some(0) => {}, - Some(n) => - for i in (1..n + 1).rev() { - runtimes.swap(i, i - 1); - }, - None => { - runtimes[MAX_RUNTIMES - 1] = Some(runtime.clone()); - for i in (1..MAX_RUNTIMES).rev() { - runtimes.swap(i, i - 1); - } - }, - } + // Lock must be released prior to calling f drop(runtimes); - Ok(runtime.with_instance(ext, f)) + Ok(versioned_runtime.with_instance(ext, f)) } } @@ -396,7 +394,6 @@ pub fn read_embedded_version(blob: &RuntimeBlob) -> Result, ext: &mut dyn Externalities, wasm_method: WasmExecutionMethod, heap_pages: u64, @@ -449,7 +446,7 @@ fn create_versioned_wasm_runtime( let mut instances = Vec::with_capacity(max_instances); instances.resize_with(max_instances, || Mutex::new(None)); - Ok(VersionedRuntime { code_hash, module: runtime, version, heap_pages, wasm_method, instances }) + Ok(VersionedRuntime { module: runtime, version, instances: Arc::new(instances) }) } #[cfg(test)] diff --git a/client/service/src/client/call_executor.rs b/client/service/src/client/call_executor.rs index 7d15ce4704ab..9f56424daf2f 100644 --- a/client/service/src/client/call_executor.rs +++ b/client/service/src/client/call_executor.rs @@ -360,6 +360,7 @@ mod tests { WasmExecutionMethod::Interpreted, Some(128), 1, + 2, ); let overrides = crate::client::wasm_override::dummy_overrides(); diff --git a/client/service/src/client/wasm_override.rs b/client/service/src/client/wasm_override.rs index ba3f2855fc7a..88b2c3895b02 100644 --- a/client/service/src/client/wasm_override.rs +++ b/client/service/src/client/wasm_override.rs @@ -282,6 +282,7 @@ mod tests { WasmExecutionMethod::Interpreted, Some(128), 1, + 2, ); let bytes = substrate_test_runtime::wasm_binary_unwrap(); let dir = tempfile::tempdir().expect("Create a temporary directory"); @@ -295,6 +296,7 @@ mod tests { WasmExecutionMethod::Interpreted, Some(128), 1, + 2, ); let version = WasmOverride::runtime_version( diff --git a/client/service/src/config.rs b/client/service/src/config.rs index d3bd4e4e4879..0fc68624fee5 100644 --- a/client/service/src/config.rs +++ b/client/service/src/config.rs @@ -132,6 +132,8 @@ pub struct Configuration { pub base_path: Option, /// Configuration of the output format that the informant uses. pub informant_output_format: sc_informant::OutputFormat, + /// Maximum number of different runtime versions that can be cached. + pub runtime_cache_size: u8, } /// Type for tasks spawned by the executor. diff --git a/client/service/test/src/client/mod.rs b/client/service/test/src/client/mod.rs index d5e23d319e83..286d819a6ce5 100644 --- a/client/service/test/src/client/mod.rs +++ b/client/service/test/src/client/mod.rs @@ -72,7 +72,12 @@ impl sc_executor::NativeExecutionDispatch for ExecutorDispatch { } fn executor() -> sc_executor::NativeElseWasmExecutor { - sc_executor::NativeElseWasmExecutor::new(sc_executor::WasmExecutionMethod::Interpreted, None, 8) + sc_executor::NativeElseWasmExecutor::new( + sc_executor::WasmExecutionMethod::Interpreted, + None, + 8, + 2, + ) } fn construct_block( diff --git a/client/service/test/src/lib.rs b/client/service/test/src/lib.rs index c44a5cdb9743..7033001db43c 100644 --- a/client/service/test/src/lib.rs +++ b/client/service/test/src/lib.rs @@ -261,6 +261,7 @@ fn node_config< announce_block: true, base_path: Some(BasePath::new(root)), informant_output_format: Default::default(), + runtime_cache_size: 2, } } diff --git a/primitives/api/test/tests/runtime_calls.rs b/primitives/api/test/tests/runtime_calls.rs index e32290b12a59..21dfd456b1a1 100644 --- a/primitives/api/test/tests/runtime_calls.rs +++ b/primitives/api/test/tests/runtime_calls.rs @@ -210,6 +210,7 @@ fn record_proof_works() { WasmExecutionMethod::Interpreted, None, 8, + 2, ); execution_proof_check_on_trie_backend( &backend, diff --git a/primitives/runtime-interface/test/src/lib.rs b/primitives/runtime-interface/test/src/lib.rs index 1749cc485367..f64b74336427 100644 --- a/primitives/runtime-interface/test/src/lib.rs +++ b/primitives/runtime-interface/test/src/lib.rs @@ -48,6 +48,7 @@ fn call_wasm_method_with_result( host_functions, 8, None, + 2, ); executor .uncached_call( diff --git a/test-utils/client/src/lib.rs b/test-utils/client/src/lib.rs index 2d1cb4bbc66a..96f3c9898395 100644 --- a/test-utils/client/src/lib.rs +++ b/test-utils/client/src/lib.rs @@ -283,7 +283,7 @@ impl Backend: sc_client_api::backend::Backend + 'static, { let executor = executor.into().unwrap_or_else(|| { - NativeElseWasmExecutor::new(WasmExecutionMethod::Interpreted, None, 8) + NativeElseWasmExecutor::new(WasmExecutionMethod::Interpreted, None, 8, 2) }); let executor = LocalCallExecutor::new( self.backend.clone(), diff --git a/test-utils/runtime/client/src/lib.rs b/test-utils/runtime/client/src/lib.rs index 2948e918cdf8..a5d1e1966e30 100644 --- a/test-utils/runtime/client/src/lib.rs +++ b/test-utils/runtime/client/src/lib.rs @@ -287,5 +287,10 @@ pub fn new() -> Client { /// Create a new native executor. pub fn new_native_executor() -> sc_executor::NativeElseWasmExecutor { - sc_executor::NativeElseWasmExecutor::new(sc_executor::WasmExecutionMethod::Interpreted, None, 8) + sc_executor::NativeElseWasmExecutor::new( + sc_executor::WasmExecutionMethod::Interpreted, + None, + 8, + 2, + ) } diff --git a/test-utils/runtime/src/system.rs b/test-utils/runtime/src/system.rs index 165fe0355628..0c72c083baae 100644 --- a/test-utils/runtime/src/system.rs +++ b/test-utils/runtime/src/system.rs @@ -342,7 +342,7 @@ mod tests { } fn executor() -> NativeElseWasmExecutor { - NativeElseWasmExecutor::new(WasmExecutionMethod::Interpreted, None, 8) + NativeElseWasmExecutor::new(WasmExecutionMethod::Interpreted, None, 8, 2) } fn new_test_ext() -> TestExternalities { diff --git a/test-utils/test-runner/src/client.rs b/test-utils/test-runner/src/client.rs index c68a33056c16..21039d3bc4b1 100644 --- a/test-utils/test-runner/src/client.rs +++ b/test-utils/test-runner/src/client.rs @@ -111,6 +111,7 @@ where config.wasm_method, config.default_heap_pages, config.max_runtime_instances, + config.runtime_cache_size, ); let (client, backend, keystore, mut task_manager) = diff --git a/test-utils/test-runner/src/utils.rs b/test-utils/test-runner/src/utils.rs index a4c45c25f969..4b44d12e1ed4 100644 --- a/test-utils/test-runner/src/utils.rs +++ b/test-utils/test-runner/src/utils.rs @@ -113,5 +113,6 @@ pub fn default_config(tokio_handle: Handle, mut chain_spec: Box) keep_blocks: KeepBlocks::All, state_pruning: Default::default(), transaction_storage: TransactionStorageMode::BlockBody, + runtime_cache_size: 2, } } diff --git a/utils/frame/benchmarking-cli/src/command.rs b/utils/frame/benchmarking-cli/src/command.rs index 48d05dd8dda9..2a0429b27908 100644 --- a/utils/frame/benchmarking-cli/src/command.rs +++ b/utils/frame/benchmarking-cli/src/command.rs @@ -137,6 +137,7 @@ impl BenchmarkCmd { wasm_method, self.heap_pages, 2, // The runtime instances cache size. + 2, // The runtime cache size ); let extensions = || -> Extensions { diff --git a/utils/frame/try-runtime/cli/src/lib.rs b/utils/frame/try-runtime/cli/src/lib.rs index 8ea2e39297a9..3872f84a62a4 100644 --- a/utils/frame/try-runtime/cli/src/lib.rs +++ b/utils/frame/try-runtime/cli/src/lib.rs @@ -678,8 +678,14 @@ pub(crate) fn build_executor( let wasm_method = shared.wasm_method; let heap_pages = shared.heap_pages.or(config.default_heap_pages); let max_runtime_instances = config.max_runtime_instances; + let runtime_cache_size = config.runtime_cache_size; - NativeElseWasmExecutor::::new(wasm_method.into(), heap_pages, max_runtime_instances) + NativeElseWasmExecutor::::new( + wasm_method.into(), + heap_pages, + max_runtime_instances, + runtime_cache_size, + ) } /// Execute the given `method` and `data` on top of `ext`, returning the results (encoded) and the