Constantly increasing memory usage #4268
Replies: 3 comments 1 reply
-
Converting to a discussion; this is too project-specific for us to resolve directly as a bug <3 |
Beta Was this translation helpful? Give feedback.
-
Note that .clear() on rust collections only drops the contained items, it doesn’t free any of the allocated capacity. I tried to look through the code but with the web interface for the repo I couldn’t find where the entities with Handle are spawned. All I could find was that the handle was being used to mutably get the mesh asset and then overwrite it. I haven’t seen that pattern before and I’m not sure how it will behave. My guess would be that perhaps the mesh data is being leaked somewhere, but it’s a hunch. I am not at all certain. |
Beta Was this translation helpful? Give feedback.
-
After changing the way I mesh the chunks and unload everything, I now removed the meshing altogether, by not spawning the PbrBundle in pub fn apply_mesh_tasks(
mut meshes: ResMut<Assets<Mesh>>,
chunkmap: Res<ChunkMap>,
mut query: Query<(&LoadedChunk, &mut MeshTask)>,
mut cmds: Commands,
settings: Res<Settings>,
materials: Res<crate::material::Materials>,
) {
let mut finished: usize = 0;
for (_, mut mesh_task) in query.iter_mut() {
if finished < settings.chunk_meshes_per_cycle as usize {
if let Some( (key, mesh) ) = future::block_on(future::poll_once(&mut mesh_task.task)) {
if let Some(entity) = chunkmap.entity(key) {
/*
cmds.entity(entity).insert_bundle(PbrBundle {
mesh: meshes.add(mesh), // must have exact size
visibility: Visibility {is_visible: true},
transform: Transform::from_matrix(Mat4::from_scale_rotation_translation(
Vec3::splat(1.0),
Quat::from_rotation_x(0.0),
Vec3::new((key[0] * CHUNK_SIZE as i64) as f32, (key[1] * CHUNK_SIZE as i64) as f32, (key[2] * CHUNK_SIZE as i64) as f32),
)),
material: materials.chunk.clone(),
..default()
});
*/
cmds.entity(entity).remove::<MeshTask>();
finished += 1;
}
}
}
};
} The memory does still increase constantly, but not as fast. Because of that, I think it is the way I despawn the entities, that is the memory problem. I check if an entity should be despawned like this: fn chunk_unload_detector(
voxelmap: Res<VoxelMap>,
chunkmap: Res<ChunkMap>,
mut query: Query<(&Transform, &mut Player)>,
mut unload_queue: ResMut<ChunkUnloadQueue>,
) {
let mut player_pos = Vec3::ZERO;
let mut player_moved: bool = false;
for (transform, mut player) in query.iter_mut().next() {
player_pos = transform.translation;
if player.chunks_moved_since_unload > 0 {
player_moved = true;
player.chunks_moved_since_unload = 0;
}
}
let chunk_x = (player_pos.x / CHUNK_SIZE as f32).round() as i64;
let chunk_y = (player_pos.y / CHUNK_SIZE as f32).round() as i64;
let chunk_z = (player_pos.z / CHUNK_SIZE as f32).round() as i64;
if player_moved {
let coords = [chunk_x, chunk_y, chunk_z];
voxelmap.map.keys().for_each(|key| {
if (key[0] - coords[0]).abs() > RENDER_DISTANCE_HOR + 1
|| (key[1] - coords[1]).abs() > RENDER_DISTANCE_VER + 1
|| (key[2] - coords[2]).abs() > RENDER_DISTANCE_HOR + 1 {
unload_queue.queue.push(*key);
}
});
chunkmap.0.keys().for_each(|key| {
if (key[0] - coords[0]).abs() > RENDER_DISTANCE_HOR + 1
|| (key[1] - coords[1]).abs() > RENDER_DISTANCE_VER + 1
|| (key[2] - coords[2]).abs() > RENDER_DISTANCE_HOR + 1 {
unload_queue.queue.push(*key);
}
});
}
} Then I go trough the fn chunk_unloader(
mut unload_queue: ResMut<ChunkUnloadQueue>,
mut chunkmap: ResMut<ChunkMap>,
mut voxelmap: ResMut<VoxelMap>,
mut cmds: Commands,
) {
for key in unload_queue.queue.drain(..) {
if let Some(entity) = chunkmap.detach_entity(key) {
cmds.entity(entity).despawn();
}
voxelmap.map.remove(&key);
}
} The fn entity_count(
query: Query<Entity>,
mesh: Res<Assets<Mesh>>,
loaded_chunks: Query<&LoadedChunk>,
chunkmap: Res<ChunkMap>,
voxelmap: Res<VoxelMap>,
gen_queue: Res<ChunkGenQueue>,
mesh_queue: Res<ChunkMeshQueue>,
unload_queue: Res<ChunkUnloadQueue>,
) {
let entities = query.iter().count();
let meshes = mesh.iter().count();
let chunks = chunkmap.0.len();
let voxels = voxelmap.map.len();
let mesh = mesh_queue.queue.len();
let gen = gen_queue.queue.len();
let unload = unload_queue.queue.len();
let loaded_c = loaded_chunks.iter().count();
println!("entities: {}\tmeshes: {}", entities, meshes);
println!("chunkmap: {}\tvoxels: {}", chunks, voxels);
println!("mesh_q: {}\tgen_q: {}", mesh, gen);
println!("unload: {}\tload_c: {}", unload, loaded_c);
println!("");
} I really do not know what else to do in this situation. |
Beta Was this translation helpful? Give feedback.
-
Bevy version
bevy commit
a291b5aaedb4affcb31df2e2e63cb0c665ffb24a
Operating system & version
Latest Arch Linux.
What I did
I created a voxel based 3D game, which stores chunks of block-data and the chunk entitiies in 2 seperate
HashMap
s.First I spawn a
PbrBundle
with the mesh of a Cube and attach its ID to the hashmap.Then I generate the Terrain and Mesh asynchronously and apply the mesh by querying over
&Handle<Mesh>
To unload the chunks I have a system which periodically checks trough one of the hashmap, which holds the entities and if its key is outside of the range of the player, the entity gets despawned and the corresponding data gets removed from both hashmaps,
Expected behaviour
I have a system to monitor every single resource and entity count and according to that, the total amount of entities and entries in the hashmaps are not getting any more.
Because of that there should not be a memory increase
What actually happened
The memory usage of the game gets constantly bigger as I load and unload new chunks,.
I even have a system which deletes everything with a keypress, but this does only free up a bit of memory.
Additional information
The repo can be found here
I copied a lot of ideas from vx_bevy which does not have this memory problem.
hashmaps
This does monitor every single Resource and entity in my Game
Despite it showing no memory increase, the memory does increase
monitoring
I am really out of ideas what to do, because everything should to work.
Did I forget to measure something or is bevy the problem here?
Beta Was this translation helpful? Give feedback.
All reactions