mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-26 23:57:56 +00:00
wasm-executor: Support growing the memory (#12520)
* As always, start with something :P * Add support for max_heap_pages * Add support for wasmtime * Make it compile * Fix compilation * Copy wrongly merged code * Fix compilation * Some fixes * Fix * Get stuff working * More work * More fixes * ... * More * FIXEs * Switch wasmi to use `RuntimeBlob` like wasmtime * Removed unused stuff * Cleanup * More cleanups * Introduce `CallContext` * Fixes * More fixes * Add builder for creating the `WasmExecutor` * Adds some docs * FMT * First round of feedback. * Review feedback round 2 * More fixes * Fix try-runtime * Update client/executor/wasmtime/src/instance_wrapper.rs Co-authored-by: Koute <koute@users.noreply.github.com> * Update client/executor/common/src/wasm_runtime.rs Co-authored-by: Koute <koute@users.noreply.github.com> * Update client/executor/common/src/runtime_blob/runtime_blob.rs Co-authored-by: Koute <koute@users.noreply.github.com> * Update client/executor/common/src/wasm_runtime.rs Co-authored-by: Koute <koute@users.noreply.github.com> * Update client/allocator/src/freeing_bump.rs Co-authored-by: Koute <koute@users.noreply.github.com> * Update client/allocator/src/freeing_bump.rs Co-authored-by: Koute <koute@users.noreply.github.com> * Feedback round 3 * FMT * Review comments --------- Co-authored-by: Koute <koute@users.noreply.github.com>
This commit is contained in:
@@ -21,25 +21,60 @@
|
||||
use super::mk_test_runtime;
|
||||
use crate::WasmExecutionMethod;
|
||||
use codec::Encode as _;
|
||||
use sc_executor_common::wasm_runtime::HeapAllocStrategy;
|
||||
|
||||
mod smaps;
|
||||
|
||||
use self::smaps::Smaps;
|
||||
|
||||
#[test]
|
||||
fn memory_consumption_interpreted() {
|
||||
let _ = sp_tracing::try_init_simple();
|
||||
|
||||
if std::env::var("RUN_TEST").is_ok() {
|
||||
memory_consumption(WasmExecutionMethod::Interpreted);
|
||||
} else {
|
||||
// We need to run the test in isolation, to not getting interfered by the other tests.
|
||||
let executable = std::env::current_exe().unwrap();
|
||||
let output = std::process::Command::new(executable)
|
||||
.env("RUN_TEST", "1")
|
||||
.args(&["--nocapture", "memory_consumption_interpreted"])
|
||||
.output()
|
||||
.unwrap();
|
||||
|
||||
assert!(output.status.success());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn memory_consumption_compiled() {
|
||||
let _ = sp_tracing::try_init_simple();
|
||||
|
||||
if std::env::var("RUN_TEST").is_ok() {
|
||||
memory_consumption(WasmExecutionMethod::Compiled {
|
||||
instantiation_strategy:
|
||||
sc_executor_wasmtime::InstantiationStrategy::LegacyInstanceReuse,
|
||||
});
|
||||
} else {
|
||||
// We need to run the test in isolation, to not getting interfered by the other tests.
|
||||
let executable = std::env::current_exe().unwrap();
|
||||
let status = std::process::Command::new(executable)
|
||||
.env("RUN_TEST", "1")
|
||||
.args(&["--nocapture", "memory_consumption_compiled"])
|
||||
.status()
|
||||
.unwrap();
|
||||
|
||||
assert!(status.success());
|
||||
}
|
||||
}
|
||||
|
||||
fn memory_consumption(wasm_method: WasmExecutionMethod) {
|
||||
// This aims to see if linear memory stays backed by the physical memory after a runtime call.
|
||||
//
|
||||
// For that we make a series of runtime calls, probing the RSS for the VMA matching the linear
|
||||
// memory. After the call we expect RSS to be equal to 0.
|
||||
|
||||
let runtime = mk_test_runtime(
|
||||
WasmExecutionMethod::Compiled {
|
||||
instantiation_strategy:
|
||||
sc_executor_wasmtime::InstantiationStrategy::LegacyInstanceReuse,
|
||||
},
|
||||
1024,
|
||||
);
|
||||
let runtime = mk_test_runtime(wasm_method, HeapAllocStrategy::Static { extra_pages: 1024 });
|
||||
|
||||
let mut instance = runtime.new_instance().unwrap();
|
||||
let heap_base = instance
|
||||
|
||||
@@ -24,7 +24,7 @@ use codec::{Decode, Encode};
|
||||
use sc_executor_common::{
|
||||
error::{Error, WasmError},
|
||||
runtime_blob::RuntimeBlob,
|
||||
wasm_runtime::WasmModule,
|
||||
wasm_runtime::{HeapAllocStrategy, WasmModule},
|
||||
};
|
||||
use sc_runtime_test::wasm_binary_unwrap;
|
||||
use sp_core::{
|
||||
@@ -52,11 +52,13 @@ macro_rules! test_wasm_execution {
|
||||
paste::item! {
|
||||
#[test]
|
||||
fn [<$method_name _interpreted>]() {
|
||||
let _ = sp_tracing::try_init_simple();
|
||||
$method_name(WasmExecutionMethod::Interpreted);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn [<$method_name _compiled_recreate_instance_cow>]() {
|
||||
let _ = sp_tracing::try_init_simple();
|
||||
$method_name(WasmExecutionMethod::Compiled {
|
||||
instantiation_strategy: sc_executor_wasmtime::InstantiationStrategy::RecreateInstanceCopyOnWrite
|
||||
});
|
||||
@@ -64,6 +66,7 @@ macro_rules! test_wasm_execution {
|
||||
|
||||
#[test]
|
||||
fn [<$method_name _compiled_recreate_instance_vanilla>]() {
|
||||
let _ = sp_tracing::try_init_simple();
|
||||
$method_name(WasmExecutionMethod::Compiled {
|
||||
instantiation_strategy: sc_executor_wasmtime::InstantiationStrategy::RecreateInstance
|
||||
});
|
||||
@@ -71,6 +74,7 @@ macro_rules! test_wasm_execution {
|
||||
|
||||
#[test]
|
||||
fn [<$method_name _compiled_pooling_cow>]() {
|
||||
let _ = sp_tracing::try_init_simple();
|
||||
$method_name(WasmExecutionMethod::Compiled {
|
||||
instantiation_strategy: sc_executor_wasmtime::InstantiationStrategy::PoolingCopyOnWrite
|
||||
});
|
||||
@@ -78,6 +82,7 @@ macro_rules! test_wasm_execution {
|
||||
|
||||
#[test]
|
||||
fn [<$method_name _compiled_pooling_vanilla>]() {
|
||||
let _ = sp_tracing::try_init_simple();
|
||||
$method_name(WasmExecutionMethod::Compiled {
|
||||
instantiation_strategy: sc_executor_wasmtime::InstantiationStrategy::Pooling
|
||||
});
|
||||
@@ -85,6 +90,7 @@ macro_rules! test_wasm_execution {
|
||||
|
||||
#[test]
|
||||
fn [<$method_name _compiled_legacy_instance_reuse>]() {
|
||||
let _ = sp_tracing::try_init_simple();
|
||||
$method_name(WasmExecutionMethod::Compiled {
|
||||
instantiation_strategy: sc_executor_wasmtime::InstantiationStrategy::LegacyInstanceReuse
|
||||
});
|
||||
@@ -474,7 +480,10 @@ fn should_trap_when_heap_exhausted(wasm_method: WasmExecutionMethod) {
|
||||
}
|
||||
}
|
||||
|
||||
fn mk_test_runtime(wasm_method: WasmExecutionMethod, pages: u64) -> Arc<dyn WasmModule> {
|
||||
fn mk_test_runtime(
|
||||
wasm_method: WasmExecutionMethod,
|
||||
pages: HeapAllocStrategy,
|
||||
) -> Arc<dyn WasmModule> {
|
||||
let blob = RuntimeBlob::uncompress_if_needed(wasm_binary_unwrap())
|
||||
.expect("failed to create a runtime blob out of test runtime");
|
||||
|
||||
@@ -490,7 +499,8 @@ fn mk_test_runtime(wasm_method: WasmExecutionMethod, pages: u64) -> Arc<dyn Wasm
|
||||
|
||||
test_wasm_execution!(returns_mutable_static);
|
||||
fn returns_mutable_static(wasm_method: WasmExecutionMethod) {
|
||||
let runtime = mk_test_runtime(wasm_method, 1024);
|
||||
let runtime =
|
||||
mk_test_runtime(wasm_method, HeapAllocStrategy::Dynamic { maximum_pages: Some(1024) });
|
||||
|
||||
let mut instance = runtime.new_instance().unwrap();
|
||||
let res = instance.call_export("returns_mutable_static", &[0]).unwrap();
|
||||
@@ -505,7 +515,8 @@ fn returns_mutable_static(wasm_method: WasmExecutionMethod) {
|
||||
|
||||
test_wasm_execution!(returns_mutable_static_bss);
|
||||
fn returns_mutable_static_bss(wasm_method: WasmExecutionMethod) {
|
||||
let runtime = mk_test_runtime(wasm_method, 1024);
|
||||
let runtime =
|
||||
mk_test_runtime(wasm_method, HeapAllocStrategy::Dynamic { maximum_pages: Some(1024) });
|
||||
|
||||
let mut instance = runtime.new_instance().unwrap();
|
||||
let res = instance.call_export("returns_mutable_static_bss", &[0]).unwrap();
|
||||
@@ -530,9 +541,12 @@ fn restoration_of_globals(wasm_method: WasmExecutionMethod) {
|
||||
//
|
||||
// The fixture performs 2 allocations of 768KB and this theoretically gives 1536KB, however, due
|
||||
// to our allocator algorithm there are inefficiencies.
|
||||
const REQUIRED_MEMORY_PAGES: u64 = 32;
|
||||
const REQUIRED_MEMORY_PAGES: u32 = 32;
|
||||
|
||||
let runtime = mk_test_runtime(wasm_method, REQUIRED_MEMORY_PAGES);
|
||||
let runtime = mk_test_runtime(
|
||||
wasm_method,
|
||||
HeapAllocStrategy::Static { extra_pages: REQUIRED_MEMORY_PAGES },
|
||||
);
|
||||
let mut instance = runtime.new_instance().unwrap();
|
||||
|
||||
// On the first invocation we allocate approx. 768KB (75%) of stack and then trap.
|
||||
@@ -546,7 +560,7 @@ fn restoration_of_globals(wasm_method: WasmExecutionMethod) {
|
||||
|
||||
test_wasm_execution!(interpreted_only heap_is_reset_between_calls);
|
||||
fn heap_is_reset_between_calls(wasm_method: WasmExecutionMethod) {
|
||||
let runtime = mk_test_runtime(wasm_method, 1024);
|
||||
let runtime = mk_test_runtime(wasm_method, HeapAllocStrategy::Static { extra_pages: 1024 });
|
||||
let mut instance = runtime.new_instance().unwrap();
|
||||
|
||||
let heap_base = instance
|
||||
@@ -651,6 +665,15 @@ fn wasm_tracing_should_work(wasm_method: WasmExecutionMethod) {
|
||||
assert_eq!(len, 2);
|
||||
}
|
||||
|
||||
test_wasm_execution!(allocate_two_gigabyte);
|
||||
fn allocate_two_gigabyte(wasm_method: WasmExecutionMethod) {
|
||||
let runtime = mk_test_runtime(wasm_method, HeapAllocStrategy::Dynamic { maximum_pages: None });
|
||||
|
||||
let mut instance = runtime.new_instance().unwrap();
|
||||
let res = instance.call_export("allocate_two_gigabyte", &[0]).unwrap();
|
||||
assert_eq!(10 * 1024 * 1024 * 205, u32::decode(&mut &res[..]).unwrap());
|
||||
}
|
||||
|
||||
test_wasm_execution!(memory_is_cleared_between_invocations);
|
||||
fn memory_is_cleared_between_invocations(wasm_method: WasmExecutionMethod) {
|
||||
// This is based on the code generated by compiling a runtime *without*
|
||||
@@ -713,7 +736,7 @@ fn memory_is_cleared_between_invocations(wasm_method: WasmExecutionMethod) {
|
||||
|
||||
let runtime = crate::wasm_runtime::create_wasm_runtime_with_code::<HostFunctions>(
|
||||
wasm_method,
|
||||
1024,
|
||||
HeapAllocStrategy::Dynamic { maximum_pages: Some(1024) },
|
||||
RuntimeBlob::uncompress_if_needed(&binary[..]).unwrap(),
|
||||
true,
|
||||
None,
|
||||
|
||||
Reference in New Issue
Block a user