Repository: GuillaumeGomez/sysinfo (Rust)

Issue:
Process cpu_usage() returns NaN in some cases
Hello,
I'm using `sysinfo` on version `0.15.2` on Linux mint 19.
`cargo -V` outputs `cargo 1.46.0 (149022b1d 2020-07-17)`.
`rustc -V` outputs `rustc 1.46.0 (04488afe3 2020-08-24)`.

When `system.refresh_process(pid)` is called too often, the cpu_usage() of this process becomes NaN (or sometimes inf).
I have tried to understand where is this comes from, and I think that the bug is in `system.rs`, in the function `refresh_process` (line 380):
```
let total_time = (if old > new { 1 } else { new - old }) as f32;
```
If by any chance `new == old`, then `total_time` would be zero. 
`total_time` is then sent as an argument to `compute_cpu_usage`, which uses it in the denominator.

The code to reproduce:
```
fn main() {
    let mut system: System = System::new();
    system.refresh_processes();

    let first_5_pids: Vec<Pid> = system.get_processes()
        .iter()
        .take(5)
        .map(|(pid, _)| *pid as Pid)
        .collect::<Vec<Pid>>();

    first_5_pids.iter().for_each(|pid| {
        system.refresh_process(*pid as Pid);
        let proc = system.get_process(*pid as Pid).unwrap();
        println!("pid: {}, cpu: {}", proc.pid(), proc.cpu_usage());
    });
}
```

the output is as follows:
```
pid: 673, cpu: 0
pid: 1736, cpu: NaN
pid: 58, cpu: NaN
pid: 684, cpu: NaN
pid: 52, cpu: NaN
```


Discussion:
This is indeed where the bug is coming from. However, I'm not too aware on how to compare floats and check if they're equal. If you have any directions, it'd be awesome! (You can also send a PR if you want to go faster :wink: ).
I appreciate the quick reply :) 
there are some crates that handle this, like [float_cmp](https://docs.rs/float-cmp/0.8.0/float_cmp/). Alternatively, you can use `round()` or something like that.

I don't know if I will have the time to send a PR though.

Best regards
I'd rather not add a dependency for such a specific case. I can always add a precision level to perform the comparison though.
I think the best practice is to `abs` the 2 floats, `abs` the difference and check if its smaller than `std::f64:: EPSILON` for example
I published the new version.



Patch:
diff --git a/Cargo.toml b/Cargo.toml
index 105770ad4..397cdb52a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sysinfo"
-version = "0.15.2"
+version = "0.15.3"
 authors = ["Guillaume Gomez <guillaume1.gomez@gmail.com>"]
 
 description = "Library to get system information such as processes, processors, disks, components and networks"
diff --git a/src/linux/system.rs b/src/linux/system.rs
index 22e0bfc2a..befd4c870 100644
--- a/src/linux/system.rs
+++ b/src/linux/system.rs
@@ -377,7 +377,7 @@ impl SystemExt for System {
         if found && !self.processors.is_empty() {
             self.refresh_processors(Some(1));
             let (new, old) = get_raw_times(&self.global_processor);
-            let total_time = (if old > new { 1 } else { new - old }) as f32;
+            let total_time = (if old >= new { 1 } else { new - old }) as f32;
 
             if let Some(p) = self.process_list.tasks.get_mut(&pid) {
                 compute_cpu_usage(p, self.processors.len() as u64, total_time);
diff --git a/src/windows/process.rs b/src/windows/process.rs
index a6d7e91f2..57701fdbc 100644
--- a/src/windows/process.rs
+++ b/src/windows/process.rs
@@ -739,9 +739,10 @@ pub(crate) fn compute_cpu_usage(p: &mut Process, nb_processors: u64, now: ULARGE
             &mut fuser as *mut FILETIME as *mut c_void,
             size_of::<FILETIME>(),
         );
+        let old = check_sub(*now.QuadPart(), p.old_cpu);
         p.cpu_usage = (check_sub(*sys.QuadPart(), p.old_sys_cpu) as f32
             + check_sub(*user.QuadPart(), p.old_user_cpu) as f32)
-            / check_sub(*now.QuadPart(), p.old_cpu) as f32
+            / if old == 0 { 1 } else { old } as f32
             / nb_processors as f32
             * 100.;
         p.old_cpu = *now.QuadPart();


Test patch:
diff --git a/tests/process.rs b/tests/process.rs
index 9df22dc73..265b9fac6 100644
--- a/tests/process.rs
+++ b/tests/process.rs
@@ -104,3 +104,25 @@ fn test_process_disk_usage() {
         p.disk_usage().written_bytes
     );
 }
+
+#[test]
+fn cpu_usage_is_not_nan() {
+    let mut system = sysinfo::System::new();
+    system.refresh_processes();
+
+    let first_pids = system.get_processes()
+        .iter()
+        .take(10)
+        .map(|(&pid, _)| pid)
+        .collect::<Vec<_>>();
+    let mut checked = 0;
+
+    first_pids.into_iter().for_each(|pid| {
+        system.refresh_process(pid);
+        if let Some(p) = system.get_process(pid) {
+            assert!(!p.cpu_usage().is_nan());
+            checked += 1;
+        }
+    });
+    assert!(checked > 0);
+}