rendy_memory/
utilization.rs1use {
2 colorful::{core::color_string::CString, Color, Colorful as _},
3 gfx_hal::memory::Properties,
4};
5
6#[derive(Clone, Copy, Debug)]
8pub struct MemoryUtilization {
9 pub used: u64,
11 pub effective: u64,
13}
14
15#[derive(Clone, Copy, Debug)]
17pub struct MemoryHeapUtilization {
18 pub utilization: MemoryUtilization,
20
21 pub size: u64,
23}
24
25#[derive(Clone, Copy, Debug)]
27pub struct MemoryTypeUtilization {
28 pub utilization: MemoryUtilization,
30
31 pub properties: Properties,
33
34 pub heap_index: usize,
36}
37
38#[derive(Clone, Debug)]
40pub struct TotalMemoryUtilization {
41 pub types: Vec<MemoryTypeUtilization>,
43
44 pub heaps: Vec<MemoryHeapUtilization>,
46}
47
48impl std::fmt::Display for TotalMemoryUtilization {
49 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50 const MB: u64 = 1024 * 1024;
51
52 writeln!(fmt, "!!! Memory utilization !!!")?;
53 for (index, heap) in self.heaps.iter().enumerate() {
54 let size = heap.size;
55 let MemoryUtilization { used, effective } = heap.utilization;
56 let usage_basis_points = used * 10000 / size;
57 let fill = if usage_basis_points > 10000 {
58 50
60 } else {
61 (usage_basis_points / 200) as usize
62 };
63 let effective_basis_points = if used > 0 {
64 effective * 10000 / used
65 } else {
66 10000
67 };
68
69 let line = ("|".repeat(fill) + &(" ".repeat(50 - fill)))
70 .gradient_with_color(Color::Green, Color::Red);
71 writeln!(
72 fmt,
73 "Heap {}:\n{:6} / {:<6} or{} {{ effective:{} }} [{}]",
74 format!("{}", index).magenta(),
75 format!("{}MB", used / MB),
76 format!("{}MB", size / MB),
77 format_basis_points(usage_basis_points),
78 format_basis_points_inverted(effective_basis_points),
79 line
80 )?;
81
82 for ty in self.types.iter().filter(|ty| ty.heap_index == index) {
83 let properties = ty.properties;
84 let MemoryUtilization { used, effective } = ty.utilization;
85 let usage_basis_points = used * 10000 / size;
86 let effective_basis_points = if used > 0 {
87 effective * 10000 / used
88 } else {
89 0
90 };
91
92 writeln!(
93 fmt,
94 " {:>6} or{} {{ effective:{} }} | {:?}",
95 format!("{}MB", used / MB),
96 format_basis_points(usage_basis_points),
97 format_basis_points_inverted(effective_basis_points),
98 properties,
99 )?;
100 }
101 }
102
103 Ok(())
104 }
105}
106
107fn format_basis_points(basis_points: u64) -> CString {
108 debug_assert!(basis_points <= 10000);
109 let s = format!("{:>3}.{:02}%", basis_points / 100, basis_points % 100);
110 if basis_points > 7500 {
111 s.red()
112 } else if basis_points > 5000 {
113 s.yellow()
114 } else if basis_points > 2500 {
115 s.green()
116 } else if basis_points > 100 {
117 s.blue()
118 } else {
119 s.white()
120 }
121}
122
123fn format_basis_points_inverted(basis_points: u64) -> CString {
124 debug_assert!(basis_points <= 10000);
125 let s = format!("{:>3}.{:02}%", basis_points / 100, basis_points % 100);
126 if basis_points > 9900 {
127 s.white()
128 } else if basis_points > 7500 {
129 s.blue()
130 } else if basis_points > 5000 {
131 s.green()
132 } else if basis_points > 2500 {
133 s.yellow()
134 } else {
135 s.red()
136 }
137}