feat(collections): add FrozenCeleritySet build-once string set (#22) - #170
Merged
Conversation
Completes the 1.2.0 frozen-collections family: FrozenCeleritySet is the set counterpart of FrozenCelerityDictionary. Build-once, immutable, with a perfect-hash (collision-free) layout searched at construction and a linear-probing fallback when the chosen hasher collides two elements' raw codes, so Contains is single-probe on the fast path and always correct. Unlike the frozen dictionary (which rejects duplicate keys), duplicate elements are silently deduplicated — set semantics, matching BCL FrozenSet and the mutable CeleritySet. Implements IReadOnlySet<string> (SetEquals, IsSubsetOf, IsSupersetOf, Overlaps, ...). The null element is stored out-of-band; the empty string is an ordinary element. Full parity rollout in one PR: - Collection: src/Celerity/Collections/FrozenCeleritySet.cs (convenience type + <THasher> overload). - Dedicated tests: FrozenCeleritySetTests (construction, null element, dedupe, perfect vs fallback, set-algebra matrix, enumeration, non-generic). - Differential layer: CsCheck model property test + Celerity.Fuzz target, both vs a HashSet<string> oracle. - Cross-collection shared tests: SetIEnumerableConstructorTests extended (mirror of the dict IEnumerableConstructorTests); inapplicable mutation / loadFactor shared files noted. - Benchmark: FrozenCeleritySetBenchmark (Build + Contains vs BCL FrozenSet<string>), registered in Program.cs CoreBenchmarks. - Dashboard: ship card + COLLECTIONS entry in web/index.html, web/dev/bench/index.html, web/dev/bench/detail.html (FrozenSet added to BCL_TYPES). - Docs: docs/api/collections.md section, README list / decision table / quick start; AOT smoke test exercises the new instantiations. - CHANGELOG + ROADMAP updated. All 2166 tests pass; AOT smoke test passes; 3000 fuzz cases pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Coverage
|
Benchmarks2 regressions Highlights
Collections (124)
Hashers (90)
Same-runner A/B: main ( |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & why
Implements
FrozenCeleritySet— the build-once, read-manystringset, completing the 1.2.0 frozen-collections family (FrozenCelerityDictionary→FrozenCeleritySet). Closes the frozen-collections umbrella issue #22 (the dictionary half shipped earlier via #62; this is the set counterpart that made the family whole, mirroring theIntDictionary → IntSet/CelerityDictionary → CeleritySetparity pattern).It is the only open issue on the current milestone (1.2.0); there were no open bugs or
priority:highitems, so this is the normal tier-(b) pick: the next planned feature on the current milestone.Design
IEnumerable<string>; the constructor searches a small parameter space (power-of-two table size × a per-build mixing seed) for a perfect (collision-free) placement. On the fast path (IsPerfectlyHashed == true)Containsis a single hash + index + equality check."A"/"Ł"under low-byteStringFnV1AHasher), a perfect layout is impossible, so the build falls back to open-addressed linear probing — still correct, just not single-probe.FrozenSet<T>and the mutableCeleritySet) — the one intentional contract difference from the frozen dictionary, which rejects duplicate keys.IReadOnlySet<string>(SetEquals/IsSubsetOf/IsProperSubsetOf/IsSupersetOf/IsProperSupersetOf/Overlaps). Thenullelement is stored out-of-band; the empty string is an ordinary element. AOT-safe; hot-path membership is allocation-free.Parity rollout (all in this PR)
src/Celerity/Collections/FrozenCeleritySet.cs(convenience type +<THasher>overload).FrozenCeleritySetTestsmirroringFrozenCelerityDictionaryTests+ the full set-algebra matrix.CollectionModelPropertyTests.FrozenCeleritySet_ShouldMatch_BclHashSet) and aCelerity.Fuzztarget (FrozenCeleritySet), both vs aHashSet<string>oracle.SetIEnumerableConstructorTestsextended (the mirror of the dictIEnumerableConstructorTests). Inapplicable shared files (SetConstructorValidationTests— no loadFactor/capacity;TryAdd*— immutable; dictionary-only files) noted in the changelog.FrozenCeleritySetBenchmark(Build+Containsvs BCLFrozenSet<string>), registered inProgram.csCoreBenchmarks.web/index.html;COLLECTIONSentry inweb/dev/bench/index.htmlanddetail.html(FrozenSetadded toBCL_TYPESso the baseline series resolves).docs/api/collections.mdsection + README (list, decision table, quick start); AOT smoke test exercises the new instantiations.Test plan
dotnet build(Debug + Release) — clean (the 3 warnings are pre-existing, unrelated files).dotnet test— 2166 passed, 0 failed (Debug and Release), including the 2000-iteration CsCheck property test.Celerity.Fuzz --target FrozenCeleritySet --iterations 3000— all pass.Celerity.AotSmokeTest— all checks pass (validates the new generic instantiations).main, the benchmark workflow republishesdata.jsto gh-pages and the dashboard surfacesFrozenCeleritySet(Build / Contains vsFrozenSet<string>).🤖 Generated with Claude Code