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