Repository navigation
perf(hermitcrab): share trailing analysis template slot batches - #546
johnml1135 wants to merge 4 commits into
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #546 +/- ##
==========================================
+ Coverage 74.57% 74.69% +0.12%
==========================================
Files 453 454 +1
Lines 38314 38431 +117
Branches 5280 5304 +24
==========================================
+ Hits 28573 28707 +134
+ Misses 8576 8567 -9
+ Partials 1165 1157 -8 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
…k guard, avoid per-node closures The shared walk is only taken when MaxAlternatives is 0, so its limit check could never fire; the guard comment now names all five fallback conditions; Walk checks admitted templates with a loop instead of a capturing lambda. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#522 removed AnalysisStateKey along with the analysis-cascade memo and kept the same identity as AnalysisStratumRule.AnalysisMergeKey, so the shared-walk equivalence test now compares outputs under that key. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
d6f481e to
5ed55e0
Compare
| if ( | ||
| !_hasSharedSlots | ||
| || _morpher.TraceManager.IsTracing | ||
| || _morpher.MaxDegreeOfParallelism != 1 |
There was a problem hiding this comment.
Minor: F4. A default Morpher never takes the shared walk: maxDegreeOfParallelism defaults to 0 (Morpher.cs:29), so this guard sends every call to base.Apply and only callers who pass degree 1 get fewer batches. The PR body defers parallel sharing but presents the speedup as general; say in the description that it needs degree 1, or say why the default should not be covered.
Public API, target framework, package, machine.py parity: None verified. Findings: F1 addressed, F2 addressed, F3 addressed, F4 new. Reviewed at 5ed55e0 |
…round AnalysisScope.TemplateMemo no longer wraps the battery on master, so the statement that #546 composes with it is removed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Quick summary
With no alternative limit, sequential untraced HermitCrab analysis runs one slot batch for templates with identical trailing slots. Sharing requires the same morphological rule objects in the same order and the same optionality, while retaining each template's output order and first-seen words. Tracing, parallel walks, finite alternative limits, custom compiled templates, changed slot optionality, and grammars without shared tails use the original battery.
Where to look
SharedWalkMatchesPerTemplateWalkInOrdercompares both ordered HermitCrabWordequality and completeAnalysisStateKeysequences across four grammar arrangements and 2,904 input/state combinations.UntracedBatteryRunsSharedSlotBatchOncepins 2 batches -> 1, then verifies the next call executes again; actually disabling sharing fails withExpected: 1; But was: 2, and restoring it passes.TracedAndParallelBatteriesKeepPerTemplateWalk,SharedWalkPreservesBatteryAlternativeLimit,AlternativeLimitStopsBeforeLaterTemplateAdmission, andChangedSlotOptionalityPreservesPerTemplateWalkcover tracing, parallelism, early limits, and mutable optionality. The latter two reproduced three failures before the compatibility guards were added.AnalysisStratumRule.ApplyTemplateBatterystill wraps the same battery boundary; the full HermitCrab suite covers the existing memo and merge-equivalent analysis contracts.Deliberately not included
Parallel sharing needs a separate design for
ParallelApplySlots' layered breadth-first queue. This change shares the sequential depth-first walk; the existing parallel implementation remains in use. Corpus measurements are deterministic samples with capped pairs excluded; full-corpus parity and CI coverage remain unverified.Validation
Commands ran with WSL
~/.dotnet, existing NuGet caches, package sources cleared by an uncommitted temporaryNuGet.Config, and bounded worker counts. No network was used and the config is excluded from the commit.dotnet test tests/SIL.Machine.Morphology.HermitCrab.Tests -c Release --no-restore -m:1-- 126 passed, 0 failed, 0 skipped in the summary; the existing explicit corpus test is not selected by default../local_check.sh-- FAILED (build test): SentencePiece's native build cannot findcmake(MSB3073, exit 127). Restore and CSharpier passed; no steps were skipped../local_check.sh --agent-strict-- FAILED (build test) for the same missing CMake dependency; the blocking comment scan, restore, and CSharpier passed. These local runs do not collect CI coverage.git diff --check aab237b2...HEAD-- clean.The PR #480-head self-check runner was copied outside the worktree and built with a ProjectReference to this HermitCrab project (0 warnings/errors). Its loaded assembly hash matches this worktree's Release assembly. All 60 fixtures were attempted with
--include-pathological, both normally and with--no-memoization; fixture contents and self-check assertions were unchanged. The no-memoization flag selects degree 0, exercising the original parallel path.aab237b2The requested 60/60 baseline could not be reproduced. Both assemblies fail traced-rule attribution in
boundary-leftover-in-narrowing-lhs-strrep;deep-optional-affix-nestingalso crosses its 15-second budget in three runs. The latter has no shared slot tails and uses the original walk. These conformance and native-build blockers remain for caller review.Exact runner invocations, repeated against the unchanged base assembly:
Issue / porting context
This is new work relative to PR #490, not row 2's memo: that memo reduces battery invocations, while this change reduces repeated slot batches inside one invocation. The precedent is sillsdev/PanGloss ledger entry 095,
docs/divergences/095-shared-template-slot-batches.md, and itsstratum.rsslot trie.Parity argument and measured evidence
Each trie edge represents the same ordered rules and optionality beneath the same preceding slots in last-slot-first walk order. Every admitted template below it therefore reaches the edge with the same word its own walk reaches; a slot batch depends on that word and the rules, without template identity. Recursing through batch outputs in their existing order, then taking the optional unchanged-word continuation, preserves each template's exact depth-first emission sequence and admits or loses no parses.
Every template has its own output set, and those sets are unioned in template order with the existing comparer. The same first-seen representatives and ordered words therefore reach downstream deduplication and merge-equivalent folding. Admissions remain per template. Positive limits use the original walk to retain early termination; slot count/optionality changes also fall back, preserving the existing mutable-slot behavior.
All intermediate words and outputs are local to one battery call; only topology, configuration snapshots, and compiled rules persist.
AnalysisScope.TemplateMemostill avoids a battery on a hit and stores the same complete outputs on a miss. No memo keys, retained-word bounds, replay rules, or trace events change.Single-threaded measurements compare the original per-template walk (sharing disabled) with sharing enabled, using the same final source and a new analysis scope for each parse. Temporary counters exist only in the output-directory build. Both modes use the existing memo and are warmed, with their order alternated per input.
All completed segmentable pairs have identical morpheme-ID/surface signature lists after ordinal sorting, including multiplicity: zero differences and zero errors. Sena additionally has 28 matching invalid-shape outcomes and no capped pairs; Mbugwe excludes 61 pairs that hit a two-second watchdog in either mode. Samples select 200 evenly spaced nonempty rows from each existing word list. No corpus words, parse examples, private-project data, or grammar contents are included here or copied into the worktree.
The fixture is the only PR #480 grammar with shared trailing slots, identified by a structural scan of rule order and optionality; one ten-word pass executes 20 -> 10 batches. Wall times sum only completed
ParseWordcalls, exclude loading/signature formatting, and were collected under concurrent local validation load with counters/watchdogs, so they are secondary figures.🤖 Generated with Claude Code
This change is