Skip to content

feat(collections): add IndexedPriorityQueue — addressable heap with O(log n) decrease-key / remove - #283

Merged
marius-bughiu merged 4 commits into
mainfrom
feat/issue-282-indexed-priority-queue
Jul 21, 2026
Merged

feat(collections): add IndexedPriorityQueue — addressable heap with O(log n) decrease-key / remove#283
marius-bughiu merged 4 commits into
mainfrom
feat/issue-282-indexed-priority-queue

Conversation

@marius-bughiu

Copy link
Copy Markdown
Owner

What & why

Adds IndexedPriorityQueue<TElement, TPriority, THasher> — an addressable (indexed) binary min-heap. Unlike the BCL PriorityQueue<TElement, TPriority>, it keeps an element→heap-slot index (a dogfooded CelerityDictionary<TElement, int, THasher>) so it can:

  • change a queued element's priorityUpdate / TryUpdate / EnqueueOrUpdate (decrease-key and increase-key) — in O(log n),
  • remove an arbitrary elementRemove / Remove(out priority) — in O(log n),
  • answer Contains / GetPriority / TryGetPriority in O(1).

Documented BCL-beating workload: the priority-relaxation loop of Dijkstra / Prim / A* and reschedulable event queues. The addressable heap stays at O(distinct elements), whereas the BCL heap's only substitute — lazy deletion (re-enqueue + skip stale entries on the way out) — grows the heap by one entry per update and can't answer "what is X's current priority?". It pairs with the recently-shipped DisjointSet<T> (union-find / Kruskal's MST) to round out the graph-algorithm primitives the BCL omits.

Min-heap by default (Comparer<TPriority>.Default); a custom IComparer<TPriority> gives a max-heap or any order. Each element is a key (appears at most once), so Enqueue throws on a duplicate — TryEnqueue / EnqueueOrUpdate cover the may-exist cases. The out-of-band default(TElement) / null element is handled for free by the dogfooded index.

Closes #282.

Parity rollout (all in this PR)

  • Collectionsrc/Celerity/Collections/IndexedPriorityQueue.cs (sealed, IReadOnlyCollection<KeyValuePair<TElement, TPriority>>, allocation-free struct enumerator, EnsureCapacity / TrimExcess, version-checked enumeration).
  • Dedicated testsIndexedPriorityQueueTests (47 cases: min-order, duplicate/throw contract, decrease-/increase-key, arbitrary remove, custom comparer, capacity, seeding, null element, a Dijkstra scenario), IndexedPriorityQueueEnumerationTests (heap-order enumeration, generic/non-generic, LINQ, Reset, mutation-invalidation for every op, read-doesn't-invalidate), and IndexedPriorityQueueDifferentialTests (seeded min-and max-heap differential: 40 seeds × 800 ops reconciled against a Dictionary oracle after every op, plus a monotonic full-drain check).
  • BenchmarkIndexedPriorityQueueBenchmark vs PriorityQueue<int, int> on Enqueue and the headline DecreaseKey (in-place update vs the lazy-deletion emulation), registered in Program.cs's CoreBenchmarks.
  • Dashboard — ship card in web/index.html; COLLECTIONS entries in web/dev/bench/index.html (Enqueue / DecreaseKey) and web/dev/bench/detail.html; PriorityQueue added to BCL_TYPES so the baseline arm is classified as the BCL reference.
  • Docs — full section in docs/api/collections.md (mechanism, method table, choosing-it, a runnable Dijkstra example) + README (Collections list, a details block, a "Choosing a collection" decision-table row).
  • AOT smoke test — new IndexedPriorityQueue block in Celerity.AotSmokeTest.
  • CHANGELOG — one terse [Unreleased] bullet, matching the current brevity standard.

Facets that genuinely don't apply

  • Cross-collection shared set/dict suites (AddAndTryAddTests, SetConstructorValidationTests, …) — not a hash-table set/dict; like Deque / DisjointSet / the sketches it has no rows in those files.
  • ROADMAP — no status to flip; milestone work is done. This is a post-roadmap tier-(c) enhancement in the graph-algorithms lane (distinct from the recent standalone-collection additions).

Test plan

  • dotnet build (net8.0 / net9.0 / net10.0) — 0 errors, 0 new warnings.
  • dotnet test full suite on net10.0 — 4263 passed, 0 failed (includes the new 47 dedicated + enumeration + differential cases).
  • Benchmarks project builds in Release; new class registered in the core suite.
  • AOT smoke-test executable runs green (all checks passed) with the new coverage.
  • CI matrix (net8.0 / net9.0 / net10.0, Windows/Linux/macOS), coverage gate, Native AOT publish job, and the per-PR benchmark run.
  • On merge to main, the benchmark workflow republishes data.js to gh-pages and the dashboard surfaces the new IndexedPriorityQueue card.

Note: a pre-existing latent drift — DisjointSetBenchmark uses [Params] int ElementCount, which the dashboard's (ItemCount: N) regex does not parse, so its card renders no data. This PR uses ItemCount to render correctly; the DisjointSet fix is out of scope and flagged separately.

…(log n) decrease-key / remove

Adds `IndexedPriorityQueue<TElement, TPriority, THasher>`, an addressable
binary min-heap that keeps an element->heap-slot index (a dogfooded
`CelerityDictionary`) so it can, unlike the BCL `PriorityQueue<,>`, change a
queued element's priority (Update / decrease-key / increase-key) and remove an
arbitrary element in O(log n), and answer Contains / TryGetPriority in O(1).

The documented BCL-beating workload is the priority-relaxation loop of
Dijkstra / Prim / A* and reschedulable event queues: the addressable heap holds
O(distinct elements) where the BCL's only substitute — lazy deletion — grows
the heap by one entry per update. Completes the graph-algorithm primitives with
the recently-shipped DisjointSet (union-find). Min-heap by default; a custom
IComparer<TPriority> gives a max-heap. Each element is a key (appears once).

Full parity rollout in one PR:
- collection: src/Celerity/Collections/IndexedPriorityQueue.cs
- dedicated tests: IndexedPriorityQueueTests, ...EnumerationTests,
  ...DifferentialTests (seeded min/max-heap differential vs a Dictionary oracle)
- benchmark: IndexedPriorityQueueBenchmark vs PriorityQueue<,>, registered in
  Program.cs CoreBenchmarks
- dashboard: web/index.html ship card + COLLECTIONS arrays in
  web/dev/bench/{index,detail}.html (PriorityQueue added to BCL_TYPES)
- docs: docs/api/collections.md section + README (list, details, decision table)
- AOT smoke test coverage
- CHANGELOG [Unreleased]

Cross-collection shared set/dict suites do not apply (not a hash-table
set/dict, like Deque / DisjointSet / the sketches). No ROADMAP status to flip —
milestone work is done; this is a post-roadmap tier-(c) enhancement.

Closes #282

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 19, 2026 01:25
@github-actions

github-actions Bot commented Jul 19, 2026

Copy link
Copy Markdown

Coverage

Metric Value
Line 98.55% (6571/6668)
Branch 97.01% (2759/2844)
Files below 100% line coverage
File Line Branch
src/Celerity/Collections/TopKEntry.cs 80% n/a
src/Celerity/Collections/XorFilter.cs 94.29% 90%
src/Celerity/Collections/EnumMap.cs 95.09% 92.19%
src/Celerity/Collections/IndexedPriorityQueue.cs 96.23% 90.91%
src/Celerity/Collections/CuckooFilter.cs 96.6% 90.38%

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces IndexedPriorityQueue<TElement, TPriority, THasher>, an addressable (indexed) binary heap for Celerity.Collections that supports Update (decrease-/increase-key) and arbitrary Remove in O(log n), and complements it with tests, benchmarks, docs, and dashboard wiring.

Changes:

  • Add the new IndexedPriorityQueue collection implementation (indexed min-heap with element→slot index).
  • Add comprehensive unit + enumeration + differential tests, plus an AOT smoke-test block.
  • Add benchmark + dashboard registration and update README/docs/changelog to document the new type.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
web/index.html Adds the new collection to the “What ships in the box” ship card list.
web/dev/bench/index.html Registers IndexedPriorityQueue in the dashboard collection list and classifies PriorityQueue as a BCL baseline type.
web/dev/bench/detail.html Adds IndexedPriorityQueue to the detail-page collection list and BCL baseline classification set.
src/Celerity/Collections/IndexedPriorityQueue.cs Implements the addressable heap + index map, plus version-checked struct enumeration and capacity management.
src/Celerity.Tests/Collections/IndexedPriorityQueueTests.cs Core behavioral tests (enqueue/dequeue, update, remove, comparer, capacity, null/default element, Dijkstra-shaped scenario).
src/Celerity.Tests/Collections/IndexedPriorityQueueEnumerationTests.cs Enumerator behavior and mutation invalidation coverage (generic/non-generic/LINQ/reset).
src/Celerity.Tests/Collections/IndexedPriorityQueueDifferentialTests.cs Seeded differential test suite vs a dictionary oracle for both min-heap and max-heap comparers.
src/Celerity.Benchmarks/Program.cs Registers the new benchmark in the core benchmark suite.
src/Celerity.Benchmarks/IndexedPriorityQueueBenchmark.cs Adds benchmark comparing IndexedPriorityQueue to BCL PriorityQueue (enqueue + decrease-key via lazy deletion).
src/Celerity.AotSmokeTest/Program.cs Adds a smoke-test block covering enqueue/peek/dequeue, update, remove, lookups, growth, and custom comparer.
README.md Documents the new collection and adds a usage snippet + decision-table row.
docs/api/collections.md Adds a full API docs section with mechanism notes and a runnable Dijkstra example.
CHANGELOG.md Adds an Unreleased entry for IndexedPriorityQueue.

Comment thread CHANGELOG.md Outdated

### Added

- **`IndexedPriorityQueue<TElement, TPriority, THasher>`** in `Celerity.Collections` — an addressable binary min-heap that, unlike the BCL `PriorityQueue<,>`, can change a queued element's priority (`Update` / decrease-key) and remove an arbitrary element in `O(log n)`, and answer `Contains` / `TryGetPriority` in `O(1)`. It keeps the heap at `O(distinct elements)` where the BCL's only substitute — lazy deletion — grows it by one entry per update, so it wins on the priority-relaxation loop of Dijkstra / Prim / A\* and any reschedulable event queue. Each element is a key (appears once); a custom `IComparer<TPriority>` gives a max-heap. Ships with dedicated + differential tests, a benchmark vs `PriorityQueue<,>` (registered in the core suite), dashboard cards, and docs. Not thread-safe. Closes [#282](https://github.com/marius-bughiu/Celerity/issues/282).
Comment on lines +214 to +224
public bool EnqueueOrUpdate(TElement element, TPriority priority)
{
if (_index.TryGetValue(element, out int slot))
{
UpdateAt(slot, priority);
return false;
}

TryEnqueue(element, priority);
return true;
}
Comment on lines +569 to +574
private void Grow()
{
int newCapacity = _elements.Length == 0 ? DefaultCapacity : _elements.Length * 2;
Resize(newCapacity);
_version++;
}
@github-actions

github-actions Bot commented Jul 19, 2026

Copy link
Copy Markdown

Benchmarks

5 regressions ⚠️ vs main, 2 improvements ✅ (rows past ±10% beyond noise).

Highlights

Benchmark This PR StdDev main Δ
DequeBenchmark.LinkedList_PushFront(ItemCount: 1000) 32.95 μs 2.66 μs 27.92 μs +18.0% ⚠️
LruCacheBenchmark.LruCache_Get(ItemCount: 1000) 8.45 μs 811.8 ns 7.42 μs +13.8% ⚠️
SwissSetBenchmark.HashSet_Remove(ItemCount: 1000) 28.18 μs 1.54 μs 32.03 μs -12.0% ✅
CelerityMultiMapBenchmark.Dictionary_Remove(ItemCount: 100000) 2.48 ms 465.22 μs 1.87 ms +32.3% ⚠️
CelerityMultiMapBenchmark.CelerityMultiMap_Remove(ItemCount: 100000) 2.24 ms 285.76 μs 1.90 ms +18.4% ⚠️
BitSetBenchmark.BitArray_Xor(ItemCount: 1024) 99.8 ns 1.7 ns 88.9 ns +12.2% ⚠️
PooledCelerityDictionaryBenchmark.Dictionary_Insert(ItemCount: 1000) 13.41 μs 592.7 ns 15.07 μs -11.0% ✅
Collections (304)
Benchmark This PR StdDev main Δ
TopKSketchBenchmark.Dictionary_Add(ItemCount: 1000) 14.71 μs 151.2 ns 13.97 μs +5.3%
TopKSketchBenchmark.TopKSketch_Add(ItemCount: 1000) 82.56 μs 888.5 ns 81.66 μs +1.1%
TopKSketchBenchmark.Dictionary_Add(ItemCount: 100000) 3.43 ms 60.06 μs 3.34 ms +2.7%
TopKSketchBenchmark.TopKSketch_Add(ItemCount: 100000) 13.71 ms 7.85 μs 13.74 ms -0.2%
TopKSketchBenchmark.Dictionary_TopK(ItemCount: 1000) 34.0 ns 0.2 ns 33.0 ns +3.0%
TopKSketchBenchmark.TopKSketch_TopK(ItemCount: 1000) 1.35 μs 12.1 ns 1.31 μs +3.2%
TopKSketchBenchmark.Dictionary_TopK(ItemCount: 100000) 33.6 ns 0.9 ns 32.4 ns +3.8%
TopKSketchBenchmark.TopKSketch_TopK(ItemCount: 100000) 1.29 μs 30.4 ns 1.27 μs +1.7%
CountMinSketchBenchmark.Dictionary_Add(ItemCount: 1000) 8.07 μs 39.9 ns 8.08 μs -0.2%
LongSetBenchmark.HashSet_Add(ItemCount: 1000) 10.31 μs 43.4 ns 11.19 μs -7.9%
CountMinSketchBenchmark.CountMinSketch_Add(ItemCount: 1000) 9.85 μs 138.3 ns 9.99 μs -1.4%
LongSetBenchmark.LongSet_Add(ItemCount: 1000) 7.49 μs 47.6 ns 7.71 μs -2.8%
CountMinSketchBenchmark.Dictionary_Add(ItemCount: 100000) 1.12 ms 5.15 μs 1.15 ms -2.0%
LongSetBenchmark.HashSet_Add(ItemCount: 100000) 4.09 ms 110.21 μs 4.09 ms -0.2%
CountMinSketchBenchmark.CountMinSketch_Add(ItemCount: 100000) 888.77 μs 4.82 μs 886.55 μs +0.3%
LongSetBenchmark.LongSet_Add(ItemCount: 100000) 5.33 ms 45.86 μs 5.33 ms -0.0%
LongSetBenchmark.HashSet_Contains(ItemCount: 1000) 3.95 μs 4.5 ns 3.97 μs -0.3%
LongSetBenchmark.LongSet_Contains(ItemCount: 1000) 1.62 μs 4.2 ns 1.62 μs -0.0%
LongSetBenchmark.HashSet_Contains(ItemCount: 100000) 1.25 ms 20.86 μs 1.24 ms +0.4%
LongSetBenchmark.LongSet_Contains(ItemCount: 100000) 451.70 μs 10.52 μs 459.60 μs -1.7%
CelerityMultiSetBenchmark.Dictionary_Count(ItemCount: 1000) 7.64 μs 24.5 ns 7.64 μs +0.1%
CelerityMultiSetBenchmark.CelerityMultiSet_Count(ItemCount: 1000) 4.19 μs 19.0 ns 4.13 μs +1.4%
CelerityMultiSetBenchmark.Dictionary_Count(ItemCount: 100000) 1.04 ms 18.89 μs 1.06 ms -1.6%
CelerityMultiSetBenchmark.CelerityMultiSet_Count(ItemCount: 100000) 482.31 μs 36.36 μs 521.94 μs -7.6%
DequeBenchmark.LinkedList_Enumerate(ItemCount: 1000) 1.26 μs 20.6 ns 1.28 μs -1.5%
DequeBenchmark.Deque_Enumerate(ItemCount: 1000) 824.6 ns 0.6 ns 825.3 ns -0.1%
DequeBenchmark.LinkedList_Enumerate(ItemCount: 100000) 118.11 μs 79.3 ns 118.25 μs -0.1%
DequeBenchmark.Deque_Enumerate(ItemCount: 100000) 81.97 μs 73.8 ns 81.92 μs +0.1%
CountMinSketchBenchmark.Dictionary_Estimate(ItemCount: 1000) 3.64 μs 17.7 ns 3.63 μs +0.1%
CountMinSketchBenchmark.CountMinSketch_Estimate(ItemCount: 1000) 6.31 μs 13.5 ns 6.32 μs -0.2%
CountMinSketchBenchmark.Dictionary_Estimate(ItemCount: 100000) 412.11 μs 525.0 ns 412.06 μs +0.0%
CountMinSketchBenchmark.CountMinSketch_Estimate(ItemCount: 100000) 1.77 ms 46.70 μs 1.77 ms -0.0%
HashCachingDictionaryBenchmark.Dictionary_Insert(ItemCount: 1000) 10.45 μs 96.5 ns 10.32 μs +1.3%
HashCachingDictionaryBenchmark.HashCachingDictionary_Insert(ItemCount: 1000) 8.00 μs 94.9 ns 7.94 μs +0.8%
HashCachingDictionaryBenchmark.Dictionary_Insert(ItemCount: 100000) 3.98 ms 69.35 μs 4.01 ms -0.8%
HashCachingDictionaryBenchmark.HashCachingDictionary_Insert(ItemCount: 100000) 5.52 ms 280.95 μs 5.65 ms -2.4%
CelerityMultiSetBenchmark.Dictionary_Lookup(ItemCount: 1000) 3.58 μs 23.6 ns 3.61 μs -0.7%
HashCachingDictionaryBenchmark.Dictionary_Lookup(ItemCount: 1000) 3.62 μs 48.7 ns 3.62 μs -0.1%
CelerityMultiSetBenchmark.CelerityMultiSet_Lookup(ItemCount: 1000) 1.48 μs 2.1 ns 1.48 μs -0.2%
HashCachingDictionaryBenchmark.HashCachingDictionary_Lookup(ItemCount: 1000) 2.18 μs 8.5 ns 2.23 μs -2.1%
CelerityMultiSetBenchmark.Dictionary_Lookup(ItemCount: 100000) 433.45 μs 1.29 μs 437.16 μs -0.8%
HashCachingDictionaryBenchmark.Dictionary_Lookup(ItemCount: 100000) 1.24 ms 4.89 μs 1.25 ms -0.1%
CelerityMultiSetBenchmark.CelerityMultiSet_Lookup(ItemCount: 100000) 163.95 μs 423.9 ns 164.19 μs -0.1%
HashCachingDictionaryBenchmark.HashCachingDictionary_Lookup(ItemCount: 100000) 663.35 μs 4.60 μs 657.64 μs +0.9%
DequeBenchmark.LinkedList_PushFront(ItemCount: 1000) 32.95 μs 2.66 μs 27.92 μs +18.0% ⚠️
DequeBenchmark.Deque_PushFront(ItemCount: 1000) 17.78 μs 2.17 μs 16.85 μs +5.5%
DequeBenchmark.LinkedList_PushFront(ItemCount: 100000) 1.41 ms 24.86 μs 1.42 ms -1.1%
DequeBenchmark.Deque_PushFront(ItemCount: 100000) 487.75 μs 7.19 μs 535.06 μs -8.8%
DequeBenchmark.LinkedList_Queue(ItemCount: 1000) 43.11 μs 2.72 μs 45.22 μs -4.7%
DequeBenchmark.Deque_Queue(ItemCount: 1000) 23.78 μs 2.75 μs 21.72 μs +9.5%
DequeBenchmark.LinkedList_Queue(ItemCount: 100000) 3.69 ms 65.05 μs 3.68 ms +0.3%
DequeBenchmark.Deque_Queue(ItemCount: 100000) 352.96 μs 10.89 μs 349.42 μs +1.0%
CelerityMultiSetBenchmark.Dictionary_Remove(ItemCount: 1000) 40.94 μs 3.45 μs 40.40 μs +1.4%
HashCachingDictionaryBenchmark.Dictionary_Remove(ItemCount: 1000) 61.29 μs 5.50 μs 63.36 μs -3.3%
LongSetBenchmark.HashSet_Remove(ItemCount: 1000) 56.98 μs 5.18 μs 54.79 μs +4.0%
CelerityMultiSetBenchmark.CelerityMultiSet_Remove(ItemCount: 1000) 77.05 μs 1.66 μs 77.30 μs -0.3%
HashCachingDictionaryBenchmark.HashCachingDictionary_Remove(ItemCount: 1000) 89.49 μs 4.79 μs 86.43 μs +3.5%
LongSetBenchmark.LongSet_Remove(ItemCount: 1000) 63.36 μs 5.34 μs 60.90 μs +4.0%
CelerityMultiSetBenchmark.Dictionary_Remove(ItemCount: 100000) 441.84 μs 7.58 μs 438.30 μs +0.8%
HashCachingDictionaryBenchmark.Dictionary_Remove(ItemCount: 100000) 1.58 ms 41.54 μs 1.56 ms +1.0%
LongSetBenchmark.HashSet_Remove(ItemCount: 100000) 1.51 ms 19.48 μs 1.51 ms -0.3%
CelerityMultiSetBenchmark.CelerityMultiSet_Remove(ItemCount: 100000) 1.26 ms 12.62 μs 1.29 ms -2.4%
HashCachingDictionaryBenchmark.HashCachingDictionary_Remove(ItemCount: 100000) 1.61 ms 141.42 μs 2.45 ms -34.6%
LongSetBenchmark.LongSet_Remove(ItemCount: 100000) 1.24 ms 76.54 μs 1.23 ms +1.1%
IntSetBenchmark.HashSet_Add(ItemCount: 1000) 12.95 μs 218.7 ns 12.36 μs +4.8%
SwissSetBenchmark.HashSet_Add(ItemCount: 1000) 12.55 μs 196.2 ns 12.62 μs -0.5%
IntSetBenchmark.IntSet_Add(ItemCount: 1000) 9.55 μs 145.7 ns 9.34 μs +2.2%
SwissSetBenchmark.SwissSet_Add(ItemCount: 1000) 25.66 μs 98.2 ns 26.00 μs -1.3%
IntSetBenchmark.HashSet_Add(ItemCount: 100000) 5.28 ms 112.73 μs 5.18 ms +1.9%
SwissSetBenchmark.HashSet_Add(ItemCount: 100000) 4.96 ms 54.75 μs 4.99 ms -0.6%
IntSetBenchmark.IntSet_Add(ItemCount: 100000) 3.51 ms 22.09 μs 3.50 ms +0.4%
SwissSetBenchmark.SwissSet_Add(ItemCount: 100000) 4.46 ms 117.43 μs 4.48 ms -0.5%
BitSetBenchmark.BitArray_And(ItemCount: 1024) 94.9 ns 0.5 ns 91.0 ns +4.3%
BitSetBenchmark.BitSet_And(ItemCount: 1024) 1.23 μs 3.9 ns 1.23 μs -0.1%
BitSetBenchmark.BitArray_And(ItemCount: 1000000) 46.42 μs 278.3 ns 46.10 μs +0.7%
BitSetBenchmark.BitSet_And(ItemCount: 1000000) 5.03 ms 3.35 μs 5.03 ms -0.0%
FrozenCeleritySetBenchmark.FrozenSet_Build(ItemCount: 1000) 176.02 μs 3.49 μs 170.79 μs +3.1%
FrozenCeleritySetBenchmark.FrozenCeleritySet_Build(ItemCount: 1000) 2.30 ms 21.09 μs 2.28 ms +0.7%
FrozenCeleritySetBenchmark.FrozenSet_Build(ItemCount: 100000) 29.22 ms 471.06 μs 29.14 ms +0.3%
FrozenCeleritySetBenchmark.FrozenCeleritySet_Build(ItemCount: 100000) 1.45 s 53.02 ms 1.37 s +6.3%
FrozenCeleritySetBenchmark.FrozenSet_Contains(ItemCount: 1000) 7.09 μs 4.9 ns 7.10 μs -0.2%
IntSetBenchmark.HashSet_Contains(ItemCount: 1000) 4.71 μs 6.3 ns 4.72 μs -0.1%
SwissSetBenchmark.HashSet_Contains(ItemCount: 1000) 4.75 μs 10.5 ns 4.75 μs -0.1%
FrozenCeleritySetBenchmark.FrozenCeleritySet_Contains(ItemCount: 1000) 79.03 μs 133.5 ns 78.96 μs +0.1%
IntSetBenchmark.IntSet_Contains(ItemCount: 1000) 1.92 μs 22.8 ns 1.91 μs +0.2%
SwissSetBenchmark.SwissSet_Contains(ItemCount: 1000) 2.73 μs 1.6 ns 2.74 μs -0.2%
FrozenCeleritySetBenchmark.FrozenSet_Contains(ItemCount: 100000) 1.80 ms 54.15 μs 1.89 ms -4.6%
IntSetBenchmark.HashSet_Contains(ItemCount: 100000) 1.51 ms 4.58 μs 1.51 ms -0.0%
SwissSetBenchmark.HashSet_Contains(ItemCount: 100000) 1.51 ms 8.08 μs 1.46 ms +3.4%
FrozenCeleritySetBenchmark.FrozenCeleritySet_Contains(ItemCount: 100000) 8.18 ms 25.10 μs 8.14 ms +0.4%
IntSetBenchmark.IntSet_Contains(ItemCount: 100000) 493.45 μs 7.53 μs 491.61 μs +0.4%
SwissSetBenchmark.SwissSet_Contains(ItemCount: 100000) 448.91 μs 25.02 μs 487.26 μs -7.9%
SwissSetBenchmark.HashSet_ContainsMissing(ItemCount: 1000) 4.57 μs 6.6 ns 4.58 μs -0.3%
SwissSetBenchmark.SwissSet_ContainsMissing(ItemCount: 1000) 2.51 μs 3.5 ns 2.51 μs +0.0%
SwissSetBenchmark.HashSet_ContainsMissing(ItemCount: 100000) 2.00 ms 6.74 μs 1.99 ms +0.5%
SwissSetBenchmark.SwissSet_ContainsMissing(ItemCount: 100000) 316.52 μs 1.52 μs 316.30 μs +0.1%
IndexedPriorityQueueBenchmark.PriorityQueue_DecreaseKey(ItemCount: 1000) 79.73 μs 2.46 μs 76.66 μs +4.0%
IndexedPriorityQueueBenchmark.IndexedPriorityQueue_DecreaseKey(ItemCount: 1000) 179.35 μs 641.4 ns 178.23 μs +0.6%
IndexedPriorityQueueBenchmark.PriorityQueue_DecreaseKey(ItemCount: 100000) 35.48 ms 796.44 μs 35.01 ms +1.3%
IndexedPriorityQueueBenchmark.IndexedPriorityQueue_DecreaseKey(ItemCount: 100000) 53.94 ms 143.59 μs 53.85 ms +0.2%
IndexedPriorityQueueBenchmark.PriorityQueue_Enqueue(ItemCount: 1000) 4.71 μs 74.3 ns 4.57 μs +3.0%
IndexedPriorityQueueBenchmark.IndexedPriorityQueue_Enqueue(ItemCount: 1000) 28.22 μs 131.6 ns 28.14 μs +0.3%
IndexedPriorityQueueBenchmark.PriorityQueue_Enqueue(ItemCount: 100000) 1.17 ms 19.83 μs 1.15 ms +0.9%
IndexedPriorityQueueBenchmark.IndexedPriorityQueue_Enqueue(ItemCount: 100000) 6.03 ms 93.17 μs 6.06 ms -0.5%
LruCacheBenchmark.Dictionary_Get(ItemCount: 1000) 25.15 μs 1.16 μs 24.44 μs +2.9%
LruCacheBenchmark.LruCache_Get(ItemCount: 1000) 8.45 μs 811.8 ns 7.42 μs +13.8% ⚠️
LruCacheBenchmark.Dictionary_Get(ItemCount: 100000) 24.68 μs 192.0 ns 25.26 μs -2.3%
LruCacheBenchmark.LruCache_Get(ItemCount: 100000) 7.67 μs 40.6 ns 7.52 μs +1.9%
LruCacheBenchmark.Dictionary_GetMissing(ItemCount: 1000) 4.59 μs 2.3 ns 4.62 μs -0.6%
LruCacheBenchmark.LruCache_GetMissing(ItemCount: 1000) 3.62 μs 3.0 ns 3.61 μs +0.2%
LruCacheBenchmark.Dictionary_GetMissing(ItemCount: 100000) 536.89 μs 2.24 μs 568.82 μs -5.6%
LruCacheBenchmark.LruCache_GetMissing(ItemCount: 100000) 1.56 ms 2.25 μs 1.55 ms +0.1%
CelerityMultiMapBenchmark.Dictionary_Insert(ItemCount: 1000) 27.42 μs 484.0 ns 26.39 μs +3.9%
CelerityMultiMapBenchmark.CelerityMultiMap_Insert(ItemCount: 1000) 39.24 μs 195.6 ns 36.89 μs +6.4%
CelerityMultiMapBenchmark.Dictionary_Insert(ItemCount: 100000) 14.21 ms 1.07 ms 12.43 ms +14.3%
CelerityMultiMapBenchmark.CelerityMultiMap_Insert(ItemCount: 100000) 18.54 ms 182.42 μs 17.69 ms +4.8%
CelerityMultiMapBenchmark.Dictionary_Lookup(ItemCount: 1000) 5.02 μs 80.1 ns 5.10 μs -1.7%
CelerityMultiMapBenchmark.CelerityMultiMap_Lookup(ItemCount: 1000) 2.45 μs 2.5 ns 2.45 μs +0.2%
CelerityMultiMapBenchmark.Dictionary_Lookup(ItemCount: 100000) 1.79 ms 2.50 μs 1.75 ms +2.7%
CelerityMultiMapBenchmark.CelerityMultiMap_Lookup(ItemCount: 100000) 706.59 μs 4.83 μs 700.34 μs +0.9%
BitSetBenchmark.BitArray_Or(ItemCount: 1024) 92.7 ns 2.2 ns 88.2 ns +5.1%
BitSetBenchmark.BitSet_Or(ItemCount: 1024) 1.23 μs 2.0 ns 1.23 μs +0.1%
BitSetBenchmark.BitArray_Or(ItemCount: 1000000) 47.37 μs 624.3 ns 46.58 μs +1.7%
BitSetBenchmark.BitSet_Or(ItemCount: 1000000) 5.04 ms 11.00 μs 5.03 ms +0.1%
BitSetBenchmark.BitArray_PopCount(ItemCount: 1024) 1.29 μs 67.2 ns 1.27 μs +1.5%
BitSetBenchmark.BitSet_PopCount(ItemCount: 1024) 7.5 ns 0.6 ns 6.9 ns +8.6%
BitSetBenchmark.BitArray_PopCount(ItemCount: 1000000) 5.48 ms 1.07 μs 5.48 ms -0.1%
BitSetBenchmark.BitSet_PopCount(ItemCount: 1000000) 5.55 μs 4.9 ns 5.55 μs -0.1%
LruCacheBenchmark.Dictionary_Put(ItemCount: 1000) 89.33 μs 1.77 μs 93.26 μs -4.2%
LruCacheBenchmark.LruCache_Put(ItemCount: 1000) 487.59 μs 15.78 μs 491.75 μs -0.8%
LruCacheBenchmark.Dictionary_Put(ItemCount: 100000) 7.88 ms 48.84 μs 7.64 ms +3.2%
LruCacheBenchmark.LruCache_Put(ItemCount: 100000) 6.45 ms 20.20 μs 6.38 ms +1.1%
CelerityMultiMapBenchmark.Dictionary_Remove(ItemCount: 1000) 31.93 μs 3.75 μs 26.75 μs +19.4%
IntSetBenchmark.HashSet_Remove(ItemCount: 1000) 28.16 μs 777.2 ns 27.98 μs +0.6%
CelerityMultiMapBenchmark.CelerityMultiMap_Remove(ItemCount: 1000) 145.06 μs 7.53 μs 145.01 μs +0.0%
IntSetBenchmark.IntSet_Remove(ItemCount: 1000) 83.81 μs 6.56 μs 82.84 μs +1.2%
SwissSetBenchmark.HashSet_Remove(ItemCount: 1000) 28.18 μs 1.54 μs 32.03 μs -12.0% ✅
SwissSetBenchmark.SwissSet_Remove(ItemCount: 1000) 67.43 μs 8.55 μs 70.52 μs -4.4%
CelerityMultiMapBenchmark.Dictionary_Remove(ItemCount: 100000) 2.48 ms 465.22 μs 1.87 ms +32.3% ⚠️
IntSetBenchmark.HashSet_Remove(ItemCount: 100000) 1.68 ms 15.37 μs 1.68 ms -0.3%
CelerityMultiMapBenchmark.CelerityMultiMap_Remove(ItemCount: 100000) 2.24 ms 285.76 μs 1.90 ms +18.4% ⚠️
IntSetBenchmark.IntSet_Remove(ItemCount: 100000) 1.47 ms 19.87 μs 1.44 ms +2.5%
SwissSetBenchmark.HashSet_Remove(ItemCount: 100000) 1.72 ms 20.61 μs 1.71 ms +0.6%
SwissSetBenchmark.SwissSet_Remove(ItemCount: 100000) 874.63 μs 21.27 μs 859.86 μs +1.7%
BitSetBenchmark.BitArray_Xor(ItemCount: 1024) 99.8 ns 1.7 ns 88.9 ns +12.2% ⚠️
BitSetBenchmark.BitSet_Xor(ItemCount: 1024) 1.23 μs 2.0 ns 1.23 μs +0.3%
BitSetBenchmark.BitArray_Xor(ItemCount: 1000000) 46.66 μs 359.9 ns 46.06 μs +1.3%
BitSetBenchmark.BitSet_Xor(ItemCount: 1000000) 5.04 ms 9.56 μs 5.03 ms +0.0%
SmallSetBenchmark.HashSet_Add(ItemCount: 8) 177.6 ns 2.1 ns 173.0 ns +2.7%
SmallSetBenchmark.SmallSet_Add(ItemCount: 8) 47.9 ns 1.0 ns 47.8 ns +0.2%
SmallSetBenchmark.HashSet_Add(ItemCount: 64) 779.9 ns 27.8 ns 726.7 ns +7.3%
SmallSetBenchmark.SmallSet_Add(ItemCount: 64) 1.93 μs 294.2 ns 1.67 μs +16.0%
RobinHoodSetBenchmark.HashSet_Add(ItemCount: 1000) 12.51 μs 221.4 ns 12.57 μs -0.5%
RobinHoodSetBenchmark.RobinHoodSet_Add(ItemCount: 1000) 17.43 μs 169.9 ns 17.22 μs +1.2%
RobinHoodSetBenchmark.HashSet_Add(ItemCount: 100000) 4.42 ms 456.66 μs 4.45 ms -0.7%
RobinHoodSetBenchmark.RobinHoodSet_Add(ItemCount: 100000) 6.22 ms 75.68 μs 6.19 ms +0.5%
DisjointSetBenchmark.Dictionary_Components(ElementCount: 1000) 19.50 μs 101.6 ns n/a 🆕 new
DisjointSetBenchmark.DisjointSet_Components(ElementCount: 1000) 16.97 μs 164.5 ns n/a 🆕 new
DisjointSetBenchmark.Dictionary_Components(ElementCount: 100000) 4.53 ms 187.35 μs n/a 🆕 new
DisjointSetBenchmark.DisjointSet_Components(ElementCount: 100000) 3.18 ms 60.89 μs n/a 🆕 new
DisjointSetBenchmark.Dictionary_Connected(ElementCount: 1000) 9.44 μs 256.2 ns n/a 🆕 new
DisjointSetBenchmark.DisjointSet_Connected(ElementCount: 1000) 12.21 μs 15.5 ns n/a 🆕 new
DisjointSetBenchmark.Dictionary_Connected(ElementCount: 100000) 257.21 μs 6.35 μs n/a 🆕 new
DisjointSetBenchmark.DisjointSet_Connected(ElementCount: 100000) 341.83 μs 3.46 μs n/a 🆕 new
SmallSetBenchmark.HashSet_Contains(ItemCount: 8) 37.5 ns 0.3 ns 37.2 ns +0.7%
SmallSetBenchmark.SmallSet_Contains(ItemCount: 8) 19.2 ns 0.1 ns 19.0 ns +0.9%
SmallSetBenchmark.HashSet_Contains(ItemCount: 64) 299.5 ns 0.2 ns 300.1 ns -0.2%
SmallSetBenchmark.SmallSet_Contains(ItemCount: 64) 1.13 μs 15.3 ns 1.10 μs +2.4%
RobinHoodSetBenchmark.HashSet_Contains(ItemCount: 1000) 4.72 μs 5.3 ns 4.73 μs -0.3%
RobinHoodSetBenchmark.RobinHoodSet_Contains(ItemCount: 1000) 2.42 μs 2.9 ns 2.42 μs -0.1%
RobinHoodSetBenchmark.HashSet_Contains(ItemCount: 100000) 1.64 ms 64.03 μs 1.59 ms +3.6%
RobinHoodSetBenchmark.RobinHoodSet_Contains(ItemCount: 100000) 736.58 μs 2.80 μs 739.40 μs -0.4%
RobinHoodSetBenchmark.HashSet_ContainsMissing(ItemCount: 1000) 4.55 μs 12.0 ns 4.46 μs +2.0%
RobinHoodSetBenchmark.RobinHoodSet_ContainsMissing(ItemCount: 1000) 2.72 μs 2.2 ns 2.72 μs -0.0%
RobinHoodSetBenchmark.HashSet_ContainsMissing(ItemCount: 100000) 1.91 ms 19.85 μs 1.93 ms -0.8%
RobinHoodSetBenchmark.RobinHoodSet_ContainsMissing(ItemCount: 100000) 1.18 ms 2.04 μs 1.18 ms -0.1%
SmallDictionaryBenchmark.Dictionary_Insert(ItemCount: 8) 179.8 ns 4.5 ns 163.8 ns +9.8%
SmallDictionaryBenchmark.SmallDictionary_Insert(ItemCount: 8) 92.8 ns 0.9 ns 88.5 ns +4.9%
SmallDictionaryBenchmark.Dictionary_Insert(ItemCount: 64) 852.4 ns 7.8 ns 825.9 ns +3.2%
SmallDictionaryBenchmark.SmallDictionary_Insert(ItemCount: 64) 1.11 μs 8.5 ns 1.09 μs +1.2%
CelerityDictionaryBenchmark.Dictionary_Insert(ItemCount: 1000) 13.85 μs 294.3 ns 13.62 μs +1.7%
PooledCelerityDictionaryBenchmark.Dictionary_Insert(ItemCount: 1000) 13.41 μs 592.7 ns 15.07 μs -11.0% ✅
CelerityDictionaryBenchmark.CelerityDictionary_Insert(ItemCount: 1000) 12.42 μs 128.5 ns 12.10 μs +2.6%
PooledCelerityDictionaryBenchmark.PooledCelerityDictionary_Insert(ItemCount: 1000) 8.40 μs 323.7 ns 8.73 μs -3.8%
CelerityDictionaryBenchmark.Dictionary_Insert(ItemCount: 100000) 4.19 ms 96.52 μs 4.17 ms +0.3%
PooledCelerityDictionaryBenchmark.Dictionary_Insert(ItemCount: 100000) 5.07 ms 75.46 μs 5.11 ms -0.8%
CelerityDictionaryBenchmark.CelerityDictionary_Insert(ItemCount: 100000) 4.79 ms 51.34 μs 4.76 ms +0.5%
PooledCelerityDictionaryBenchmark.PooledCelerityDictionary_Insert(ItemCount: 100000) 3.02 ms 11.54 μs 2.99 ms +0.8%
SmallDictionaryBenchmark.Dictionary_Lookup(ItemCount: 8) 37.1 ns 0.1 ns 37.1 ns +0.1%
SmallDictionaryBenchmark.SmallDictionary_Lookup(ItemCount: 8) 24.1 ns 3.3 ns 25.5 ns -5.3%
SmallDictionaryBenchmark.Dictionary_Lookup(ItemCount: 64) 295.8 ns 0.8 ns 297.2 ns -0.5%
SmallDictionaryBenchmark.SmallDictionary_Lookup(ItemCount: 64) 1.11 μs 11.8 ns 1.10 μs +0.9%
CelerityDictionaryBenchmark.Dictionary_Lookup(ItemCount: 1000) 4.75 μs 21.6 ns 4.75 μs +0.0%
PooledCelerityDictionaryBenchmark.Dictionary_Lookup(ItemCount: 1000) 4.74 μs 14.9 ns 4.73 μs +0.3%
CelerityDictionaryBenchmark.CelerityDictionary_Lookup(ItemCount: 1000) 2.23 μs 86.3 ns 2.15 μs +3.9%
PooledCelerityDictionaryBenchmark.PooledCelerityDictionary_Lookup(ItemCount: 1000) 2.39 μs 21.9 ns 2.53 μs -5.7%
CelerityDictionaryBenchmark.Dictionary_Lookup(ItemCount: 100000) 1.58 ms 1.67 μs 1.59 ms -0.3%
PooledCelerityDictionaryBenchmark.Dictionary_Lookup(ItemCount: 100000) 1.60 ms 13.68 μs 1.55 ms +2.9%
CelerityDictionaryBenchmark.CelerityDictionary_Lookup(ItemCount: 100000) 692.31 μs 2.01 μs 717.61 μs -3.5%
PooledCelerityDictionaryBenchmark.PooledCelerityDictionary_Lookup(ItemCount: 100000) 698.02 μs 4.19 μs 718.90 μs -2.9%
SmallDictionaryBenchmark.Dictionary_Remove(ItemCount: 8) 1.52 μs 249.1 ns 1.41 μs +7.8%
SmallSetBenchmark.HashSet_Remove(ItemCount: 8) 619.3 ns 219.4 ns 382.8 ns +61.8%
SmallDictionaryBenchmark.SmallDictionary_Remove(ItemCount: 8) 1.20 μs 93.0 ns 1.41 μs -14.3%
SmallSetBenchmark.SmallSet_Remove(ItemCount: 8) 1.37 μs 228.9 ns 1.29 μs +6.3%
SmallDictionaryBenchmark.Dictionary_Remove(ItemCount: 64) 5.87 μs 655.4 ns 5.52 μs +6.2%
SmallSetBenchmark.HashSet_Remove(ItemCount: 64) 1.60 μs 292.8 ns 1.40 μs +14.3%
SmallDictionaryBenchmark.SmallDictionary_Remove(ItemCount: 64) 25.04 μs 4.46 μs 24.98 μs +0.2%
SmallSetBenchmark.SmallSet_Remove(ItemCount: 64) 24.62 μs 4.51 μs 21.75 μs +13.2%
CelerityDictionaryBenchmark.Dictionary_Remove(ItemCount: 1000) 79.58 μs 6.17 μs 84.76 μs -6.1%
PooledCelerityDictionaryBenchmark.Dictionary_Remove(ItemCount: 1000) 81.69 μs 6.72 μs 80.45 μs +1.5%
CelerityDictionaryBenchmark.CelerityDictionary_Remove(ItemCount: 1000) 140.52 μs 8.24 μs 147.58 μs -4.8%
PooledCelerityDictionaryBenchmark.PooledCelerityDictionary_Remove(ItemCount: 1000) 150.11 μs 13.47 μs 147.85 μs +1.5%
RobinHoodSetBenchmark.HashSet_Remove(ItemCount: 1000) 29.43 μs 4.01 μs 31.18 μs -5.6%
RobinHoodSetBenchmark.RobinHoodSet_Remove(ItemCount: 1000) 133.66 μs 5.71 μs 135.36 μs -1.3%
CelerityDictionaryBenchmark.Dictionary_Remove(ItemCount: 100000) 2.46 ms 314.40 μs 2.11 ms +16.3%
PooledCelerityDictionaryBenchmark.Dictionary_Remove(ItemCount: 100000) 2.07 ms 30.22 μs 2.05 ms +1.2%
CelerityDictionaryBenchmark.CelerityDictionary_Remove(ItemCount: 100000) 1.55 ms 44.74 μs 1.65 ms -5.8%
PooledCelerityDictionaryBenchmark.PooledCelerityDictionary_Remove(ItemCount: 100000) 1.59 ms 54.58 μs 1.57 ms +1.1%
RobinHoodSetBenchmark.HashSet_Remove(ItemCount: 100000) 1.70 ms 15.20 μs 1.72 ms -1.0%
RobinHoodSetBenchmark.RobinHoodSet_Remove(ItemCount: 100000) 1.39 ms 57.58 μs 1.39 ms +0.4%
DisjointSetBenchmark.Dictionary_Union(ElementCount: 1000) 98.89 μs 1.55 μs n/a 🆕 new
DisjointSetBenchmark.DisjointSet_Union(ElementCount: 1000) 27.48 μs 259.6 ns n/a 🆕 new
DisjointSetBenchmark.Dictionary_Union(ElementCount: 100000) 43.22 ms 2.04 ms n/a 🆕 new
DisjointSetBenchmark.DisjointSet_Union(ElementCount: 100000) 8.16 ms 45.05 μs n/a 🆕 new
EnumMapBenchmark.Dictionary_Add 619.8 ns 6.6 ns 630.2 ns -1.6%
EnumMapBenchmark.EnumMap_Add 109.5 ns 0.2 ns 109.9 ns -0.4%
CuckooFilterBenchmark.HashSet_Add(ItemCount: 1000) 13.00 μs 89.8 ns 12.59 μs +3.2%
HyperLogLogBenchmark.HashSet_Add(ItemCount: 1000) 12.67 μs 169.0 ns 12.56 μs +1.0%
PooledCeleritySetBenchmark.HashSet_Add(ItemCount: 1000) 12.63 μs 236.2 ns 12.52 μs +0.8%
CuckooFilterBenchmark.CuckooFilter_Add(ItemCount: 1000) 8.01 μs 24.1 ns 7.93 μs +1.0%
HyperLogLogBenchmark.HyperLogLog_Add(ItemCount: 1000) 29.85 μs 89.3 ns 29.98 μs -0.4%
PooledCeleritySetBenchmark.PooledCeleritySet_Add(ItemCount: 1000) 9.70 μs 193.3 ns 9.81 μs -1.1%
CuckooFilterBenchmark.HashSet_Add(ItemCount: 100000) 4.85 ms 102.76 μs 4.86 ms -0.2%
HyperLogLogBenchmark.HashSet_Add(ItemCount: 100000) 5.04 ms 66.83 μs 5.04 ms +0.0%
PooledCeleritySetBenchmark.HashSet_Add(ItemCount: 100000) 5.08 ms 40.95 μs 5.07 ms +0.2%
CuckooFilterBenchmark.CuckooFilter_Add(ItemCount: 100000) 2.32 ms 3.25 μs 2.32 ms +0.0%
HyperLogLogBenchmark.HyperLogLog_Add(ItemCount: 100000) 496.49 μs 17.92 μs 502.92 μs -1.3%
PooledCeleritySetBenchmark.PooledCeleritySet_Add(ItemCount: 100000) 3.14 ms 3.69 μs 3.12 ms +0.7%
XorFilterBenchmark.HashSet_Build(ItemCount: 1000) 8.23 μs 35.0 ns 8.22 μs +0.1%
XorFilterBenchmark.XorFilter_Build(ItemCount: 1000) 40.75 μs 1.42 μs 43.03 μs -5.3%
XorFilterBenchmark.HashSet_Build(ItemCount: 100000) 2.09 ms 39.01 μs 2.07 ms +1.1%
XorFilterBenchmark.XorFilter_Build(ItemCount: 100000) 13.61 ms 91.03 μs 13.67 ms -0.5%
CuckooFilterBenchmark.HashSet_Contains(ItemCount: 1000) 4.74 μs 4.1 ns 4.74 μs +0.1%
PooledCeleritySetBenchmark.HashSet_Contains(ItemCount: 1000) 4.72 μs 8.2 ns 4.71 μs +0.1%
XorFilterBenchmark.HashSet_Contains(ItemCount: 1000) 4.75 μs 10.6 ns 4.74 μs +0.2%
CuckooFilterBenchmark.CuckooFilter_Contains(ItemCount: 1000) 5.56 μs 6.1 ns 5.56 μs -0.1%
PooledCeleritySetBenchmark.PooledCeleritySet_Contains(ItemCount: 1000) 2.04 μs 36.2 ns 2.05 μs -0.3%
XorFilterBenchmark.XorFilter_Contains(ItemCount: 1000) 7.57 μs 8.7 ns 7.56 μs +0.2%
CuckooFilterBenchmark.HashSet_Contains(ItemCount: 100000) 1.52 ms 8.05 μs 1.48 ms +3.1%
PooledCeleritySetBenchmark.HashSet_Contains(ItemCount: 100000) 1.50 ms 9.03 μs 1.52 ms -1.2%
XorFilterBenchmark.HashSet_Contains(ItemCount: 100000) 1.52 ms 3.73 μs 1.59 ms -4.3%
CuckooFilterBenchmark.CuckooFilter_Contains(ItemCount: 100000) 1.97 ms 2.25 μs 1.97 ms +0.0%
PooledCeleritySetBenchmark.PooledCeleritySet_Contains(ItemCount: 100000) 509.83 μs 25.91 μs 491.64 μs +3.7%
XorFilterBenchmark.XorFilter_Contains(ItemCount: 100000) 802.10 μs 1.41 μs 801.73 μs +0.0%
CuckooFilterBenchmark.HashSet_ContainsMissing(ItemCount: 1000) 4.57 μs 3.7 ns 4.57 μs -0.1%
XorFilterBenchmark.HashSet_ContainsMissing(ItemCount: 1000) 4.56 μs 5.8 ns 4.57 μs -0.1%
CuckooFilterBenchmark.CuckooFilter_ContainsMissing(ItemCount: 1000) 9.63 μs 9.1 ns 9.63 μs -0.0%
XorFilterBenchmark.XorFilter_ContainsMissing(ItemCount: 1000) 7.55 μs 5.9 ns 7.55 μs +0.0%
CuckooFilterBenchmark.HashSet_ContainsMissing(ItemCount: 100000) 1.93 ms 57.01 μs 2.01 ms -4.0%
XorFilterBenchmark.HashSet_ContainsMissing(ItemCount: 100000) 1.99 ms 4.14 μs 2.00 ms -0.3%
CuckooFilterBenchmark.CuckooFilter_ContainsMissing(ItemCount: 100000) 985.88 μs 1.39 μs 986.67 μs -0.1%
XorFilterBenchmark.XorFilter_ContainsMissing(ItemCount: 100000) 805.17 μs 365.0 ns 804.83 μs +0.0%
EnumMapBenchmark.Dictionary_Enumerate 43.2 ns 0.1 ns 43.1 ns +0.2%
EnumMapBenchmark.EnumMap_Enumerate 38.1 ns 0.2 ns 38.1 ns +0.1%
HyperLogLogBenchmark.HashSet_Estimate(ItemCount: 1000) 0.0 ns 0.0 ns 0.0 ns -55.7%
HyperLogLogBenchmark.HyperLogLog_Estimate(ItemCount: 1000) 26.59 μs 76.9 ns 26.58 μs +0.1%
HyperLogLogBenchmark.HashSet_Estimate(ItemCount: 100000) 0.0 ns 0.0 ns 0.0 ns -21.1%
HyperLogLogBenchmark.HyperLogLog_Estimate(ItemCount: 100000) 27.91 μs 218.8 ns 27.81 μs +0.3%
LongDictionaryBenchmark.Dictionary_Insert(ItemCount: 1000) 15.02 μs 213.1 ns 15.06 μs -0.3%
SwissDictionaryBenchmark.Dictionary_Insert(ItemCount: 1000) 13.14 μs 90.5 ns 13.02 μs +0.9%
LongDictionaryBenchmark.LongDictionary_Insert(ItemCount: 1000) 8.58 μs 63.2 ns 8.65 μs -0.8%
SwissDictionaryBenchmark.SwissDictionary_Insert(ItemCount: 1000) 29.63 μs 222.3 ns 29.56 μs +0.2%
LongDictionaryBenchmark.Dictionary_Insert(ItemCount: 100000) 5.23 ms 38.11 μs 5.27 ms -0.8%
SwissDictionaryBenchmark.Dictionary_Insert(ItemCount: 100000) 4.83 ms 167.28 μs 4.88 ms -1.0%
LongDictionaryBenchmark.LongDictionary_Insert(ItemCount: 100000) 7.61 ms 47.10 μs 7.72 ms -1.4%
SwissDictionaryBenchmark.SwissDictionary_Insert(ItemCount: 100000) 3.88 ms 29.83 μs 3.88 ms -0.1%
EnumMapBenchmark.Dictionary_Lookup 135.7 ns 0.1 ns 135.7 ns +0.1%
EnumMapBenchmark.EnumMap_Lookup 69.7 ns 0.0 ns 70.2 ns -0.7%
LongDictionaryBenchmark.Dictionary_Lookup(ItemCount: 1000) 5.04 μs 37.7 ns 5.04 μs +0.1%
SwissDictionaryBenchmark.Dictionary_Lookup(ItemCount: 1000) 4.84 μs 6.9 ns 4.84 μs -0.0%
LongDictionaryBenchmark.LongDictionary_Lookup(ItemCount: 1000) 2.29 μs 7.5 ns 2.28 μs +0.6%
SwissDictionaryBenchmark.SwissDictionary_Lookup(ItemCount: 1000) 3.18 μs 259.2 ns 2.94 μs +8.1%
LongDictionaryBenchmark.Dictionary_Lookup(ItemCount: 100000) 1.58 ms 6.59 μs 1.58 ms -0.1%
SwissDictionaryBenchmark.Dictionary_Lookup(ItemCount: 100000) 1.61 ms 6.18 μs 1.56 ms +2.7%
LongDictionaryBenchmark.LongDictionary_Lookup(ItemCount: 100000) 664.07 μs 20.94 μs 681.36 μs -2.5%
SwissDictionaryBenchmark.SwissDictionary_Lookup(ItemCount: 100000) 674.79 μs 3.44 μs 677.18 μs -0.4%
EnumMapBenchmark.Dictionary_Remove 2.65 μs 133.1 ns 2.49 μs +6.7%
EnumMapBenchmark.EnumMap_Remove 1.07 μs 175.1 ns 1.21 μs -11.1%
LongDictionaryBenchmark.Dictionary_Remove(ItemCount: 1000) 82.67 μs 8.02 μs 82.29 μs +0.5%
PooledCeleritySetBenchmark.HashSet_Remove(ItemCount: 1000) 30.81 μs 3.43 μs 27.82 μs +10.8%
SwissDictionaryBenchmark.Dictionary_Remove(ItemCount: 1000) 76.19 μs 7.01 μs 76.51 μs -0.4%
LongDictionaryBenchmark.LongDictionary_Remove(ItemCount: 1000) 81.56 μs 6.81 μs 89.29 μs -8.7%
PooledCeleritySetBenchmark.PooledCeleritySet_Remove(ItemCount: 1000) 145.13 μs 8.20 μs 150.87 μs -3.8%
SwissDictionaryBenchmark.SwissDictionary_Remove(ItemCount: 1000) 74.79 μs 7.90 μs 72.32 μs +3.4%
CuckooFilterBenchmark.HashSet_Remove(ItemCount: 1000) 13.61 μs 28.7 ns 13.59 μs +0.1%
CuckooFilterBenchmark.CuckooFilter_Remove(ItemCount: 1000) 14.30 μs 59.3 ns 14.35 μs -0.4%
LongDictionaryBenchmark.Dictionary_Remove(ItemCount: 100000) 1.98 ms 41.41 μs 1.99 ms -0.5%
PooledCeleritySetBenchmark.HashSet_Remove(ItemCount: 100000) 1.69 ms 19.82 μs 1.68 ms +0.2%
SwissDictionaryBenchmark.Dictionary_Remove(ItemCount: 100000) 2.00 ms 23.07 μs 2.01 ms -0.4%
LongDictionaryBenchmark.LongDictionary_Remove(ItemCount: 100000) 1.79 ms 74.15 μs 1.79 ms +0.0%
PooledCeleritySetBenchmark.PooledCeleritySet_Remove(ItemCount: 100000) 1.37 ms 69.28 μs 1.39 ms -1.4%
SwissDictionaryBenchmark.SwissDictionary_Remove(ItemCount: 100000) 1.31 ms 37.75 μs 1.29 ms +1.7%
CuckooFilterBenchmark.HashSet_Remove(ItemCount: 100000) 3.76 ms 42.20 μs 3.74 ms +0.5%
CuckooFilterBenchmark.CuckooFilter_Remove(ItemCount: 100000) 4.51 ms 6.38 μs 4.50 ms +0.3%
Hashers (100)
Benchmark This PR StdDev main Δ
StringHasherBenchmark.Bcl_GetHashCode(Shape: ShortAscii) 15.40 μs 13.7 ns 15.40 μs -0.0%
StringHasherBenchmark.EqualityComparer_Default(Shape: ShortAscii) 15.41 μs 58.9 ns 15.38 μs +0.1%
StringHasherBenchmark.Djb2(Shape: ShortAscii) 22.03 μs 17.6 ns 22.05 μs -0.1%
StringHasherBenchmark.Djb2A(Shape: ShortAscii) 22.06 μs 65.0 ns 22.04 μs +0.1%
StringHasherBenchmark.Sdbm(Shape: ShortAscii) 33.01 μs 320.9 ns 32.87 μs +0.4%
StringHasherBenchmark.Elf(Shape: ShortAscii) 44.01 μs 201.8 ns 43.99 μs +0.0%
StringHasherBenchmark.Crc32(Shape: ShortAscii) 49.95 μs 73.2 ns 49.93 μs +0.0%
StringHasherBenchmark.Adler32(Shape: ShortAscii) 96.29 μs 162.9 ns 96.33 μs -0.0%
StringHasherBenchmark.FnV1(Shape: ShortAscii) 25.35 μs 32.6 ns 25.38 μs -0.1%
StringHasherBenchmark.FnV1_64(Shape: ShortAscii) 25.49 μs 46.4 ns 25.48 μs +0.0%
StringHasherBenchmark.FnV1A(Shape: ShortAscii) 10.67 μs 48.2 ns 10.64 μs +0.3%
StringHasherBenchmark.FnV1A_Full(Shape: ShortAscii) 22.86 μs 16.7 ns 22.87 μs -0.1%
StringHasherBenchmark.FnV1A_64(Shape: ShortAscii) 25.77 μs 47.0 ns 25.74 μs +0.1%
StringHasherBenchmark.JenkinsOaat(Shape: ShortAscii) 39.31 μs 50.7 ns 39.31 μs +0.0%
StringHasherBenchmark.Murmur2(Shape: ShortAscii) 15.24 μs 33.8 ns 15.20 μs +0.2%
StringHasherBenchmark.Murmur3(Shape: ShortAscii) 17.25 μs 222.8 ns 17.36 μs -0.7%
StringHasherBenchmark.XxHash32(Shape: ShortAscii) 16.91 μs 11.2 ns 16.91 μs +0.0%
StringHasherBenchmark.XxHash64(Shape: ShortAscii) 18.08 μs 49.2 ns 18.11 μs -0.2%
StringHasherBenchmark.XxHash3(Shape: ShortAscii) 14.88 μs 61.2 ns 14.88 μs +0.0%
StringHasherBenchmark.CityHash64(Shape: ShortAscii) 15.23 μs 14.0 ns 15.23 μs +0.0%
StringHasherBenchmark.MetroHash64(Shape: ShortAscii) 15.02 μs 15.8 ns 15.02 μs +0.0%
StringHasherBenchmark.SipHash13(Shape: ShortAscii) 27.38 μs 20.7 ns 27.40 μs -0.1%
StringHasherBenchmark.SipHash24(Shape: ShortAscii) 38.51 μs 57.1 ns 38.51 μs -0.0%
StringHasherBenchmark.HalfSipHash24(Shape: ShortAscii) 50.01 μs 69.6 ns 50.01 μs -0.0%
StringHasherBenchmark.HighwayHash64(Shape: ShortAscii) 479.25 μs 390.5 ns 480.53 μs -0.3%
StringHasherBenchmark.Bcl_GetHashCode(Shape: LongAscii) 97.30 μs 673.3 ns 96.96 μs +0.3%
StringHasherBenchmark.EqualityComparer_Default(Shape: LongAscii) 96.61 μs 47.6 ns 96.65 μs -0.0%
StringHasherBenchmark.Djb2(Shape: LongAscii) 229.43 μs 103.9 ns 229.45 μs -0.0%
StringHasherBenchmark.Djb2A(Shape: LongAscii) 229.50 μs 279.8 ns 229.39 μs +0.0%
StringHasherBenchmark.Sdbm(Shape: LongAscii) 308.20 μs 121.2 ns 308.16 μs +0.0%
StringHasherBenchmark.Elf(Shape: LongAscii) 582.77 μs 4.93 μs 577.73 μs +0.9%
StringHasherBenchmark.Crc32(Shape: LongAscii) 589.90 μs 249.4 ns 590.08 μs -0.0%
StringHasherBenchmark.Adler32(Shape: LongAscii) 788.79 μs 1.06 μs 789.62 μs -0.1%
StringHasherBenchmark.FnV1(Shape: LongAscii) 289.75 μs 124.7 ns 289.77 μs -0.0%
StringHasherBenchmark.FnV1_64(Shape: LongAscii) 284.96 μs 636.8 ns 284.54 μs +0.1%
StringHasherBenchmark.FnV1A(Shape: LongAscii) 122.56 μs 338.2 ns 122.35 μs +0.2%
StringHasherBenchmark.FnV1A_Full(Shape: LongAscii) 281.97 μs 134.9 ns 282.02 μs -0.0%
StringHasherBenchmark.FnV1A_64(Shape: LongAscii) 287.08 μs 322.2 ns 287.08 μs +0.0%
StringHasherBenchmark.JenkinsOaat(Shape: LongAscii) 378.92 μs 330.7 ns 378.77 μs +0.0%
StringHasherBenchmark.Murmur2(Shape: LongAscii) 102.10 μs 256.6 ns 102.03 μs +0.1%
StringHasherBenchmark.Murmur3(Shape: LongAscii) 113.15 μs 136.1 ns 113.66 μs -0.4%
StringHasherBenchmark.XxHash32(Shape: LongAscii) 73.29 μs 116.6 ns 73.28 μs +0.0%
StringHasherBenchmark.XxHash64(Shape: LongAscii) 90.80 μs 910.8 ns 90.44 μs +0.4%
StringHasherBenchmark.XxHash3(Shape: LongAscii) 70.31 μs 183.0 ns 70.14 μs +0.2%
StringHasherBenchmark.CityHash64(Shape: LongAscii) 122.57 μs 1.11 μs 123.40 μs -0.7%
StringHasherBenchmark.MetroHash64(Shape: LongAscii) 79.12 μs 2.40 μs 77.67 μs +1.9%
StringHasherBenchmark.SipHash13(Shape: LongAscii) 115.00 μs 223.1 ns 114.90 μs +0.1%
StringHasherBenchmark.SipHash24(Shape: LongAscii) 161.21 μs 570.0 ns 161.54 μs -0.2%
StringHasherBenchmark.HalfSipHash24(Shape: LongAscii) 247.83 μs 184.3 ns 247.85 μs -0.0%
StringHasherBenchmark.HighwayHash64(Shape: LongAscii) 844.85 μs 10.79 μs 823.31 μs +2.6%
StringHasherBenchmark.Bcl_GetHashCode(Shape: NonAscii) 22.98 μs 172.0 ns 22.88 μs +0.4%
StringHasherBenchmark.EqualityComparer_Default(Shape: NonAscii) 22.87 μs 38.4 ns 22.85 μs +0.1%
StringHasherBenchmark.Djb2(Shape: NonAscii) 43.41 μs 32.2 ns 43.44 μs -0.1%
StringHasherBenchmark.Djb2A(Shape: NonAscii) 43.43 μs 51.9 ns 43.45 μs -0.1%
StringHasherBenchmark.Sdbm(Shape: NonAscii) 61.61 μs 55.9 ns 61.62 μs -0.0%
StringHasherBenchmark.Elf(Shape: NonAscii) 99.84 μs 321.4 ns 99.86 μs -0.0%
StringHasherBenchmark.Crc32(Shape: NonAscii) 102.71 μs 112.1 ns 102.69 μs +0.0%
StringHasherBenchmark.Adler32(Shape: NonAscii) 175.56 μs 318.2 ns 175.53 μs +0.0%
StringHasherBenchmark.FnV1(Shape: NonAscii) 47.65 μs 38.3 ns 47.65 μs -0.0%
StringHasherBenchmark.FnV1_64(Shape: NonAscii) 50.02 μs 42.2 ns 50.06 μs -0.1%
StringHasherBenchmark.FnV1A(Shape: NonAscii) 21.68 μs 53.0 ns 21.65 μs +0.1%
StringHasherBenchmark.FnV1A_Full(Shape: NonAscii) 45.06 μs 31.1 ns 45.10 μs -0.1%
StringHasherBenchmark.FnV1A_64(Shape: NonAscii) 49.66 μs 75.5 ns 49.62 μs +0.1%
StringHasherBenchmark.JenkinsOaat(Shape: NonAscii) 73.14 μs 61.6 ns 73.15 μs -0.0%
StringHasherBenchmark.Murmur2(Shape: NonAscii) 27.28 μs 123.6 ns 27.27 μs +0.0%
StringHasherBenchmark.Murmur3(Shape: NonAscii) 31.84 μs 60.3 ns 31.91 μs -0.2%
StringHasherBenchmark.XxHash32(Shape: NonAscii) 23.92 μs 19.4 ns 23.91 μs +0.0%
StringHasherBenchmark.XxHash64(Shape: NonAscii) 29.14 μs 36.5 ns 29.13 μs +0.0%
StringHasherBenchmark.XxHash3(Shape: NonAscii) 22.87 μs 55.6 ns 23.05 μs -0.8%
StringHasherBenchmark.CityHash64(Shape: NonAscii) 22.08 μs 52.8 ns 22.08 μs -0.0%
StringHasherBenchmark.MetroHash64(Shape: NonAscii) 25.64 μs 16.5 ns 25.64 μs -0.0%
StringHasherBenchmark.SipHash13(Shape: NonAscii) 36.97 μs 120.7 ns 37.00 μs -0.1%
StringHasherBenchmark.SipHash24(Shape: NonAscii) 51.81 μs 649.2 ns 51.45 μs +0.7%
StringHasherBenchmark.HalfSipHash24(Shape: NonAscii) 73.31 μs 409.3 ns 73.31 μs -0.0%
StringHasherBenchmark.HighwayHash64(Shape: NonAscii) 511.70 μs 4.74 μs 510.80 μs +0.2%
IntegerHasherBenchmark.Guid_Bcl 1.15 μs 4.7 ns 1.16 μs -1.1%
IntegerHasherBenchmark.Guid_EqualityComparer 2.70 μs 32.7 ns 2.67 μs +1.1%
IntegerHasherBenchmark.Guid_Celerity 7.06 μs 3.9 ns 7.08 μs -0.2%
IntegerHasherBenchmark.Int32_Bcl 598.4 ns 0.6 ns 598.5 ns -0.0%
IntegerHasherBenchmark.Int32_EqualityComparer 588.7 ns 0.6 ns 588.7 ns -0.0%
IntegerHasherBenchmark.Int32_Identity 590.9 ns 1.0 ns 590.9 ns +0.0%
IntegerHasherBenchmark.Int32_WangNaive 1.11 μs 13.3 ns 1.10 μs +0.8%
IntegerHasherBenchmark.Int32_Wang 2.64 μs 4.0 ns 2.64 μs +0.1%
IntegerHasherBenchmark.Int32_Murmur3 2.37 μs 0.8 ns 2.37 μs -0.1%
IntegerHasherBenchmark.Int64_Bcl 1.21 μs 1.1 ns 1.21 μs -0.1%
IntegerHasherBenchmark.Int64_EqualityComparer 1.10 μs 8.4 ns 1.10 μs +0.4%
IntegerHasherBenchmark.Int64_Identity 590.1 ns 0.7 ns 591.9 ns -0.3%
IntegerHasherBenchmark.Int64_WangNaive 1.63 μs 6.3 ns 1.63 μs +0.1%
IntegerHasherBenchmark.Int64_Wang 3.65 μs 2.8 ns 3.65 μs -0.0%
IntegerHasherBenchmark.Int64_Murmur3 2.08 μs 2.1 ns 2.08 μs +0.0%
IntegerHasherBenchmark.UInt32_Bcl 599.0 ns 2.3 ns 598.4 ns +0.1%
IntegerHasherBenchmark.UInt32_EqualityComparer 589.2 ns 1.2 ns 589.0 ns +0.0%
IntegerHasherBenchmark.UInt32_Default 1.10 μs 1.0 ns 1.10 μs +0.0%
IntegerHasherBenchmark.UInt32_Wang 2.65 μs 12.1 ns 2.64 μs +0.2%
IntegerHasherBenchmark.UInt32_Murmur3 2.37 μs 3.2 ns 2.37 μs +0.0%
IntegerHasherBenchmark.UInt64_Bcl 1.21 μs 0.8 ns 1.21 μs -0.1%
IntegerHasherBenchmark.UInt64_EqualityComparer 1.10 μs 0.8 ns 1.10 μs -0.0%
IntegerHasherBenchmark.UInt64_Default 2.08 μs 1.7 ns 2.08 μs -0.1%
IntegerHasherBenchmark.UInt64_Wang 3.65 μs 3.2 ns 3.65 μs +0.0%
IntegerHasherBenchmark.UInt64_WangNaive 1.63 μs 1.8 ns 1.63 μs +0.1%

Same-runner A/B (sharded 6-way): main (9fd8d26) and this PR were built and benchmarked back-to-back on the same runner per shard, so hardware variance cancels out. ⚠️ = PR mean ≥ +10% slower than main and beyond combined std-dev; ✅ = correspondingly faster.

- EnqueueOrUpdate no longer double-probes the index: extract InsertNew() so the
  known-absent path inserts directly instead of re-probing via TryEnqueue.
- Grow() guards against int overflow and the Array.MaxLength ceiling (a naive
  `* 2` wraps negative past ~1B elements); throws at the array ceiling rather
  than corrupting.
- Condense the CHANGELOG entry to the brevity standard (CONTRIBUTING.md).

Addresses Copilot review comments on #283.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 19, 2026 14:34

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated 2 comments.

Comment on lines +73 to +75
// Bumped on every structural mutation (enqueue, dequeue, update-that-moves, remove, clear, and any
// capacity change that reallocates the heap arrays) so active enumerators detect concurrent modification.
private int _version;
Comment thread src/Celerity/Collections/IndexedPriorityQueue.cs Outdated
- Fix the _version field comment: an update always bumps the version (its
  priority change is observable via GetPriority), not only "update-that-moves".
- Drop the redundant _version++ in Grow(): it is only called from InsertNew(),
  whose own bump already covers the enqueue, so growth no longer double-counts.

Addresses Copilot review comments on #283.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 21, 2026 19:09

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

CHANGELOG.md:9

  • This CHANGELOG bullet is substantially longer than the contributor guidance allows ("a few sentences at most"), which is also a release-safety concern because release notes are extracted verbatim from this section. Consider tightening it to a single concise, user-facing sentence and leaving implementation/workload detail to the PR body/docs.
- **`IndexedPriorityQueue<TElement, TPriority, THasher>`** in `Celerity.Collections` — an addressable binary min-heap that, unlike the BCL `PriorityQueue<,>`, can change a queued element's priority (`Update` / decrease-key) and remove an arbitrary element in `O(log n)`, and answer `Contains` / `TryGetPriority` in `O(1)`. It wins on the priority-relaxation loop of Dijkstra / Prim / A\* and reschedulable event queues, where the BCL's only substitute — lazy deletion — grows the heap by one entry per update. Each element is a key (appears once); a custom `IComparer<TPriority>` gives a max-heap. Not thread-safe. Closes [#282](https://github.com/marius-bughiu/Celerity/issues/282).

Comment on lines +125 to +127
_index = new CelerityDictionary<TElement, int, THasher>(capacity);
if (capacity > 0)
_index.EnsureCapacity(capacity);
The constructor built the element->slot index with `new CelerityDictionary(capacity)`
and then called `EnsureCapacity(capacity)`. The ctor sizes the table by
NextPowerOfTwo(capacity), which is too small to hold that many entries under the
load factor, so EnsureCapacity reallocated and rehashed — two allocations for a
large pre-sized queue. Build it empty and size once via EnsureCapacity instead.

Addresses a Copilot review comment on #283.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 21, 2026 19:54

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

CHANGELOG.md:9

  • This new CHANGELOG bullet is much longer than the repo guidance (CLAUDE.md says entries should be a few user-facing sentences, since the release workflow uses the section as the GitHub Release body and overly long sections can break releases). Please condense this to a short entry.
- **`IndexedPriorityQueue<TElement, TPriority, THasher>`** in `Celerity.Collections` — an addressable binary min-heap that, unlike the BCL `PriorityQueue<,>`, can change a queued element's priority (`Update` / decrease-key) and remove an arbitrary element in `O(log n)`, and answer `Contains` / `TryGetPriority` in `O(1)`. It wins on the priority-relaxation loop of Dijkstra / Prim / A\* and reschedulable event queues, where the BCL's only substitute — lazy deletion — grows the heap by one entry per update. Each element is a key (appears once); a custom `IComparer<TPriority>` gives a max-heap. Not thread-safe. Closes [#282](https://github.com/marius-bughiu/Celerity/issues/282).

@marius-bughiu
marius-bughiu merged commit 179bebb into main Jul 21, 2026
13 of 14 checks passed
@marius-bughiu
marius-bughiu deleted the feat/issue-282-indexed-priority-queue branch July 24, 2026 22:42
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.

Add IndexedPriorityQueue<TElement, TPriority, THasher> — addressable heap with O(log n) decrease-key / remove

2 participants