From 405ce64a02fd55ebb383ce797910b2ec82dc97b4 Mon Sep 17 00:00:00 2001 From: Clement Tsang <34804052+ClementTsang@users.noreply.github.com> Date: Sun, 4 Apr 2021 20:48:19 -0400 Subject: [PATCH] refactor: Switch from fnv to fxhash (#444) Switches to fxhash from fnv, which should be a bit faster. --- .vscode/settings.json | 1 + Cargo.lock | 17 ++++++++++------- Cargo.toml | 2 +- src/app/data_harvester.rs | 6 +++--- src/app/data_harvester/processes.rs | 12 ++++++------ src/data_conversion.rs | 27 +++++++++++++++------------ 6 files changed, 36 insertions(+), 29 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index b6cc5b59..a5014719 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -77,6 +77,7 @@ "fedoracentos", "fpath", "fract", + "fxhash", "getpwuid", "gnueabihf", "gotop", diff --git a/Cargo.lock b/Cargo.lock index 0142d3bc..89f072c3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -248,9 +248,9 @@ dependencies = [ "ctrlc", "dirs-next", "fern", - "fnv", "futures", "futures-timer", + "fxhash", "heim", "indexmap", "itertools", @@ -551,12 +551,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - [[package]] name = "futures" version = "0.3.12" @@ -673,6 +667,15 @@ dependencies = [ "slab", ] +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + [[package]] name = "getrandom" version = "0.1.15" diff --git a/Cargo.toml b/Cargo.toml index ee88a928..108c3225 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,7 +43,7 @@ crossterm = "0.18.2" ctrlc = { version = "3.1", features = ["termination"] } clap = "2.33" dirs-next = "2.0.0" -fnv = "1.0.7" +fxhash = "0.2.1" futures = "0.3.12" indexmap = "~1.6" itertools = "0.10.0" diff --git a/src/app/data_harvester.rs b/src/app/data_harvester.rs index 207bb23a..989fcf6c 100644 --- a/src/app/data_harvester.rs +++ b/src/app/data_harvester.rs @@ -3,7 +3,7 @@ use std::time::Instant; #[cfg(target_os = "linux")] -use fnv::FnvHashMap; +use fxhash::FxHashMap; #[cfg(not(target_os = "linux"))] use sysinfo::{System, SystemExt}; @@ -85,7 +85,7 @@ pub struct DataCollector { #[cfg(target_os = "linux")] previous_average_cpu_time: Option<(cpu::PastCpuWork, cpu::PastCpuTotal)>, #[cfg(target_os = "linux")] - pid_mapping: FnvHashMap, + pid_mapping: FxHashMap, #[cfg(target_os = "linux")] prev_idle: f64, #[cfg(target_os = "linux")] @@ -116,7 +116,7 @@ impl DataCollector { #[cfg(target_os = "linux")] previous_average_cpu_time: None, #[cfg(target_os = "linux")] - pid_mapping: FnvHashMap::default(), + pid_mapping: FxHashMap::default(), #[cfg(target_os = "linux")] prev_idle: 0_f64, #[cfg(target_os = "linux")] diff --git a/src/app/data_harvester/processes.rs b/src/app/data_harvester/processes.rs index 52e80c27..e2efea79 100644 --- a/src/app/data_harvester/processes.rs +++ b/src/app/data_harvester/processes.rs @@ -12,7 +12,7 @@ use crate::utils::error; use crate::utils::error::BottomError; #[cfg(target_os = "linux")] -use fnv::{FnvHashMap, FnvHashSet}; +use fxhash::{FxHashMap, FxHashSet}; #[cfg(not(target_os = "linux"))] use sysinfo::{ProcessExt, ProcessorExt, System, SystemExt}; @@ -338,9 +338,9 @@ fn get_uid_and_gid(path: &Path) -> (Option, Option) { #[allow(clippy::too_many_arguments)] #[cfg(target_os = "linux")] fn read_proc( - pid: Pid, cpu_usage: f64, cpu_fraction: f64, - pid_mapping: &mut FnvHashMap, use_current_cpu_total: bool, - time_difference_in_secs: u64, mem_total_kb: u64, page_file_kb: u64, + pid: Pid, cpu_usage: f64, cpu_fraction: f64, pid_mapping: &mut FxHashMap, + use_current_cpu_total: bool, time_difference_in_secs: u64, mem_total_kb: u64, + page_file_kb: u64, ) -> error::Result { use std::io::prelude::*; use std::io::BufReader; @@ -491,13 +491,13 @@ fn read_proc( #[cfg(target_os = "linux")] pub fn get_process_data( prev_idle: &mut f64, prev_non_idle: &mut f64, - pid_mapping: &mut FnvHashMap, use_current_cpu_total: bool, + pid_mapping: &mut FxHashMap, use_current_cpu_total: bool, time_difference_in_secs: u64, mem_total_kb: u64, page_file_kb: u64, ) -> crate::utils::error::Result> { // TODO: [PROC THREADS] Add threads if let Ok((cpu_usage, cpu_fraction)) = cpu_usage_calculation(prev_idle, prev_non_idle) { - let mut pids_to_clear: FnvHashSet = pid_mapping.keys().cloned().collect(); + let mut pids_to_clear: FxHashSet = pid_mapping.keys().cloned().collect(); let process_vector: Vec = std::fs::read_dir("/proc")? .filter_map(|dir| { if let Ok(dir) = dir { diff --git a/src/data_conversion.rs b/src/data_conversion.rs index d407f827..884bd2a7 100644 --- a/src/data_conversion.rs +++ b/src/data_conversion.rs @@ -6,6 +6,7 @@ use crate::{ utils::{self, gen_util::*}, }; use data_harvester::processes::ProcessSorting; +use fxhash::FxBuildHasher; use indexmap::IndexSet; use std::collections::{HashMap, VecDeque}; @@ -584,7 +585,7 @@ pub fn convert_process_data( // TODO [THREAD]: Thread highlighting and hiding support // For macOS see https://github.com/hishamhm/htop/pull/848/files - let mut complete_pid_set: fnv::FnvHashSet = + let mut complete_pid_set: fxhash::FxHashSet = existing_converted_process_data.keys().copied().collect(); for process in ¤t_data.process_harvest { @@ -724,10 +725,12 @@ pub fn tree_process_data( // Let's first build up a (really terrible) parent -> child mapping... // At the same time, let's make a mapping of PID -> process data! - let mut parent_child_mapping: HashMap> = HashMap::default(); + let mut parent_child_mapping: HashMap> = HashMap::default(); let mut pid_process_mapping: HashMap = HashMap::default(); // We actually already have this stored, but it's unfiltered... oh well. - let mut orphan_set: IndexSet = IndexSet::new(); - let mut collapsed_set: IndexSet = IndexSet::new(); + let mut orphan_set: IndexSet = + IndexSet::with_hasher(FxBuildHasher::default()); + let mut collapsed_set: IndexSet = + IndexSet::with_hasher(FxBuildHasher::default()); filtered_process_data.iter().for_each(|process| { if let Some(ppid) = process.ppid { @@ -740,7 +743,7 @@ pub fn tree_process_data( // Create a mapping for the process if it DNE. parent_child_mapping .entry(process.pid) - .or_insert_with(IndexSet::new); + .or_insert_with(|| IndexSet::with_hasher(FxBuildHasher::default())); pid_process_mapping.insert(process.pid, process); if process.is_collapsed_entry { @@ -752,7 +755,7 @@ pub fn tree_process_data( orphan_set.remove(&process.pid); parent_child_mapping .entry(ppid) - .or_insert_with(IndexSet::new) + .or_insert_with(|| IndexSet::with_hasher(FxBuildHasher::default())) .insert(process.pid); } }); @@ -777,10 +780,9 @@ pub fn tree_process_data( /// A post-order traversal to correctly prune entire branches that only contain children /// that are disabled and themselves are also disabled ~~wait that sounds wrong~~. - /// /// Basically, go through the hashmap, and prune out all branches that are no longer relevant. fn prune_disabled_pids( - current_pid: Pid, parent_child_mapping: &mut HashMap>, + current_pid: Pid, parent_child_mapping: &mut HashMap>, pid_process_mapping: &HashMap, ) -> bool { // Let's explore all the children first, and make sure they (and their children) @@ -816,7 +818,7 @@ pub fn tree_process_data( fn sort_remaining_pids( current_pid: Pid, sort_type: &ProcessSorting, is_sort_descending: bool, - parent_child_mapping: &mut HashMap>, + parent_child_mapping: &mut HashMap>, pid_process_mapping: &HashMap, ) { // Sorting is special for tree data. So, by default, things are "sorted" @@ -855,7 +857,7 @@ pub fn tree_process_data( .iter() .rev() .map(|(pid, _proc)| *pid) - .collect::>(); + .collect::>(); } } } @@ -964,8 +966,8 @@ pub fn tree_process_data( /// A DFS traversal to correctly build the prefix lines (the pretty '├' and '─' lines) and /// the correct order to the PID tree as a vector. fn build_explored_pids( - current_pid: Pid, parent_child_mapping: &HashMap>, - prev_drawn_lines: &str, collapsed_set: &IndexSet, + current_pid: Pid, parent_child_mapping: &HashMap>, + prev_drawn_lines: &str, collapsed_set: &IndexSet, ) -> (Vec, Vec) { let mut explored_pids: Vec = vec![current_pid]; let mut lines: Vec = vec![]; @@ -1062,6 +1064,7 @@ pub fn tree_process_data( &p.name } )); + Some(p) } None => None,