deps: Switch to using hashbrown for general hashmap usage (#1092)

* deps: replace fxhash with hashbrown + ahash

* replace std hashmap with hashbrown + ahash

* fmt

* some more fmt
This commit is contained in:
Clement Tsang 2023-04-12 00:03:27 -04:00 committed by GitHub
parent 857b5bade0
commit e61e5f2af6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 75 additions and 64 deletions

39
Cargo.lock generated
View File

@ -17,6 +17,17 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "ahash"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f"
dependencies = [
"cfg-if",
"once_cell",
"version_check",
]
[[package]] [[package]]
name = "aho-corasick" name = "aho-corasick"
version = "0.7.18" version = "0.7.18"
@ -111,7 +122,7 @@ dependencies = [
"dirs", "dirs",
"fern", "fern",
"filedescriptor", "filedescriptor",
"fxhash", "hashbrown 0.13.2",
"humantime", "humantime",
"humantime-serde", "humantime-serde",
"indexmap", "indexmap",
@ -522,15 +533,6 @@ version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[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.2.6" version = "0.2.6"
@ -554,6 +556,15 @@ version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]]
name = "hashbrown"
version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e"
dependencies = [
"ahash",
]
[[package]] [[package]]
name = "heck" name = "heck"
version = "0.4.1" version = "0.4.1"
@ -604,7 +615,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"hashbrown", "hashbrown 0.12.3",
] ]
[[package]] [[package]]
@ -1379,6 +1390,12 @@ dependencies = [
"typenum", "typenum",
] ]
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]] [[package]]
name = "wait-timeout" name = "wait-timeout"
version = "0.2.0" version = "0.2.0"

View File

@ -83,7 +83,7 @@ ctrlc = { version = "3.2.5", features = ["termination"] }
# dhat = "0.3.2" # dhat = "0.3.2"
dirs = "5.0.0" dirs = "5.0.0"
fern = { version = "0.6.2", optional = true } fern = { version = "0.6.2", optional = true }
fxhash = "0.2.1" hashbrown = "0.13.2"
humantime = "2.1.0" humantime = "2.1.0"
humantime-serde = "1.1.1" humantime-serde = "1.1.1"
indexmap = "1.9.3" indexmap = "1.9.3"

View File

@ -1,6 +1,5 @@
use std::{ use std::{
cmp::{max, min}, cmp::{max, min},
collections::HashMap,
time::Instant, time::Instant,
}; };
@ -8,6 +7,7 @@ use concat_string::concat_string;
use data_farmer::*; use data_farmer::*;
use data_harvester::temperature; use data_harvester::temperature;
use filter::*; use filter::*;
use hashbrown::HashMap;
use layout_manager::*; use layout_manager::*;
pub use states::*; pub use states::*;
use typed_builder::*; use typed_builder::*;

View File

