diff --git a/crates/wasmtime/src/config.rs b/crates/wasmtime/src/config.rs index ca3935e1b6..df57b82e1f 100644 --- a/crates/wasmtime/src/config.rs +++ b/crates/wasmtime/src/config.rs @@ -23,30 +23,89 @@ use wasmtime_runtime::{ #[derive(Debug, Copy, Clone)] pub struct ModuleLimits { /// The maximum number of imported functions for a module (default is 1000). + /// + /// This value controls the capacity of the `VMFunctionImport` table and the + /// `VMCallerCheckedAnyfunc` table in each instance's `VMContext` structure. + /// + /// The allocated size of the `VMFunctionImport` table will be `imported_functions * sizeof(VMFunctionImport)` + /// for each instance regardless of how many functions an instance imports. + /// + /// The allocated size of the `VMCallerCheckedAnyfunc` table will be + /// `imported_functions * functions * sizeof(VMCallerCheckedAnyfunc)` for each instance regardless of + /// how many functions are imported and defined by an instance. pub imported_functions: u32, /// The maximum number of imported tables for a module (default is 0). + /// + /// This value controls the capacity of the `VMTableImport` table in each instance's + /// `VMContext` structure. + /// + /// The allocated size of the table will be `imported_tables * sizeof(VMTableImport)` for each + /// instance regardless of how many tables an instance imports. pub imported_tables: u32, /// The maximum number of imported linear memories for a module (default is 0). + /// + /// This value controls the capacity of the `VMMemoryImport` table in each instance's + /// `VMContext` structure. + /// + /// The allocated size of the table will be `imported_memories * sizeof(VMMemoryImport)` for each + /// instance regardless of how many memories an instance imports. pub imported_memories: u32, /// The maximum number of imported globals for a module (default is 0). + /// + /// This value controls the capacity of the `VMGlobalImport` table in each instance's + /// `VMContext` structure. + /// + /// The allocated size of the table will be `imported_globals * sizeof(VMGlobalImport)` for each + /// instance regardless of how many globals an instance imports. pub imported_globals: u32, /// The maximum number of defined types for a module (default is 100). + /// + /// This value controls the capacity of the `VMSharedSignatureIndex` table in each instance's + /// `VMContext` structure. + /// + /// The allocated size of the table will be `types * sizeof(VMSharedSignatureIndex)` for each + /// instance regardless of how many types are defined by an instance's module. pub types: u32, /// The maximum number of defined functions for a module (default is 10000). + /// + /// This value controls the capacity of the `VMCallerCheckedAnyfunc` table in each instance's + /// `VMContext` structure. + /// + /// The allocated size of the `VMCallerCheckedAnyfunc` table will be + /// `imported_functions * functions * sizeof(VMCallerCheckedAnyfunc)` for each instance + /// regardless of how many functions are imported and defined by an instance. pub functions: u32, /// The maximum number of defined tables for a module (default is 1). + /// + /// This value controls the capacity of the `VMTableDefinition` table in each instance's + /// `VMContext` structure. + /// + /// The allocated size of the table will be `tables * sizeof(VMTableDefinition)` for each + /// instance regardless of how many tables are defined by an instance's module. pub tables: u32, /// The maximum number of defined linear memories for a module (default is 1). + /// + /// This value controls the capacity of the `VMMemoryDefinition` table in each instance's + /// `VMContext` structure. + /// + /// The allocated size of the table will be `memories * sizeof(VMMemoryDefinition)` for each + /// instance regardless of how many memories are defined by an instance's module. pub memories: u32, /// The maximum number of defined globals for a module (default is 10). + /// + /// This value controls the capacity of the `VMGlobalDefinition` table in each instance's + /// `VMContext` structure. + /// + /// The allocated size of the table will be `globals * sizeof(VMGlobalDefinition)` for each + /// instance regardless of how many globals are defined by an instance's module. pub globals: u32, /// The maximum table elements for any table defined in a module (default is 10000). @@ -56,6 +115,10 @@ pub struct ModuleLimits { /// /// If a table's maximum element limit is unbounded or greater than this value, /// the maximum will be `table_elements` for the purpose of any `table.grow` instruction. + /// + /// This value is used to reserve the maximum space for each supported table; table elements + /// are pointer-sized in the Wasmtime runtime. Therefore, the space reserved for each instance + /// is `tables * table_elements * sizeof::<*const ()>`. pub table_elements: u32, /// The maximum number of pages for any linear memory defined in a module (default is 160). @@ -68,7 +131,11 @@ pub struct ModuleLimits { /// If a memory's maximum page limit is unbounded or greater than this value, /// the maximum will be `memory_pages` for the purpose of any `memory.grow` instruction. /// - /// This value cannot exceed any memory reservation size limits placed on instances. + /// This value is used to control the maximum accessible space for each linear memory of an instance. + /// + /// The reservation size of each linear memory is controlled by the + /// [`static_memory_maximum_size`](Config::static_memory_maximum_size) setting and this value cannot + /// exceed the configured static memory maximum size. pub memory_pages: u32, } @@ -144,6 +211,33 @@ impl Into for ModuleLimits { #[derive(Debug, Copy, Clone)] pub struct InstanceLimits { /// The maximum number of concurrent instances supported (default is 1000). + /// + /// This value has a direct impact on the amount of memory allocated by the pooling + /// instance allocator. + /// + /// The pooling instance allocator allocates three memory pools with sizes depending on this value: + /// + /// * An instance pool, where each entry in the pool can store the runtime representation + /// of an instance, including a maximal `VMContext` structure (see [`ModuleLimits`](ModuleLimits) + /// for the various settings that control the size of each instance's `VMContext` structure). + /// + /// * A memory pool, where each entry in the pool contains the reserved address space for each + /// linear memory supported by an instance. + /// + /// * A table pool, where each entry in the pool contains the space needed for each WebAssembly table + /// supported by an instance (see `[ModuleLimits::table_elements`] to control the size of each table). + /// + /// Additionally, this value will also control the maximum number of execution stacks allowed for + /// asynchronous execution (one per instance), when enabled. + /// + /// The memory pool will reserve a large quantity of host process address space to elide the bounds + /// checks required for correct WebAssembly memory semantics. Even for 64-bit address spaces, the + /// address space is limited when dealing with a large number of supported instances. + /// + /// For example, on Linux x86_64, the userland address space limit is 128 TiB. That might seem like a lot, + /// but each linear memory will *reserve* 6 GiB of space by default. Multiply that by the number of linear + /// memories each instance supports and then by the number of supported instances and it becomes apparent + /// that address space can be exhausted depending on the number of supported instances. pub count: u32, }