11//! An allocator used to control the lifetime of allocations
22
3- use bevy:: { ecs:: system:: Resource , prelude:: ResMut , reflect:: PartialReflect } ;
3+ use bevy:: {
4+ app:: { App , Plugin , PostUpdate } ,
5+ diagnostic:: { Diagnostic , DiagnosticPath , Diagnostics , RegisterDiagnostic } ,
6+ ecs:: system:: { Res , Resource } ,
7+ prelude:: ResMut ,
8+ reflect:: PartialReflect ,
9+ } ;
410use parking_lot:: { RwLock , RwLockReadGuard , RwLockWriteGuard } ;
511use std:: {
612 cell:: UnsafeCell ,
@@ -11,6 +17,14 @@ use std::{
1117 sync:: { atomic:: AtomicU64 , Arc } ,
1218} ;
1319
20+ /// The path used for the total number of allocations diagnostic
21+ pub const ALLOCATOR_TOTAL_DIAG_PATH : DiagnosticPath =
22+ DiagnosticPath :: const_new ( "scripting_allocator_total" ) ;
23+
24+ /// The path used for the total number of deallocated allocations diagnostic
25+ pub const ALLOCATOR_TOTAL_COLLECTED_DIAG_PATH : DiagnosticPath =
26+ DiagnosticPath :: const_new ( "scripting_allocator_total_collected" ) ;
27+
1428#[ derive( Clone , Debug ) ]
1529/// Unique identifier for an allocation
1630pub struct ReflectAllocationId ( pub ( crate ) Arc < u64 > ) ;
@@ -214,9 +228,34 @@ impl ReflectAllocator {
214228
215229/// Cleans up dangling script allocations
216230#[ profiling:: function]
217- pub fn garbage_collector ( allocator : ResMut < AppReflectAllocator > ) {
231+ pub fn garbage_collector ( allocator : ResMut < AppReflectAllocator > , mut diagnostics : Diagnostics ) {
218232 let mut allocator = allocator. write ( ) ;
219- allocator. clean_garbage_allocations ( )
233+ let before = allocator. allocations . len ( ) ;
234+ allocator. clean_garbage_allocations ( ) ;
235+ let after = allocator. allocations . len ( ) ;
236+ diagnostics. add_measurement ( & ALLOCATOR_TOTAL_DIAG_PATH , || after as f64 ) ;
237+ diagnostics. add_measurement ( & ALLOCATOR_TOTAL_COLLECTED_DIAG_PATH , || {
238+ ( before - after) as f64
239+ } ) ;
240+ }
241+
242+ /// Measures the number of allocations in the allocator and other diagnostics when enabled
243+ pub fn measure_allocations ( allocator : Res < AppReflectAllocator > , mut diagnostics : Diagnostics ) {
244+ let allocator = allocator. read ( ) ;
245+ let allocations_count = allocator. allocations . len ( ) ;
246+ diagnostics. add_measurement ( & ALLOCATOR_TOTAL_DIAG_PATH , || allocations_count as f64 ) ;
247+ }
248+
249+ /// A plugin which registers various allocator diagnostics
250+ pub struct AllocatorDiagnosticPlugin ;
251+ impl Plugin for AllocatorDiagnosticPlugin {
252+ fn build ( & self , app : & mut App ) {
253+ app. register_diagnostic ( Diagnostic :: new ( ALLOCATOR_TOTAL_DIAG_PATH ) . with_suffix ( " allocs" ) )
254+ . register_diagnostic (
255+ Diagnostic :: new ( ALLOCATOR_TOTAL_COLLECTED_DIAG_PATH ) . with_suffix ( " deallocs" ) ,
256+ )
257+ . add_systems ( PostUpdate , measure_allocations) ;
258+ }
220259}
221260
222261#[ cfg( test) ]
0 commit comments