diff --git a/Cargo.lock b/Cargo.lock index cd893650..62da730c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,19 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "getrandom 0.3.3", + "once_cell", + "version_check", + "zerocopy", +] + [[package]] name = "aho-corasick" version = "1.1.3" @@ -533,6 +546,7 @@ checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" name = "pathfinding" version = "4.14.0" dependencies = [ + "ahash", "codspeed-criterion-compat", "deprecate-until", "iai-callgrind", @@ -545,7 +559,6 @@ dependencies = [ "rand", "rand_xorshift", "regex", - "rustc-hash", "thiserror", "trybuild", "version_check", @@ -721,12 +734,6 @@ version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" -[[package]] -name = "rustc-hash" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" - [[package]] name = "rustc_version" version = "0.4.1" diff --git a/Cargo.toml b/Cargo.toml index 9ca98786..d5b839da 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,7 +39,7 @@ iai = [] [dependencies] num-traits = "0.2.19" indexmap = "2.11.4" -rustc-hash = "2.1.1" +ahash = "0.8.12" integer-sqrt = "0.1.5" thiserror = "2.0.17" deprecate-until = "0.1.1" diff --git a/src/directed/count_paths.rs b/src/directed/count_paths.rs index 29b4533f..6c77d2f0 100644 --- a/src/directed/count_paths.rs +++ b/src/directed/count_paths.rs @@ -1,14 +1,17 @@ //! Count the total number of possible paths to reach a destination. -use std::hash::Hash; +use std::collections::HashMap; +use std::hash::{BuildHasherDefault, Hash}; -use rustc_hash::FxHashMap; +use ahash::AHasher; + +type AHashMap = HashMap>; fn cached_count_paths( start: T, successors: &mut FN, success: &mut FS, - cache: &mut FxHashMap, + cache: &mut AHashMap, ) -> usize where T: Eq + Hash, @@ -66,6 +69,6 @@ where start, &mut successors, &mut success, - &mut FxHashMap::default(), + &mut AHashMap::default(), ) } diff --git a/src/directed/dfs.rs b/src/directed/dfs.rs index 15049889..ea0fa0cb 100644 --- a/src/directed/dfs.rs +++ b/src/directed/dfs.rs @@ -1,11 +1,14 @@ //! Compute a path using the [depth-first search //! algorithm](https://en.wikipedia.org/wiki/Depth-first_search). -use std::collections::HashSet; -use std::hash::Hash; +use std::collections::{HashMap, HashSet}; +use std::hash::{BuildHasherDefault, Hash}; use std::iter::FusedIterator; -use rustc_hash::{FxHashMap, FxHashSet}; +use ahash::AHasher; + +type AHashMap = HashMap>; +type AHashSet = HashSet>; /// Compute a path using the [depth-first search /// algorithm](https://en.wikipedia.org/wiki/Depth-first_search). @@ -54,8 +57,8 @@ where FS: FnMut(&N) -> bool, { let mut to_visit = vec![start]; - let mut visited = FxHashSet::default(); - let mut parents = FxHashMap::default(); + let mut visited = AHashSet::default(); + let mut parents = AHashMap::default(); while let Some(node) = to_visit.pop() { if visited.insert(node.clone()) { if success(&node) { @@ -77,7 +80,7 @@ where None } -fn build_path(mut node: N, parents: &FxHashMap) -> Vec +fn build_path(mut node: N, parents: &AHashMap) -> Vec where N: Clone + Eq + Hash, { diff --git a/src/directed/dijkstra.rs b/src/directed/dijkstra.rs index 86958ebe..ceee8a42 100644 --- a/src/directed/dijkstra.rs +++ b/src/directed/dijkstra.rs @@ -5,10 +5,14 @@ use super::reverse_path; use crate::FxIndexMap; use indexmap::map::Entry::{Occupied, Vacant}; use num_traits::Zero; -use rustc_hash::{FxHashMap, FxHashSet}; use std::cmp::Ordering; -use std::collections::{BinaryHeap, HashMap}; -use std::hash::Hash; +use std::collections::{BinaryHeap, HashMap, HashSet}; +use std::hash::{BuildHasherDefault, Hash}; + +use ahash::AHasher; + +type AHashMap = HashMap>; +type AHashSet = HashSet>; /// Compute a shortest path using the [Dijkstra search /// algorithm](https://en.wikipedia.org/wiki/Dijkstra's_algorithm). @@ -326,9 +330,9 @@ impl Ord for SmallestHolder { /// Struct returned by [`dijkstra_reach`]. pub struct DijkstraReachable { to_see: BinaryHeap>, - seen: FxHashSet, + seen: AHashSet, parents: FxIndexMap, - total_costs: FxHashMap, + total_costs: AHashMap, successors: FN, } @@ -422,10 +426,10 @@ where let mut parents: FxIndexMap = FxIndexMap::default(); parents.insert(start.clone(), (usize::MAX, Zero::zero())); - let mut total_costs = FxHashMap::default(); + let mut total_costs = AHashMap::default(); total_costs.insert(start.clone(), Zero::zero()); - let seen = FxHashSet::default(); + let seen = AHashSet::default(); DijkstraReachable { to_see, diff --git a/src/lib.rs b/src/lib.rs index cfd162f1..692604ef 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -122,12 +122,12 @@ pub mod utils; mod noderefs; pub use noderefs::NodeRefs; +use ahash::AHasher; use indexmap::{IndexMap, IndexSet}; -use rustc_hash::FxHasher; use std::hash::BuildHasherDefault; -type FxIndexMap = IndexMap>; -type FxIndexSet = IndexSet>; +type FxIndexMap = IndexMap>; +type FxIndexSet = IndexSet>; /// Export all public functions and structures for an easy access. pub mod prelude { diff --git a/src/noderefs.rs b/src/noderefs.rs index b11c7019..6fa4b4fb 100644 --- a/src/noderefs.rs +++ b/src/noderefs.rs @@ -1,8 +1,12 @@ -use rustc_hash::FxHashSet; -use std::hash::Hash; +use std::collections::HashSet; +use std::hash::{BuildHasherDefault, Hash}; use std::iter::FromIterator; use std::ops::Deref; +use ahash::AHasher; + +type AHashSet = HashSet>; + /// A set of node references. /// /// Can be created from a single node reference or an iterable of @@ -22,19 +26,19 @@ use std::ops::Deref; /// let refs: NodeRefs = NodeRefs::from_iter([&red, &blue, &green]); /// ``` #[derive(Debug, Clone, PartialEq, Eq)] -pub struct NodeRefs<'a, N>(FxHashSet<&'a N>) +pub struct NodeRefs<'a, N>(AHashSet<&'a N>) where N: Eq + Hash + Clone; impl<'a, N: Eq + Hash + Clone> FromIterator<&'a N> for NodeRefs<'a, N> { fn from_iter>(iter: T) -> Self { - NodeRefs(FxHashSet::from_iter(iter)) + NodeRefs(AHashSet::from_iter(iter)) } } impl<'a, N: Eq + Hash + Clone> From<&'a N> for NodeRefs<'a, N> { fn from(value: &'a N) -> Self { - NodeRefs(FxHashSet::from_iter([value])) + NodeRefs(AHashSet::from_iter([value])) } } @@ -57,7 +61,7 @@ impl<'a, N: Eq + Hash + Clone> IntoIterator for &'a NodeRefs<'a, N> { } impl<'a, N: Eq + Hash + Clone> Deref for NodeRefs<'a, N> { - type Target = FxHashSet<&'a N>; + type Target = AHashSet<&'a N>; fn deref(&self) -> &Self::Target { &self.0 @@ -78,7 +82,7 @@ mod tests { let refs = NodeRefs::from_iter(&nodes); assert_eq!( refs.0, - FxHashSet::from_iter([&nodes[0], &nodes[1], &nodes[2]]) + AHashSet::from_iter([&nodes[0], &nodes[1], &nodes[2]]) ); } @@ -86,7 +90,7 @@ mod tests { fn test_from_single_ref() { let node = Node(42); let refs = NodeRefs::from(&node); - assert_eq!(refs.0, FxHashSet::from_iter([&node])); + assert_eq!(refs.0, AHashSet::from_iter([&node])); } #[test] diff --git a/src/undirected/connected_components.rs b/src/undirected/connected_components.rs index 1f543d37..76ed4d50 100644 --- a/src/undirected/connected_components.rs +++ b/src/undirected/connected_components.rs @@ -2,10 +2,10 @@ use std::collections::hash_map::Entry::{Occupied, Vacant}; use std::collections::{HashMap, HashSet}; -use std::hash::Hash; +use std::hash::{BuildHasherDefault, Hash}; use std::marker::PhantomData; -use rustc_hash::{FxBuildHasher, FxHashMap, FxHashSet}; +use ahash::AHasher; /// A connected component implementation for various generic types. /// @@ -107,8 +107,14 @@ where let (_, gindices) = Self::separate_components(groups); // Pre-size the hash map to reduce reallocations let estimated_capacity = gindices.iter().filter(|&&n| n != usize::MAX).count(); - let mut gb: FxHashMap> = - FxHashMap::with_capacity_and_hasher(estimated_capacity, FxBuildHasher); + let mut gb: HashMap< + usize, + HashSet>, + BuildHasherDefault, + > = HashMap::with_capacity_and_hasher( + estimated_capacity, + BuildHasherDefault::::default(), + ); for (i, n) in gindices .into_iter() .enumerate()