@@ -36,40 +36,42 @@ impl PrevProcDetails {
36
36
}
37
37
}
38
38
39
+ fn calculate_idle_values ( line : String ) -> ( f64 , f64 ) {
40
+ /// Converts a `Option<&str>` value to an f64. If it fails to parse or is `None`, then it will return `0_f64`.
41
+ fn str_to_f64 ( val : Option < & str > ) -> f64 {
42
+ val. and_then ( |v| v. parse :: < f64 > ( ) . ok ( ) ) . unwrap_or ( 0_f64 )
43
+ }
44
+
45
+ let mut val = line. split_whitespace ( ) ;
46
+ let user = str_to_f64 ( val. next ( ) ) ;
47
+ let nice: f64 = str_to_f64 ( val. next ( ) ) ;
48
+ let system: f64 = str_to_f64 ( val. next ( ) ) ;
49
+ let idle: f64 = str_to_f64 ( val. next ( ) ) ;
50
+ let iowait: f64 = str_to_f64 ( val. next ( ) ) ;
51
+ let irq: f64 = str_to_f64 ( val. next ( ) ) ;
52
+ let softirq: f64 = str_to_f64 ( val. next ( ) ) ;
53
+ let steal: f64 = str_to_f64 ( val. next ( ) ) ;
54
+
55
+ // Note we do not get guest/guest_nice, as they are calculated as part of user/nice respectively
56
+
57
+ let idle = idle + iowait;
58
+ let non_idle = user + nice + system + irq + softirq + steal;
59
+
60
+ ( idle, non_idle)
61
+ }
62
+
39
63
fn cpu_usage_calculation (
40
64
prev_idle : & mut f64 , prev_non_idle : & mut f64 ,
41
65
) -> error:: Result < ( f64 , f64 ) > {
42
66
use std:: io:: prelude:: * ;
43
67
use std:: io:: BufReader ;
44
68
45
69
// From SO answer: https://stackoverflow.com/a/23376195
46
-
47
70
let mut reader = BufReader :: new ( std:: fs:: File :: open ( "/proc/stat" ) ?) ;
48
71
let mut first_line = String :: new ( ) ;
49
72
reader. read_line ( & mut first_line) ?;
50
73
51
- let val = first_line. split_whitespace ( ) . collect :: < Vec < & str > > ( ) ;
52
-
53
- // SC in case that the parsing will fail due to length:
54
- if val. len ( ) <= 10 {
55
- return Err ( error:: BottomError :: InvalidIo ( format ! (
56
- "CPU parsing will fail due to too short of a return value; saw {} values, expected 10 values." ,
57
- val. len( )
58
- ) ) ) ;
59
- }
60
-
61
- let user: f64 = val[ 1 ] . parse :: < _ > ( ) . unwrap_or ( 0_f64 ) ;
62
- let nice: f64 = val[ 2 ] . parse :: < _ > ( ) . unwrap_or ( 0_f64 ) ;
63
- let system: f64 = val[ 3 ] . parse :: < _ > ( ) . unwrap_or ( 0_f64 ) ;
64
- let idle: f64 = val[ 4 ] . parse :: < _ > ( ) . unwrap_or ( 0_f64 ) ;
65
- let iowait: f64 = val[ 5 ] . parse :: < _ > ( ) . unwrap_or ( 0_f64 ) ;
66
- let irq: f64 = val[ 6 ] . parse :: < _ > ( ) . unwrap_or ( 0_f64 ) ;
67
- let softirq: f64 = val[ 7 ] . parse :: < _ > ( ) . unwrap_or ( 0_f64 ) ;
68
- let steal: f64 = val[ 8 ] . parse :: < _ > ( ) . unwrap_or ( 0_f64 ) ;
69
- let guest: f64 = val[ 9 ] . parse :: < _ > ( ) . unwrap_or ( 0_f64 ) ;
70
-
71
- let idle = idle + iowait;
72
- let non_idle = user + nice + system + irq + softirq + steal + guest;
74
+ let ( idle, non_idle) = calculate_idle_values ( first_line) ;
73
75
74
76
let total = idle + non_idle;
75
77
let prev_total = * prev_idle + * prev_non_idle;
@@ -294,3 +296,47 @@ pub fn get_process_data(
294
296
) )
295
297
}
296
298
}
299
+
300
+ #[ cfg( test) ]
301
+ mod tests {
302
+ use super :: * ;
303
+
304
+ #[ test]
305
+ fn test_proc_cpu_parse ( ) {
306
+ assert_eq ! (
307
+ ( 100_f64 , 200_f64 ) ,
308
+ calculate_idle_values( "100 0 100 100" . to_string( ) ) ,
309
+ "Failed to properly calculate idle/non-idle for /proc/stat CPU with 4 values"
310
+ ) ;
311
+ assert_eq ! (
312
+ ( 120_f64 , 200_f64 ) ,
313
+ calculate_idle_values( "100 0 100 100 20" . to_string( ) ) ,
314
+ "Failed to properly calculate idle/non-idle for /proc/stat CPU with 5 values"
315
+ ) ;
316
+ assert_eq ! (
317
+ ( 120_f64 , 230_f64 ) ,
318
+ calculate_idle_values( "100 0 100 100 20 30" . to_string( ) ) ,
319
+ "Failed to properly calculate idle/non-idle for /proc/stat CPU with 6 values"
320
+ ) ;
321
+ assert_eq ! (
322
+ ( 120_f64 , 270_f64 ) ,
323
+ calculate_idle_values( "100 0 100 100 20 30 40" . to_string( ) ) ,
324
+ "Failed to properly calculate idle/non-idle for /proc/stat CPU with 7 values"
325
+ ) ;
326
+ assert_eq ! (
327
+ ( 120_f64 , 320_f64 ) ,
328
+ calculate_idle_values( "100 0 100 100 20 30 40 50" . to_string( ) ) ,
329
+ "Failed to properly calculate idle/non-idle for /proc/stat CPU with 8 values"
330
+ ) ;
331
+ assert_eq ! (
332
+ ( 120_f64 , 320_f64 ) ,
333
+ calculate_idle_values( "100 0 100 100 20 30 40 50 100" . to_string( ) ) ,
334
+ "Failed to properly calculate idle/non-idle for /proc/stat CPU with 9 values"
335
+ ) ;
336
+ assert_eq ! (
337
+ ( 120_f64 , 320_f64 ) ,
338
+ calculate_idle_values( "100 0 100 100 20 30 40 50 100 200" . to_string( ) ) ,
339
+ "Failed to properly calculate idle/non-idle for /proc/stat CPU with 10 values"
340
+ ) ;
341
+ }
342
+ }
0 commit comments