axhash-dashmap
Concurrent DashMap and DashSet collections for Rust.
Powered by dashmap (multi-shard RwLock) · Fueled by axhash (AES-NI accelerated hashing)
Why axhash-dashmap?
dashmap::DashMap defaults to RandomState — a secure but slower hasher that
re-seeds on every process start. axhash-dashmap swaps the hasher for
axhash, which exploits hardware AES instructions (AES-NI on x86-64, AES on
ARMv8) to produce hashes at near-memory-bandwidth speed.
In a sharded concurrent map, every shard lookup begins with a hash to determine which shard to lock. A faster hasher therefore reduces latency at the point of highest contention.
Ecosystem
| Crate | Description |
|---|---|
axhash |
High-performance hashing engine |
axhash-map |
Fast HashMap/HashSet powered by hashbrown |
axhash-indexmap |
Ordered maps with AxHash |
axhash-dashmap |
Concurrent DashMap powered by AxHash |
┌─────────────────────────────────────────────────────────────────┐
│ axhash-dashmap │
│ │
│ Type aliases (Serde-compatible) │
│ DashMap<K, V> DashSet<T> │
│ │
│ Branded newtypes (ergonomic constructors) │
│ AxDashMap<K, V> AxDashSet<T> │
│ │ │ │
│ dashmap::DashMap dashmap::DashSet │
│ ┌──────────┬─── ··· ───┬──────────┐ │
│ │ shard 0 │ shard 1 │ shard N │ ← parking_lot::RwLock │
│ └──────────┴─── ··· ───┴──────────┘ │
│ │ │
│ BuildHasherDefault<AxHasher> │
│ (AES-NI — shard selection + bucket probing) │
└─────────────────────────────────────────────────────────────────┘
Key points:
- Only the hash step changes. All concurrency guarantees, shard-locking
semantics, and deadlock-safety properties of
dashmapare fully preserved. - Zero overhead.
AxDashMapis a#[inline(always)]newtype; the compiler sees through it entirely. - AES is detected at runtime. A portable software fallback is used automatically on CPUs without AES instructions — you ship one binary.
Two usage modes
Mode 1 — Type alias (DashMap / DashSet)
Plain type aliases over dashmap with BuildHasherDefault<AxHasher> baked in.
Because there is no wrapper struct, Serde and other #[derive]-based crates
work out of the box.
use ;
use BuildHasherDefault;
// Serde-compatible — no custom wrapper type in the type hierarchy.
let map: =
with_hasher;
map.insert;
Mode 2 — Branded newtype (AxDashMap / AxDashSet)
A thin newtype wrapper that adds ::new() / ::with_capacity() /
::with_shard_amount() constructors (dashmap::DashMap::new() is only defined
for RandomState — not for generic S). Every DashMap method is accessible
transparently via Deref.
use AxDashMap;
let map: = new;
map.insert;
assert_eq!;
| Need | Use |
|---|---|
::new() / ::with_capacity() / ::with_shard_amount() |
AxDashMap / AxDashSet |
Serde #[derive(Serialize, Deserialize)] |
DashMap / DashSet |
| Custom / seeded hasher | AxDashMap::with_hasher(AxBuildHasher::with_seed(s)) |
Raw dashmap access |
RawDashMap / RawDashSet |
Installation
[]
= "0.1"
Optional features
# Enable serde::Serialize / Deserialize on DashMap / DashSet
= { = "0.1", = ["serde"] }
# Enable rayon parallel iterators
= { = "0.1", = ["rayon"] }
Quick start
AxDashMap
use AxDashMap;
// Create — zero-overhead newtype wrapper.
let scores: = new;
scores.insert;
scores.insert;
scores.insert;
// Lookup (returns a Ref guard — no clone needed).
assert_eq!;
// Entry API — increment atomically within a shard lock.
scores.entry.and_modify;
assert_eq!;
// Concurrent iteration.
let total: u32 = scores.iter.map.sum;
assert_eq!;
// Bulk mutation without extra allocation.
scores.alter_all;
assert_eq!;
// Predicate-based removal.
scores.retain;
AxDashSet
use AxDashSet;
let seen: = new;
seen.insert;
seen.insert;
seen.insert; // duplicate — silently ignored
assert_eq!;
assert!;
Concurrent usage with Arc
use Arc;
use AxDashMap;
let map: = new;
let handles: =
.map
.collect;
for h in handles
assert_eq!;
Constructors
AxDashMap
| Goal | Call |
|---|---|
| Empty map, default shards | AxDashMap::new() |
| Pre-allocated map | AxDashMap::with_capacity(n) |
| Custom shard count | AxDashMap::with_shard_amount(shards) |
| Capacity + shard count | AxDashMap::with_capacity_and_shard_amount(n, shards) |
| Default (zero seed) | AxDashMap::default() |
| Seeded hasher | AxDashMap::with_hasher(AxBuildHasher::with_seed(s)) |
| Seeded + capacity | AxDashMap::with_capacity_and_hasher(n, AxBuildHasher::with_seed(s)) |
| Seeded + shard count | AxDashMap::with_hasher_and_shard_amount(AxBuildHasher::with_seed(s), shards) |
Shard count tip:
shard_amountmust be a power of two. Default = logical CPUs × 4, rounded up to the next power of two. More shards → less contention under high thread counts. Fewer shards → lower memory overhead for small maps.
AxDashSet
| Goal | Call |
|---|---|
| Empty set, default shards | AxDashSet::new() |
| Pre-allocated set | AxDashSet::with_capacity(n) |
| Default (zero seed) | AxDashSet::default() |
| Seeded hasher | AxDashSet::with_hasher(AxBuildHasher::with_seed(s)) |
| Seeded + capacity | AxDashSet::with_capacity_and_hasher(n, AxBuildHasher::with_seed(s)) |
Seeded construction
Supply a random seed to harden against hash-flooding attacks when keys come from untrusted input (e.g. HTTP parameters, user-supplied JSON):
use ;
// In production: derive seed from OS entropy (rand, getrandom, etc.).
let seed: u64 = 0xdeadbeef_cafebabe;
let map: =
with_hasher;
map.insert;
All dashmap methods are available
AxDashMap and AxDashSet implement Deref / DerefMut to the underlying
dashmap::DashMap / dashmap::DashSet, so every method is directly accessible
without extra imports — entry, iter, alter, alter_all, retain,
into_read_only, shrink_to_fit, get_mut, and more.
use AxDashMap;
let map: = new;
map.insert;
// entry — modify-or-insert within a single shard lock.
map.entry.and_modify;
// retain — predicate-based removal.
map.insert;
map.retain;
assert!;
// into_read_only — zero-copy promotion to a read-only view.
let map: = .into_iter.collect;
let ro = map.into_inner.into_read_only;
assert_eq!;
Interoperability with raw dashmap types
The crate re-exports RawDashMap and RawDashSet and provides From
conversions in both directions so you can cross the boundary without a direct
dashmap dependency in your own Cargo.toml.
use BuildHasherDefault;
use ;
// Wrap a raw dashmap.
let raw: =
with_hasher;
raw.insert;
let ax: = raw.into;
assert_eq!;
// Unwrap back to dashmap.
let raw: = ax.into;
assert_eq!;
Feature flags
| Flag | Default | Effect |
|---|---|---|
serde |
❌ off | Enables serde::Serialize / Deserialize on DashMap / DashSet. |
rayon |
❌ off | Enables rayon parallel iterators on DashMap / DashSet. |
Dependency footprint
axhash-dashmap
├── axhash-core (AxHasher + AxBuildHasher — AES hash engine)
└── dashmap (multi-shard RwLock concurrent map, no default features)
License
MIT — see LICENSE.