mirror of
https://github.com/ClementTsang/bottom.git
synced 2025-07-23 13:45:12 +02:00
refactor: Switch from fnv to fxhash (#444)
Switches to fxhash from fnv, which should be a bit faster.
This commit is contained in:
parent
476aaff45c
commit
405ce64a02
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
@ -77,6 +77,7 @@
|
|||||||
"fedoracentos",
|
"fedoracentos",
|
||||||
"fpath",
|
"fpath",
|
||||||
"fract",
|
"fract",
|
||||||
|
"fxhash",
|
||||||
"getpwuid",
|
"getpwuid",
|
||||||
"gnueabihf",
|
"gnueabihf",
|
||||||
"gotop",
|
"gotop",
|
||||||
|
17
Cargo.lock
generated
17
Cargo.lock
generated
@ -248,9 +248,9 @@ dependencies = [
|
|||||||
"ctrlc",
|
"ctrlc",
|
||||||
"dirs-next",
|
"dirs-next",
|
||||||
"fern",
|
"fern",
|
||||||
"fnv",
|
|
||||||
"futures",
|
"futures",
|
||||||
"futures-timer",
|
"futures-timer",
|
||||||
|
"fxhash",
|
||||||
"heim",
|
"heim",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"itertools",
|
"itertools",
|
||||||
@ -551,12 +551,6 @@ dependencies = [
|
|||||||
"num-traits",
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "fnv"
|
|
||||||
version = "1.0.7"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures"
|
name = "futures"
|
||||||
version = "0.3.12"
|
version = "0.3.12"
|
||||||
@ -673,6 +667,15 @@ dependencies = [
|
|||||||
"slab",
|
"slab",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fxhash"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.1.15"
|
version = "0.1.15"
|
||||||
|
@ -43,7 +43,7 @@ crossterm = "0.18.2"
|
|||||||
ctrlc = { version = "3.1", features = ["termination"] }
|
ctrlc = { version = "3.1", features = ["termination"] }
|
||||||
clap = "2.33"
|
clap = "2.33"
|
||||||
dirs-next = "2.0.0"
|
dirs-next = "2.0.0"
|
||||||
fnv = "1.0.7"
|
fxhash = "0.2.1"
|
||||||
futures = "0.3.12"
|
futures = "0.3.12"
|
||||||
indexmap = "~1.6"
|
indexmap = "~1.6"
|
||||||
itertools = "0.10.0"
|
itertools = "0.10.0"
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
use fnv::FnvHashMap;
|
use fxhash::FxHashMap;
|
||||||
|
|
||||||
#[cfg(not(target_os = "linux"))]
|
#[cfg(not(target_os = "linux"))]
|
||||||
use sysinfo::{System, SystemExt};
|
use sysinfo::{System, SystemExt};
|
||||||
@ -85,7 +85,7 @@ pub struct DataCollector {
|
|||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
previous_average_cpu_time: Option<(cpu::PastCpuWork, cpu::PastCpuTotal)>,
|
previous_average_cpu_time: Option<(cpu::PastCpuWork, cpu::PastCpuTotal)>,
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
pid_mapping: FnvHashMap<crate::Pid, processes::PrevProcDetails>,
|
pid_mapping: FxHashMap<crate::Pid, processes::PrevProcDetails>,
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
prev_idle: f64,
|
prev_idle: f64,
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
@ -116,7 +116,7 @@ impl DataCollector {
|
|||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
previous_average_cpu_time: None,
|
previous_average_cpu_time: None,
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
pid_mapping: FnvHashMap::default(),
|
pid_mapping: FxHashMap::default(),
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
prev_idle: 0_f64,
|
prev_idle: 0_f64,
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
|
@ -12,7 +12,7 @@ use crate::utils::error;
|
|||||||
use crate::utils::error::BottomError;
|
use crate::utils::error::BottomError;
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
use fnv::{FnvHashMap, FnvHashSet};
|
use fxhash::{FxHashMap, FxHashSet};
|
||||||
|
|
||||||
#[cfg(not(target_os = "linux"))]
|
#[cfg(not(target_os = "linux"))]
|
||||||
use sysinfo::{ProcessExt, ProcessorExt, System, SystemExt};
|
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)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
fn read_proc(
|
fn read_proc(
|
||||||
pid: Pid, cpu_usage: f64, cpu_fraction: f64,
|
pid: Pid, cpu_usage: f64, cpu_fraction: f64, pid_mapping: &mut FxHashMap<Pid, PrevProcDetails>,
|
||||||
pid_mapping: &mut FnvHashMap<Pid, PrevProcDetails>, use_current_cpu_total: bool,
|
use_current_cpu_total: bool, time_difference_in_secs: u64, mem_total_kb: u64,
|
||||||
time_difference_in_secs: u64, mem_total_kb: u64, page_file_kb: u64,
|
page_file_kb: u64,
|
||||||
) -> error::Result<ProcessHarvest> {
|
) -> error::Result<ProcessHarvest> {
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::io::BufReader;
|
use std::io::BufReader;
|
||||||
@ -491,13 +491,13 @@ fn read_proc(
|
|||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
pub fn get_process_data(
|
pub fn get_process_data(
|
||||||
prev_idle: &mut f64, prev_non_idle: &mut f64,
|
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,
|
time_difference_in_secs: u64, mem_total_kb: u64, page_file_kb: u64,
|
||||||
) -> crate::utils::error::Result<Vec<ProcessHarvest>> {
|
) -> crate::utils::error::Result<Vec<ProcessHarvest>> {
|
||||||
// TODO: [PROC THREADS] Add threads
|
// TODO: [PROC THREADS] Add threads
|
||||||
|
|
||||||
if let Ok((cpu_usage, cpu_fraction)) = cpu_usage_calculation(prev_idle, prev_non_idle) {
|
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")?
|
let process_vector: Vec<ProcessHarvest> = std::fs::read_dir("/proc")?
|
||||||
.filter_map(|dir| {
|
.filter_map(|dir| {
|
||||||
if let Ok(dir) = dir {
|
if let Ok(dir) = dir {
|
||||||
|
@ -6,6 +6,7 @@ use crate::{
|
|||||||
utils::{self, gen_util::*},
|
utils::{self, gen_util::*},
|
||||||
};
|
};
|
||||||
use data_harvester::processes::ProcessSorting;
|
use data_harvester::processes::ProcessSorting;
|
||||||
|
use fxhash::FxBuildHasher;
|
||||||
use indexmap::IndexSet;
|
use indexmap::IndexSet;
|
||||||
use std::collections::{HashMap, VecDeque};
|
use std::collections::{HashMap, VecDeque};
|
||||||
|
|
||||||
@ -584,7 +585,7 @@ pub fn convert_process_data(
|
|||||||
// TODO [THREAD]: Thread highlighting and hiding support
|
// TODO [THREAD]: Thread highlighting and hiding support
|
||||||
// For macOS see https://github.com/hishamhm/htop/pull/848/files
|
// 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();
|
existing_converted_process_data.keys().copied().collect();
|
||||||
|
|
||||||
for process in ¤t_data.process_harvest {
|
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...
|
// Let's first build up a (really terrible) parent -> child mapping...
|
||||||
// At the same time, let's make a mapping of PID -> process data!
|
// 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 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 orphan_set: IndexSet<Pid, FxBuildHasher> =
|
||||||
let mut collapsed_set: IndexSet<Pid> = IndexSet::new();
|
IndexSet::with_hasher(FxBuildHasher::default());
|
||||||
|
let mut collapsed_set: IndexSet<Pid, FxBuildHasher> =
|
||||||
|
IndexSet::with_hasher(FxBuildHasher::default());
|
||||||
|
|
||||||
filtered_process_data.iter().for_each(|process| {
|
filtered_process_data.iter().for_each(|process| {
|
||||||
if let Some(ppid) = process.ppid {
|
if let Some(ppid) = process.ppid {
|
||||||
@ -740,7 +743,7 @@ pub fn tree_process_data(
|
|||||||
// Create a mapping for the process if it DNE.
|
// Create a mapping for the process if it DNE.
|
||||||
parent_child_mapping
|
parent_child_mapping
|
||||||
.entry(process.pid)
|
.entry(process.pid)
|
||||||
.or_insert_with(IndexSet::new);
|
.or_insert_with(|| IndexSet::with_hasher(FxBuildHasher::default()));
|
||||||
pid_process_mapping.insert(process.pid, process);
|
pid_process_mapping.insert(process.pid, process);
|
||||||
|
|
||||||
if process.is_collapsed_entry {
|
if process.is_collapsed_entry {
|
||||||
@ -752,7 +755,7 @@ pub fn tree_process_data(
|
|||||||
orphan_set.remove(&process.pid);
|
orphan_set.remove(&process.pid);
|
||||||
parent_child_mapping
|
parent_child_mapping
|
||||||
.entry(ppid)
|
.entry(ppid)
|
||||||
.or_insert_with(IndexSet::new)
|
.or_insert_with(|| IndexSet::with_hasher(FxBuildHasher::default()))
|
||||||
.insert(process.pid);
|
.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
|
/// 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~~.
|
/// 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.
|
/// Basically, go through the hashmap, and prune out all branches that are no longer relevant.
|
||||||
fn prune_disabled_pids(
|
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>,
|
pid_process_mapping: &HashMap<Pid, &ConvertedProcessData>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
// Let's explore all the children first, and make sure they (and their children)
|
// 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(
|
fn sort_remaining_pids(
|
||||||
current_pid: Pid, sort_type: &ProcessSorting, is_sort_descending: bool,
|
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>,
|
pid_process_mapping: &HashMap<Pid, &ConvertedProcessData>,
|
||||||
) {
|
) {
|
||||||
// Sorting is special for tree data. So, by default, things are "sorted"
|
// Sorting is special for tree data. So, by default, things are "sorted"
|
||||||
@ -855,7 +857,7 @@ pub fn tree_process_data(
|
|||||||
.iter()
|
.iter()
|
||||||
.rev()
|
.rev()
|
||||||
.map(|(pid, _proc)| *pid)
|
.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
|
/// A DFS traversal to correctly build the prefix lines (the pretty '├' and '─' lines) and
|
||||||
/// the correct order to the PID tree as a vector.
|
/// the correct order to the PID tree as a vector.
|
||||||
fn build_explored_pids(
|
fn build_explored_pids(
|
||||||
current_pid: Pid, parent_child_mapping: &HashMap<Pid, IndexSet<Pid>>,
|
current_pid: Pid, parent_child_mapping: &HashMap<Pid, IndexSet<Pid, FxBuildHasher>>,
|
||||||
prev_drawn_lines: &str, collapsed_set: &IndexSet<Pid>,
|
prev_drawn_lines: &str, collapsed_set: &IndexSet<Pid, FxBuildHasher>,
|
||||||
) -> (Vec<Pid>, Vec<String>) {
|
) -> (Vec<Pid>, Vec<String>) {
|
||||||
let mut explored_pids: Vec<Pid> = vec![current_pid];
|
let mut explored_pids: Vec<Pid> = vec![current_pid];
|
||||||
let mut lines: Vec<String> = vec![];
|
let mut lines: Vec<String> = vec![];
|
||||||
@ -1062,6 +1064,7 @@ pub fn tree_process_data(
|
|||||||
&p.name
|
&p.name
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
|
||||||
Some(p)
|
Some(p)
|
||||||
}
|
}
|
||||||
None => None,
|
None => None,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user