Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Protect against NaN and infinities better and in more places #311

Merged
merged 3 commits into from
Jul 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions src/ui/pages/cpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::ui::widgets::graph_box::ResGraphBox;
use crate::utils::cpu::{CpuData, CpuInfo};
use crate::utils::settings::SETTINGS;
use crate::utils::units::{convert_frequency, convert_temperature};
use crate::utils::{cpu, NaNDefault, NUM_CPUS};
use crate::utils::{cpu, FiniteOr, NUM_CPUS};

mod imp {
use std::cell::{Cell, RefCell};
Expand Down Expand Up @@ -347,7 +347,8 @@ impl ResCPU {
.saturating_sub(imp.old_total_usage.get().1);
let work_total_time = sum_total_delta.saturating_sub(idle_total_delta);

let total_fraction = ((work_total_time as f64) / (sum_total_delta as f64)).nan_default(0.0);
let total_fraction =
((work_total_time as f64) / (sum_total_delta as f64)).finite_or_default();

imp.total_cpu.graph().push_data_point(total_fraction);

Expand Down Expand Up @@ -375,7 +376,7 @@ impl ResCPU {
let work_thread_time = sum_thread_delta.saturating_sub(idle_thread_delta);
let curr_threadbox = &imp.thread_graphs.borrow()[i];
let thread_fraction =
((work_thread_time as f64) / (sum_thread_delta as f64)).nan_default(0.0);
((work_thread_time as f64) / (sum_thread_delta as f64)).finite_or_default();

curr_threadbox.graph().push_data_point(thread_fraction);
curr_threadbox.set_subtitle(&format!("{} %", (thread_fraction * 100.0).round()));
Expand Down
4 changes: 2 additions & 2 deletions src/ui/pages/gpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::config::PROFILE;
use crate::i18n::{i18n, i18n_f};
use crate::utils::gpu::{Gpu, GpuData};
use crate::utils::units::{convert_frequency, convert_power, convert_storage, convert_temperature};
use crate::utils::{pci, NaNDefault};
use crate::utils::{pci, FiniteOr};

mod imp {
use std::cell::{Cell, RefCell};
Expand Down Expand Up @@ -361,7 +361,7 @@ impl ResGPU {

let used_vram_fraction =
if let (Some(total_vram), Some(used_vram)) = (total_vram, used_vram) {
Some((*used_vram as f64 / *total_vram as f64).nan_default(0.0))
Some((*used_vram as f64 / *total_vram as f64).finite_or_default())
} else {
None
};
Expand Down
4 changes: 2 additions & 2 deletions src/ui/pages/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::config::PROFILE;
use crate::i18n::{i18n, i18n_f};
use crate::utils::memory::{self, MemoryData, MemoryDevice};
use crate::utils::units::convert_storage;
use crate::utils::NaNDefault;
use crate::utils::FiniteOr;

mod imp {
use std::cell::{Cell, RefCell};
Expand Down Expand Up @@ -331,7 +331,7 @@ impl ResMemory {
let used_swap = total_swap.saturating_sub(free_swap);

let memory_fraction = used_mem as f64 / total_mem as f64;
let swap_fraction = (used_swap as f64 / total_swap as f64).nan_default(0.0);
let swap_fraction = (used_swap as f64 / total_swap as f64).finite_or_default();

let formatted_used_mem = convert_storage(used_mem as f64, false);
let formatted_total_mem = convert_storage(total_mem as f64, false);
Expand Down
8 changes: 4 additions & 4 deletions src/utils/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use crate::i18n::i18n;
use super::{
boot_time,
process::{Process, ProcessAction},
NaNDefault,
FiniteOr,
};

// This contains executable names that are blacklisted from being recognized as applications
Expand Down Expand Up @@ -516,7 +516,7 @@ impl AppsContext {
} else {
((new.gfx.saturating_sub(old.gfx) as f32)
/ (timestamp.saturating_sub(timestamp_last) as f32))
.nan_default(0.0)
.finite_or_default()
/ 1_000_000.0
}
})
Expand Down Expand Up @@ -554,7 +554,7 @@ impl AppsContext {
} else {
((new.enc.saturating_sub(old.enc) as f32)
/ (timestamp.saturating_sub(timestamp_last) as f32))
.nan_default(0.0)
.finite_or_default()
/ 1_000_000.0
}
})
Expand Down Expand Up @@ -592,7 +592,7 @@ impl AppsContext {
} else {
((new.dec.saturating_sub(old.dec) as f32)
/ (timestamp.saturating_sub(timestamp_last) as f32))
.nan_default(0.0)
.finite_or_default()
/ 1_000_000.0
}
})
Expand Down
68 changes: 57 additions & 11 deletions src/utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,27 +83,73 @@ pub fn boot_time() -> Result<DateTime> {
})
}

