1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
use crate::Size;
#[cfg(feature = "colorful")]
use colorful::{core::color_string::CString, Color, Colorful as _};
use hal::memory::Properties;
#[derive(Clone, Copy, Debug)]
pub struct MemoryUtilization {
pub used: Size,
pub effective: Size,
}
#[derive(Clone, Copy, Debug)]
pub struct MemoryHeapUtilization {
pub utilization: MemoryUtilization,
pub size: Size,
}
#[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>,
}
#[cfg(feature = "colorful")]
impl std::fmt::Display for TotalMemoryUtilization {
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
const MB: Size = 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(())
}
}
#[cfg(feature = "colorful")]
fn format_basis_points(basis_points: Size) -> 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()
}
}
#[cfg(feature = "colorful")]
fn format_basis_points_inverted(basis_points: Size) -> 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()
}
}