@ -15,7 +15,7 @@
use std::{collections::BTreeMap, time::Instant, vec::Vec}; use std::{collections::BTreeMap, time::Instant, vec::Vec};
use fxhash::FxHashMap; use hashbrown::HashMap;
#[cfg(feature = "battery")] #[cfg(feature = "battery")]
use crate::data_harvester::batteries; use crate::data_harvester::batteries;
@ -48,7 +48,7 @@ pub struct ProcessData {
pub process_harvest: BTreeMap<Pid, ProcessHarvest>, pub process_harvest: BTreeMap<Pid, ProcessHarvest>,
/// A mapping between a process PID to any children process PIDs. /// A mapping between a process PID to any children process PIDs.
pub process_parent_mapping: FxHashMap<Pid, Vec<Pid>>, pub process_parent_mapping: HashMap<Pid, Vec<Pid>>,
/// PIDs corresponding to processes that have no parents. /// PIDs corresponding to processes that have no parents.
pub orphan_pids: Vec<Pid>, pub orphan_pids: Vec<Pid>,

View File

@ -3,15 +3,12 @@
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
use fxhash::FxHashMap; use hashbrown::HashMap;
#[cfg(feature = "battery")] #[cfg(feature = "battery")]
use starship_battery::{Battery, Manager}; use starship_battery::{Battery, Manager};
use sysinfo::{System, SystemExt}; use sysinfo::{System, SystemExt};
use self::temperature::TemperatureType; use self::temperature::TemperatureType;
use super::DataFilters; use super::DataFilters;
use crate::app::layout_manager::UsedWidgets; use crate::app::layout_manager::UsedWidgets;
@ -111,7 +108,7 @@ pub struct DataCollector {
filters: DataFilters, filters: DataFilters,
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
pid_mapping: FxHashMap<crate::Pid, processes::PrevProcDetails>, pid_mapping: HashMap<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")]
@ -132,7 +129,7 @@ impl DataCollector {
data: Data::default(), data: Data::default(),
sys: System::new_with_specifics(sysinfo::RefreshKind::new()), sys: System::new_with_specifics(sysinfo::RefreshKind::new()),
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
pid_mapping: FxHashMap::default(), pid_mapping: HashMap::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")]

View File

@ -1,9 +1,9 @@
//! Data collection about disks (e.g. I/O, usage, space). //! Data collection about disks (e.g. I/O, usage, space).
use std::collections::HashMap; use cfg_if::cfg_if;
use hashbrown::HashMap;
use crate::app::filter::Filter; use crate::app::filter::Filter;
use cfg_if::cfg_if;
cfg_if! { cfg_if! {
if #[cfg(target_os = "freebsd")] { if #[cfg(target_os = "freebsd")] {
@ -114,9 +114,8 @@ pub(self) fn keep_disk_entry(
mod test { mod test {
use regex::Regex; use regex::Regex;
use crate::app::filter::Filter;
use super::keep_disk_entry; use super::keep_disk_entry;
use crate::app::filter::Filter;
fn run_filter(disk_filter: &Option<Filter>, mount_filter: &Option<Filter>) -> Vec<usize> { fn run_filter(disk_filter: &Option<Filter>, mount_filter: &Option<Filter>) -> Vec<usize> {
let targets = [ let targets = [

View File

@ -7,7 +7,6 @@
use core_foundation::base::{mach_port_t, CFAllocatorRef}; use core_foundation::base::{mach_port_t, CFAllocatorRef};
use core_foundation::dictionary::CFMutableDictionaryRef; use core_foundation::dictionary::CFMutableDictionaryRef;
use libc::c_char; use libc::c_char;
use mach2::kern_return::kern_return_t; use mach2::kern_return::kern_return_t;
use mach2::port::MACH_PORT_NULL; use mach2::port::MACH_PORT_NULL;

View File

@ -1,5 +1,4 @@
use anyhow::bail; use anyhow::bail;
use mach2::kern_return; use mach2::kern_return;
use super::{bindings::*, IoIterator}; use super::{bindings::*, IoIterator};

View File

@ -1,4 +1,5 @@
use std::mem::{size_of, zeroed}; use std::mem::{size_of, zeroed};
use windows::Win32::Foundation::TRUE; use windows::Win32::Foundation::TRUE;
use windows::Win32::System::ProcessStatus::{GetPerformanceInfo, PERFORMANCE_INFORMATION}; use windows::Win32::System::ProcessStatus::{GetPerformanceInfo, PERFORMANCE_INFORMATION};

View File

@ -2,9 +2,8 @@
use std::time::Instant; use std::time::Instant;
use crate::app::Filter;
use super::NetworkHarvest; use super::NetworkHarvest;
use crate::app::Filter;
// TODO: Eventually make it so that this thing also takes individual usage into account, so we can show per-interface! // TODO: Eventually make it so that this thing also takes individual usage into account, so we can show per-interface!
pub fn get_network_data( pub fn get_network_data(

View File

@ -2,6 +2,7 @@
use std::io; use std::io;
use hashbrown::HashMap;
use serde::{Deserialize, Deserializer}; use serde::{Deserialize, Deserializer};
use sysinfo::System; use sysinfo::System;
@ -38,9 +39,9 @@ pub fn get_process_data(
) )
} }
fn get_freebsd_process_cpu_usage(pids: &[i32]) -> io::Result<std::collections::HashMap<i32, f64>> { fn get_freebsd_process_cpu_usage(pids: &[i32]) -> io::Result<HashMap<i32, f64>> {
if pids.is_empty() { if pids.is_empty() {
return Ok(std::collections::HashMap::new()); return Ok(HashMap::new());
} }
let output = std::process::Command::new("ps") let output = std::process::Command::new("ps")

View File

@ -3,7 +3,7 @@
use std::fs::File; use std::fs::File;
use std::io::{BufRead, BufReader}; use std::io::{BufRead, BufReader};
use fxhash::{FxHashMap, FxHashSet}; use hashbrown::{HashMap, HashSet};
use procfs::process::{Process, Stat}; use procfs::process::{Process, Stat};
use sysinfo::{ProcessStatus, System}; use sysinfo::{ProcessStatus, System};
@ -231,7 +231,7 @@ pub(crate) struct ProcHarvestOptions {
} }
pub(crate) fn get_process_data( pub(crate) fn get_process_data(
sys: &System, prev_proc: PrevProc<'_>, pid_mapping: &mut FxHashMap<Pid, PrevProcDetails>, sys: &System, prev_proc: PrevProc<'_>, pid_mapping: &mut HashMap<Pid, PrevProcDetails>,
proc_harvest_options: ProcHarvestOptions, time_difference_in_secs: u64, total_memory: u64, proc_harvest_options: ProcHarvestOptions, time_difference_in_secs: u64, total_memory: u64,
user_table: &mut UserTable, user_table: &mut UserTable,
) -> crate::utils::error::Result<Vec<ProcessHarvest>> { ) -> crate::utils::error::Result<Vec<ProcessHarvest>> {
@ -261,7 +261,7 @@ pub(crate) fn get_process_data(
cpu_usage /= num_processors; cpu_usage /= num_processors;
} }
let mut pids_to_clear: FxHashSet<Pid> = pid_mapping.keys().cloned().collect(); let mut pids_to_clear: HashSet<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| {

View File

@ -1,5 +1,6 @@
//! Process data collection for macOS. Uses sysinfo and custom bindings. //! Process data collection for macOS. Uses sysinfo and custom bindings.
use hashbrown::HashMap;
use sysinfo::System; use sysinfo::System;
use super::ProcessHarvest; use super::ProcessHarvest;
@ -26,9 +27,7 @@ pub(crate) fn fallback_macos_ppid(pid: Pid) -> Option<Pid> {
.ok() .ok()
} }
fn get_macos_process_cpu_usage( fn get_macos_process_cpu_usage(pids: &[Pid]) -> std::io::Result<HashMap<i32, f64>> {
pids: &[Pid],
) -> std::io::Result<std::collections::HashMap<i32, f64>> {
use itertools::Itertools; use itertools::Itertools;
let output = std::process::Command::new("ps") let output = std::process::Command::new("ps")
.args(["-o", "pid=,pcpu=", "-p"]) .args(["-o", "pid=,pcpu=", "-p"])
@ -38,7 +37,7 @@ fn get_macos_process_cpu_usage(
.collect::<String>(), .collect::<String>(),
) )
.output()?; .output()?;
let mut result = std::collections::HashMap::new(); let mut result = HashMap::new();
String::from_utf8_lossy(&output.stdout) String::from_utf8_lossy(&output.stdout)
.split_whitespace() .split_whitespace()
.chunks(2) .chunks(2)

View File

@ -1,8 +1,8 @@
//! Shared process data harvesting code from macOS and FreeBSD via sysinfo. //! Shared process data harvesting code from macOS and FreeBSD via sysinfo.
use std::collections::HashMap;
use std::io; use std::io;
use hashbrown::HashMap;
use sysinfo::{CpuExt, PidExt, ProcessExt, ProcessStatus, System, SystemExt}; use sysinfo::{CpuExt, PidExt, ProcessExt, ProcessStatus, System, SystemExt};
use super::ProcessHarvest; use super::ProcessHarvest;

View File

@ -1,12 +1,12 @@
//! Unix-specific parts of process collection. //! Unix-specific parts of process collection.
use fxhash::FxHashMap; use hashbrown::HashMap;
use crate::utils::error; use crate::utils::error;
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct UserTable { pub struct UserTable {
pub uid_user_mapping: FxHashMap<libc::uid_t, String>, pub uid_user_mapping: HashMap<libc::uid_t, String>,
} }
impl UserTable { impl UserTable {

View File

@ -1,9 +1,5 @@
//! This file is meant to house (OS specific) implementations on how to kill processes. //! This file is meant to house (OS specific) implementations on how to kill processes.
#[cfg(target_family = "unix")]
use crate::utils::error::BottomError;
use crate::Pid;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
use windows::Win32::{ use windows::Win32::{
Foundation::HANDLE, Foundation::HANDLE,
@ -12,6 +8,10 @@ use windows::Win32::{
}, },
}; };
#[cfg(target_family = "unix")]
use crate::utils::error::BottomError;
use crate::Pid;
/// Based from [this SO answer](https://stackoverflow.com/a/55231715). /// Based from [this SO answer](https://stackoverflow.com/a/55231715).
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
struct Process(HANDLE); struct Process(HANDLE);

View File

@ -1,5 +1,6 @@
use std::{collections::HashMap, ops::Range, time::Instant}; use std::{ops::Range, time::Instant};
use hashbrown::HashMap;
use indexmap::IndexMap; use indexmap::IndexMap;
use unicode_segmentation::{GraphemeCursor, GraphemeIncomplete, UnicodeSegmentation}; use unicode_segmentation::{GraphemeCursor, GraphemeIncomplete, UnicodeSegmentation};

View File

@ -1,21 +1,20 @@
use std::{ use std::{
borrow::Cow, borrow::Cow,
collections::{HashMap, HashSet},
convert::TryInto, convert::TryInto,
str::FromStr, str::FromStr,
time::{Duration, Instant}, time::{Duration, Instant},
}; };
use clap::ArgMatches; use clap::ArgMatches;
use hashbrown::{HashMap, HashSet};
use layout_options::*; use layout_options::*;
use regex::Regex; use regex::Regex;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use typed_builder::*;
#[cfg(feature = "battery")] #[cfg(feature = "battery")]
use starship_battery::Manager; use starship_battery::Manager;
use typed_builder::*;
use crate::{ use crate::{
app::{filter::Filter, layout_manager::*, *}, app::{filter::Filter, layout_manager::*, *},
canvas::{canvas_styling::CanvasColours, ColourScheme}, canvas::{canvas_styling::CanvasColours, ColourScheme},
@ -826,9 +825,8 @@ mod test {
use clap::ArgMatches; use clap::ArgMatches;
use crate::{app::App, canvas::canvas_styling::CanvasColours};
use super::{get_color_scheme, get_widget_layout, Config}; use super::{get_color_scheme, get_widget_layout, Config};
use crate::{app::App, canvas::canvas_styling::CanvasColours};
fn create_app(mut config: Config, matches: ArgMatches) -> App { fn create_app(mut config: Config, matches: ArgMatches) -> App {
let (layout, id, ty) = get_widget_layout(&matches, &config).unwrap(); let (layout, id, ty) = get_widget_layout(&matches, &config).unwrap();

View File

@ -1,7 +1,7 @@
use std::{borrow::Cow, collections::BTreeMap}; use std::{borrow::Cow, collections::BTreeMap};
use const_format::formatcp; use const_format::formatcp;
use fxhash::{FxHashMap, FxHashSet}; use hashbrown::{HashMap, HashSet};
use itertools::Itertools; use itertools::Itertools;
use crate::{ use crate::{
@ -63,14 +63,14 @@ impl ProcessSearchState {
#[derive(Clone, Debug, Eq, PartialEq)] #[derive(Clone, Debug, Eq, PartialEq)]
pub enum ProcWidgetMode { pub enum ProcWidgetMode {
Tree { collapsed_pids: FxHashSet<Pid> }, Tree { collapsed_pids: HashSet<Pid> },
Grouped, Grouped,
Normal, Normal,
} }
type ProcessTable = SortDataTable<ProcWidgetData, ProcColumn>; type ProcessTable = SortDataTable<ProcWidgetData, ProcColumn>;
type SortTable = DataTable<Cow<'static, str>, SortTableColumn>; type SortTable = DataTable<Cow<'static, str>, SortTableColumn>;
type StringPidMap = FxHashMap<String, Vec<Pid>>; type StringPidMap = HashMap<String, Vec<Pid>>;
pub struct ProcWidgetState { pub struct ProcWidgetState {
pub mode: ProcWidgetMode, pub mode: ProcWidgetMode,
@ -215,7 +215,7 @@ impl ProcWidgetState {
show_memory_as_values, show_memory_as_values,
); );
let id_pid_map = FxHashMap::default(); let id_pid_map = HashMap::default();
let mut table = ProcWidgetState { let mut table = ProcWidgetState {
proc_search: process_search_state, proc_search: process_search_state,
@ -271,7 +271,7 @@ impl ProcWidgetState {
} }
fn get_tree_data( fn get_tree_data(
&self, collapsed_pids: &FxHashSet<Pid>, data_collection: &DataCollection, &self, collapsed_pids: &HashSet<Pid>, data_collection: &DataCollection,
) -> Vec<ProcWidgetData> { ) -> Vec<ProcWidgetData> {
const BRANCH_END: char = '└'; const BRANCH_END: char = '└';
const BRANCH_VERTICAL: char = '│'; const BRANCH_VERTICAL: char = '│';
@ -305,11 +305,11 @@ impl ProcWidgetState {
None None
} }
}) })
.collect::<FxHashSet<_>>(); .collect::<HashSet<_>>();
#[inline] #[inline]
fn is_ancestor_shown( fn is_ancestor_shown(
current_process: &ProcessHarvest, kept_pids: &FxHashSet<Pid>, current_process: &ProcessHarvest, kept_pids: &HashSet<Pid>,
process_harvest: &BTreeMap<Pid, ProcessHarvest>, process_harvest: &BTreeMap<Pid, ProcessHarvest>,
) -> bool { ) -> bool {
if let Some(ppid) = current_process.parent_pid { if let Some(ppid) = current_process.parent_pid {
@ -330,10 +330,10 @@ impl ProcWidgetState {
// - The process contains some descendant that matches. // - The process contains some descendant that matches.
// - The process's parent (and only parent, not any ancestor) matches. // - The process's parent (and only parent, not any ancestor) matches.
let filtered_tree = { let filtered_tree = {
let mut filtered_tree = FxHashMap::default(); let mut filtered_tree: HashMap<Pid, Vec<Pid>> = HashMap::default();
// We do a simple DFS traversal to build our filtered parent-to-tree mappings. // We do a simple DFS traversal to build our filtered parent-to-tree mappings.
let mut visited_pids = FxHashMap::default(); let mut visited_pids: HashMap<Pid, bool> = HashMap::default();
let mut stack = orphan_pids let mut stack = orphan_pids
.iter() .iter()
.filter_map(|process| process_harvest.get(process)) .filter_map(|process| process_harvest.get(process))
@ -534,9 +534,9 @@ impl ProcWidgetState {
.unwrap_or(true) .unwrap_or(true)
}); });
let mut id_pid_map: FxHashMap<String, Vec<Pid>> = FxHashMap::default(); let mut id_pid_map: HashMap<String, Vec<Pid>> = HashMap::default();
let mut filtered_data: Vec<ProcWidgetData> = if let ProcWidgetMode::Grouped = self.mode { let mut filtered_data: Vec<ProcWidgetData> = if let ProcWidgetMode::Grouped = self.mode {
let mut id_process_mapping: FxHashMap<&String, ProcessHarvest> = FxHashMap::default(); let mut id_process_mapping: HashMap<&String, ProcessHarvest> = HashMap::default();
for process in filtered_iter { for process in filtered_iter {
let id = if is_using_command { let id = if is_using_command {
&process.command &process.command

View File

@ -6,7 +6,6 @@ use bottom::constants::DEFAULT_BATTERY_LAYOUT;
use bottom::constants::{DEFAULT_LAYOUT, DEFAULT_WIDGET_ID}; use bottom::constants::{DEFAULT_LAYOUT, DEFAULT_WIDGET_ID};
use bottom::options::{layout_options::Row, Config}; use bottom::options::{layout_options::Row, Config};
use bottom::utils::error; use bottom::utils::error;
use toml_edit::de::from_str; use toml_edit::de::from_str;
// TODO: Could move these into the library files rather than external tbh. // TODO: Could move these into the library files rather than external tbh.

View File

@ -1,4 +1,6 @@
use std::{collections::HashMap, env, process::Command}; use std::{env, process::Command};
use hashbrown::HashMap;
/// Returns a QEMU runner target given an architecture. /// Returns a QEMU runner target given an architecture.
fn get_qemu_target(arch: &str) -> &str { fn get_qemu_target(arch: &str) -> &str {