pub trait NaNDefault {
/// Returns the given `default` value if the variable is NaN,
pub trait FiniteOr {
/// Returns the given `x` value if the variable is NaN or infinite,
/// and returns itself otherwise.
#[must_use]
fn nan_default(&self, default: Self) -> Self;
fn finite_or(&self, x: Self) -> Self;

/// Returns itself is the variable is finite (i.e. neither NaN nor infinite), otherwise returns its default
fn finite_or_default(&self) -> Self;

/// Returns itself is the variable is finite (i.e. neither NaN nor infinite), otherwise runs `f`
fn finite_or_else<F: FnOnce(Self) -> Self>(&self, f: F) -> Self
where
Self: Sized;
}

impl NaNDefault for f64 {
fn nan_default(&self, default: Self) -> Self {
if self.is_nan() {
default
impl FiniteOr for f64 {
fn finite_or(&self, x: Self) -> Self {
if !self.is_finite() {
x
} else {
*self
}
}

fn finite_or_default(&self) -> Self {
if !self.is_finite() {
Self::default()
} else {
*self
}
}

fn finite_or_else<F: FnOnce(Self) -> Self>(&self, f: F) -> Self
where
Self: Sized,
{
if !self.is_finite() {
f(*self)
} else {
*self
}
}
}

impl NaNDefault for f32 {
fn nan_default(&self, default: Self) -> Self {
if self.is_nan() {
default
impl FiniteOr for f32 {
fn finite_or(&self, x: Self) -> Self {
if !self.is_finite() {
x
} else {
*self
}
}

fn finite_or_default(&self) -> Self {
if !self.is_finite() {
Self::default()
} else {
*self
}
}

fn finite_or_else<F: FnOnce(Self) -> Self>(&self, f: F) -> Self
where
Self: Sized,
{
if !self.is_finite() {
f(*self)
} else {
*self
}
Expand Down
11 changes: 6 additions & 5 deletions src/utils/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use gtk::{
use crate::config;

use super::{
boot_time, NaNDefault, FLATPAK_APP_PATH, FLATPAK_SPAWN, IS_FLATPAK, NUM_CPUS, TICK_RATE,
boot_time, FiniteOr, FLATPAK_APP_PATH, FLATPAK_SPAWN, IS_FLATPAK, NUM_CPUS, TICK_RATE,
};

static OTHER_PROCESS: LazyLock<Mutex<(ChildStdin, ChildStdout)>> = LazyLock::new(|| {
Expand Down Expand Up @@ -270,7 +270,8 @@ impl Process {
* 1000.0;
let delta_time = self.data.timestamp.saturating_sub(self.timestamp_last);

delta_cpu_time / (delta_time * *TICK_RATE as u64 * *NUM_CPUS as u64) as f32
(delta_cpu_time / (delta_time * *TICK_RATE as u64 * *NUM_CPUS as u64) as f32)
.finite_or_default()
}
}

Expand Down Expand Up @@ -320,7 +321,7 @@ impl Process {
} else {
((usage.gfx.saturating_sub(old_usage.gfx) as f32)
/ (self.data.timestamp.saturating_sub(self.timestamp_last) as f32)
.nan_default(0.0))
.finite_or_default())
/ 1_000_000.0
};

Expand All @@ -345,7 +346,7 @@ impl Process {
} else {
((usage.enc.saturating_sub(old_usage.enc) as f32)
/ (self.data.timestamp.saturating_sub(self.timestamp_last) as f32)
.nan_default(0.0))
.finite_or_default())
/ 1_000_000.0
};

Expand All @@ -370,7 +371,7 @@ impl Process {
} else {
((usage.dec.saturating_sub(old_usage.dec) as f32)
/ (self.data.timestamp.saturating_sub(self.timestamp_last) as f32)
.nan_default(0.0))
.finite_or_default())
/ 1_000_000.0
};

Expand Down