Skip to content

Abstract default hasher + switch to foldhash (quality)#129

Merged
arthurprs merged 3 commits into
masterfrom
land-hasher-foldhash
Jun 26, 2026
Merged

Abstract default hasher + switch to foldhash (quality)#129
arthurprs merged 3 commits into
masterfrom
land-hasher-foldhash

Conversation

@arthurprs

Copy link
Copy Markdown
Owner

Summary

Makes the default hasher an implementation detail and switches it to foldhash (quality).

Re-lands the hasher work from #126, which got merged into its stacked base (evolve-lifecycle-with-state) instead of master and so never reached master. This branches directly off master.

1. Abstract the default hasher behind an opaque newtype

DefaultHashBuilder was a public type alias (= ahash::RandomState), leaking the concrete hasher. It's now an opaque newtype wrapping a private, cfg-selected inner hasher, so the algorithm can change with no public-API churn. The ahash feature is renamed to custom-hasher (wired via dep:foldhash), so the crate name no longer appears in the public feature list.

2. Switch the underlying hasher: ahash → foldhash (quality)

Moves type DefaultHasherImpl from ahash::RandomState to foldhash::quality::RandomState. quality (over fast) is deliberate: the cache reuses one hash for both shard selection and hashbrown's bucket/tag bits, needing good avalanche (see the compute_shard_index comment). RandomState keeps per-instance random seeding.

3. Doc note on compute_shard_index

Documents why the shard-bit rotation is tied to usize::BITS, not u64::BITS: on 32-bit a usize-width hasher leaves the top 32 bits zero, so u64::BITS / 2 there would send every key to shard 0.

Breaking

  • features = ["ahash"]["custom-hasher"]; don't depend on the concrete hasher behind DefaultHashBuilder.
  • foldhash is non-cryptographic and (unlike ahash) makes no HashDoS-resistance guarantee — disable custom-hasher for SipHash on adversarial-key workloads.

Verification

cargo build / test (58 + doctests) / clippy / doc -D warnings clean; --no-default-features compiles.

BREAKING (0.7.0). `DefaultHashBuilder` was a public type alias for
`ahash::RandomState`, leaking the concrete hasher; the `ahash` feature
leaked it too. Both are now implementation-agnostic:

- `DefaultHashBuilder` is an opaque newtype wrapping a private, cfg-selected
  inner hasher. The algorithm can change with no public-API churn.
- The `ahash` feature is renamed to `custom-hasher` and pulls the hasher
  crate via `dep:ahash`, so the crate name no longer appears as a feature.

Migration: replace feature `ahash` with `custom-hasher`; don't name the
concrete hasher behind `DefaultHashBuilder`.
Exercises the DefaultHashBuilder abstraction: swapping the inner hasher
touches only the private `DefaultHasherImpl` alias and the optional
dependency — the public `DefaultHashBuilder` type and the `custom-hasher`
feature are unchanged.

foldhash's `quality` variant gives stronger distribution than its `fast`
variant while staying far faster than the std SipHash fallback.
@arthurprs arthurprs merged commit 7dff1b1 into master Jun 26, 2026
12 checks passed
@arthurprs arthurprs deleted the land-hasher-foldhash branch June 26, 2026 16:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant