Repository navigation
HermitCrab analysis: lean trace keeps shape text instead of Word objects #563
Description
TraceManager retains about 1 GB on the worst Mbugwe word because every trace node pins a Word or a deep clone of one. The smallest trigger is parsing Mbugwe yɔɔna with IsTracing = true: 1,031.95 MiB retained (peak 1,035 MiB) for 21,200 analysis events and 41,130 synthesis steps. Any CLI, test or API user who traces a heavy word can run out of memory, while consumers read only shape strings.
Problem (census, memory)
Study: C2-trace-memory.md in the round inputs. TraceManager appends one Trace node per callback and never removes one. Nodes pin a Word by live reference, or by Word.Clone() at six sites (TraceManager.cs:38, 49, 130, 136, 185, 202). Each Word carries its own shape, node feature structures and dictionaries. Measured retained trace: Mbugwe yɔɔna 1,031.95 MiB, kojeema 1,009 MiB, woocha 667 MiB; Aweti tsãnekozokwawut 652 MiB. Per counted step about 17 KB on yɔɔna, 3.4 KB to 36 KB across heavy words. A traced census run that pins no Words peaked at 203.31 MiB over all 40 Mbugwe words (an inference, not a like-for-like measurement). FieldWorks Try-a-Word uses its own FwXmlTraceManager, which keeps strings only, so FieldWorks is unaffected; this concerns the CLI, tests and API.
This is a memory track: steps are 0% by construction.
Proposed change
Add an opt-in TraceManager.RetainWords (default true, behaviour unchanged). When false, no callback stores a Word and no Clone() runs; each node stores the text the CLI would print (regex form for analysis node types, as ParseCommand.cs:78-98) in new read-only Trace.InputText and OutputText, computed at most once per frozen Word in an internal per-Word field that the copy constructor does not copy (no dictionary keyed on words). In full mode the text properties are filled lazily. The CLI sets RetainWords = false. XML docs state that Input and Output are null in lean mode.
Soundness
Does not touch the search: analysis events, synthesis steps and parses are identical by construction, verified by tests (same node types, sources, subrule indices, failure reasons and text node by node in both modes; parses equal with tracing off, full and lean; CLI output byte-identical on the test grammar).
Memory bound
Text per distinct traced Word (about 50-150 bytes) plus the node itself (about 120 bytes, estimated). Freed with the trace. Retained trace bytes est. -90 to -97% (a study estimate, unmeasured), so yɔɔna falls from about 1 GB to the order of tens of MB.
Measurement plan
Add a parse_product_trace_lean arm beside the existing product-trace arm in the census harness context mode. Per word report allocated MB, peak MB, retained trace MB, node count and parse count for both arms on Mbugwe (stride 40), Aweti (stride 2), Sena (stride 100), Amharic (limit 28), Indonesian (all 70) and conformance. Steps check: census counts identical with and without the change on Indonesian and Mbugwe yɔɔna. Stress fixture "Deep derivation": one unordered stratum, 10 optional derivational suffixes with short ambiguous allomorphs, 15 roots, 10 long words (6-9 suffixes) so the tree grows combinatorially.
Kill criterion
If lean mode cuts retained trace bytes on yɔɔna by under 50%, stop and report what still holds the memory (node count, Word.CurrentTrace links, text, other). Any change in parses or step counts: blocked.
Overlaps
- PR Trace HermitCrab failure reasons and template slot outcomes #534 adds node kinds and fields to
Traceand pins rejected intermediate words, so it likely makes trace memory worse (unmeasured; measure on yɔɔna before landing). The lean mode must project Trace HermitCrab failure reasons and template slot outcomes #534's fields too if Trace HermitCrab failure reasons and template slot outcomes #534 lands first; they are strings, IDs and reasons, so they carry over directly. - No ledger row covers trace memory. Independent of the pruning issues, and also reduces trace nodes only if those land.
- Flipping the default of
RetainWordsis a separate owner decision.
Related
- PR HermitCrab optimization round record: what was tried, and a faster package that is not mergeable #490: HermitCrab optimization round record (ledger rows cited above are in it).
- PR Add a conformance suite for HermitCrab, with its adequacy argument #480: HermitCrab conformance suite. Conformance per-fixture verdicts must be identical with and without the change.
- Units: deterministic analysis events and synthesis steps, never ms. "% less work" = (off - on) / off per grammar, never pooled. Census figures are ceilings unless stated. Ranges marked "est." are estimates that the shadow phase replaces with measurements.
- Owner constraint: no memo or cache; any new structure must be grammar-sized and at most a few MB.
🤖 Generated with Claude Code
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fields🆕 New
Activity