Skip to content

Commit

Permalink
PR 올렸으나 디버깅을 위해서 해당 브랜치에 선반영
Browse files Browse the repository at this point in the history
  • Loading branch information
notinmybackyaard committed Feb 26, 2025
1 parent 30024f0 commit eff3867
Show file tree
Hide file tree
Showing 4 changed files with 158 additions and 109 deletions.
6 changes: 2 additions & 4 deletions src/entities/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ use crate::storage::Storage;
use crate::tracking::TrackingTimestamp;
use alloc::boxed::Box;
use alloc::vec::Vec;
use core::any::type_name;
use core::iter::repeat_with;
use core::mem::size_of;

Expand Down Expand Up @@ -430,12 +429,11 @@ impl Storage for Entities {
self.list = Some((self.data.len() - end - 1, begin));
}
fn memory_usage(&self) -> Option<StorageMemoryUsage> {
Some(StorageMemoryUsage {
storage_name: type_name::<Self>().into(),
Some(StorageMemoryUsage::Entities {
allocated_memory_bytes: (self.data.capacity() * size_of::<EntityId>())
+ size_of::<Entities>(),
used_memory_bytes: (self.data.len() * size_of::<EntityId>()) + size_of::<Entities>(),
component_count: self.data.len(),
entity_count: self.data.len(),
})
}
fn is_empty(&self) -> bool {
Expand Down
62 changes: 43 additions & 19 deletions src/memory_usage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,50 @@ pub struct WorldMemoryUsage<'w>(pub(crate) &'w World);

pub struct AllStoragesMemoryUsage<'a>(pub(crate) &'a AllStorages);

/// A trait to query the amount of memory a storage uses.
pub struct StorageMemoryUsage {
#[allow(missing_docs)]
pub storage_name: Cow<'static, str>,
/// Amount of memory used by the storage in bytes.
pub used_memory_bytes: usize,
/// Amount of memory allocated by the storage in bytes (including reserved memory).
pub allocated_memory_bytes: usize,
#[allow(missing_docs)]
pub component_count: usize,
#[derive(Debug)]
pub struct SparseSetMemoryUsage {
pub spase: usize,
pub dense: usize,
pub data: usize,
pub insertion_data: usize,
pub modification_data: usize,
pub deletion_data: usize,
pub removal_data: usize,
pub self_data: usize,
}

impl core::fmt::Debug for StorageMemoryUsage {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_fmt(format_args!(
"{}: {} bytes used for {} components ({} bytes reserved in total)",
self.storage_name,
self.used_memory_bytes,
self.component_count,
self.allocated_memory_bytes
))
impl SparseSetMemoryUsage {
pub fn sum(&self) -> usize {
self.spase
+ self.dense
+ self.data
+ self.insertion_data
+ self.modification_data
+ self.deletion_data
+ self.removal_data
+ self.self_data
}
}

/// A enum to query the amount of memory a storage uses.
#[allow(missing_docs, unused)]
#[derive(Debug)]
pub enum StorageMemoryUsage {
Entities {
used_memory_bytes: usize,
allocated_memory_bytes: usize,
entity_count: usize,
},
SparseSet {
storage_name: Cow<'static, str>,
used_memory_usage: SparseSetMemoryUsage,
allocated_memory_usage: SparseSetMemoryUsage,
used_memory_bytes: usize,
allocated_memory_bytes: usize,
component_count: usize,
},
Unique {
storage_name: Cow<'static, str>,
used_memory_bytes: usize,
},
}
195 changes: 112 additions & 83 deletions src/sparse_set/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use crate::borrow::{NonSend, NonSendSync, NonSync};
use crate::component::Component;
use crate::entity_id::EntityId;
use crate::error;
use crate::memory_usage::StorageMemoryUsage;
use crate::memory_usage::{SparseSetMemoryUsage, StorageMemoryUsage};
use crate::r#mut::Mut;
use crate::storage::{Storage, StorageId};
use crate::tracking::{Tracking, TrackingTimestamp};
Expand Down Expand Up @@ -745,6 +745,40 @@ impl<T: Component> SparseSet<T> {
}
}

impl<T: Component> SparseSet<T> {
fn private_memory_usage(&self) -> StorageMemoryUsage {
let used_memory_usage = SparseSetMemoryUsage {
spase: self.sparse.used_memory(),
dense: self.dense.len() * size_of::<EntityId>(),
data: self.data.len() * size_of::<T>(),
insertion_data: self.insertion_data.len() * size_of::<TrackingTimestamp>(),
modification_data: self.modification_data.len() * size_of::<TrackingTimestamp>(),
deletion_data: self.deletion_data.len() * size_of::<(EntityId, TrackingTimestamp, T)>(),
removal_data: self.removal_data.len() * size_of::<(EntityId, TrackingTimestamp)>(),
self_data: size_of::<Self>(),
};
let allocated_memory_usage = SparseSetMemoryUsage {
spase: self.sparse.reserved_memory(),
dense: self.dense.capacity() * size_of::<EntityId>(),
data: self.data.capacity() * size_of::<T>(),
insertion_data: self.insertion_data.capacity() * size_of::<TrackingTimestamp>(),
modification_data: self.modification_data.capacity() * size_of::<TrackingTimestamp>(),
deletion_data: self.deletion_data.capacity()
* size_of::<(EntityId, TrackingTimestamp, T)>(),
removal_data: self.removal_data.capacity() * size_of::<(EntityId, TrackingTimestamp)>(),
self_data: size_of::<Self>(),
};
StorageMemoryUsage::SparseSet {
storage_name: type_name::<Self>().into(),
used_memory_bytes: used_memory_usage.sum(),
allocated_memory_bytes: allocated_memory_usage.sum(),
used_memory_usage,
allocated_memory_usage,
component_count: self.len(),
}
}
}

impl<T: Ord + Component> SparseSet<T> {
/// Sorts the `SparseSet`, but may not preserve the order of equal elements.
pub fn sort_unstable(&mut self) {
Expand All @@ -761,31 +795,12 @@ impl<T: 'static + Component + Send + Sync> Storage for SparseSet<T> {
fn clear(&mut self, current: TrackingTimestamp) {
self.private_clear(current);
}
fn memory_usage(&self) -> Option<StorageMemoryUsage> {
Some(StorageMemoryUsage {
storage_name: type_name::<Self>().into(),
allocated_memory_bytes: self.sparse.reserved_memory()
+ (self.dense.capacity() * size_of::<EntityId>())
+ (self.data.capacity() * size_of::<T>())
+ (self.insertion_data.capacity() * size_of::<TrackingTimestamp>())
+ (self.modification_data.capacity() * size_of::<TrackingTimestamp>())
+ (self.deletion_data.capacity() * size_of::<(T, EntityId)>())
+ (self.removal_data.capacity() * size_of::<EntityId>())
+ size_of::<Self>(),
used_memory_bytes: self.sparse.used_memory()
+ (self.dense.len() * size_of::<EntityId>())
+ (self.data.len() * size_of::<T>())
+ (self.insertion_data.len() * size_of::<TrackingTimestamp>())
+ (self.modification_data.len() * size_of::<TrackingTimestamp>())
+ (self.deletion_data.len() * size_of::<(EntityId, T)>())
+ (self.removal_data.len() * size_of::<EntityId>())
+ size_of::<Self>(),
component_count: self.len(),
})
}
fn sparse_array(&self) -> Option<&SparseArray<EntityId, BUCKET_SIZE>> {
Some(&self.sparse)
}
fn memory_usage(&self) -> Option<StorageMemoryUsage> {
Some(self.private_memory_usage())
}
fn is_empty(&self) -> bool {
self.is_empty()
}
Expand Down Expand Up @@ -831,29 +846,12 @@ impl<T: 'static + Component + Sync> Storage for NonSend<SparseSet<T>> {
fn clear(&mut self, current: TrackingTimestamp) {
self.private_clear(current);
}
fn memory_usage(&self) -> Option<StorageMemoryUsage> {
Some(StorageMemoryUsage {
storage_name: type_name::<Self>().into(),
allocated_memory_bytes: self.sparse.reserved_memory()
+ (self.dense.capacity() * size_of::<EntityId>())
+ (self.data.capacity() * size_of::<T>())
+ (self.insertion_data.capacity() * size_of::<u32>())
+ (self.deletion_data.capacity() * size_of::<(T, EntityId)>())
+ (self.removal_data.capacity() * size_of::<EntityId>())
+ size_of::<Self>(),
used_memory_bytes: self.sparse.used_memory()
+ (self.dense.len() * size_of::<EntityId>())
+ (self.data.len() * size_of::<T>())
+ (self.insertion_data.len() * size_of::<u32>())
+ (self.deletion_data.len() * size_of::<(EntityId, T)>())
+ (self.removal_data.len() * size_of::<EntityId>())
+ size_of::<Self>(),
component_count: self.len(),
})
}
fn sparse_array(&self) -> Option<&SparseArray<EntityId, BUCKET_SIZE>> {
Some(&self.sparse)
}
fn memory_usage(&self) -> Option<StorageMemoryUsage> {
Some(self.private_memory_usage())
}
fn is_empty(&self) -> bool {
self.0.is_empty()
}
Expand Down Expand Up @@ -899,29 +897,12 @@ impl<T: 'static + Component + Send> Storage for NonSync<SparseSet<T>> {
fn clear(&mut self, current: TrackingTimestamp) {
self.private_clear(current);
}
fn memory_usage(&self) -> Option<StorageMemoryUsage> {
Some(StorageMemoryUsage {
storage_name: type_name::<Self>().into(),
allocated_memory_bytes: self.sparse.reserved_memory()
+ (self.dense.capacity() * size_of::<EntityId>())
+ (self.data.capacity() * size_of::<T>())
+ (self.insertion_data.capacity() * size_of::<u32>())
+ (self.deletion_data.capacity() * size_of::<(T, EntityId)>())
+ (self.removal_data.capacity() * size_of::<EntityId>())
+ size_of::<Self>(),
used_memory_bytes: self.sparse.used_memory()
+ (self.dense.len() * size_of::<EntityId>())
+ (self.data.len() * size_of::<T>())
+ (self.insertion_data.len() * size_of::<u32>())
+ (self.deletion_data.len() * size_of::<(EntityId, T)>())
+ (self.removal_data.len() * size_of::<EntityId>())
+ size_of::<Self>(),
component_count: self.len(),
})
}
fn sparse_array(&self) -> Option<&SparseArray<EntityId, BUCKET_SIZE>> {
Some(&self.sparse)
}
fn memory_usage(&self) -> Option<StorageMemoryUsage> {
Some(self.private_memory_usage())
}
fn is_empty(&self) -> bool {
self.0.is_empty()
}
Expand Down Expand Up @@ -967,29 +948,12 @@ impl<T: 'static + Component> Storage for NonSendSync<SparseSet<T>> {
fn clear(&mut self, current: TrackingTimestamp) {
self.private_clear(current);
}
fn memory_usage(&self) -> Option<StorageMemoryUsage> {
Some(StorageMemoryUsage {
storage_name: type_name::<Self>().into(),
allocated_memory_bytes: self.sparse.reserved_memory()
+ (self.dense.capacity() * size_of::<EntityId>())
+ (self.data.capacity() * size_of::<T>())
+ (self.insertion_data.capacity() * size_of::<u32>())
+ (self.deletion_data.capacity() * size_of::<(T, EntityId)>())
+ (self.removal_data.capacity() * size_of::<EntityId>())
+ size_of::<Self>(),
used_memory_bytes: self.sparse.used_memory()
+ (self.dense.len() * size_of::<EntityId>())
+ (self.data.len() * size_of::<T>())
+ (self.insertion_data.len() * size_of::<u32>())
+ (self.deletion_data.len() * size_of::<(EntityId, T)>())
+ (self.removal_data.len() * size_of::<EntityId>())
+ size_of::<Self>(),
component_count: self.len(),
})
}
fn sparse_array(&self) -> Option<&SparseArray<EntityId, BUCKET_SIZE>> {
Some(&self.sparse)
}
fn memory_usage(&self) -> Option<StorageMemoryUsage> {
Some(self.private_memory_usage())
}
fn is_empty(&self) -> bool {
self.0.is_empty()
}
Expand Down Expand Up @@ -1030,6 +994,7 @@ impl<T: 'static + Component> Storage for NonSendSync<SparseSet<T>> {
mod tests {
use super::*;
use crate::Component;
use std::println;

#[derive(PartialEq, Eq, Debug)]
struct STR(&'static str);
Expand Down Expand Up @@ -1416,4 +1381,68 @@ mod tests {
assert_eq!(sparse_set.insertion_data.len(), 1);
assert_eq!(sparse_set.modification_data.len(), 1);
}

/// Makes sure the `memory_usage` method is up-to-date with the current `SparseSet` data.
#[test]
fn memory_usage() {
let mut sparse_set = SparseSet::new();
sparse_set.track_all();

sparse_set
.insert(
EntityId::new_from_parts(0, 0),
I32(0),
TrackingTimestamp::new(0),
)
.assert_inserted();
sparse_set.delete(
EntityId::new_from_index_and_gen(0, 0),
TrackingTimestamp::new(0),
);

sparse_set
.insert(
EntityId::new_from_parts(0, 0),
I32(1),
TrackingTimestamp::new(0),
)
.assert_inserted();
sparse_set.dyn_remove(
EntityId::new_from_index_and_gen(0, 0),
TrackingTimestamp::new(0),
);

sparse_set
.insert(
EntityId::new_from_parts(0, 0),
I32(2),
TrackingTimestamp::new(0),
)
.assert_inserted();

let expected_sparse_memory = sparse_set.sparse.used_memory();
let expected_dense_memory = 1 * size_of::<EntityId>();
let expected_data_memory = 1 * size_of::<I32>();
let expected_insertion_tracking_memory = 1 * size_of::<TrackingTimestamp>();
let expected_modification_tracking_memory = 1 * size_of::<TrackingTimestamp>();
let expected_deletion_tracking_memory = 1 * size_of::<(EntityId, TrackingTimestamp, I32)>();
let expected_removal_tracking_memory = 1 * size_of::<(EntityId, TrackingTimestamp)>();
let expected_self_memory = size_of::<SparseSet<I32>>();
let expected_total_memory = expected_sparse_memory
+ expected_dense_memory
+ expected_data_memory
+ expected_insertion_tracking_memory
+ expected_modification_tracking_memory
+ expected_deletion_tracking_memory
+ expected_removal_tracking_memory
+ expected_self_memory;

let StorageMemoryUsage::SparseSet {
used_memory_bytes, ..
} = sparse_set.private_memory_usage()
else {
unreachable!()
};
assert_eq!(used_memory_bytes, expected_total_memory);
}
}
4 changes: 1 addition & 3 deletions src/unique.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,9 @@ pub struct UniqueStorage<T: Unique> {

impl<T: Unique> Storage for UniqueStorage<T> {
fn memory_usage(&self) -> Option<StorageMemoryUsage> {
Some(StorageMemoryUsage {
Some(StorageMemoryUsage::Unique {
storage_name: type_name::<Self>().into(),
allocated_memory_bytes: size_of::<Self>(),
used_memory_bytes: size_of::<Self>(),
component_count: 1,
})
}
fn is_empty(&self) -> bool {
Expand Down

0 comments on commit eff3867

Please sign in to comment.