depends-on: #2638
True multi-step lazy2 deferral at L7/L8 — the untried half of #2765
#2765 proposed two libdeflate mechanisms; only the cost-based accept rule landed (now lazyAcceptCost). The multi-step deferral was never implemented and #2765 was closed. The lazy loop still does exactly one pos+1 probe and then commits.
libdeflate's deflate_compress_lazy2 keeps deferring while each next position strictly improves: on a better lookahead it emits the pending byte as a literal and re-probes at pos+2, pos+3, … catching cascading-improvement runs that a single lookahead misses. This is the one L7/L8 ratio lever lazyAcceptCost did not capture.
Plan (measurement-first)
- Restructure the lazy loop's accept arm into a deferral loop (emit literal, advance one, re-probe) with libdeflate's depth ladder (full / half / quarter), bounded by a small step cap.
- Measure ratio + speed at L7/L8 on both corpora before proof work.
- Keep it only if it clears a real ratio win at acceptable speed.
Heuristic — the matcher contracts are quantified over the lookahead, so proof churn is re-threading the loop's termination/measure. More restructuring than the accept-rule change was, but the ratio is the reason to do it.
Risk: our matcher differs from libdeflate's (no length-3 coverage below L-deep, different insertion policy), so their thresholds may not transfer; the spike finds out cheaply.
🤖 Prepared with Claude Code
depends-on: #2638
True multi-step lazy2 deferral at L7/L8 — the untried half of #2765
#2765 proposed two libdeflate mechanisms; only the cost-based accept rule landed (now
lazyAcceptCost). The multi-step deferral was never implemented and #2765 was closed. The lazy loop still does exactly onepos+1probe and then commits.libdeflate's
deflate_compress_lazy2keeps deferring while each next position strictly improves: on a better lookahead it emits the pending byte as a literal and re-probes atpos+2,pos+3, … catching cascading-improvement runs that a single lookahead misses. This is the one L7/L8 ratio leverlazyAcceptCostdid not capture.Plan (measurement-first)
Heuristic — the matcher contracts are quantified over the lookahead, so proof churn is re-threading the loop's termination/measure. More restructuring than the accept-rule change was, but the ratio is the reason to do it.
Risk: our matcher differs from libdeflate's (no length-3 coverage below L-deep, different insertion policy), so their thresholds may not transfer; the spike finds out cheaply.
🤖 Prepared with Claude Code