use std::collections::HashMap;
use std::hash::BuildHasher;
use std::hash::Hash;
use crate::prelude::GMListChunk;
use crate::util::bench::Stopwatch;
use crate::util::fmt::format_bytes;
use crate::wad::GMData;
impl GMData {
pub fn optimize_memory(&mut self) {
let stopwatch = Stopwatch::start();
let freed_bytes: usize = optimize_memory(self);
let human_size: String = format_bytes(freed_bytes);
log::debug!("Freed {human_size} ({freed_bytes} bytes) in {stopwatch}");
}
pub fn optimize_memory_silent(&mut self) {
optimize_memory(self);
}
}
fn optimize_memory(data: &mut GMData) -> usize {
let mut freed_bytes: usize = 0;
freed_bytes += shrink_list_chunk(&mut data.animation_curves);
freed_bytes += shrink_list_chunk(&mut data.audio_groups);
freed_bytes += shrink_list_chunk(&mut data.audios);
freed_bytes += shrink_list_chunk(&mut data.backgrounds);
freed_bytes += shrink_list_chunk(&mut data.codes);
freed_bytes += shrink_list_chunk(&mut data.embedded_images);
freed_bytes += shrink_list_chunk(&mut data.extensions);
freed_bytes += shrink_list_chunk(&mut data.feature_flags);
freed_bytes += shrink_list_chunk(&mut data.filter_effects);
freed_bytes += shrink_list_chunk(&mut data.fonts);
freed_bytes += shrink_list_chunk(&mut data.functions);
freed_bytes += shrink_list_chunk(&mut data.game_end_scripts);
freed_bytes += shrink_list_chunk(&mut data.game_objects);
freed_bytes += shrink_list_chunk(&mut data.global_init_scripts);
freed_bytes += shrink_list_chunk(&mut data.particle_emitters);
freed_bytes += shrink_list_chunk(&mut data.particle_systems);
freed_bytes += shrink_list_chunk(&mut data.paths);
freed_bytes += shrink_list_chunk(&mut data.rooms);
freed_bytes += shrink_list_chunk(&mut data.ui_nodes);
freed_bytes += shrink_list_chunk(&mut data.scripts);
freed_bytes += shrink_list_chunk(&mut data.sequences);
freed_bytes += shrink_list_chunk(&mut data.shaders);
freed_bytes += shrink_list_chunk(&mut data.sounds);
freed_bytes += shrink_list_chunk(&mut data.sprites);
freed_bytes += shrink_list_chunk(&mut data.texture_group_infos);
freed_bytes += shrink_list_chunk(&mut data.texture_page_items);
freed_bytes += shrink_list_chunk(&mut data.texture_pages);
freed_bytes += shrink_list_chunk(&mut data.timelines);
freed_bytes += shrink_list_chunk(&mut data.variables);
for code in &mut data.codes {
freed_bytes += shrink_vec(&mut code.instructions);
}
for sequence in &mut data.sequences {
freed_bytes += shrink_hashmap(&mut sequence.function_ids);
}
for texture_page in &mut data.texture_pages {
let Some(image) = &mut texture_page.image else {
continue;
};
freed_bytes += image.optimize_memory();
}
freed_bytes
}
fn shrink_list_chunk<T: GMListChunk>(chunk: &mut T) -> usize {
shrink_vec(chunk.elements_mut())
}
fn shrink_vec<T>(vector: &mut Vec<T>) -> usize {
let before = vector.capacity();
vector.shrink_to_fit();
let after = vector.capacity();
before - after
}
fn shrink_hashmap<K: Hash + Eq, V, S: BuildHasher>(hashmap: &mut HashMap<K, V, S>) -> usize {
let before = hashmap.capacity();
hashmap.shrink_to_fit();
let after = hashmap.capacity();
before - after
}