Skip to content

perf(engine): optimize FEN, repetition tracking, and game import/export - #17

Merged
denyrt merged 4 commits into
mainfrom
perf/fen-optimization
Oct 22, 2026
Merged

denyrt merged 4 commits into
mainfrom
perf/fen-optimization

Conversation

@denyrt

@denyrt denyrt commented Oct 22, 2026 •

Copy link
Copy Markdown
Member

Summary

Reduce allocations and repeated work when replaying, restoring, and exporting games.

  • Defer historical FEN strings until requested, reusing existing position snapshots. Add PlyCount, indexed FEN access, and span-based formatting.
  • Separate internal FEN parsing and formatting, with clearer validation boundaries and method names.
  • Replace repetition FEN strings with exact structural keys. Preserve side-to-move, castling rights, and legally available en passant; exclude move counters.
  • Export PGN using a single position and shared SAN logic, without constructing game history, undo snapshots, or repetition tracking.
  • Add ChessGame.FromRecordJson and PGN parsing overloads that return the game built during validation, avoiding a second replay.
  • Extend regression tests, benchmarks, documentation, and package-consumer checks.

Validation

The following checks were completed during implementation:

# Passed
pwsh -NoProfile -File scripts/Verify-SolutionStructure.ps1

# Succeeded; NU1900: NuGet vulnerability data unavailable
dotnet restore ChessRealms.Engine.slnx --locked-mode -m:1 -p:BuildInParallel=false

# Succeeded; no errors, two NU1900 warnings
dotnet build ChessRealms.Engine.slnx -c Release --no-restore -m:1 -p:UseSharedCompilation=false

# 1728 passed
dotnet test ChessRealms.Engine.slnx -c Release --no-build --filter "TestCategory!=Deep"

# 16 passed after the FEN refactor; see limitation below
dotnet test ChessRealms.Engine.slnx -c Release --no-build --filter "TestCategory=Deep"

# Passed
dotnet pack src/ChessRealms.Engine/ChessRealms.Engine.csproj -c Release --no-build --no-restore -o artifacts/benchmarks/pgn-direct-import-2026-10-22/package

# Package and symbols verified
pwsh -NoProfile -File scripts/Verify-Package.ps1 -PackagePath artifacts/benchmarks/pgn-direct-import-2026-10-22/package/ChessRealms.Engine.1.1.0.nupkg -ExpectedPackageId ChessRealms.Engine -ExpectedPackageVersion 1.1.0

# Isolated consumer passed
pwsh -NoProfile -File scripts/Test-PackageConsumer.ps1 -PackagePath artifacts/benchmarks/pgn-direct-import-2026-10-22/package/ChessRealms.Engine.1.1.0.nupkg -ExpectedPackageId ChessRealms.Engine -ExpectedPackageVersion 1.1.0

# Passed for the complete PR diff
git diff --check origin/main...HEAD

Coverage includes FEN buffer boundaries, arbitrary-precision counters, history and undo, repetition equality and hash collisions, legal and pinned en passant, import diagnostics, and document/game independence.

Local benchmarks and allocation probes covered 0-, 20-, and 120-ply games. Selected 120-ply results:

Comparison Time per operation Allocated bytes per operation
PGN string export, before/after export optimization 665 → 170 µs 84,856 → 5,408
PGN Parse + ToGame versus direct import, same final build 737 → 387 µs ≈146,752 → ≈74,500

These are separate comparisons from short local in-process measurements, not cumulative gains or server-load results. Raw reports and allocation probes are retained locally under ignored artifacts/benchmarks/.

Validation limits:

  • Deep perft was not rerun after the final PGN import change, which exposes the already-validated game without changing move generation, legality, or move application.
  • NuGet vulnerability auditing could not complete because its data source was unavailable.

Compatibility and risks

Existing public signatures, serialization formats, and PGN output contracts are preserved. New public APIs are additive.

History still returns an independent snapshot and materializes its FEN strings when accessed. Callers can use indexed or span-based FEN access to avoid requesting the entire snapshot.

Direct imports preserve validation, history, undo, counters, and repetition state. PGN documents remain independent of subsequent game changes, and their declared result remains separate from the engine outcome. Failed PGN TryParse calls expose neither a partial document nor a partial game.

Review should focus on repetition identity, en passant normalization, and restoration/undo behavior. Allocation reductions depend on the workload; collection growth and arbitrary-precision arithmetic can still allocate.

The package version remains 1.1.0; this PR does not publish a release.

Checklist

  • The changes focus on reducing game-processing overhead while preserving behavior.
  • Tests were added or updated when behavior changed.
  • Documentation was updated where required.
  • Relevant local validation passed, with limitations documented above.
  • No credentials, personal data, or unintended generated files are included.

@denyrt
denyrt merged commit dc5995e into main Oct 22, 2026
5 checks passed
@denyrt
denyrt deleted the perf/fen-optimization branch October 22, 2026 20:50
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.

1 participant