Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Switch to pooling copy-on-write instantiation strategy for WASM #11232

Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion 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,
}
koute marked this conversation as resolved.
Show resolved Hide resolved

/// 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