Skip to content

Commit 2aaa54b

Browse files
Merge pull request #68 from marius-bughiu/docs/choosing-a-collection
Add "Choosing a collection" section to README
2 parents 2d863bb + c0396f6 commit 2aaa54b

2 files changed

Lines changed: 26 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ All notable changes to Celerity are documented here. This project follows [Keep
66

77
### Added
88

9+
- `README.md` — new "Choosing a collection" section: a decision table mapping common workloads (`int`-keyed, `long`-keyed, `Guid` / `string` / other-keyed dictionaries, the two set shapes) onto the right Celerity type, plus a short note on picking a hasher and an honest "where Celerity is not the right answer today" list (concurrent access, mutable `IDictionary<,>` consumers, `FrozenDictionary`-style build-once lookups). Sits between the Quick start and Benchmarks sections so a reader who has scanned the API surface can pick the right type without spelunking `docs/api/`. Implements the "Document when to use which collection" item from issue #15.
910
- `README.md` — new "Quick start" section with concrete, runnable usage examples for `IntDictionary`, `CelerityDictionary` (with `GuidHasher`, `StringFnV1AHasher`, `DefaultHasher<T>`), the sets (`IntSet`, `CeleritySet`), and the `IEnumerable<KeyValuePair<,>>` constructor. Covers indexer get/set, `TryAdd` / `Add` semantics, `TryGetValue`, removal, and bulk-load from a BCL `Dictionary<,>`. Closes the "Add usage examples to README" item from issue #15.
1011

1112
## [1.1.2] - 2026-05-01

README.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,31 @@ Duplicate keys (including duplicate `default(TKey)` / zero-key entries) throw `A
108108

109109
Implement `IHashProvider<T>` as a `struct` to plug in your own hash function. See [Custom hashing](#custom-hashing) below for the contract and a worked example.
110110

111+
## Choosing a collection
112+
113+
Celerity ships specialised types because each one buys a different tradeoff. Use the table below to pick the right one; if your workload doesn't appear here, the BCL collection is usually the right starting point.
114+
115+
| Your workload | Use | Why |
116+
|---|---|---|
117+
| Dictionary keyed by `int` | `IntDictionary<TValue>` | Avoids generic boxing / `EqualityComparer<int>` dispatch; defaults to `Int32WangNaiveHasher`. |
118+
| Dictionary keyed by `long` | `LongDictionary<TValue>` | 64-bit equivalent of `IntDictionary`; defaults to `Int64WangHasher`. |
119+
| Dictionary keyed by `Guid`, `string`, or any other type | `CelerityDictionary<TKey, TValue, THasher>` | Pick a struct hasher from `Celerity.Hashing` (e.g. `GuidHasher`, `StringFnV1AHasher`) so the JIT can inline `Hash()` on the probe path. |
120+
| Set of `int` values | `IntSet` | Same fast path as `IntDictionary`, membership only. |
121+
| Set of any other type | `CeleritySet<T, THasher>` | Same hasher choice as `CelerityDictionary`. |
122+
| Need a stable iteration order, multi-threaded access, or a frozen / read-only post-build view | BCL `Dictionary<,>`, `ConcurrentDictionary<,>`, `FrozenDictionary<,>` | Celerity is single-threaded, iteration order is unspecified, and `FrozenCelerityDictionary` is still on the [1.2.0 roadmap](ROADMAP.md). |
123+
124+
Notes on picking a hasher once the collection is settled:
125+
126+
- For `int` / `long` keys, the convenience subclasses (`IntDictionary<TValue>`, `IntSet`, `LongDictionary<TValue>`) already pick a sensible default — only override when you have evidence of clustered or adversarial keys, in which case switch to `Int32Murmur3Hasher` / `Int64Murmur3Hasher`.
127+
- For arbitrary types, `DefaultHasher<T>` (which delegates to `EqualityComparer<T>.Default.GetHashCode()`) is a safe fallback. It still benefits from the struct-hasher devirtualisation; the inner `EqualityComparer<T>` dispatch is the only unavoidable cost. Replace it with a hand-written struct hasher if profiling shows `Hash` on the hot path.
128+
- The full hasher matrix lives in [`docs/api/hashing.md`](docs/api/hashing.md).
129+
130+
A few cases where Celerity is **not** the right answer today:
131+
132+
- **Concurrent reads/writes from multiple threads.** Celerity collections are single-threaded; use `ConcurrentDictionary<,>` or wrap a BCL `Dictionary<,>` in your own lock.
133+
- **You need `IDictionary<,>` (mutable interface), `LINQ`-heavy code that relies on `Count`-via-extension on the boxed surface, or anything that depends on a specific iteration order.** Celerity exposes `IReadOnlyDictionary<,>` only and does not guarantee iteration order across versions.
134+
- **Build-once / read-many lookup tables for string keys.** Today the BCL `FrozenDictionary<,>` will outperform `CelerityDictionary` on lookups; the Celerity equivalent (`FrozenCelerityDictionary`) is planned for 1.2.0 ([#62](https://github.com/marius-bughiu/Celerity/issues/62)).
135+
111136
## Benchmarks
112137

113138
#### CelerityDictionary

0 commit comments

Comments
 (0)