Complete task002 through task016 across cache correctness, editor lifecycle, C boundaries, build and release governance, dictionary provenance, performance, interactive workflows, tests, documentation, and final cleanup.
67 lines
2.5 KiB
Markdown
67 lines
2.5 KiB
Markdown
# Complete DP Cache Signatures Instead of Invalidation Watchers
|
|
|
|
## Context
|
|
|
|
`ekp-para` caches width-dependent DP and rendered results. The old key was
|
|
only the line width, with a special `(width . looseness)` cons when looseness
|
|
was non-zero. Two failures followed:
|
|
|
|
- changing a cost parameter reused a result computed under the old value;
|
|
- the cons key never hit an `eql` hash table when reconstructed.
|
|
|
|
The DP reads six cost parameters at runtime, so paragraph identity alone
|
|
cannot make those cached results valid.
|
|
|
|
## Decision
|
|
|
|
Use one flat signature containing line width, looseness, and all six runtime
|
|
cost parameters. Compare keys with structural `equal`.
|
|
|
|
Paragraph-construction inputs remain in `ekp--para-key`; DP-only inputs
|
|
remain in `ekp--dp-key`. No cache-clearing side effect crosses that boundary.
|
|
|
|
## Alternatives Rejected
|
|
|
|
### Variable watchers that clear caches
|
|
|
|
Watchers would spread ownership across seven variables and discard
|
|
width-independent paragraph work. Forgetting the next parameter would
|
|
silently recreate the bug.
|
|
|
|
### An integer hash of all parameters
|
|
|
|
A hash collision would become a correctness failure. Structural keys make
|
|
collisions harmless because equality is still checked.
|
|
|
|
### A memoized global signature object
|
|
|
|
It saves small list allocations but adds mutable global state and comparison
|
|
logic. A 100,000-hit microbenchmark measured approximately 0.37 seconds for
|
|
the complete key versus 0.17 seconds for the old scalar key: about two
|
|
microseconds per lookup, below the cost threshold that would justify another
|
|
state owner.
|
|
|
|
## Consequences
|
|
|
|
- Algorithm changes take effect on the next call without manual flushing.
|
|
- Returning to a previous parameter set can reuse its prior cached result.
|
|
- Non-zero looseness now receives real cache hits.
|
|
- Cache lookup performs structural hashing over eight small scalar values.
|
|
- Each distinct parameter set can retain its own result in the paragraph
|
|
cache; normal interactive configuration has low cardinality, but a caller
|
|
that sweeps parameters should clear caches between experiments.
|
|
- No public API, C ABI, saved-file format, or paragraph representation
|
|
changed.
|
|
|
|
## Verification
|
|
|
|
- The old model failed both the parameter-isolation and identical-signature
|
|
tests.
|
|
- The new model passes all six parameter cases and the cache-identity check.
|
|
- Full ERT, C/Elisp fuzz, warning-clean byte compilation, and checkdoc pass.
|
|
|
|
## Rollback
|
|
|
|
Revert the key/table change and these regression tests. No migration or data
|
|
cleanup is necessary because caches are process-local.
|