From 8ae8e115760f5bca96410acd5a81c3d70def2a70 Mon Sep 17 00:00:00 2001 From: Benjamin Kampmann Date: Mon, 2 Jul 2018 16:51:52 +0200 Subject: [PATCH] Use Transient HashMaps to cache wasmi modules for execution. refs #257 --- Cargo.lock | 10 +++++++++- substrate/executor/Cargo.toml | 2 ++ substrate/executor/src/lib.rs | 4 ++++ substrate/executor/src/wasm_executor.rs | 19 ++++++++++++++++++- 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 244ed07aeeb86..e61cdd53790fc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1713,7 +1713,7 @@ dependencies = [ "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2155,6 +2155,7 @@ dependencies = [ "ed25519 0.1.0", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2164,6 +2165,7 @@ dependencies = [ "substrate-runtime-io 0.1.0", "substrate-serializer 0.1.0", "substrate-state-machine 0.1.0", + "transient-hashmap 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "triehash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "wabt 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "wasmi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2913,6 +2915,11 @@ dependencies = [ "trace-time 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "transient-hashmap" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "triehash" version = "0.1.0" @@ -3436,6 +3443,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum trace-time 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5aea07da6582e957c6e737eeb63a5af79e648eeeaaaba8fd9a417f1124bafa41" "checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" "checksum transaction-pool 1.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be1efb673ddf49ab4a99893eb3af02f6563636033fb832c2b7f937641ad62b17" +"checksum transient-hashmap 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aeb4b191d033a35edfce392a38cdcf9790b6cebcb30fa690c312c29da4dc433e" "checksum triehash 0.1.0 (git+https://github.com/paritytech/parity.git)" = "" "checksum triehash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2033893a813c70e7d8a739ca6c36dc0a7a2c913ec718d7cbf84a3837bbe3c7ce" "checksum try-lock 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee2aa4715743892880f70885373966c83d73ef1b0838a664ef0c76fffd35e7c2" diff --git a/substrate/executor/Cargo.toml b/substrate/executor/Cargo.toml index 58152c27a9309..aff400a20d2a2 100644 --- a/substrate/executor/Cargo.toml +++ b/substrate/executor/Cargo.toml @@ -10,6 +10,8 @@ substrate-runtime-io = { path = "../runtime-io" } substrate-primitives = { path = "../primitives" } substrate-serializer = { path = "../serializer" } substrate-state-machine = { path = "../state-machine" } +lazy_static = "1.0" +transient-hashmap = "0.4.1" ed25519 = { path = "../ed25519" } serde = "1.0" serde_derive = "1.0" diff --git a/substrate/executor/src/lib.rs b/substrate/executor/src/lib.rs index 6c79977c5efd6..7fef23e1fde21 100644 --- a/substrate/executor/src/lib.rs +++ b/substrate/executor/src/lib.rs @@ -39,8 +39,12 @@ extern crate wasmi; extern crate byteorder; extern crate rustc_hex; extern crate triehash; +extern crate transient_hashmap; #[macro_use] extern crate log; +#[macro_use] +extern crate lazy_static; + #[macro_use] extern crate error_chain; diff --git a/substrate/executor/src/wasm_executor.rs b/substrate/executor/src/wasm_executor.rs index d230cc19865d1..2b1c9fa6587f2 100644 --- a/substrate/executor/src/wasm_executor.rs +++ b/substrate/executor/src/wasm_executor.rs @@ -17,7 +17,11 @@ //! Rust implementation of Substrate contracts. use std::cmp::Ordering; +use std::sync::Mutex; use std::collections::HashMap; +use std::collections::hash_map::DefaultHasher; +use std::hash::Hasher; +use transient_hashmap::TransientHashMap; use wasmi::{ Module, ModuleInstance, MemoryInstance, MemoryRef, TableRef, ImportsBuilder, }; @@ -463,6 +467,11 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, #[derive(Debug, Default, Clone)] pub struct WasmExecutor; +lazy_static! { + static ref MODULE_CACHE: Mutex> = Mutex::new({ TransientHashMap::new(60) }); +} + + impl CodeExecutor for WasmExecutor { type Error = Error; @@ -473,7 +482,15 @@ impl CodeExecutor for WasmExecutor { method: &str, data: &[u8], ) -> Result> { - let module = Module::from_buffer(code).expect("all modules compiled with rustc are valid wasm code; qed"); + + let mut cache = MODULE_CACHE.lock().unwrap(); + let module = cache.entry({ + let mut h = DefaultHasher::new(); + h.write(code); + h.finish() + }).or_insert_with(|| Module::from_buffer(code) + .expect("all modules compiled with rustc are valid wasm code; qed") + ); // start module instantiation. Don't run 'start' function yet. let intermediate_instance = ModuleInstance::new(