1use crate::util::read_to_string_mut;
4
5use std::ops::Sub;
6use std::path::Path;
7use std::time::Duration;
8use std::{fs, io};
9
10#[derive(Debug, Clone, PartialEq, Eq)]
12pub struct Uptime {
13 raw: String,
14}
15
16impl Uptime {
17 fn path() -> &'static Path {
18 Path::new("/proc/uptime")
19 }
20
21 #[cfg(test)]
22 fn from_string(raw: String) -> Self {
23 Self { raw }
24 }
25
26 pub fn read() -> io::Result<Self> {
28 Ok(Self {
29 raw: fs::read_to_string(Self::path())?,
30 })
31 }
32
33 pub fn reload(&mut self) -> io::Result<()> {
35 read_to_string_mut(Self::path(), &mut self.raw)
36 }
37
38 pub fn all_infos<'a>(&'a self) -> impl Iterator<Item = Duration> + 'a {
40 self.raw
41 .split(' ')
42 .filter_map(|v| v.trim().parse().ok())
43 .map(Duration::from_secs_f64)
44 }
45
46 pub fn uptime(&self) -> Option<Duration> {
48 self.all_infos().next()
49 }
50
51 pub fn idletime(&self) -> Option<Duration> {
54 self.all_infos().nth(1)
55 }
56}
57
58#[derive(Debug, Clone, PartialEq, Eq)]
60pub struct Hostname {
61 raw: String,
62}
63
64impl Hostname {
65 fn path() -> &'static Path {
66 Path::new("/proc/sys/kernel/hostname")
67 }
68
69 #[cfg(test)]
70 fn from_string(raw: String) -> Self {
71 Self { raw }
72 }
73
74 pub fn read() -> io::Result<Self> {
76 Ok(Self {
77 raw: fs::read_to_string(Self::path())?,
78 })
79 }
80
81 pub fn reload(&mut self) -> io::Result<()> {
83 read_to_string_mut(Self::path(), &mut self.raw)
84 }
85
86 pub fn hostname(&self) -> &str {
88 self.raw.trim()
89 }
90
91 pub fn into_string(self) -> String {
93 self.raw
94 }
95}
96
97#[derive(Debug, Clone, PartialEq, Eq)]
99pub struct OsRelease {
100 raw: String,
101}
102
103impl OsRelease {
104 fn path() -> &'static Path {
105 Path::new("/proc/sys/kernel/osrelease")
106 }
107
108 #[cfg(test)]
109 fn from_string(raw: String) -> Self {
110 Self { raw }
111 }
112
113 pub fn read() -> io::Result<Self> {
115 Ok(Self {
116 raw: fs::read_to_string(Self::path())?,
117 })
118 }
119
120 pub fn reload(&mut self) -> io::Result<()> {
122 read_to_string_mut(Self::path(), &mut self.raw)
123 }
124
125 pub fn full_str(&self) -> &str {
127 self.raw.trim()
128 }
129
130 pub fn into_string(self) -> String {
132 self.raw
133 }
134}
135
136#[derive(Debug, Clone, PartialEq, Eq)]
138pub struct LoadAvg {
139 raw: String,
140}
141
142impl LoadAvg {
143 fn path() -> &'static Path {
144 Path::new("/proc/loadavg")
145 }
146
147 #[cfg(test)]
148 fn from_string(raw: String) -> Self {
149 Self { raw }
150 }
151
152 pub fn read() -> io::Result<Self> {
154 Ok(Self {
155 raw: fs::read_to_string(Self::path())?,
156 })
157 }
158
159 pub fn reload(&mut self) -> io::Result<()> {
161 read_to_string_mut(Self::path(), &mut self.raw)
162 }
163
164 pub fn values<'a>(&'a self) -> impl Iterator<Item = &'a str> {
166 self.raw.split(' ').map(str::trim)
167 }
168
169 pub fn average(&self) -> Option<(f32, f32, f32)> {
172 let mut vals = self.values().take(3).map(|v| v.parse().ok());
173 Some((vals.next()??, vals.next()??, vals.next()??))
174 }
175
176 pub fn threads(&self) -> Option<(usize, usize)> {
178 let mut vals = self.values().nth(3)?.split('/').map(|v| v.parse().ok());
179 Some((vals.next()??, vals.next()??))
180 }
181
182 pub fn newest_pid(&self) -> Option<u32> {
184 self.values().last()?.parse().ok()
185 }
186}
187
188#[derive(Debug, Clone, Copy, PartialEq, Eq)]
189pub struct CpuStat {
190 pub user: usize,
192 pub nice: usize,
194 pub system: usize,
196 pub idle: usize,
198 pub iowait: usize,
200 pub irq: usize,
202 pub softirq: usize,
204}
205
206impl CpuStat {
207 pub fn total_time(&self) -> usize {
209 self.user
210 + self.nice
211 + self.system
212 + self.idle
213 + self.iowait
214 + self.irq
215 + self.softirq
216 }
217
218 pub fn active_time(&self) -> usize {
220 self.user + self.nice + self.system + self.irq + self.softirq
221 }
222
223 pub fn usage(&self, previous: &Self) -> f64 {
227 let diff = *self - *previous;
228
229 if diff.total_time() == 0 {
230 return 0.0;
231 }
232
233 diff.active_time() as f64 / diff.total_time() as f64
234 }
235}
236
237impl Sub for CpuStat {
238 type Output = Self;
239
240 fn sub(self, other: Self) -> Self {
241 Self {
242 user: self.user - other.user,
243 nice: self.nice - other.nice,
244 system: self.system - other.system,
245 idle: self.idle - other.idle,
246 iowait: self.iowait - other.iowait,
247 irq: self.irq - other.irq,
248 softirq: self.softirq - other.softirq,
249 }
250 }
251}
252
253impl FromIterator<usize> for CpuStat {
254 fn from_iter<T>(iter: T) -> Self
255 where
256 T: IntoIterator<Item = usize>,
257 {
258 let mut iter = iter.into_iter();
259
260 Self {
261 user: iter.next().unwrap_or(0),
262 nice: iter.next().unwrap_or(0),
263 system: iter.next().unwrap_or(0),
264 idle: iter.next().unwrap_or(0),
265 iowait: iter.next().unwrap_or(0),
266 irq: iter.next().unwrap_or(0),
267 softirq: iter.next().unwrap_or(0),
268 }
269 }
270}
271
272#[derive(Debug, Clone, PartialEq, Eq)]
274pub struct Stat {
275 raw: String,
276}
277
278impl Stat {
279 fn path() -> &'static Path {
280 Path::new("/proc/loadavg")
281 }
282
283 #[cfg(test)]
284 fn from_string(raw: String) -> Self {
285 Self { raw }
286 }
287
288 pub fn read() -> io::Result<Self> {
290 Ok(Self {
291 raw: fs::read_to_string(Self::path())?,
292 })
293 }
294
295 pub fn reload(&mut self) -> io::Result<()> {
297 read_to_string_mut(Self::path(), &mut self.raw)
298 }
299
300 pub fn values<'a>(
302 &'a self,
303 ) -> impl Iterator<Item = (&'a str, impl Iterator<Item = usize> + '_)> {
304 self.raw.trim().lines().map(str::trim).filter_map(|s| {
305 let (key, rest) = s.split_once(' ')?;
306
307 Some((key, rest.split(' ').filter_map(|v| v.parse().ok())))
308 })
309 }
310
311 pub fn cpu(&self) -> Option<CpuStat> {
312 self.values()
313 .find(|(k, _)| *k == "cpu")
314 .map(|(_, v)| v.collect())
315 }
316
317 pub fn cpu_nth(&self, nth: usize) -> Option<CpuStat> {
318 let nk = format!("cpu{}", nth);
319 self.values()
320 .find(|(k, _)| *k == nk)
321 .map(|(_, v)| v.collect())
322 }
323}
324
325#[cfg(test)]
329mod tests {
330 use super::*;
331
332 fn uptime() -> Uptime {
333 Uptime::from_string("220420.83 5275548.45\n".into())
334 }
335
336 #[test]
337 fn uptime_methods() {
338 assert_eq!(uptime().uptime().unwrap().as_secs(), 220420);
340 assert_eq!(uptime().idletime().unwrap().as_secs(), 5275548);
342 }
343
344 #[test]
345 fn hostname() {
346 let name = Hostname::from_string("test-hostname\n".into());
348 assert_eq!(name.hostname(), "test-hostname");
349 }
350
351 #[test]
352 fn os_release() {
353 let name = OsRelease::from_string("test-hostname\n".into());
355 assert_eq!(name.full_str(), "test-hostname");
356 }
357
358 #[test]
359 fn load_avg() {
360 let s =
361 LoadAvg::from_string("13.37 15.82 16.64 14/1444 436826\n".into());
362 assert_eq!(s.average().unwrap(), (13.37, 15.82, 16.64));
363 assert_eq!(s.threads().unwrap(), (14, 1444));
364 assert_eq!(s.newest_pid().unwrap(), 436826);
365 }
366
367 #[test]
368 fn stat() {
369 let first = Stat::from_string("\
370cpu 47500 2396 21138 741776 6759 0 516 0 0 0
371cpu0 1657 25 649 31631 152 0 40 0 0 0
372cpu1 1895 140 624 31335 197 0 9 0 0 0
373cpu2 2155 69 696 31185 101 0 2 0 0 0
374cpu3 2830 72 723 30280 259 0 15 0 0 0
375cpu4 2378 11 776 30813 247 0 1 0 0 0
376cpu5 2402 326 724 30541 193 0 0 0 0 0
377cpu6 1488 13 1217 31159 76 0 1 0 0 0
378cpu7 1537 50 861 31563 111 0 12 0 0 0
379cpu8 2164 22 1279 30611 120 0 0 0 0 0
380cpu9 2760 24 682 30418 292 0 6 0 0 0
381cpu10 2454 440 676 30409 206 0 0 0 0 0
382cpu11 1944 10 709 31251 284 0 0 0 0 0
383cpu12 2050 75 957 30479 634 0 0 0 0 0
384cpu13 1751 180 583 31385 303 0 6 0 0 0
385cpu14 1684 77 753 30998 414 0 162 0 0 0
386cpu15 1922 53 561 31603 73 0 0 0 0 0
387cpu16 2189 75 1108 30151 605 0 36 0 0 0
388cpu17 2113 240 1212 30252 393 0 0 0 0 0
389cpu18 1547 89 1132 30984 346 0 68 0 0 0
390cpu19 2009 87 1479 30265 360 0 7 0 0 0
391cpu20 1832 20 1260 30762 268 0 1 0 0 0
392cpu21 1396 10 669 31952 157 0 0 0 0 0
393cpu22 1466 249 908 30772 567 0 142 0 0 0
394cpu23 1868 33 890 30967 388 0 0 0 0 0
395intr 5968724 39 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1830 0 21 658 0 0 0 0 0 0 0 185 0 206 0 0 0 0 0 0 0 0 0 0 0 0 0 10756 12407 32939 620 3309 8687 22003 1735 1 0 0 0 0 0 0 0 492 0 0 0 0 0 0 0 0 0 0 0 0 23 67418 0 169 169 169 169 0 4770 0 0 0 0 0 0 0 72534 90229 23 36684 79 45360 4 74224 17 64117 72 65789 38 87 25 212 0 0 0 2973 0 3527 0 82311 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
396ctxt 9220606
397btime 1698004999
398processes 10505
399procs_running 3
400procs_blocked 1
401softirq 1572362 6570 73617 6 106501 103799 0 729 724985 18 556137\n\
402 ".into());
403
404 assert!(first.cpu_nth(0).is_some());
405 assert_eq!(
406 first.cpu().unwrap(),
407 CpuStat {
408 user: 47500,
409 nice: 2396,
410 system: 21138,
411 idle: 741776,
412 iowait: 6759,
413 irq: 0,
414 softirq: 516
415 }
416 );
417
418 let second = Stat::from_string("\
419cpu 598326 3695 207316 16449301 11326 0 5035 0 0 0
420cpu0 17756 59 5304 695144 394 0 2671 0 0 0
421cpu1 24815 195 5214 689481 343 0 281 0 0 0
422cpu2 23030 111 5271 691609 188 0 28 0 0 0
423cpu3 37215 147 7633 674968 428 0 23 0 0 0
424cpu4 35260 43 6956 677812 425 0 2 0 0 0
425cpu5 32865 364 7053 679702 371 0 25 0 0 0
426cpu6 15264 65 17016 681953 264 0 2 0 0 0
427cpu7 25513 94 15448 677409 368 0 30 0 0 0
428cpu8 23536 72 16582 678224 276 0 0 0 0 0
429cpu9 27646 68 5548 685186 406 0 1031 0 0 0
430cpu10 27508 495 5536 686719 309 0 0 0 0 0
431cpu11 25780 38 5424 688852 413 0 0 0 0 0
432cpu12 27720 133 5704 686025 849 0 0 0 0 0
433cpu13 25348 288 5167 689086 472 0 10 0 0 0
434cpu14 22885 160 5622 690560 608 0 287 0 0 0
435cpu15 25662 95 6380 688143 248 0 0 0 0 0
436cpu16 24917 118 7501 686875 852 0 106 0 0 0
437cpu17 24053 320 7208 688030 711 0 0 0 0 0
438cpu18 19499 154 16800 681362 768 0 128 0 0 0
439cpu19 21094 126 16548 680076 501 0 12 0 0 0
440cpu20 21863 58 17398 678483 597 0 14 0 0 0
441cpu21 23657 93 5421 691105 246 0 15 0 0 0
442cpu22 22550 310 5334 690909 719 0 358 0 0 0
443cpu23 22883 81 5240 691578 558 0 2 0 0 0
444intr 93982176 39 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 47273 0 21 658 0 0 0 0 0 0 0 462 0 520 0 0 0 0 0 0 0 0 0 0 0 0 0 67446 34716 59371 10575 28561 29891 81562 29376 1 0 0 0 0 0 0 0 718 0 0 0 0 0 0 0 0 0 0 0 0 23 94910 0 3608 3608 3608 3608 0 82604 0 0 0 0 0 0 0 127375 128843 23 60563 802 75923 571 96606 158 104005 128 94386 71 214 204 401 0 0 0 2973 0 5386 0 1757983 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
445ctxt 157231394
446btime 1698004999
447processes 93053
448procs_running 5
449procs_blocked 0
450softirq 19512683 120053 1138489 8 420631 143436 0 10350 10473743 18 7205955\n\
451 ".into());
452
453 let first_cpu = first.cpu().unwrap();
454 let second_cpu = second.cpu().unwrap();
455
456 let usage = second_cpu.usage(&first_cpu);
457 assert_eq!(usage, 0.04514286735257322);
458 }
459}