joule_profiler_source_procfs/
counters.rs1use crate::snapshot::{GlobalSnapshot, ProcSnapshot};
2
3#[derive(Debug, Clone, Copy, Default)]
5pub struct MinMax(pub Option<u64>, Option<u64>);
6
7impl MinMax {
8 pub fn update(&mut self, value: u64) {
10 self.0 = Some(self.0.map_or(value, |m| m.min(value)));
11 self.1 = Some(self.1.map_or(value, |m| m.max(value)));
12 }
13
14 pub fn reset(&mut self) {
15 self.0 = None;
16 self.1 = None;
17 }
18
19 pub fn min(&self) -> Option<u64> {
20 self.0
21 }
22
23 pub fn max(&self) -> Option<u64> {
24 self.1
25 }
26}
27
28#[derive(Debug, Default, Clone, Copy)]
34pub struct ProcCounters {
35 pub vm_size: MinMax,
37
38 pub rss: MinMax,
40
41 pub pss: MinMax,
43
44 pub shared: MinMax,
46
47 pub anon: MinMax,
49
50 pub begin_read_bytes: u64,
52
53 pub begin_write_bytes: u64,
55
56 pub end_read_bytes: u64,
58
59 pub end_write_bytes: u64,
61}
62
63impl ProcCounters {
64 pub fn update(&mut self, snapshot: &ProcSnapshot) {
69 self.vm_size.update(snapshot.vm_size);
70 self.rss.update(snapshot.rss);
71 self.pss.update(snapshot.pss);
72 self.shared.update(snapshot.shared);
73 self.anon.update(snapshot.anon);
74 self.end_read_bytes = self.end_read_bytes.max(snapshot.read_bytes);
75 self.end_write_bytes = self.end_write_bytes.max(snapshot.write_bytes);
76 }
77
78 pub fn reset(&mut self) {
80 self.vm_size.reset();
81 self.rss.reset();
82 self.pss.reset();
83 self.shared.reset();
84 self.anon.reset();
85 self.begin_read_bytes = self.end_read_bytes;
86 self.begin_write_bytes = self.end_write_bytes;
87 }
88}
89
90pub fn compute_mem_used(
99 mem_total: u64,
100 mem_available: Option<MinMax>,
101 mem_free: MinMax,
102 cached: MinMax,
103) -> MinMax {
104 if let Some(available) = mem_available {
105 MinMax(
106 Some(mem_total.saturating_sub(available.max().unwrap_or_default())),
107 Some(mem_total.saturating_sub(available.min().unwrap_or_default())),
108 )
109 } else {
110 MinMax(
111 Some(mem_total.saturating_sub(
112 mem_free.max().unwrap_or_default() + cached.max().unwrap_or_default(),
113 )),
114 Some(mem_total.saturating_sub(
115 mem_free.min().unwrap_or_default() + cached.min().unwrap_or_default(),
116 )),
117 )
118 }
119}
120
121#[derive(Debug, Default, Clone, Copy)]
127pub struct GlobalCounters {
128 pub mem_available: Option<MinMax>,
130
131 pub mem_free: MinMax,
133
134 pub cached: MinMax,
136
137 pub anon: Option<MinMax>,
139
140 pub swap_free: MinMax,
142}
143
144impl GlobalCounters {
145 pub fn update(&mut self, snapshot: &GlobalSnapshot) {
147 self.mem_free.update(snapshot.mem_free);
148 self.cached.update(snapshot.cached);
149 self.swap_free.update(snapshot.swap_free);
150 if let Some(v) = snapshot.mem_available {
151 self.mem_available.get_or_insert_default().update(v);
152 }
153 if let Some(v) = snapshot.anon {
154 self.anon.get_or_insert_default().update(v);
155 }
156 }
157
158 pub fn reset(&mut self) {
160 self.mem_free.reset();
161 self.cached.reset();
162 self.swap_free.reset();
163 if let Some(v) = &mut self.mem_available {
164 v.reset();
165 }
166 if let Some(v) = &mut self.anon {
167 v.reset();
168 }
169 }
170}
171
172#[derive(Debug, Default, Clone, Copy)]
173pub struct Counters {
174 pub proc: ProcCounters,
175 pub global: GlobalCounters,
176}
177
178impl Counters {
179 pub fn update(&mut self, proc: &ProcSnapshot, global: &GlobalSnapshot) {
180 self.proc.update(proc);
181 self.global.update(global);
182 }
183
184 pub fn reset(&mut self) {
185 self.proc.reset();
186 self.global.reset();
187 }
188}