Skip to content

Commit

Permalink
Switch to pooling copy-on-write instantiation strategy for WASM (pari…
Browse files Browse the repository at this point in the history
…tytech#11232)

* Switch to pooling copy-on-write instantiation strategy for WASM

* Fix benchmark compilation

* Fix `cargo fmt`

* Fix compilation of another benchmark I've missed

* Cleanups according to review comments

* Move `max_memory_size` to `Semantics`

* Set `memory_guaranteed_dense_image_size` to `max_memory_size`

* Rename `wasm_instantiation_strategy` to `wasmtime_instantiation_strategy`

* Update the doc-comments regarding the instantiation strategy

* Extend the integration tests to test every instantiation strategy

* Don't drop the temporary directory until the runtime is dropped in benchmarks

* Don't drop the temporary directory until the runtime is dropped in tests
  • Loading branch information
koute authored and ark0f committed Feb 27, 2023
1 parent eda65db commit 1367dc6
Show file tree
Hide file tree
Showing 21 changed files with 728 additions and 238 deletions.
13 changes: 13 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions bin/node/cli/benches/block_production.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use sc_consensus::{
use sc_service::{
config::{
DatabaseSource, KeepBlocks, KeystoreConfig, NetworkConfiguration, OffchainWorkerConfig,
PruningMode, WasmExecutionMethod,
PruningMode, WasmExecutionMethod, WasmtimeInstantiationStrategy,
},
BasePath, Configuration, Role,
};
Expand Down Expand Up @@ -77,7 +77,9 @@ fn new_node(tokio_handle: Handle) -> node_cli::service::NewFullBase {
state_pruning: Some(PruningMode::ArchiveAll),
keep_blocks: KeepBlocks::All,
chain_spec: spec,
wasm_method: WasmExecutionMethod::Compiled,
wasm_method: WasmExecutionMethod::Compiled {
instantiation_strategy: WasmtimeInstantiationStrategy::PoolingCopyOnWrite,
},
execution_strategies: ExecutionStrategies {
syncing: execution_strategy,
importing: execution_strategy,
Expand Down
6 changes: 5 additions & 1 deletion bin/node/executor/benches/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ use node_runtime::{
UncheckedExtrinsic,
};
use node_testing::keyring::*;
#[cfg(feature = "wasmtime")]
use sc_executor::WasmtimeInstantiationStrategy;
use sc_executor::{Externalities, NativeElseWasmExecutor, RuntimeVersionOf, WasmExecutionMethod};
use sp_core::{
storage::well_known_keys,
Expand Down Expand Up @@ -183,7 +185,9 @@ fn bench_execute_block(c: &mut Criterion) {
ExecutionMethod::Native,
ExecutionMethod::Wasm(WasmExecutionMethod::Interpreted),
#[cfg(feature = "wasmtime")]
ExecutionMethod::Wasm(WasmExecutionMethod::Compiled),
ExecutionMethod::Wasm(WasmExecutionMethod::Compiled {
instantiation_strategy: WasmtimeInstantiationStrategy::PoolingCopyOnWrite,
}),
];

for strategy in execution_methods {
Expand Down
11 changes: 9 additions & 2 deletions bin/node/testing/src/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ use sc_client_api::{
};
use sc_client_db::PruningMode;
use sc_consensus::{BlockImport, BlockImportParams, ForkChoiceStrategy, ImportResult, ImportedAux};
use sc_executor::{NativeElseWasmExecutor, WasmExecutionMethod};
use sc_executor::{NativeElseWasmExecutor, WasmExecutionMethod, WasmtimeInstantiationStrategy};
use sp_api::ProvideRuntimeApi;
use sp_block_builder::BlockBuilder;
use sp_consensus::BlockOrigin;
Expand Down Expand Up @@ -398,7 +398,14 @@ 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, 2),
NativeElseWasmExecutor::new(
WasmExecutionMethod::Compiled {
instantiation_strategy: WasmtimeInstantiationStrategy::PoolingCopyOnWrite,
},
None,
8,
2,
),
&keyring.generate_genesis(),
None,
None,
Expand Down
69 changes: 57 additions & 12 deletions client/cli/src/arg_enums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,36 @@

use clap::ArgEnum;

/// The instantiation strategy to use in compiled mode.
#[derive(Debug, Clone, Copy, ArgEnum)]
#[clap(rename_all = "kebab-case")]
pub enum WasmtimeInstantiationStrategy {
/// Pool the instances to avoid initializing everything from scratch
/// on each instantiation. Use copy-on-write memory when possible.
PoolingCopyOnWrite,

/// Recreate the instance from scratch on every instantiation.
/// Use copy-on-write memory when possible.
RecreateInstanceCopyOnWrite,

/// Pool the instances to avoid initializing everything from scratch
/// on each instantiation.
Pooling,

/// Recreate the instance from scratch on every instantiation. Very slow.
RecreateInstance,

/// Legacy instance reuse mechanism. DEPRECATED. Will be removed in the future.
///
/// Should only be used in case of encountering any issues with the new default
/// instantiation strategy.
LegacyInstanceReuse,
}

/// The default [`WasmtimeInstantiationStrategy`].
pub const DEFAULT_WASMTIME_INSTANTIATION_STRATEGY: WasmtimeInstantiationStrategy =
WasmtimeInstantiationStrategy::PoolingCopyOnWrite;

/// How to execute Wasm runtime code.
#[derive(Debug, Clone, Copy)]
pub enum WasmExecutionMethod {
Expand Down Expand Up @@ -71,18 +101,33 @@ impl WasmExecutionMethod {
}
}

impl Into<sc_service::config::WasmExecutionMethod> for WasmExecutionMethod {
fn into(self) -> sc_service::config::WasmExecutionMethod {
match self {
WasmExecutionMethod::Interpreted =>
sc_service::config::WasmExecutionMethod::Interpreted,
#[cfg(feature = "wasmtime")]
WasmExecutionMethod::Compiled => sc_service::config::WasmExecutionMethod::Compiled,
#[cfg(not(feature = "wasmtime"))]
WasmExecutionMethod::Compiled => panic!(
"Substrate must be compiled with \"wasmtime\" feature for compiled Wasm execution"
),
}
/// Converts the execution method and instantiation strategy command line arguments
/// into an execution method which can be used internally.
pub fn execution_method_from_cli(
execution_method: WasmExecutionMethod,
_instantiation_strategy: WasmtimeInstantiationStrategy,
) -> sc_service::config::WasmExecutionMethod {
match execution_method {
WasmExecutionMethod::Interpreted => sc_service::config::WasmExecutionMethod::Interpreted,
#[cfg(feature = "wasmtime")]
WasmExecutionMethod::Compiled => sc_service::config::WasmExecutionMethod::Compiled {
instantiation_strategy: match _instantiation_strategy {
WasmtimeInstantiationStrategy::PoolingCopyOnWrite =>
sc_service::config::WasmtimeInstantiationStrategy::PoolingCopyOnWrite,
WasmtimeInstantiationStrategy::RecreateInstanceCopyOnWrite =>
sc_service::config::WasmtimeInstantiationStrategy::RecreateInstanceCopyOnWrite,
WasmtimeInstantiationStrategy::Pooling =>
sc_service::config::WasmtimeInstantiationStrategy::Pooling,
WasmtimeInstantiationStrategy::RecreateInstance =>
sc_service::config::WasmtimeInstantiationStrategy::RecreateInstance,
WasmtimeInstantiationStrategy::LegacyInstanceReuse =>
sc_service::config::WasmtimeInstantiationStrategy::LegacyInstanceReuse,
},
},
#[cfg(not(feature = "wasmtime"))]
WasmExecutionMethod::Compiled => panic!(
"Substrate must be compiled with \"wasmtime\" feature for compiled Wasm execution"
),
}
}

Expand Down
32 changes: 27 additions & 5 deletions client/cli/src/params/import_params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@

use crate::{
arg_enums::{
ExecutionStrategy, WasmExecutionMethod, DEFAULT_EXECUTION_BLOCK_CONSTRUCTION,
DEFAULT_EXECUTION_IMPORT_BLOCK, DEFAULT_EXECUTION_IMPORT_BLOCK_VALIDATOR,
DEFAULT_EXECUTION_OFFCHAIN_WORKER, DEFAULT_EXECUTION_OTHER, DEFAULT_EXECUTION_SYNCING,
DEFAULT_WASM_EXECUTION_METHOD,
ExecutionStrategy, WasmExecutionMethod, WasmtimeInstantiationStrategy,
DEFAULT_EXECUTION_BLOCK_CONSTRUCTION, DEFAULT_EXECUTION_IMPORT_BLOCK,
DEFAULT_EXECUTION_IMPORT_BLOCK_VALIDATOR, DEFAULT_EXECUTION_OFFCHAIN_WORKER,
DEFAULT_EXECUTION_OTHER, DEFAULT_EXECUTION_SYNCING,
DEFAULT_WASMTIME_INSTANTIATION_STRATEGY, DEFAULT_WASM_EXECUTION_METHOD,
},
params::{DatabaseParams, PruningParams},
};
Expand Down Expand Up @@ -62,6 +63,27 @@ pub struct ImportParams {
)]
pub wasm_method: WasmExecutionMethod,

/// The WASM instantiation method to use.
///
/// Only has an effect when `wasm-execution` is set to `compiled`.
///
/// The copy-on-write strategies are only supported on Linux.
/// If the copy-on-write variant of a strategy is unsupported
/// the executor will fall back to the non-CoW equivalent.
///
/// The fastest (and the default) strategy available is `pooling-copy-on-write`.
///
/// The `legacy-instance-reuse` strategy is deprecated and will
/// be removed in the future. It should only be used in case of
/// issues with the default instantiation strategy.
#[clap(
long,
value_name = "STRATEGY",
default_value_t = DEFAULT_WASMTIME_INSTANTIATION_STRATEGY,
arg_enum,
)]
pub wasmtime_instantiation_strategy: WasmtimeInstantiationStrategy,

/// Specify the path where local WASM runtimes are stored.
///
/// These runtimes will override on-chain runtimes when the version matches.
Expand All @@ -85,7 +107,7 @@ impl ImportParams {

/// Get the WASM execution method from the parameters
pub fn wasm_method(&self) -> sc_service::config::WasmExecutionMethod {
self.wasm_method.into()
crate::execution_method_from_cli(self.wasm_method, self.wasmtime_instantiation_strategy)
}

/// Enable overriding on-chain WASM with locally-stored WASM
Expand Down
2 changes: 2 additions & 0 deletions client/executor/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ paste = "1.0"
regex = "1.5.5"
criterion = "0.3"
env_logger = "0.9"
num_cpus = "1.13.1"
tempfile = "3.3.0"

[[bench]]
name = "bench"
Expand Down
Loading

0 comments on commit 1367dc6

Please sign in to comment.