refactor: Switch from fnv to fxhash (#444)

Switches to fxhash from fnv, which should be a bit faster.
This commit is contained in:
Clement Tsang 2021-04-04 20:48:19 -04:00 committed by GitHub
parent 476aaff45c
commit 405ce64a02
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 36 additions and 29 deletions

View File

@ -77,6 +77,7 @@
"fedoracentos",
"fpath",
"fract",
"fxhash",
"getpwuid",
"gnueabihf",
"gotop",

17
Cargo.lock generated
View File

@ -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"

View File

@ -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"

View File

@ -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<crate::Pid, processes::PrevProcDetails>,
pid_mapping: FxHashMap<crate::Pid, processes::PrevProcDetails>,
#[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")]

View File

@ -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<u32>, Option<u32>) {
#[allow(clippy::too_many_arguments)]
#[cfg(target_os = "linux")]
fn read_proc(
pid: Pid, cpu_usage: f64, cpu_fraction: f64,
pid_mapping: &mut FnvHashMap<Pid, PrevProcDetails>, 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<Pid, PrevProcDetails>,
use_current_cpu_total: bool, time_difference_in_secs: u64, mem_total_kb: u64,
page_file_kb: u64,
) -> error::Result<ProcessHarvest> {
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<Pid, PrevProcDetails>, use_current_cpu_total: bool,
pid_mapping: &mut FxHashMap<Pid, PrevProcDetails>, use_current_cpu_total: bool,
time_difference_in_secs: u64, mem_total_kb: u64, page_file_kb: u64,
) -> crate::utils::error::Result<Vec<ProcessHarvest>> {
// 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> = pid_mapping.keys().cloned().collect();
let mut pids_to_clear: FxHashSet<Pid> = pid_mapping.keys().cloned().collect();
let process_vector: Vec<ProcessHarvest> = std::fs::read_dir("/proc")?
.filter_map(|dir| {
if let Ok(dir) = dir {

View File

@ -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<Pid> =
let mut complete_pid_set: fxhash::FxHashSet<Pid> =
existing_converted_process_data.keys().copied().collect();
for process in &current_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<Pid, IndexSet<Pid>> = HashMap::default();
let mut parent_child_mapping: HashMap<Pid, IndexSet<Pid, FxBuildHasher>> = HashMap::default();
let mut pid_process_mapping: HashMap<Pid, &ConvertedProcessData> = HashMap::default(); // We actually already have this stored, but it's unfiltered... oh well.
let mut orphan_set: IndexSet<Pid> = IndexSet::new();
let mut collapsed_set: IndexSet<Pid> = IndexSet::new();
let mut orphan_set: IndexSet<Pid, FxBuildHasher> =
IndexSet::with_hasher(FxBuildHasher::default());
let mut collapsed_set: IndexSet<Pid, FxBuildHasher> =
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<Pid, IndexSet<Pid>>,
current_pid: Pid, parent_child_mapping: &mut HashMap<Pid, IndexSet<Pid, FxBuildHasher>>,
pid_process_mapping: &HashMap<Pid, &ConvertedProcessData>,
) -> 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<Pid, IndexSet<Pid>>,
parent_child_mapping: &mut HashMap<Pid, IndexSet<Pid, FxBuildHasher>>,
pid_process_mapping: &HashMap<Pid, &ConvertedProcessData>,
) {
// 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::<IndexSet<Pid>>();
.collect::<IndexSet<Pid, FxBuildHasher>>();
}
}
}
@ -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<Pid, IndexSet<Pid>>,
prev_drawn_lines: &str, collapsed_set: &IndexSet<Pid>,
current_pid: Pid, parent_child_mapping: &HashMap<Pid, IndexSet<Pid, FxBuildHasher>>,
prev_drawn_lines: &str, collapsed_set: &IndexSet<Pid, FxBuildHasher>,
) -> (Vec<Pid>, Vec<String>) {
let mut explored_pids: Vec<Pid> = vec![current_pid];
let mut lines: Vec<String> = vec![];
@ -1062,6 +1064,7 @@ pub fn tree_process_data(
&p.name
}
));
Some(p)
}
None => None,