Skip to content

Commit ff37883

Browse files
committed
Initial working version.
1 parent 99c66d2 commit ff37883

File tree

8 files changed

+163
-4
lines changed

8 files changed

+163
-4
lines changed

README.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# bevy_datasize
2+
3+
This is a library for tracking memory usage in [Bevy] apps.
4+
5+
[Bevy]: https://lib.rs/bevy

examples/components.rs

+20-3
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,30 @@
11
use bevy::prelude::*;
2-
use bevy_datasize::DataSize;
2+
use bevy_datasize::{DataSize, MemoryUsage, MemoryUsagePlugin, RegisterSizedTypes};
33

44
#[derive(Component, DataSize)]
55
struct MyComponent {
66
pub vec: Vec<u8>,
77
}
88

99
fn main() {
10-
let component = MyComponent { vec: vec![0; 4096] };
10+
App::new()
11+
.add_plugins(MinimalPlugins)
12+
.add_plugin(MemoryUsagePlugin)
13+
.register_sized_component::<MyComponent>()
14+
.add_startup_system(spawn_entities)
15+
.add_system(print_size)
16+
.run();
17+
}
18+
19+
fn spawn_entities(mut commands: Commands) {
20+
for _ in 0..8 {
21+
let component = MyComponent { vec: vec![0; 1024] };
22+
commands.spawn().insert(component);
23+
}
24+
}
25+
26+
fn print_size(memory_usage: Res<MemoryUsage>) {
27+
let bytes = memory_usage.get_usage::<MyComponent>().unwrap();
1128

12-
println!("{}", component.estimate_heap_size());
29+
println!("Memory usage: {} bytes", bytes);
1330
}

src/app_ext.rs

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
use std::any::Any;
2+
3+
use bevy::app::App;
4+
use bevy::ecs::component::Component;
5+
6+
use crate::{systems::update_datasize_for_component, DataSize, MemoryUsage};
7+
8+
pub trait RegisterSizedTypes {
9+
fn register_sized_component<T>(&mut self) -> &mut Self
10+
where
11+
T: Any + Component + DataSize;
12+
}
13+
14+
impl RegisterSizedTypes for App {
15+
fn register_sized_component<T>(&mut self) -> &mut Self
16+
where
17+
T: Any + Component + DataSize,
18+
{
19+
let mut memory_usage = self.world.get_resource_mut::<MemoryUsage>().expect(
20+
"Cannot find resource `MemoryUsage`. Did you forget to add the `MemoryUsagePlugin`?",
21+
);
22+
23+
memory_usage.register_type::<T>();
24+
25+
self.add_system(update_datasize_for_component::<T>);
26+
27+
self
28+
}
29+
}

src/config.rs

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#[derive(Debug)]
2+
pub struct MemoryConfig {
3+
pub tracking_enabled: bool,
4+
}
5+
6+
impl Default for MemoryConfig {
7+
fn default() -> Self {
8+
Self {
9+
tracking_enabled: true,
10+
}
11+
}
12+
}

src/lib.rs

+21-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,24 @@
11
#![doc = include_str!("../README.md")]
2-
#![warn(missing_docs)]
32

43
pub use datasize::DataSize;
4+
5+
mod app_ext;
6+
mod config;
7+
mod plugin;
8+
mod resource;
9+
mod systems;
10+
11+
pub use app_ext::RegisterSizedTypes;
12+
pub use config::MemoryConfig;
13+
pub use plugin::MemoryUsagePlugin;
14+
pub use resource::MemoryUsage;
15+
16+
pub fn estimate_stack_and_heap_size<T>(value: &T) -> usize
17+
where
18+
T: DataSize,
19+
{
20+
let stack_size = std::mem::size_of::<T>();
21+
let heap_size = value.estimate_heap_size();
22+
23+
stack_size + heap_size
24+
}

src/plugin.rs

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
use bevy::app::Plugin;
2+
3+
use crate::{MemoryConfig, MemoryUsage};
4+
5+
pub struct MemoryUsagePlugin;
6+
7+
impl Plugin for MemoryUsagePlugin {
8+
fn build(&self, app: &mut bevy::prelude::App) {
9+
app.init_resource::<MemoryConfig>();
10+
app.init_resource::<MemoryUsage>();
11+
}
12+
}

src/resource.rs

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
use std::any::{Any, TypeId};
2+
3+
use bevy::utils::HashMap;
4+
5+
#[derive(Debug, Default)]
6+
pub struct MemoryUsage {
7+
pub(crate) datasizes: HashMap<TypeId, usize>,
8+
}
9+
10+
impl MemoryUsage {
11+
pub fn register_type<T>(&mut self)
12+
where
13+
T: Any,
14+
{
15+
let type_id = TypeId::of::<T>();
16+
17+
self.datasizes.insert(type_id, 0);
18+
}
19+
20+
pub fn update_usage<T>(&mut self, total_bytes: usize)
21+
where
22+
T: Any,
23+
{
24+
let type_id = TypeId::of::<T>();
25+
26+
let entry = self
27+
.datasizes
28+
.get_mut(&type_id)
29+
.expect("Memory usage not tracked for this type. Did you forget to register the type?");
30+
31+
*entry = total_bytes;
32+
}
33+
34+
pub fn get_usage<T>(&self) -> Option<usize>
35+
where
36+
T: Any,
37+
{
38+
let type_id = TypeId::of::<T>();
39+
40+
self.datasizes.get(&type_id).copied()
41+
}
42+
}

src/systems.rs

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
use std::any::Any;
2+
3+
use bevy::prelude::*;
4+
use datasize::DataSize;
5+
6+
use crate::{estimate_stack_and_heap_size, MemoryConfig, MemoryUsage};
7+
8+
pub fn update_datasize_for_component<T>(
9+
query: Query<&T>,
10+
memory_config: Res<MemoryConfig>,
11+
mut memory_usage: ResMut<MemoryUsage>,
12+
) where
13+
T: Any + Component + DataSize,
14+
{
15+
if !memory_config.tracking_enabled {
16+
return;
17+
}
18+
19+
let total_bytes: usize = query.iter().map(estimate_stack_and_heap_size).sum();
20+
21+
memory_usage.update_usage::<T>(total_bytes);
22+
}

0 commit comments

Comments
 (0)