Refactor configuration for the pooling allocator (#5205)
This commit changes the APIs in the `wasmtime` crate for configuring the pooling allocator. I plan on adding a few more configuration options in the near future and the current structure was feeling unwieldy for adding these new abstractions. The previous `struct`-based API has been replaced with a builder-style API in a similar shape as to `Config`. This is done to help make it easier to add more configuration options in the future through adding more methods as opposed to adding more field which could break prior initializations.
This commit is contained in:
@@ -354,17 +354,13 @@ async fn fuel_eventually_finishes() {
|
||||
|
||||
#[tokio::test]
|
||||
async fn async_with_pooling_stacks() {
|
||||
let mut pool = PoolingAllocationConfig::default();
|
||||
pool.instance_count(1)
|
||||
.instance_memory_pages(1)
|
||||
.instance_table_elements(0);
|
||||
let mut config = Config::new();
|
||||
config.async_support(true);
|
||||
config.allocation_strategy(InstanceAllocationStrategy::Pooling {
|
||||
strategy: PoolingAllocationStrategy::NextAvailable,
|
||||
instance_limits: InstanceLimits {
|
||||
count: 1,
|
||||
memory_pages: 1,
|
||||
table_elements: 0,
|
||||
..Default::default()
|
||||
},
|
||||
});
|
||||
config.allocation_strategy(InstanceAllocationStrategy::Pooling(pool));
|
||||
config.dynamic_memory_guard_size(0);
|
||||
config.static_memory_guard_size(0);
|
||||
config.static_memory_maximum_size(65536);
|
||||
@@ -383,17 +379,14 @@ async fn async_with_pooling_stacks() {
|
||||
|
||||
#[tokio::test]
|
||||
async fn async_host_func_with_pooling_stacks() -> Result<()> {
|
||||
let mut pooling = PoolingAllocationConfig::default();
|
||||
pooling
|
||||
.instance_count(1)
|
||||
.instance_memory_pages(1)
|
||||
.instance_table_elements(0);
|
||||
let mut config = Config::new();
|
||||
config.async_support(true);
|
||||
config.allocation_strategy(InstanceAllocationStrategy::Pooling {
|
||||
strategy: PoolingAllocationStrategy::NextAvailable,
|
||||
instance_limits: InstanceLimits {
|
||||
count: 1,
|
||||
memory_pages: 1,
|
||||
table_elements: 0,
|
||||
..Default::default()
|
||||
},
|
||||
});
|
||||
config.allocation_strategy(InstanceAllocationStrategy::Pooling(pooling));
|
||||
config.dynamic_memory_guard_size(0);
|
||||
config.static_memory_guard_size(0);
|
||||
config.static_memory_maximum_size(65536);
|
||||
|
||||
@@ -40,14 +40,10 @@ fn linear_memory_limits() -> Result<()> {
|
||||
return Ok(());
|
||||
}
|
||||
test(&Engine::default())?;
|
||||
let mut pool = PoolingAllocationConfig::default();
|
||||
pool.instance_memory_pages(65536);
|
||||
test(&Engine::new(Config::new().allocation_strategy(
|
||||
InstanceAllocationStrategy::Pooling {
|
||||
strategy: PoolingAllocationStrategy::NextAvailable,
|
||||
instance_limits: InstanceLimits {
|
||||
memory_pages: 65536,
|
||||
..Default::default()
|
||||
},
|
||||
},
|
||||
InstanceAllocationStrategy::Pooling(pool),
|
||||
))?)?;
|
||||
return Ok(());
|
||||
|
||||
|
||||
@@ -350,16 +350,11 @@ fn test_initial_table_limits_exceeded() -> Result<()> {
|
||||
|
||||
#[test]
|
||||
fn test_pooling_allocator_initial_limits_exceeded() -> Result<()> {
|
||||
let mut pool = PoolingAllocationConfig::default();
|
||||
pool.instance_count(1).instance_memories(2);
|
||||
let mut config = Config::new();
|
||||
config.wasm_multi_memory(true);
|
||||
config.allocation_strategy(InstanceAllocationStrategy::Pooling {
|
||||
strategy: PoolingAllocationStrategy::NextAvailable,
|
||||
instance_limits: InstanceLimits {
|
||||
count: 1,
|
||||
memories: 2,
|
||||
..Default::default()
|
||||
},
|
||||
});
|
||||
config.allocation_strategy(InstanceAllocationStrategy::Pooling(pool));
|
||||
|
||||
let engine = Engine::new(&config)?;
|
||||
let module = Module::new(
|
||||
@@ -721,15 +716,10 @@ fn custom_limiter_detect_grow_failure() -> Result<()> {
|
||||
if std::env::var("WASMTIME_TEST_NO_HOG_MEMORY").is_ok() {
|
||||
return Ok(());
|
||||
}
|
||||
let mut pool = PoolingAllocationConfig::default();
|
||||
pool.instance_memory_pages(10).instance_table_elements(10);
|
||||
let mut config = Config::new();
|
||||
config.allocation_strategy(InstanceAllocationStrategy::Pooling {
|
||||
strategy: PoolingAllocationStrategy::NextAvailable,
|
||||
instance_limits: InstanceLimits {
|
||||
memory_pages: 10,
|
||||
table_elements: 10,
|
||||
..Default::default()
|
||||
},
|
||||
});
|
||||
config.allocation_strategy(InstanceAllocationStrategy::Pooling(pool));
|
||||
let engine = Engine::new(&config).unwrap();
|
||||
let linker = Linker::new(&engine);
|
||||
|
||||
@@ -829,16 +819,11 @@ async fn custom_limiter_async_detect_grow_failure() -> Result<()> {
|
||||
if std::env::var("WASMTIME_TEST_NO_HOG_MEMORY").is_ok() {
|
||||
return Ok(());
|
||||
}
|
||||
let mut pool = PoolingAllocationConfig::default();
|
||||
pool.instance_memory_pages(10).instance_table_elements(10);
|
||||
let mut config = Config::new();
|
||||
config.async_support(true);
|
||||
config.allocation_strategy(InstanceAllocationStrategy::Pooling {
|
||||
strategy: PoolingAllocationStrategy::NextAvailable,
|
||||
instance_limits: InstanceLimits {
|
||||
memory_pages: 10,
|
||||
table_elements: 10,
|
||||
..Default::default()
|
||||
},
|
||||
});
|
||||
config.allocation_strategy(InstanceAllocationStrategy::Pooling(pool));
|
||||
let engine = Engine::new(&config).unwrap();
|
||||
let linker = Linker::new(&engine);
|
||||
|
||||
|
||||
@@ -186,19 +186,14 @@ fn guards_present() -> Result<()> {
|
||||
fn guards_present_pooling() -> Result<()> {
|
||||
const GUARD_SIZE: u64 = 65536;
|
||||
|
||||
let mut pool = PoolingAllocationConfig::default();
|
||||
pool.instance_count(2).instance_memory_pages(10);
|
||||
let mut config = Config::new();
|
||||
config.static_memory_maximum_size(1 << 20);
|
||||
config.dynamic_memory_guard_size(GUARD_SIZE);
|
||||
config.static_memory_guard_size(GUARD_SIZE);
|
||||
config.guard_before_linear_memory(true);
|
||||
config.allocation_strategy(InstanceAllocationStrategy::Pooling {
|
||||
strategy: PoolingAllocationStrategy::default(),
|
||||
instance_limits: InstanceLimits {
|
||||
count: 2,
|
||||
memory_pages: 10,
|
||||
..Default::default()
|
||||
},
|
||||
});
|
||||
config.allocation_strategy(InstanceAllocationStrategy::Pooling(pool));
|
||||
let engine = Engine::new(&config)?;
|
||||
|
||||
let mut store = Store::new(&engine, ());
|
||||
|
||||
@@ -4,16 +4,12 @@ use wasmtime::*;
|
||||
|
||||
#[test]
|
||||
fn successful_instantiation() -> Result<()> {
|
||||
let mut pool = PoolingAllocationConfig::default();
|
||||
pool.instance_count(1)
|
||||
.instance_memory_pages(1)
|
||||
.instance_table_elements(10);
|
||||
let mut config = Config::new();
|
||||
config.allocation_strategy(InstanceAllocationStrategy::Pooling {
|
||||
strategy: PoolingAllocationStrategy::NextAvailable,
|
||||
instance_limits: InstanceLimits {
|
||||
count: 1,
|
||||
memory_pages: 1,
|
||||
table_elements: 10,
|
||||
..Default::default()
|
||||
},
|
||||
});
|
||||
config.allocation_strategy(InstanceAllocationStrategy::Pooling(pool));
|
||||
config.dynamic_memory_guard_size(0);
|
||||
config.static_memory_guard_size(0);
|
||||
config.static_memory_maximum_size(65536);
|
||||
@@ -30,16 +26,12 @@ fn successful_instantiation() -> Result<()> {
|
||||
|
||||
#[test]
|
||||
fn memory_limit() -> Result<()> {
|
||||
let mut pool = PoolingAllocationConfig::default();
|
||||
pool.instance_count(1)
|
||||
.instance_memory_pages(3)
|
||||
.instance_table_elements(10);
|
||||
let mut config = Config::new();
|
||||
config.allocation_strategy(InstanceAllocationStrategy::Pooling {
|
||||
strategy: PoolingAllocationStrategy::NextAvailable,
|
||||
instance_limits: InstanceLimits {
|
||||
count: 1,
|
||||
memory_pages: 3,
|
||||
table_elements: 10,
|
||||
..Default::default()
|
||||
},
|
||||
});
|
||||
config.allocation_strategy(InstanceAllocationStrategy::Pooling(pool));
|
||||
config.dynamic_memory_guard_size(0);
|
||||
config.static_memory_guard_size(65536);
|
||||
config.static_memory_maximum_size(3 * 65536);
|
||||
@@ -109,16 +101,12 @@ fn memory_limit() -> Result<()> {
|
||||
|
||||
#[test]
|
||||
fn memory_init() -> Result<()> {
|
||||
let mut pool = PoolingAllocationConfig::default();
|
||||
pool.instance_count(1)
|
||||
.instance_memory_pages(2)
|
||||
.instance_table_elements(0);
|
||||
let mut config = Config::new();
|
||||
config.allocation_strategy(InstanceAllocationStrategy::Pooling {
|
||||
strategy: PoolingAllocationStrategy::NextAvailable,
|
||||
instance_limits: InstanceLimits {
|
||||
count: 1,
|
||||
memory_pages: 2,
|
||||
table_elements: 0,
|
||||
..Default::default()
|
||||
},
|
||||
});
|
||||
config.allocation_strategy(InstanceAllocationStrategy::Pooling(pool));
|
||||
|
||||
let engine = Engine::new(&config)?;
|
||||
|
||||
@@ -142,16 +130,12 @@ fn memory_init() -> Result<()> {
|
||||
|
||||
#[test]
|
||||
fn memory_guard_page_trap() -> Result<()> {
|
||||
let mut pool = PoolingAllocationConfig::default();
|
||||
pool.instance_count(1)
|
||||
.instance_memory_pages(2)
|
||||
.instance_table_elements(0);
|
||||
let mut config = Config::new();
|
||||
config.allocation_strategy(InstanceAllocationStrategy::Pooling {
|
||||
strategy: PoolingAllocationStrategy::NextAvailable,
|
||||
instance_limits: InstanceLimits {
|
||||
count: 1,
|
||||
memory_pages: 2,
|
||||
table_elements: 0,
|
||||
..Default::default()
|
||||
},
|
||||
});
|
||||
config.allocation_strategy(InstanceAllocationStrategy::Pooling(pool));
|
||||
|
||||
let engine = Engine::new(&config)?;
|
||||
|
||||
@@ -210,16 +194,12 @@ fn memory_zeroed() -> Result<()> {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mut pool = PoolingAllocationConfig::default();
|
||||
pool.instance_count(1)
|
||||
.instance_memory_pages(1)
|
||||
.instance_table_elements(0);
|
||||
let mut config = Config::new();
|
||||
config.allocation_strategy(InstanceAllocationStrategy::Pooling {
|
||||
strategy: PoolingAllocationStrategy::NextAvailable,
|
||||
instance_limits: InstanceLimits {
|
||||
count: 1,
|
||||
memory_pages: 1,
|
||||
table_elements: 0,
|
||||
..Default::default()
|
||||
},
|
||||
});
|
||||
config.allocation_strategy(InstanceAllocationStrategy::Pooling(pool));
|
||||
config.dynamic_memory_guard_size(0);
|
||||
config.static_memory_guard_size(0);
|
||||
config.static_memory_maximum_size(65536);
|
||||
@@ -253,16 +233,12 @@ fn memory_zeroed() -> Result<()> {
|
||||
#[test]
|
||||
fn table_limit() -> Result<()> {
|
||||
const TABLE_ELEMENTS: u32 = 10;
|
||||
let mut pool = PoolingAllocationConfig::default();
|
||||
pool.instance_count(1)
|
||||
.instance_memory_pages(1)
|
||||
.instance_table_elements(TABLE_ELEMENTS);
|
||||
let mut config = Config::new();
|
||||
config.allocation_strategy(InstanceAllocationStrategy::Pooling {
|
||||
strategy: PoolingAllocationStrategy::NextAvailable,
|
||||
instance_limits: InstanceLimits {
|
||||
count: 1,
|
||||
memory_pages: 1,
|
||||
table_elements: TABLE_ELEMENTS,
|
||||
..Default::default()
|
||||
},
|
||||
});
|
||||
config.allocation_strategy(InstanceAllocationStrategy::Pooling(pool));
|
||||
config.dynamic_memory_guard_size(0);
|
||||
config.static_memory_guard_size(0);
|
||||
config.static_memory_maximum_size(65536);
|
||||
@@ -340,16 +316,12 @@ fn table_limit() -> Result<()> {
|
||||
|
||||
#[test]
|
||||
fn table_init() -> Result<()> {
|
||||
let mut pool = PoolingAllocationConfig::default();
|
||||
pool.instance_count(1)
|
||||
.instance_memory_pages(0)
|
||||
.instance_table_elements(6);
|
||||
let mut config = Config::new();
|
||||
config.allocation_strategy(InstanceAllocationStrategy::Pooling {
|
||||
strategy: PoolingAllocationStrategy::NextAvailable,
|
||||
instance_limits: InstanceLimits {
|
||||
count: 1,
|
||||
memory_pages: 0,
|
||||
table_elements: 6,
|
||||
..Default::default()
|
||||
},
|
||||
});
|
||||
config.allocation_strategy(InstanceAllocationStrategy::Pooling(pool));
|
||||
|
||||
let engine = Engine::new(&config)?;
|
||||
|
||||
@@ -390,16 +362,12 @@ fn table_zeroed() -> Result<()> {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mut pool = PoolingAllocationConfig::default();
|
||||
pool.instance_count(1)
|
||||
.instance_memory_pages(1)
|
||||
.instance_table_elements(10);
|
||||
let mut config = Config::new();
|
||||
config.allocation_strategy(InstanceAllocationStrategy::Pooling {
|
||||
strategy: PoolingAllocationStrategy::NextAvailable,
|
||||
instance_limits: InstanceLimits {
|
||||
count: 1,
|
||||
memory_pages: 1,
|
||||
table_elements: 10,
|
||||
..Default::default()
|
||||
},
|
||||
});
|
||||
config.allocation_strategy(InstanceAllocationStrategy::Pooling(pool));
|
||||
config.dynamic_memory_guard_size(0);
|
||||
config.static_memory_guard_size(0);
|
||||
config.static_memory_maximum_size(65536);
|
||||
@@ -434,16 +402,12 @@ fn table_zeroed() -> Result<()> {
|
||||
#[test]
|
||||
fn instantiation_limit() -> Result<()> {
|
||||
const INSTANCE_LIMIT: u32 = 10;
|
||||
let mut pool = PoolingAllocationConfig::default();
|
||||
pool.instance_count(INSTANCE_LIMIT)
|
||||
.instance_memory_pages(1)
|
||||
.instance_table_elements(10);
|
||||
let mut config = Config::new();
|
||||
config.allocation_strategy(InstanceAllocationStrategy::Pooling {
|
||||
strategy: PoolingAllocationStrategy::NextAvailable,
|
||||
instance_limits: InstanceLimits {
|
||||
count: INSTANCE_LIMIT,
|
||||
memory_pages: 1,
|
||||
table_elements: 10,
|
||||
..Default::default()
|
||||
},
|
||||
});
|
||||
config.allocation_strategy(InstanceAllocationStrategy::Pooling(pool));
|
||||
config.dynamic_memory_guard_size(0);
|
||||
config.static_memory_guard_size(0);
|
||||
config.static_memory_maximum_size(65536);
|
||||
@@ -484,16 +448,12 @@ fn instantiation_limit() -> Result<()> {
|
||||
|
||||
#[test]
|
||||
fn preserve_data_segments() -> Result<()> {
|
||||
let mut pool = PoolingAllocationConfig::default();
|
||||
pool.instance_count(2)
|
||||
.instance_memory_pages(1)
|
||||
.instance_table_elements(10);
|
||||
let mut config = Config::new();
|
||||
config.allocation_strategy(InstanceAllocationStrategy::Pooling {
|
||||
strategy: PoolingAllocationStrategy::NextAvailable,
|
||||
instance_limits: InstanceLimits {
|
||||
count: 2,
|
||||
memory_pages: 1,
|
||||
table_elements: 10,
|
||||
..Default::default()
|
||||
},
|
||||
});
|
||||
config.allocation_strategy(InstanceAllocationStrategy::Pooling(pool));
|
||||
let engine = Engine::new(&config)?;
|
||||
let m = Module::new(
|
||||
&engine,
|
||||
@@ -536,16 +496,12 @@ fn multi_memory_with_imported_memories() -> Result<()> {
|
||||
// This test checks that the base address for the defined memory is correct for the instance
|
||||
// despite the presence of an imported memory.
|
||||
|
||||
let mut pool = PoolingAllocationConfig::default();
|
||||
pool.instance_count(1)
|
||||
.instance_memories(2)
|
||||
.instance_memory_pages(1);
|
||||
let mut config = Config::new();
|
||||
config.allocation_strategy(InstanceAllocationStrategy::Pooling {
|
||||
strategy: PoolingAllocationStrategy::NextAvailable,
|
||||
instance_limits: InstanceLimits {
|
||||
count: 1,
|
||||
memories: 2,
|
||||
memory_pages: 1,
|
||||
..Default::default()
|
||||
},
|
||||
});
|
||||
config.allocation_strategy(InstanceAllocationStrategy::Pooling(pool));
|
||||
config.wasm_multi_memory(true);
|
||||
|
||||
let engine = Engine::new(&config)?;
|
||||
@@ -581,15 +537,11 @@ fn drop_externref_global_during_module_init() -> Result<()> {
|
||||
}
|
||||
}
|
||||
|
||||
let mut pool = PoolingAllocationConfig::default();
|
||||
pool.instance_count(1);
|
||||
let mut config = Config::new();
|
||||
config.wasm_reference_types(true);
|
||||
config.allocation_strategy(InstanceAllocationStrategy::Pooling {
|
||||
strategy: PoolingAllocationStrategy::NextAvailable,
|
||||
instance_limits: InstanceLimits {
|
||||
count: 1,
|
||||
..Default::default()
|
||||
},
|
||||
});
|
||||
config.allocation_strategy(InstanceAllocationStrategy::Pooling(pool));
|
||||
|
||||
let engine = Engine::new(&config)?;
|
||||
|
||||
@@ -630,15 +582,10 @@ fn drop_externref_global_during_module_init() -> Result<()> {
|
||||
#[test]
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
fn instance_too_large() -> Result<()> {
|
||||
let mut pool = PoolingAllocationConfig::default();
|
||||
pool.instance_size(16).instance_count(1);
|
||||
let mut config = Config::new();
|
||||
config.allocation_strategy(InstanceAllocationStrategy::Pooling {
|
||||
strategy: PoolingAllocationStrategy::NextAvailable,
|
||||
instance_limits: InstanceLimits {
|
||||
size: 16,
|
||||
count: 1,
|
||||
..Default::default()
|
||||
},
|
||||
});
|
||||
config.allocation_strategy(InstanceAllocationStrategy::Pooling(pool));
|
||||
|
||||
let engine = Engine::new(&config)?;
|
||||
let expected = "\
|
||||
|
||||
@@ -2,8 +2,7 @@ use once_cell::sync::Lazy;
|
||||
use std::path::Path;
|
||||
use std::sync::{Condvar, Mutex};
|
||||
use wasmtime::{
|
||||
Config, Engine, InstanceAllocationStrategy, InstanceLimits, PoolingAllocationStrategy, Store,
|
||||
Strategy,
|
||||
Config, Engine, InstanceAllocationStrategy, PoolingAllocationConfig, Store, Strategy,
|
||||
};
|
||||
use wasmtime_wast::WastContext;
|
||||
|
||||
@@ -79,16 +78,12 @@ fn run_wast(wast: &str, strategy: Strategy, pooling: bool) -> anyhow::Result<()>
|
||||
// However, these limits may become insufficient in the future as the wast tests change.
|
||||
// If a wast test fails because of a limit being "exceeded" or if memory/table
|
||||
// fails to grow, the values here will need to be adjusted.
|
||||
cfg.allocation_strategy(InstanceAllocationStrategy::Pooling {
|
||||
strategy: PoolingAllocationStrategy::NextAvailable,
|
||||
instance_limits: InstanceLimits {
|
||||
count: 450,
|
||||
memories: 2,
|
||||
tables: 4,
|
||||
memory_pages: 805,
|
||||
..Default::default()
|
||||
},
|
||||
});
|
||||
let mut pool = PoolingAllocationConfig::default();
|
||||
pool.instance_count(450)
|
||||
.instance_memories(2)
|
||||
.instance_tables(4)
|
||||
.instance_memory_pages(805);
|
||||
cfg.allocation_strategy(InstanceAllocationStrategy::Pooling(pool));
|
||||
Some(lock_pooling())
|
||||
} else {
|
||||
None
|
||||
|
||||
Reference in New Issue
Block a user