Pull Request: v0.8.5 Performance and Cross-Platform Build Tooling

Documentation home · Current changelog

Historical development record. This PR summary describes the v0.8.5 development state and is not current setup, support, or API guidance.

Audience: maintainers researching earlier implementation and release decisions.

Summary#

This PR prepares ThreadSafeCollections-FP v0.8.5 with focused performance work in Dictionary and HashSet, regression coverage for large intersections, portable benchmark timing, reproducible example builds, and the repository's first GitHub Actions workflow.

The release keeps the public collection behavior and snapshot-first locking model intact. It also retains the original HashSet comparer delegate name for source compatibility while using an unambiguous comparer type internally to avoid an FPC generic-specialization collision.

Motivation#

  • TThreadSafeHashSet.IntersectWith scanned every source item for every destination item,

giving it O(n*m) average behavior even though both collections are hash sets.

  • Dictionary insertion paths recalculated hashes and bucket positions after already performing

the same work during lookup.

  • Example compilation was manual and was not protected by CI.
  • The benchmark depended directly on Windows timing and affinity APIs.
  • Three Dictionary examples referenced the obsolete TDictionaryPair name.

Changes#

HashSet intersection#

TThreadSafeHashSet.IntersectWith still snapshots the source before locking the destination. It now builds an array-backed hash index from that snapshot using the destination set's hash and equality delegates.

CharacteristicBeforev0.8.5
Average complexityO(n*m)O(n+m)
Full-collision worst caseO(n*m)O(n*m)
Source access while destination is lockedNoneNone
Self-intersection safetyPreservedPreserved

The change preserves the snapshot-first approach introduced to prevent ABBA lock ordering and does not call the source collection while the destination lock is held.

Dictionary insertion reuse#

A new private InternalInsertNew helper accepts the precomputed hash and bucket index. The following paths now reuse lookup work when inserting a new key:

  • AddOrSetValue;
  • TryAdd;
  • AddRange.

This removes redundant hashing and bucket selection without changing duplicate-key or update semantics.

FPC generic comparer compatibility#

HashSet constructors now use the uniquely named THashSetEqualityComparer<T> delegate. The legacy public TEqualityComparer<T> delegate remains declared and assignment-compatible, with regression coverage proving it can still be passed to the constructor.

This avoids late-specialization collisions with Generics.Defaults.TEqualityComparer<T> when Dictionary and HashSet specializations are used in the same program.

Benchmarks and regression coverage#

The benchmark now includes direct scenarios for:

  • Dictionary AddRange;
  • Dictionary AddOrSetValue with new keys;
  • HashSet AddRange;
  • HashSet IntersectWith with 50% overlap.

Setup and teardown can be excluded from timed regions, and --size=N provides a quick single-size run. Windows continues to use QueryPerformanceCounter; POSIX builds use gettimeofday. The optional --affinity switch is explicitly Windows-only.

The new HashSet test covers a 10,000-item half-overlap intersection, legacy comparer compatibility, self-intersection, and intersection with an empty source.

Cross-platform example builds#

Two repository-root scripts discover examples/<project>/*.lpr and compile every real example:

ScriptIntended environmentOutput
build-examples.ps1PowerShell on Windows or POSIXexample-bin/
build-examples.shBash on Linux, macOS, or Git Bashexample-bin/

Compiler units are isolated per project under example-bin/units/. Generated files are ignored, while example-bin/.gitkeep preserves the output directory in the repository.

The examples were also updated for current APIs and POSIX execution:

  • Dictionary iterators use Generics.Collections.TPair;
  • the benchmark and chat queue initialize cthreads on Unix;
  • the benchmark conditionally selects Windows or POSIX timing support.

Continuous integration#

The new GitHub Actions workflow adds:

  • an Ubuntu job that compiles all examples through the Bash script;
  • a Windows job that compiles all examples through the PowerShell script;
  • downloadable Linux and Windows example-binary artifacts.

Documentation and branding#

  • package metadata and generated API documentation target v0.8.5;
  • the changelog and HashSet documentation describe the new complexity and compatibility behavior;
  • the README documents the example build commands;
  • a scalable SVG project logo is displayed in the README;
  • v0.8.5 PR and release-note documents are included.

Compatibility#

  • No collection method was removed or renamed.
  • Existing HashSet equality functions remain constructor-compatible.
  • Dictionary duplicate-key and update behavior is unchanged.
  • HashSet intersection retains snapshot-first deadlock safety and destination comparer semantics.
  • --affinity remains supported on Windows and now reports its platform restriction elsewhere.

Validation#

CheckResult
Full FPCUnit suite118 tests passed; 0 errors, 0 failures, zero HeapTrc leaks
HashSet large-intersection regressionPassed; zero HeapTrc leaks
Dictionary test suite38 tests passed; zero HeapTrc leaks
Targeted HashSet regression testsPassed; zero HeapTrc leaks
Lazarus packageCompiled successfully as v0.8.5
PowerShell example build16/16 projects compiled
Bash/Git Bash example build16/16 projects compiled
Benchmark smoke testPassed with microsecond-resolution output
Script and workflow syntaxPowerShell, Bash, and YAML checks passed

Indicative 50%-overlap HashSet intersection timings on the development machine, excluding setup:

ItemsAverage time
10,000371 us
100,0007,995 us

The complete FPCUnit suite passed on FPC 3.2.2 / Win64: 118 tests, 0 errors, 0 failures, and zero unfreed HeapTrc blocks. This includes the 100,000-item aggressive collision stress test and the new large-snapshot intersection regression. All four GitHub-hosted example build checks passed for Linux/Bash and Windows/PowerShell on both push and pull_request events.

Review Focus#

  1. HashSet snapshot-index construction and collision-chain traversal.
  2. Dictionary reuse of precomputed hashes and bucket indices.
  3. Compatibility of the legacy HashSet comparer delegate.
  4. Platform path handling in both example-build scripts.
  5. Hosted Linux and Windows example-build results and artifacts.

Checklist#

  • [x] Performance changes implemented
  • [x] Focused regression tests added and passing
  • [x] Full FPCUnit suite passed (118 tests; zero leaks)
  • [x] Package metadata updated to v0.8.5
  • [x] All 16 examples compile through both local scripts
  • [x] Changelog and API documentation updated
  • [x] PR and release notes added
  • [x] GitHub-hosted Linux and Windows jobs confirmed after push