rendy_memory/
utilization.rsuse {
colorful::{core::color_string::CString, Color, Colorful as _},
gfx_hal::memory::Properties,
};
#[derive(Clone, Copy, Debug)]
pub struct MemoryUtilization {
pub used: u64,
pub effective: u64,
}
#[derive(Clone, Copy, Debug)]
pub struct MemoryHeapUtilization {
pub utilization: MemoryUtilization,
pub size: u64,
}
#[derive(Clone, Copy, Debug)]
pub struct MemoryTypeUtilization {
pub utilization: MemoryUtilization,
pub properties: Properties,
pub heap_index: usize,
}
#[derive(Clone, Debug)]
pub struct TotalMemoryUtilization {
pub types: Vec<MemoryTypeUtilization>,
pub heaps: Vec<MemoryHeapUtilization>,
}
impl std::fmt::Display for TotalMemoryUtilization {
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
const MB: u64 = 1024 * 1024;
writeln!(fmt, "!!! Memory utilization !!!")?;
for (index, heap) in self.heaps.iter().enumerate() {
let size = heap.size;
let MemoryUtilization { used, effective } = heap.utilization;
let usage_basis_points = used * 10000 / size;
let fill = if usage_basis_points > 10000 {
50
} else {
(usage_basis_points / 200) as usize
};
let effective_basis_points = if used > 0 {
effective * 10000 / used
} else {
10000
};
let line = ("|".repeat(fill) + &(" ".repeat(50 - fill)))
.gradient_with_color(Color::Green, Color::Red);
writeln!(
fmt,
"Heap {}:\n{:6} / {:<6} or{} {{ effective:{} }} [{}]",
format!("{}", index).magenta(),
format!("{}MB", used / MB),
format!("{}MB", size / MB),
format_basis_points(usage_basis_points),
format_basis_points_inverted(effective_basis_points),
line
)?;
for ty in self.types.iter().filter(|ty| ty.heap_index == index) {
let properties = ty.properties;
let MemoryUtilization { used, effective } = ty.utilization;
let usage_basis_points = used * 10000 / size;
let effective_basis_points = if used > 0 {
effective * 10000 / used
} else {
0
};
writeln!(
fmt,
" {:>6} or{} {{ effective:{} }} | {:?}",
format!("{}MB", used / MB),
format_basis_points(usage_basis_points),
format_basis_points_inverted(effective_basis_points),
properties,
)?;
}
}
Ok(())
}
}
fn format_basis_points(basis_points: u64) -> CString {
debug_assert!(basis_points <= 10000);
let s = format!("{:>3}.{:02}%", basis_points / 100, basis_points % 100);
if basis_points > 7500 {
s.red()
} else if basis_points > 5000 {
s.yellow()
} else if basis_points > 2500 {
s.green()
} else if basis_points > 100 {
s.blue()
} else {
s.white()
}
}
fn format_basis_points_inverted(basis_points: u64) -> CString {
debug_assert!(basis_points <= 10000);
let s = format!("{:>3}.{:02}%", basis_points / 100, basis_points % 100);
if basis_points > 9900 {
s.white()
} else if basis_points > 7500 {
s.blue()
} else if basis_points > 5000 {
s.green()
} else if basis_points > 2500 {
s.yellow()
} else {
s.red()
}
}