Starshard
English | 简体中文
Starshard is a high-performance, lazily sharded concurrent HashMap for Rust.
It is designed for real production workloads where you need:
- predictable lock behavior,
- lower write contention than a single global lock,
- optional async parity,
- and explicit control over rebalance and snapshot trade-offs.
Status
Production-ready (v2.2.0).
Roadmap capabilities shipped in v2.2.0:
- Adaptive shard expansion and rebalance (stop-the-world + online incremental).
- Snapshot modes (
Clone,Cached,Cow) with epoch-based cache invalidation.
Installation
[]
= { = "2.2.0", = ["async", "rayon", "serde", "lifecycle", "advanced"] }
# minimal:
# starshard = "2.2.0"
5-Minute Path
- Start with default sync map:
ShardedHashMap::new(64). - If you are in Tokio runtime, switch to
AsyncShardedHashMap. - If snapshots are frequent, try
SnapshotMode::Cachedfirst, thenSnapshotMode::Cow. - If shard count is user-driven or external-input-driven, use strict constructors (
try_with_*).
Migration guide:
Feature Flags
| Feature | What you get | Typical use |
|---|---|---|
async |
AsyncShardedHashMap (Tokio RwLock) |
async services and workers |
rayon |
parallel snapshot flatten in iteration | large snapshot/scan workloads |
serde |
sync serialize/deserialize + async serializable snapshot helper | persistence/export |
lifecycle |
per_shard_load, memory_stats, drain, lifecycle structs |
observability and maintenance |
advanced |
transaction/CAS/replication/diagnostic APIs | advanced concurrency and control planes |
Quick Start (Sync)
use ShardedHashMap;
let m: = new;
m.insert;
assert_eq!;
assert_eq!;
Quick Start (Async)
async
Common Operations (Cheat Sheet)
| Goal | Sync API | Async API |
|---|---|---|
| insert/update | insert(k, v) |
insert(k, v).await |
| read | get(&k) |
get(&k).await |
| delete | remove(&k) |
remove(&k).await |
| batch insert | batch_insert(items) |
batch_insert(items).await |
| batch read | batch_get(&keys) |
batch_get(&keys).await |
| conditional update | compute_if_present(&k, f) |
compute_if_present(&k, f).await |
| conditional insert | compute_if_absent(k, f) |
compute_if_absent(k, f).await |
| metrics/introspection | shard_stats() / memory_stats() |
shard_stats().await / memory_stats().await |
Constructor Strategy
Choose by strictness and control level:
- Backward-compatible clamping:
with_shards_and_hasher(...)with_shards_and_hasher_capped(...)
- Strict validation (returns
ShardCountError):try_with_shards_and_hasher(...)try_with_shards_and_hasher_capped(...)
- Snapshot mode aware:
with_snapshot_mode(...)with_shards_and_hasher_and_snapshot_mode(...)with_shards_and_hasher_capped_and_snapshot_mode(...)
Adaptive Rebalance (v2.2.0)
Stop-the-world rebalance
use ;
let m: = new;
let report = m.rebalance_to.unwrap;
assert_eq!;
assert_eq!;
Online incremental rebalance
use ShardedHashMap;
let m: = new;
m.start_rebalance_online.unwrap;
while m.rebalance_status.state == "migrating"
assert_eq!;
Semantics:
- writes route to active shards immediately,
- reads fall back to previous shards while migration is in progress,
- migration is finalized when
advance_rebalance(...)drains all source shards.
Snapshot Modes (v2.2.0)
SnapshotMode lets you pick snapshot behavior per workload:
Clone: always rebuild snapshot entries (default, lowest write-path overhead).Cached: reuse cached snapshot while no writes occur.Cow: maintain per-shard COW snapshot views for snapshot-heavy workloads.
use ;
let clone_map: =
with_snapshot_mode;
let cached_map: =
with_snapshot_mode;
let cow_map: =
with_snapshot_mode;
Mode selection guide
| Workload profile | Recommended mode |
|---|---|
| high write + low snapshot frequency | Clone |
| medium write + medium snapshot frequency | Cached |
| low write + high snapshot frequency | Cow or Cached |
Consistency Model
- Per-shard operations are linearizable for that shard.
- Global iteration/snapshot is shard-snapshot based, not a global serializable transaction.
- During online rebalance, active-first + previous-fallback keeps key reachability.
Performance Notes
- Sharding reduces contention versus a single
RwLock<HashMap<..>>under mixed load. - Lazy shard allocation keeps memory proportional to touched shards.
rayonimproves large snapshot flatten throughput when scan size is high.- For snapshot-heavy services, test
CachedandCowwith your real key distribution.
Serde Semantics
- Sync map supports direct
Serialize/Deserialize. - Hasher state is not persisted; rebuild uses
S::default(). - Async map uses
async_snapshot_serializable().awaithelper for serialization.
Examples and Benchmarks
Examples:
examples/v210_rebalance.rsexamples/snapshot_mode_clone_demo.rsexamples/snapshot_mode_cached_demo.rsexamples/snapshot_mode_cow_demo.rsexamples/mixed_workload_snapshot_tradeoff_demo.rs
Benchmark entry:
benches/bench_main.rs
Validation
Before release or upgrade verification:
Current Limits
- Not lock-free; hot-shard writer pressure can still serialize.
- Snapshot operations still materialize
Vec<(K, V)>as output format. RebalanceOptionsfieldsbackground,batch_size,max_pause_nsare forward-compatible placeholders inv2.2.0.
License
Dual license:
You may choose either license.
Disclaimer
- Benchmarks and throughput notes in this README are indicative, not guaranteed.
- Always validate behavior, latency, and memory usage under your own workload before production rollout.