Repository navigation
perf(formatter): render compact SELECT/INSERT/UPDATE/DELETE through SQL() [W5-02] - #904
Conversation
…QL() [W5-02] The compact formatter walked every statement with the visitor renderer, building many intermediate strings, although the statements' SQL() methods already produce the same compact spelling. formatStatement now returns SQL() for SelectStatement, InsertStatement, UpdateStatement and DeleteStatement when the options are compact (no clause newlines, no semicolon, no line width, no target dialect, keyword case preserve or upper). Lowercase keywords, target-dialect rewrites, SetOperation (nil sides print "()" in SQL()) and AlterTable (SQL() drops commas) stay on the visitor renderer, kept as formatStatementSlow. formatAST also skips the parts slice and join for a single statement without comments or an execute slash, still applying Unicode-identifier restoration and the statement terminator. Tests: a differential test compares the fast and slow paths over every statement in the real-world corpora (27,383 statements parsed in each of 9 dialects) for preserve/upper/lower keyword case, every target dialect and three indent settings: 492,894 comparisons, 0 mismatches. M4, GOGC=off -cpu 1, 10 interleaved rounds, the 11 compare queries: Render/compact -27.5% to -47.9% (geomean -39.3%), B/op -75%, allocs/op 1 for every query (-90%); Normalize -8.0% and Fingerprint -7.1% time, allocs -37% to -39%. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DnbRnTFErhoMJdAjVEeCg2
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Claude finished @ajitpratap0's task in 21s —— View job Review of PR #904: compact SQL() fast pathVerdict: looks good. I found no blocking issues. I read the diff and compared the new single-statement shortcut in Correctness
Risks and suggestions (all non-blocking)
Security: No concerns. The change adds no new input handling or I/O. Test coverage: Strong. Beyond the differential and option-matrix tests, there are Unicode-identifier and nil tests, plus benchmarks. |
…e-0 matrix [W5-02] Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DnbRnTFErhoMJdAjVEeCg2
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DnbRnTFErhoMJdAjVEeCg2
|
Claude finished @ajitpratap0's task in 20s —— View job Review of PR #904: compact
|
Perf gate: PASS (shadow mode: report only, this check never fails)Base
Rules: time regresses at >= +3% with p < 0.01 (Mann-Whitney U), or a suite geomean >= +1.5% (per-round geomeans, same test); allocs/op must not increase; B/op must not rise more than 2%; instructions/op must not rise more than 1.5%. An A/A control with more than 10% of benchmarks moving over 3% is noisy: re-run once, then inconclusive (neutral). Gated suite (GOGC=off, GOMAXPROCS=1)
A/A control: 0 of 32 benchmarks moved more than 3%. Instructions per operation (cmd/perfdriver)
Secondary metric: default GC, GOMAXPROCS=1 (informational)
Environmentbenchstat (primary metric) |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DnbRnTFErhoMJdAjVEeCg2
… fast path taken [W5-02] Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DnbRnTFErhoMJdAjVEeCg2
|
Claude finished @ajitpratap0's task in 19s —— View job Review of PR #904: compact
|
…ble; guard NewlinePerClause [W5-02] fast_eligible now counts only the four allowlisted statement types, and TestCompactFastOptions gains a NewlinePerClause-only case so the formatter package kills a mutation removing that guard. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DnbRnTFErhoMJdAjVEeCg2
|
Claude finished @ajitpratap0's task in 13s —— View job Review of PR #904: compact
|
|
Claude finished @ajitpratap0's task in 13s —— View job Review of PR #904: compact
|
Summary
Wave-1 task W5-02 (FMT-1) from the 2026-11 performance audit. The prototype was confirmed by an independent verifier; Codex ported it, and Opus reviewed it and ran the full gate.
Compact formatting used to walk each statement with the visitor renderer, which builds many intermediate strings, even though each statement's
SQL()already produces the same compact text.formatStatementnow returnsSQL()forSelectStatement,InsertStatement,UpdateStatementandDeleteStatementwhen all of these hold:formatStatementSlow):SetOperation, whoseSQL()prints()for a nil sideAlterTable, whoseSQL()drops commas (fixed separately in W5-02b)formatASTskips the parts slice and join. It still applies Unicode-identifier restoration and the statement terminator. This matches the general loop for one statement, including batch separators.Test Plan
TestCompactFastDifferential. It compares the fast path with the slow path, forced by setting a line width because the visitor ignores line width..sqlfile undertestdata/(259 files: 89 realworld, 40 corpus, 130 other), parsed in each of 9 dialects, whole-file and split on;\n.fast_eligiblecounts only comparisons where the statement is one of the four allowlisted types, the dialect is empty and keyword case is not lower (the test fails if it is 0).TestCompactFastOptionscovers option combinations, including anewline_per_clausecase (NewlinePerClause without AddSemicolon), so the formatter package alone catches removal of that guard (mutation-checked).TestCompactFastFormatASTSingleStatementandTestCompactFastFormatASTHandBuiltCommentsguard the single-statementformatASTshortcut (terminator, execute slash, hand-built comments).go run honnef.co/go/tools/cmd/staticcheck@latest ./pkg/formatter/...task check(includes W0-02 goldens, unchanged)task test:cbindinggo test -count=1 ./pkg/compatibility/...Re-measured after merging wave 0 (origin/main 160c417). Local
scripts/perf/ab.sh(same harness astask bench:ab): Apple M4,GOGC=off,-cpu 1, 10 interleaved base/head rounds, benchstat alpha 0.01, benchmark names from the wave-0 matrix (PLAN 2.2). The branch's own duplicateBenchmarkRenderwas dropped in favour of the matrix one. W0-02 goldens and the fulltask checkpass with no golden change. Machine is shared, so numbers are indicative; the CI gate below is authoritative. Raw output:scratchpad/perf/wave1/w5-02/ab.txt.Render/compact/*(11)Fingerprint/*(11)Normalize/*(11)The plan target was
Render/compact/*<= -30% with 1 alloc andFingerprint/complex<= -5%. Ten of 11 compact queries clear -30%;select_wherereaches -27.2% (reported, not chased).Fingerprint/complexis -10.2%.Render/sql/*is unchanged (control).CI perf gate (shadow, amd64, authoritative): PASS (table below is from head f2e016f; later commits only change tests, the gate on a237070/ada67d9d is noted at the end of this section) (check "A/B perf gate (shadow)" plus the sticky PR comment; A/A control: 0 of 32 benchmarks moved more than 3%).
Normalize/simple_select-10.80%,Normalize/join-15.18%,Normalize/complex-15.21% (all p<0.001), B/op -14% to -17%, allocs 10->7, 40->23, 110->69.Normalize/simple_select-11.83%,Normalize/join-16.75%,Normalize/complex-16.33% (all p<0.001), B/op -13.9% to -17.2%, allocs 10->7, 40->23, 110->69; suite geomean -1.63% (p<0.001); A/A control within +/-0.6%; no gated regression.Render/compact/*, so that target is covered by the local table above only (arm64, indicative); the amd64 evidence is the Normalize gain, which exercises the same fast path.Breaking Changes
None. The output is byte-identical (see the differential test).
🤖 Generated with Claude Code
https://claude.ai/code/session_01DnbRnTFErhoMJdAjVEeCg2