Migrate helix-event to foldhash

This is following `hashbrown`'s switch in v0.15 from ahash to foldhash
for its `default-haster` feature, applied only to helix-event for now.

I don't have a strong preference between the two. Benchmarks in
Spellbook, which is particularly sensitive to hashers and hash table
performance, show no perceptible difference. Foldhash is dependency-free
though.

Once we migrate to the new tree-sitter bindings and highlighter we
should be able to eliminate the remaining dependencies on ahash.
This commit is contained in:
Michael Davis 2025-02-17 17:28:57 -05:00
parent 1c47aec30c
commit 82f07fe6d1
No known key found for this signature in database
5 changed files with 15 additions and 11 deletions

6
Cargo.lock generated
View file

@ -1310,6 +1310,8 @@ version = "0.15.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
dependencies = [ dependencies = [
"allocator-api2",
"equivalent",
"foldhash", "foldhash",
] ]
@ -1371,10 +1373,10 @@ dependencies = [
name = "helix-event" name = "helix-event"
version = "25.1.1" version = "25.1.1"
dependencies = [ dependencies = [
"ahash",
"anyhow", "anyhow",
"foldhash",
"futures-executor", "futures-executor",
"hashbrown 0.14.5", "hashbrown 0.15.2",
"log", "log",
"once_cell", "once_cell",
"parking_lot", "parking_lot",

View file

@ -45,6 +45,7 @@ tempfile = "3.16.0"
bitflags = "2.8" bitflags = "2.8"
unicode-segmentation = "1.2" unicode-segmentation = "1.2"
ropey = { version = "1.6.1", default-features = false, features = ["simd"] } ropey = { version = "1.6.1", default-features = false, features = ["simd"] }
foldhash = "0.1"
[workspace.package] [workspace.package]
version = "25.1.1" version = "25.1.1"

View file

@ -12,8 +12,8 @@ homepage.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
ahash = "0.8.11" foldhash.workspace = true
hashbrown = "0.14.5" hashbrown = "0.15"
tokio = { version = "1", features = ["rt", "rt-multi-thread", "time", "sync", "parking_lot", "macros"] } tokio = { version = "1", features = ["rt", "rt-multi-thread", "time", "sync", "parking_lot", "macros"] }
# the event registry is essentially read only but must be an rwlock so we can # the event registry is essentially read only but must be an rwlock so we can
# setup new events on initialization, hardware-lock-elision hugely benefits this case # setup new events on initialization, hardware-lock-elision hugely benefits this case

View file

@ -14,8 +14,8 @@ use crate::hook::ErasedHook;
use crate::runtime_local; use crate::runtime_local;
pub struct Registry { pub struct Registry {
events: HashMap<&'static str, TypeId, ahash::RandomState>, events: HashMap<&'static str, TypeId, foldhash::fast::FixedState>,
handlers: HashMap<&'static str, Vec<ErasedHook>, ahash::RandomState>, handlers: HashMap<&'static str, Vec<ErasedHook>, foldhash::fast::FixedState>,
} }
impl Registry { impl Registry {
@ -105,8 +105,8 @@ runtime_local! {
static REGISTRY: RwLock<Registry> = RwLock::new(Registry { static REGISTRY: RwLock<Registry> = RwLock::new(Registry {
// hardcoded random number is good enough here we don't care about DOS resistance // hardcoded random number is good enough here we don't care about DOS resistance
// and avoids the additional complexity of `Option<Registry>` // and avoids the additional complexity of `Option<Registry>`
events: HashMap::with_hasher(ahash::RandomState::with_seeds(423, 9978, 38322, 3280080)), events: HashMap::with_hasher(foldhash::fast::FixedState::with_seed(72536814787)),
handlers: HashMap::with_hasher(ahash::RandomState::with_seeds(423, 99078, 382322, 3282938)), handlers: HashMap::with_hasher(foldhash::fast::FixedState::with_seed(72536814787)),
}); });
} }

View file

@ -41,8 +41,9 @@ macro_rules! runtime_local {
#[cfg(feature = "integration_test")] #[cfg(feature = "integration_test")]
pub struct RuntimeLocal<T: 'static> { pub struct RuntimeLocal<T: 'static> {
data: data: parking_lot::RwLock<
parking_lot::RwLock<hashbrown::HashMap<tokio::runtime::Id, &'static T, ahash::RandomState>>, hashbrown::HashMap<tokio::runtime::Id, &'static T, foldhash::fast::FixedState>,
>,
init: fn() -> T, init: fn() -> T,
} }
@ -53,7 +54,7 @@ impl<T> RuntimeLocal<T> {
pub const fn __new(init: fn() -> T) -> Self { pub const fn __new(init: fn() -> T) -> Self {
Self { Self {
data: parking_lot::RwLock::new(hashbrown::HashMap::with_hasher( data: parking_lot::RwLock::new(hashbrown::HashMap::with_hasher(
ahash::RandomState::with_seeds(423, 9978, 38322, 3280080), foldhash::fast::FixedState::with_seed(12345678910),
)), )),
init, init,
} }