2121mod decommit_queue;
2222mod index_allocator;
2323mod memory_pool;
24+ mod metrics;
2425mod table_pool;
2526
2627#[ cfg( feature = "gc" ) ]
@@ -54,6 +55,7 @@ use crate::runtime::vm::{
5455 mpk:: { self , ProtectionKey , ProtectionMask } ,
5556 sys:: vm:: PageMap ,
5657} ;
58+ use core:: sync:: atomic:: AtomicUsize ;
5759use std:: borrow:: Cow ;
5860use std:: fmt:: Display ;
5961use std:: sync:: { Mutex , MutexGuard } ;
@@ -65,6 +67,8 @@ use wasmtime_environ::{
6567 DefinedMemoryIndex , DefinedTableIndex , HostPtr , Module , Tunables , VMOffsets ,
6668} ;
6769
70+ pub use self :: metrics:: PoolingAllocatorMetrics ;
71+
6872#[ cfg( feature = "gc" ) ]
6973use super :: GcHeapAllocationIndex ;
7074#[ cfg( feature = "gc" ) ]
@@ -305,8 +309,12 @@ pub struct PoolingInstanceAllocator {
305309 live_component_instances : AtomicU64 ,
306310
307311 decommit_queue : Mutex < DecommitQueue > ,
312+
308313 memories : MemoryPool ,
314+ live_memories : AtomicUsize ,
315+
309316 tables : TablePool ,
317+ live_tables : AtomicUsize ,
310318
311319 #[ cfg( feature = "gc" ) ]
312320 gc_heaps : GcHeapPool ,
@@ -335,6 +343,8 @@ impl Drop for PoolingInstanceAllocator {
335343
336344 debug_assert_eq ! ( self . live_component_instances. load( Ordering :: Acquire ) , 0 ) ;
337345 debug_assert_eq ! ( self . live_core_instances. load( Ordering :: Acquire ) , 0 ) ;
346+ debug_assert_eq ! ( self . live_memories. load( Ordering :: Acquire ) , 0 ) ;
347+ debug_assert_eq ! ( self . live_tables. load( Ordering :: Acquire ) , 0 ) ;
338348
339349 debug_assert ! ( self . memories. is_empty( ) ) ;
340350 debug_assert ! ( self . tables. is_empty( ) ) ;
@@ -357,7 +367,9 @@ impl PoolingInstanceAllocator {
357367 live_core_instances : AtomicU64 :: new ( 0 ) ,
358368 decommit_queue : Mutex :: new ( DecommitQueue :: default ( ) ) ,
359369 memories : MemoryPool :: new ( config, tunables) ?,
370+ live_memories : AtomicUsize :: new ( 0 ) ,
360371 tables : TablePool :: new ( config) ?,
372+ live_tables : AtomicUsize :: new ( 0 ) ,
361373 #[ cfg( feature = "gc" ) ]
362374 gc_heaps : GcHeapPool :: new ( config) ?,
363375 #[ cfg( feature = "async" ) ]
@@ -652,23 +664,30 @@ unsafe impl InstanceAllocator for PoolingInstanceAllocator {
652664 ty : & wasmtime_environ:: Memory ,
653665 memory_index : Option < DefinedMemoryIndex > ,
654666 ) -> Result < ( MemoryAllocationIndex , Memory ) > {
655- // FIXME(rust-lang/rust#145127) this should ideally use a version of
656- // `with_flush_and_retry` but adapted for async closures instead of only
657- // sync closures. Right now that won't compile though so this is the
658- // manually expanded version of the method.
659- let e = match self . memories . allocate ( request, ty, memory_index) . await {
660- Ok ( result) => return Ok ( result) ,
661- Err ( e) => e,
662- } ;
667+ self . live_memories . fetch_add ( 1 , Ordering :: AcqRel ) ;
668+ async {
669+ // FIXME(rust-lang/rust#145127) this should ideally use a version of
670+ // `with_flush_and_retry` but adapted for async closures instead of only
671+ // sync closures. Right now that won't compile though so this is the
672+ // manually expanded version of the method.
673+ let e = match self . memories . allocate ( request, ty, memory_index) . await {
674+ Ok ( result) => return Ok ( result) ,
675+ Err ( e) => e,
676+ } ;
663677
664- if e. is :: < PoolConcurrencyLimitError > ( ) {
665- let queue = self . decommit_queue . lock ( ) . unwrap ( ) ;
666- if self . flush_decommit_queue ( queue) {
667- return self . memories . allocate ( request, ty, memory_index) . await ;
678+ if e. is :: < PoolConcurrencyLimitError > ( ) {
679+ let queue = self . decommit_queue . lock ( ) . unwrap ( ) ;
680+ if self . flush_decommit_queue ( queue) {
681+ return self . memories . allocate ( request, ty, memory_index) . await ;
682+ }
668683 }
669- }
670684
671- Err ( e)
685+ Err ( e)
686+ }
687+ . await
688+ . inspect_err ( |_| {
689+ self . live_memories . fetch_sub ( 1 , Ordering :: AcqRel ) ;
690+ } )
672691 }
673692
674693 unsafe fn deallocate_memory (
@@ -677,6 +696,7 @@ unsafe impl InstanceAllocator for PoolingInstanceAllocator {
677696 allocation_index : MemoryAllocationIndex ,
678697 memory : Memory ,
679698 ) {
699+ self . live_memories . fetch_sub ( 1 , Ordering :: AcqRel ) ;
680700 // Reset the image slot. If there is any error clearing the
681701 // image, just drop it here, and let the drop handler for the
682702 // slot unmap in a way that retains the address space
@@ -712,21 +732,28 @@ unsafe impl InstanceAllocator for PoolingInstanceAllocator {
712732 ty : & wasmtime_environ:: Table ,
713733 _table_index : DefinedTableIndex ,
714734 ) -> Result < ( super :: TableAllocationIndex , Table ) > {
715- // FIXME: see `allocate_memory` above for comments about duplication
716- // with `with_flush_and_retry`.
717- let e = match self . tables . allocate ( request, ty) . await {
718- Ok ( result) => return Ok ( result) ,
719- Err ( e) => e,
720- } ;
735+ self . live_tables . fetch_add ( 1 , Ordering :: AcqRel ) ;
736+ async {
737+ // FIXME: see `allocate_memory` above for comments about duplication
738+ // with `with_flush_and_retry`.
739+ let e = match self . tables . allocate ( request, ty) . await {
740+ Ok ( result) => return Ok ( result) ,
741+ Err ( e) => e,
742+ } ;
721743
722- if e. is :: < PoolConcurrencyLimitError > ( ) {
723- let queue = self . decommit_queue . lock ( ) . unwrap ( ) ;
724- if self . flush_decommit_queue ( queue) {
725- return self . tables . allocate ( request, ty) . await ;
744+ if e. is :: < PoolConcurrencyLimitError > ( ) {
745+ let queue = self . decommit_queue . lock ( ) . unwrap ( ) ;
746+ if self . flush_decommit_queue ( queue) {
747+ return self . tables . allocate ( request, ty) . await ;
748+ }
726749 }
727- }
728750
729- Err ( e)
751+ Err ( e)
752+ }
753+ . await
754+ . inspect_err ( |_| {
755+ self . live_tables . fetch_sub ( 1 , Ordering :: AcqRel ) ;
756+ } )
730757 }
731758
732759 unsafe fn deallocate_table (
@@ -735,6 +762,7 @@ unsafe impl InstanceAllocator for PoolingInstanceAllocator {
735762 allocation_index : TableAllocationIndex ,
736763 mut table : Table ,
737764 ) {
765+ self . live_tables . fetch_sub ( 1 , Ordering :: AcqRel ) ;
738766 let mut queue = DecommitQueue :: default ( ) ;
739767 // SAFETY: This table is no longer in use by the allocator when this
740768 // method is called and additionally all image ranges are pushed with
@@ -816,6 +844,10 @@ unsafe impl InstanceAllocator for PoolingInstanceAllocator {
816844 ) -> ( MemoryAllocationIndex , Memory ) {
817845 self . gc_heaps . deallocate ( allocation_index, gc_heap)
818846 }
847+
848+ fn as_pooling ( & self ) -> Option < & PoolingInstanceAllocator > {
849+ Some ( self )
850+ }
819851}
820852
821853#[ cfg( test) ]
0 commit comments