gfx_memory/
stats.rs

1use crate::Size;
2use hal::memory::Properties;
3
4/// Memory utilization stats.
5#[derive(Clone, Copy, Debug)]
6pub struct MemoryUtilization {
7    /// Total number of bytes allocated.
8    pub used: Size,
9    /// Effective number bytes allocated.
10    pub effective: Size,
11}
12
13/// Memory utilization of one heap.
14#[derive(Clone, Copy, Debug)]
15pub struct MemoryHeapUtilization {
16    /// Utilization.
17    pub utilization: MemoryUtilization,
18
19    /// Memory heap size.
20    pub size: Size,
21}
22
23/// Memory utilization of one type.
24#[derive(Clone, Copy, Debug)]
25pub struct MemoryTypeUtilization {
26    /// Utilization.
27    pub utilization: MemoryUtilization,
28
29    /// Memory type info.
30    pub properties: Properties,
31
32    /// Index of heap this memory type uses.
33    pub heap_index: usize,
34}
35
36/// Total memory utilization.
37#[derive(Clone, Debug)]
38pub struct TotalMemoryUtilization {
39    /// Utilization by types.
40    pub types: Vec<MemoryTypeUtilization>,
41
42    /// Utilization by heaps.
43    pub heaps: Vec<MemoryHeapUtilization>,
44}
45
46impl std::fmt::Display for TotalMemoryUtilization {
47    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
48        const MB: Size = 1024 * 1024;
49
50        writeln!(fmt, "!!! Memory utilization !!!")?;
51        for (index, heap) in self.heaps.iter().enumerate() {
52            let size = heap.size;
53            let MemoryUtilization { used, effective } = heap.utilization;
54            let usage_basis_points = used * 10000 / size;
55            let fill = if usage_basis_points > 10000 {
56                // Shouldn't happen, but just in case.
57                50
58            } else {
59                (usage_basis_points / 200) as usize
60            };
61            let effective_basis_points = if used > 0 {
62                effective * 10000 / used
63            } else {
64                10000
65            };
66
67            let line = "|".repeat(fill) + &(" ".repeat(50 - fill));
68            writeln!(
69                fmt,
70                "Heap {}:\n{:6} / {:<6} or{} {{ effective:{} }} [{}]",
71                format!("{}", index),
72                format!("{}MB", used / MB),
73                format!("{}MB", size / MB),
74                format_basis_points(usage_basis_points),
75                format_basis_points(effective_basis_points),
76                line
77            )?;
78
79            for ty in self.types.iter().filter(|ty| ty.heap_index == index) {
80                let properties = ty.properties;
81                let MemoryUtilization { used, effective } = ty.utilization;
82                let usage_basis_points = used * 10000 / size;
83                let effective_basis_points = if used > 0 {
84                    effective * 10000 / used
85                } else {
86                    0
87                };
88
89                writeln!(
90                    fmt,
91                    "         {:>6} or{} {{ effective:{} }} | {:?}",
92                    format!("{}MB", used / MB),
93                    format_basis_points(usage_basis_points),
94                    format_basis_points(effective_basis_points),
95                    properties,
96                )?;
97            }
98        }
99
100        Ok(())
101    }
102}
103
104fn format_basis_points(basis_points: Size) -> String {
105    debug_assert!(basis_points <= 10000);
106    format!("{:>3}.{:02}%", basis_points / 100, basis_points % 100)
107}