Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor configuration for the pooling allocator #5205

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
12 changes: 5 additions & 7 deletions benches/instantiation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,13 +202,11 @@ fn bench_instantiation(c: &mut Criterion) {
fn strategies() -> impl Iterator<Item = InstanceAllocationStrategy> {
[
InstanceAllocationStrategy::OnDemand,
InstanceAllocationStrategy::Pooling {
strategy: Default::default(),
instance_limits: InstanceLimits {
memory_pages: 10_000,
..Default::default()
},
},
InstanceAllocationStrategy::Pooling({
let mut config = PoolingAllocationConfig::default();
config.instance_memory_pages(10_000);
config
}),
]
.into_iter()
}
Expand Down
11 changes: 3 additions & 8 deletions benches/thread_eager_init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,15 +91,10 @@ fn test_setup() -> (Engine, Module) {
// We only expect to create one Instance at a time, with a single memory.
let pool_count = 10;

let mut pool = PoolingAllocationConfig::default();
pool.instance_count(pool_count).instance_memory_pages(1);
let mut config = Config::new();
config.allocation_strategy(InstanceAllocationStrategy::Pooling {
strategy: PoolingAllocationStrategy::NextAvailable,
instance_limits: InstanceLimits {
count: pool_count,
memory_pages: 1,
..Default::default()
},
});
config.allocation_strategy(InstanceAllocationStrategy::Pooling(pool));
let engine = Engine::new(&config).unwrap();

// The module has a memory (shouldn't matter) and a single function which is a no-op.
Expand Down
8 changes: 1 addition & 7 deletions crates/cli-flags/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ use clap::Parser;
use std::collections::HashMap;
use std::path::PathBuf;
use wasmtime::{Config, ProfilingStrategy};
#[cfg(feature = "pooling-allocator")]
use wasmtime::{InstanceLimits, PoolingAllocationStrategy};

pub const SUPPORTED_WASM_FEATURES: &[(&str, &str)] = &[
("all", "enables all supported WebAssembly features"),
Expand Down Expand Up @@ -332,11 +330,7 @@ impl CommonOptions {
#[cfg(feature = "pooling-allocator")]
{
if self.pooling_allocator {
let instance_limits = InstanceLimits::default();
config.allocation_strategy(wasmtime::InstanceAllocationStrategy::Pooling {
strategy: PoolingAllocationStrategy::NextAvailable,
instance_limits,
});
config.allocation_strategy(wasmtime::InstanceAllocationStrategy::pooling());
}
}

Expand Down
4 changes: 2 additions & 2 deletions crates/fuzzing/src/generators.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ mod codegen_settings;
pub mod component_types;
mod config;
mod instance_allocation_strategy;
mod instance_limits;
mod memory;
mod module;
mod pooling_config;
mod single_inst_module;
mod spec_test;
mod stacks;
Expand All @@ -25,9 +25,9 @@ mod value;
pub use codegen_settings::CodegenSettings;
pub use config::{Config, WasmtimeConfig};
pub use instance_allocation_strategy::InstanceAllocationStrategy;
pub use instance_limits::InstanceLimits;
pub use memory::{MemoryConfig, NormalMemoryConfig, UnalignedMemory, UnalignedMemoryCreator};
pub use module::ModuleConfig;
pub use pooling_config::PoolingAllocationConfig;
pub use single_inst_module::SingleInstModule;
pub use spec_test::SpecTest;
pub use stacks::Stacks;
Expand Down
66 changes: 28 additions & 38 deletions crates/fuzzing/src/generators/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,23 +72,20 @@ impl Config {
config.canonicalize_nans = true;

// If using the pooling allocator, update the instance limits too
if let InstanceAllocationStrategy::Pooling {
instance_limits: limits,
..
} = &mut self.wasmtime.strategy
{
if let InstanceAllocationStrategy::Pooling(pooling) = &mut self.wasmtime.strategy {
// One single-page memory
limits.memories = config.max_memories as u32;
limits.memory_pages = 10;
pooling.instance_memories = config.max_memories as u32;
pooling.instance_memory_pages = 10;

limits.tables = config.max_tables as u32;
limits.table_elements = 1_000;
pooling.instance_tables = config.max_tables as u32;
pooling.instance_table_elements = 1_000;

limits.size = 1_000_000;
pooling.instance_size = 1_000_000;

match &mut self.wasmtime.memory_config {
MemoryConfig::Normal(config) => {
config.static_memory_maximum_size = Some(limits.memory_pages * 0x10000);
config.static_memory_maximum_size =
Some(pooling.instance_memory_pages * 0x10000);
}
MemoryConfig::CustomUnaligned => unreachable!(), // Arbitrary impl for `Config` should have prevented this
}
Expand Down Expand Up @@ -122,25 +119,22 @@ impl Config {
config.max_memories = 1;
config.max_tables = 5;

if let InstanceAllocationStrategy::Pooling {
instance_limits: limits,
..
} = &mut self.wasmtime.strategy
{
if let InstanceAllocationStrategy::Pooling(pooling) = &mut self.wasmtime.strategy {
// Configure the lower bound of a number of limits to what's
// required to actually run the spec tests. Fuzz-generated inputs
// may have limits less than these thresholds which would cause the
// spec tests to fail which isn't particularly interesting.
limits.memories = 1;
limits.tables = limits.memories.max(5);
limits.table_elements = limits.memories.max(1_000);
limits.memory_pages = limits.memory_pages.max(900);
limits.count = limits.count.max(500);
limits.size = limits.size.max(64 * 1024);
pooling.instance_memories = 1;
pooling.instance_tables = pooling.instance_tables.max(5);
pooling.instance_table_elements = pooling.instance_table_elements.max(1_000);
pooling.instance_memory_pages = pooling.instance_memory_pages.max(900);
pooling.instance_count = pooling.instance_count.max(500);
pooling.instance_size = pooling.instance_size.max(64 * 1024);

match &mut self.wasmtime.memory_config {
MemoryConfig::Normal(config) => {
config.static_memory_maximum_size = Some(limits.memory_pages * 0x10000);
config.static_memory_maximum_size =
Some(pooling.instance_memory_pages * 0x10000);
}
MemoryConfig::CustomUnaligned => unreachable!(), // Arbitrary impl for `Config` should have prevented this
}
Expand Down Expand Up @@ -173,8 +167,7 @@ impl Config {
self.wasmtime.memory_guaranteed_dense_image_size,
))
.allocation_strategy(self.wasmtime.strategy.to_wasmtime())
.generate_address_map(self.wasmtime.generate_address_map)
.async_stack_zeroing(self.wasmtime.async_stack_zeroing);
.generate_address_map(self.wasmtime.generate_address_map);

self.wasmtime.codegen.configure(&mut cfg);

Expand Down Expand Up @@ -319,11 +312,7 @@ impl<'a> Arbitrary<'a> for Config {

// If using the pooling allocator, constrain the memory and module configurations
// to the module limits.
if let InstanceAllocationStrategy::Pooling {
instance_limits: limits,
..
} = &mut config.wasmtime.strategy
{
if let InstanceAllocationStrategy::Pooling(pooling) = &mut config.wasmtime.strategy {
let cfg = &mut config.module_config.config;
// If the pooling allocator is used, do not allow shared memory to
// be created. FIXME: see
Expand All @@ -333,19 +322,21 @@ impl<'a> Arbitrary<'a> for Config {
// Force the use of a normal memory config when using the pooling allocator and
// limit the static memory maximum to be the same as the pooling allocator's memory
// page limit.
if cfg.max_memory_pages < limits.memory_pages {
limits.memory_pages = cfg.max_memory_pages;
if cfg.max_memory_pages < pooling.instance_memory_pages {
pooling.instance_memory_pages = cfg.max_memory_pages;
} else {
cfg.max_memory_pages = limits.memory_pages;
cfg.max_memory_pages = pooling.instance_memory_pages;
}
config.wasmtime.memory_config = match config.wasmtime.memory_config {
MemoryConfig::Normal(mut config) => {
config.static_memory_maximum_size = Some(limits.memory_pages * 0x10000);
config.static_memory_maximum_size =
Some(pooling.instance_memory_pages * 0x10000);
MemoryConfig::Normal(config)
}
MemoryConfig::CustomUnaligned => {
let mut config: NormalMemoryConfig = u.arbitrary()?;
config.static_memory_maximum_size = Some(limits.memory_pages * 0x10000);
config.static_memory_maximum_size =
Some(pooling.instance_memory_pages * 0x10000);
MemoryConfig::Normal(config)
}
};
Expand All @@ -357,8 +348,8 @@ impl<'a> Arbitrary<'a> for Config {

// Force this pooling allocator to always be able to accommodate the
// module that may be generated.
limits.memories = cfg.max_memories as u32;
limits.tables = cfg.max_tables as u32;
pooling.instance_memories = cfg.max_memories as u32;
pooling.instance_tables = cfg.max_tables as u32;
}

Ok(config)
Expand Down Expand Up @@ -387,7 +378,6 @@ pub struct WasmtimeConfig {
padding_between_functions: Option<u16>,
generate_address_map: bool,
native_unwind_info: bool,
async_stack_zeroing: bool,
}

impl WasmtimeConfig {
Expand Down
43 changes: 4 additions & 39 deletions crates/fuzzing/src/generators/instance_allocation_strategy.rs
Original file line number Diff line number Diff line change
@@ -1,57 +1,22 @@
use super::PoolingAllocationConfig;
use arbitrary::Arbitrary;

use super::InstanceLimits;

/// Configuration for `wasmtime::InstanceAllocationStrategy`.
#[derive(Arbitrary, Clone, Debug, Eq, PartialEq, Hash)]
pub enum InstanceAllocationStrategy {
/// Use the on-demand instance allocation strategy.
OnDemand,
/// Use the pooling instance allocation strategy.
Pooling {
/// The pooling strategy to use.
strategy: PoolingAllocationStrategy,
/// The instance limits.
instance_limits: InstanceLimits,
},
Pooling(PoolingAllocationConfig),
}

impl InstanceAllocationStrategy {
/// Convert this generated strategy a Wasmtime strategy.
pub fn to_wasmtime(&self) -> wasmtime::InstanceAllocationStrategy {
match self {
InstanceAllocationStrategy::OnDemand => wasmtime::InstanceAllocationStrategy::OnDemand,
InstanceAllocationStrategy::Pooling {
strategy,
instance_limits,
} => wasmtime::InstanceAllocationStrategy::Pooling {
strategy: strategy.to_wasmtime(),
instance_limits: instance_limits.to_wasmtime(),
},
}
}
}

/// Configuration for `wasmtime::PoolingAllocationStrategy`.
#[derive(Arbitrary, Clone, Debug, PartialEq, Eq, Hash)]
pub enum PoolingAllocationStrategy {
/// Use next available instance slot.
NextAvailable,
/// Use random instance slot.
Random,
/// Use an affinity-based strategy.
ReuseAffinity,
}

impl PoolingAllocationStrategy {
fn to_wasmtime(&self) -> wasmtime::PoolingAllocationStrategy {
match self {
PoolingAllocationStrategy::NextAvailable => {
wasmtime::PoolingAllocationStrategy::NextAvailable
}
PoolingAllocationStrategy::Random => wasmtime::PoolingAllocationStrategy::Random,
PoolingAllocationStrategy::ReuseAffinity => {
wasmtime::PoolingAllocationStrategy::ReuseAffinity
InstanceAllocationStrategy::Pooling(pooling) => {
wasmtime::InstanceAllocationStrategy::Pooling(pooling.to_wasmtime())
}
}
}
Expand Down
49 changes: 0 additions & 49 deletions crates/fuzzing/src/generators/instance_limits.rs

This file was deleted.

Loading