Skip to content

refactor(parser): move token classification into internal/tokclass [W3-03a1] - #947

Open
ajitpratap0 wants to merge 6 commits into
mainfrom
perf/w3-03a1-tokclass
Open

ajitpratap0 wants to merge 6 commits into
mainfrom
perf/w3-03a1-tokclass

Conversation

@ajitpratap0

@ajitpratap0 ajitpratap0 commented Nov 3, 2026 •

Copy link
Copy Markdown
Owner

Summary

Pure move of the parser-facing token classification (compound split tables, IDENT/KEYWORD remap, COUNT..MAX -> IDENT, backtick width, type gate) from pkg/sql/parser/preprocess.go into internal/tokclass. preprocess.go keeps only the loop. Adds a parser-mode differential harness against a frozen copy of the old pass, ready for W3-03b to plug in the tokenizer parser-ready mode. Perf-neutral; no public API change.

Test Plan

  • task check pass, task test:cbinding pass, go test -count=1 ./pkg/compatibility/... pass, staticcheck clean on tokclass/parser/tokenizer.
  • Differential + coupling tests and race runs of touched packages pass (Codex evidence under scratch). One CTE timing smoke test flaked under machine load in a Codex run (2823 vs 1400 ns/op) and passed on rerun in task check.
  • CI perf-gate (layout-randomized, 20 layouts/arm, sticky comment 6612455785, base 8889402, head 0da5924 = PR head 4b58a19 merged with main; driver workflow_dispatch run 42320036752 on 4b58a19 agrees, geomean -0.02% p 0.841): PASS, "no gated metric moved past its threshold". Suite geomean -0.17% (p 0.174). A/A' control: 0 of 52 benchmarks moved more than 3% (suite geomean +0.11%, p 0.678), so the run was not noisy. allocs/op unchanged on all rows except LintRW/mariadb 16563 -> 16562 (improvement); B/op +-0.00%. Low power section: LintRule/L010 (spread 17.74%), LintRW/snowflake (4.60%), ParseError/long_prefix/validate (3.51%) and LintRW/clickhouse (3.33%); none is a target of this PR, and allocs/op, B/op and the suite geomean still guard them.
  • The PLAN target benchmarks ParseStage/preprocess and PreprocessTokens are not in the gated suite, so the gate judges this change only through ParseE2E, ParseRW and ParseFresh.
  • Local task bench:ab BASE=a72ec74d (indicative only, shared M4; 20 layouts): preprocess geomean +0.02%, allocs/op and B/op identical.
Gate table
benchmark time p A/A' spread B/op allocs/op status
ParseE2E/simple_select +0.80% 0.218 +0.62% 1.60% +0.00% 5 → 5 ok
ParseE2E/select_where -0.62% 0.120 +0.85% 1.33% +0.00% 18 → 18 ok
ParseE2E/join -0.35% 0.317 +0.43% 1.83% +0.00% 17 → 17 ok
ParseE2E/aggregate +0.44% 0.433 +1.47% 1.79% +0.00% 18 → 18 ok
ParseE2E/subquery +0.18% 0.655 +1.20% 1.15% +0.00% 14 → 14 ok
ParseE2E/cte -0.09% 0.882 +0.36% 1.57% +0.00% 21 → 21 ok
ParseE2E/window -0.53% 0.116 +0.39% 0.76% +0.00% 11 → 11 ok
ParseE2E/complex -0.58% 0.327 +0.05% 1.39% +0.00% 49 → 49 ok
ParseE2E/insert -0.78% 0.086 -0.14% 1.26% +0.00% 17 → 17 ok
ParseE2E/update -0.61% 0.203 +0.26% 1.88% +0.00% 13 → 13 ok
ParseE2E/delete -0.40% 0.570 +0.55% 2.44% +0.00% 5 → 5 ok
ParseRW/postgresql/medium -0.17% 0.820 -0.28% 1.68% +0.00% 646 → 646 ok
ParseRW/mysql/medium +0.01% 0.978 +0.04% 1.19% +0.00% 368 → 368 ok
ParseRW/mariadb/medium +0.45% 0.192 +0.03% 1.11% -0.00% 528 → 528 ok
ParseRW/sqlserver/medium -0.75% 0.174 -0.41% 1.78% -0.00% 927 → 927 ok
ParseRW/oracle/medium -0.37% 0.253 -0.13% 1.22% -0.00% 1090 → 1090 ok
ParseRW/sqlite/medium +0.00% 1.000 +1.21% 2.23% +0.00% 347 → 347 ok
ParseRW/snowflake/medium -0.82% 0.026 -0.51% 1.31% +0.00% 776 → 776 ok
ParseRW/clickhouse/medium -0.47% 0.678 +0.05% 2.68% +0.00% 383 → 383 ok
ParseFresh/simple_select -0.56% 0.344 -0.11% 2.25% +0.00% 6 → 6 ok
ParseFresh/join -0.72% 0.107 -0.55% 1.78% +0.00% 18 → 18 ok
ParseFresh/complex -0.52% 0.317 +0.27% 1.27% +0.00% 50 → 50 ok
PoolGetPut/serial -0.37% 0.218 -0.53% 1.16% +0.00% 0 → 0 ok
Tokenize/scratch/join +0.51% 0.507 +0.40% 1.91% +0.00% 0 → 0 ok
Tokenize/scratch/complex +0.46% 0.279 +0.14% 1.78% +0.00% 0 → 0 ok
Tokenize/scratch/insert +0.95% 0.433 +1.81% 2.93% +0.00% 0 → 0 ok
Normalize/simple_select +0.02% 0.989 +0.15% 0.86% +0.00% 7 → 7 ok
Normalize/join +0.10% 0.808 -0.17% 1.18% +0.00% 23 → 23 ok
Normalize/complex -0.06% 0.883 -0.38% 1.32% +0.00% 68 → 68 ok
TransformParse/simple_select +0.39% 0.386 -0.03% 1.16% +0.00% 5 → 5 ok
TransformParse/join +0.20% 0.636 +0.60% 1.17% +0.00% 17 → 17 ok
TransformParse/complex -0.18% 0.738 -0.92% 1.51% +0.00% 49 → 49 ok
LintParallel/rules +0.54% 0.495 +0.62% 1.81% +0.00% 68931 → 68931 ok
LintParallel/lint -0.07% 0.841 -0.62% 1.53% -0.00% 133239 → 133239 ok
LintRW/postgresql -0.74% 0.060 -0.87% 0.85% +0.00% 14798 → 14798 ok
LintRW/mysql -0.82% 0.165 -1.41% 1.58% -0.00% 18252 → 18252 ok
LintRW/mariadb -0.18% 0.925 -0.07% 2.65% -0.00% 16563 → 16562 ok
LintRW/sqlserver -0.19% 0.640 -0.01% 1.16% -0.00% 14526 → 14526 ok
LintRW/oracle -0.39% 0.369 -0.87% 1.61% +0.00% 17804 → 17804 ok
LintRW/sqlite +0.32% 0.779 -0.70% 1.08% -0.00% 16521 → 16521 ok
LintRW/snowflake -0.05% 0.968 -0.55% 4.60% -0.00% 16113 → 16113 ok
LintRW/clickhouse +0.80% 0.369 -0.94% 3.33% +0.00% 18657 → 18657 ok
LintRule/L007 -0.13% 0.758 +0.23% 1.74% +0.00% 1194 → 1194 ok
LintRule/L010 +0.06% 0.678 +0.11% 17.74% +0.00% 0 → 0 ok
ParseError/syntax_mid/parse -0.46% 0.228 +0.10% 1.50% +0.00% 12 → 12 ok
ParseError/syntax_mid/validate -0.56% 0.213 +0.18% 1.27% +0.00% 12 → 12 ok
ParseError/syntax_end/parse -0.67% 0.317 +0.23% 1.51% +0.00% 16 → 16 ok
ParseError/syntax_end/validate -0.40% 0.626 +1.07% 2.73% +0.00% 16 → 16 ok
ParseError/tokenize/parse -0.52% 0.409 +0.17% 1.03% +0.00% 4 → 4 ok
ParseError/tokenize/validate -0.16% 0.797 +0.82% 2.68% +0.00% 21 → 21 ok
ParseError/long_prefix/parse -0.40% 0.383 +0.44% 2.81% +0.00% 219 → 219 ok
ParseError/long_prefix/validate -0.32% 0.820 +0.90% 3.51% +0.00% 219 → 219 ok
geomean -0.17% 0.174 +0.11%
Local benchstat sec/op (indicative)
                                    │   sec/op    │   sec/op     vs base               │
PreprocessTokens/Upper                653.5n ± 1%   653.7n ± 1%       ~ (p=0.995 n=20)
PreprocessTokens/Lower                658.9n ± 1%   656.7n ± 1%       ~ (p=0.606 n=20)
ParseStage/preprocess/simple_select   41.12n ± 0%   41.17n ± 1%       ~ (p=0.499 n=20)
ParseStage/preprocess/select_where    115.9n ± 0%   115.8n ± 0%       ~ (p=0.804 n=20)
ParseStage/preprocess/join            227.6n ± 1%   227.6n ± 0%       ~ (p=0.836 n=20)
ParseStage/preprocess/aggregate       120.0n ± 0%   119.8n ± 0%       ~ (p=0.846 n=20)
ParseStage/preprocess/subquery        91.07n ± 0%   91.05n ± 0%       ~ (p=0.963 n=20)
ParseStage/preprocess/cte             151.5n ± 0%   151.6n ± 0%       ~ (p=0.693 n=20)
ParseStage/preprocess/window          109.0n ± 0%   109.2n ± 0%       ~ (p=0.112 n=20)
ParseStage/preprocess/complex         629.4n ± 1%   630.7n ± 0%       ~ (p=0.963 n=20)
ParseStage/preprocess/insert          82.49n ± 0%   82.63n ± 0%       ~ (p=0.693 n=20)
ParseStage/preprocess/update          70.75n ± 0%   70.81n ± 0%       ~ (p=0.825 n=20)
ParseStage/preprocess/delete          41.65n ± 1%   41.61n ± 0%       ~ (p=0.311 n=20)
geomean                               145.3n        145.3n       +0.02%

Breaking Changes

None.

🤖 Generated with Claude Code

https://claude.ai/code/session_01DnbRnTFErhoMJdAjVEeCg2

Test and others added 2 commits November 3, 2026 23:12
…th differential harness [W3-03a1]

Pure move of compound tables, IDENT/KEYWORD remap, COUNT..MAX -> IDENT and
backtick width rules; preprocess.go keeps only the loop. Adds a parser-mode
differential harness against a frozen copy of the old pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DnbRnTFErhoMJdAjVEeCg2
@vercel

vercel Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
gosqlx-website Ready Ready Preview Nov 6, 2026 9:21pm UTC

@github-actions

github-actions Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

Claude finished @ajitpratap0's task in 16s —— View job


Review of PR #947 (token classification move into internal/tokclass)

I read the production code (tokclass.go, compound.go, the new preprocess.go). I did not run the build or tests, and I only skimmed the large test files and remap.go.

Summary: This is a clean, well-documented refactor. preprocess.go shrinks to the loop, and the rules now live in one package that has no dependency on the parser.

Code quality

  • The package boundary is good. It imports only pkg/models and strings, and its tables are read-only, so it is safe for concurrent use.
  • The tests (TestGateIsHoleFree, the fast-path equivalence tests, and the tokenizer coupling test) are the right guard against drift between the inlined loop and tokclass.AppendReady.
  • preprocessTokensInto duplicates the body of AppendReady on purpose, to keep the gate inline. That is documented and covered by equivalence tests. If benchmarks show the compiler inlines AppendReady anyway, calling it directly would remove the duplication. The perf-gate result should decide this.

Potential issues (minor)

  1. CompoundParts does a linear scan over 11 entries for every generic keyword token. strings.EqualFold runs only when the lengths match, so the cost is small. A cheap pre-check such as "value contains a space" would skip the scan for the common single-word keyword. This is optional and should be measured before changing.
  2. CompoundPartsByKey is a linear scan and the table comment says it is "sorted by key". Nothing enforces the sort order. If a binary search is added later, a test asserting the order would be needed. Confirm tables_test.go already covers it.
  3. AppendCompound and CompoundParts hand out shared slices. The comments say not to mutate them, and AppendCompound copies the elements. CompoundParts is exported from an internal package, so the risk is contained. A caller that mutates the returned slice would corrupt global state for every parse.
  4. NormalizeInPlace sets the backtick quote from the span-width rule. This is moved behaviour, so it is fine. The Start.Line != 0 guard is subtle, and a test pointing at that case would help. The differential harness against the frozen legacy copy probably covers it.

Performance

  • This should be neutral. The same calls are made, and Gate, AppendCompound and NormalizeInPlace are small and likely to inline. The PR itself says the perf-gate verdict is pending, so wait for it.
  • The CTE timing smoke test that flaked (2823 vs 1400 ns/op) is a load-sensitive wall-clock check. Per the repo rules, it should not be loosened to hide the flake. If it flakes again in CI, investigate rather than relax the threshold.

Security: No concerns. There is no I/O, no unsafe code and no new input surface.

Test coverage: Coverage is strong: tables, gate completeness, parser-mode differential tests against a frozen legacy pass, and a tokenizer coupling test. The race and norace test files handle the build-tag split. Be aware that legacy_preprocess_test.go (638 lines) and tokstream_equiv_test.go (727 lines) are large. Make sure they are removed or repurposed once W3-03b lands, so the frozen copy does not linger.

Other

  • The CHANGELOG entry is present and "Breaking Changes: None" is accurate, since the package is internal.

Verdict: Looks good to merge once the perf-gate passes and task check is green in CI. Nothing here blocks the merge.

@github-actions github-actions Bot added documentation Improvements or additions to documentation parser tokenizer Tokenizer / lexer changes labels Nov 3, 2026
@github-actions

github-actions Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

Perf gate: PASS (shadow mode: report only, this check never fails)

Base 888940264f80, head 0da59249f30e. 20 interleaved rounds, 20 randomized code layouts per arm (-randlayout seeds 422958208822..422958208841; A/A' 422958208842..422958208861), benchtime 100ms, -cpu 1, GOMEMLIMIT 64MiB, pinned to CPU 3 (SMT siblings 2-3) with taskset.

Runner CPU: AMD EPYC 7763 64-Core Processor (x86_64). Base and head ran interleaved in this job, so the tables show their ratios only; absolute timings (raw files in the artifact) hold for this CPU and this job alone and are never compared across jobs.

  • no gated metric moved past its threshold

Rules: each arm runs 20 randomized code layouts (-ldflags=-randlayout); time regresses at >= +3% when significant at a false discovery rate of 0.01 over the suite (Benjamini-Hochberg on exact Mann-Whitney U p-values of the per-layout medians, so a regression must hold across layouts, not within one binary), or a suite geomean >= +1.5% (per-layout suite 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%. The A/A' control runs the base revision under a disjoint set of layout seeds; when more than 10% of benchmarks move over 3% in it, the run is noisy: re-run once, then inconclusive (neutral).

Gated suite (GOGC=off, GOMAXPROCS=1)

benchmark time p A/A' spread B/op allocs/op status
ParseE2E/simple_select +0.80% 0.218 +0.62% 1.60% +0.00% 5 → 5 ok
ParseE2E/select_where -0.62% 0.120 +0.85% 1.33% +0.00% 18 → 18 ok
ParseE2E/join -0.35% 0.317 +0.43% 1.83% +0.00% 17 → 17 ok
ParseE2E/aggregate +0.44% 0.433 +1.47% 1.79% +0.00% 18 → 18 ok
ParseE2E/subquery +0.18% 0.655 +1.20% 1.15% +0.00% 14 → 14 ok
ParseE2E/cte -0.09% 0.882 +0.36% 1.57% +0.00% 21 → 21 ok
ParseE2E/window -0.53% 0.116 +0.39% 0.76% +0.00% 11 → 11 ok
ParseE2E/complex -0.58% 0.327 +0.05% 1.39% +0.00% 49 → 49 ok
ParseE2E/insert -0.78% 0.086 -0.14% 1.26% +0.00% 17 → 17 ok
ParseE2E/update -0.61% 0.203 +0.26% 1.88% +0.00% 13 → 13 ok
ParseE2E/delete -0.40% 0.570 +0.55% 2.44% +0.00% 5 → 5 ok
ParseRW/postgresql/medium -0.17% 0.820 -0.28% 1.68% +0.00% 646 → 646 ok
ParseRW/mysql/medium +0.01% 0.978 +0.04% 1.19% +0.00% 368 → 368 ok
ParseRW/mariadb/medium +0.45% 0.192 +0.03% 1.11% -0.00% 528 → 528 ok
ParseRW/sqlserver/medium -0.75% 0.174 -0.41% 1.78% -0.00% 927 → 927 ok
ParseRW/oracle/medium -0.37% 0.253 -0.13% 1.22% -0.00% 1090 → 1090 ok
ParseRW/sqlite/medium +0.00% 1.000 +1.21% 2.23% +0.00% 347 → 347 ok
ParseRW/snowflake/medium -0.82% 0.026 -0.51% 1.31% +0.00% 776 → 776 ok
ParseRW/clickhouse/medium -0.47% 0.678 +0.05% 2.68% +0.00% 383 → 383 ok
ParseFresh/simple_select -0.56% 0.344 -0.11% 2.25% +0.00% 6 → 6 ok
ParseFresh/join -0.72% 0.107 -0.55% 1.78% +0.00% 18 → 18 ok
ParseFresh/complex -0.52% 0.317 +0.27% 1.27% +0.00% 50 → 50 ok
PoolGetPut/serial -0.37% 0.218 -0.53% 1.16% +0.00% 0 → 0 ok
Tokenize/scratch/join +0.51% 0.507 +0.40% 1.91% +0.00% 0 → 0 ok
Tokenize/scratch/complex +0.46% 0.279 +0.14% 1.78% +0.00% 0 → 0 ok
Tokenize/scratch/insert +0.95% 0.433 +1.81% 2.93% +0.00% 0 → 0 ok
Normalize/simple_select +0.02% 0.989 +0.15% 0.86% +0.00% 7 → 7 ok
Normalize/join +0.10% 0.808 -0.17% 1.18% +0.00% 23 → 23 ok
Normalize/complex -0.06% 0.883 -0.38% 1.32% +0.00% 68 → 68 ok
TransformParse/simple_select +0.39% 0.386 -0.03% 1.16% +0.00% 5 → 5 ok
TransformParse/join +0.20% 0.636 +0.60% 1.17% +0.00% 17 → 17 ok
TransformParse/complex -0.18% 0.738 -0.92% 1.51% +0.00% 49 → 49 ok
LintParallel/rules +0.54% 0.495 +0.62% 1.81% +0.00% 68931 → 68931 ok
LintParallel/lint -0.07% 0.841 -0.62% 1.53% -0.00% 133239 → 133239 ok
LintRW/postgresql -0.74% 0.060 -0.87% 0.85% +0.00% 14798 → 14798 ok
LintRW/mysql -0.82% 0.165 -1.41% 1.58% -0.00% 18252 → 18252 ok
LintRW/mariadb -0.18% 0.925 -0.07% 2.65% -0.00% 16563 → 16562 ok
LintRW/sqlserver -0.19% 0.640 -0.01% 1.16% -0.00% 14526 → 14526 ok
LintRW/oracle -0.39% 0.369 -0.87% 1.61% +0.00% 17804 → 17804 ok
LintRW/sqlite +0.32% 0.779 -0.70% 1.08% -0.00% 16521 → 16521 ok
LintRW/snowflake -0.05% 0.968 -0.55% 4.60% -0.00% 16113 → 16113 ok
LintRW/clickhouse +0.80% 0.369 -0.94% 3.33% +0.00% 18657 → 18657 ok
LintRule/L007 -0.13% 0.758 +0.23% 1.74% +0.00% 1194 → 1194 ok
LintRule/L010 +0.06% 0.678 +0.11% 17.74% +0.00% 0 → 0 ok
ParseError/syntax_mid/parse -0.46% 0.228 +0.10% 1.50% +0.00% 12 → 12 ok
ParseError/syntax_mid/validate -0.56% 0.213 +0.18% 1.27% +0.00% 12 → 12 ok
ParseError/syntax_end/parse -0.67% 0.317 +0.23% 1.51% +0.00% 16 → 16 ok
ParseError/syntax_end/validate -0.40% 0.626 +1.07% 2.73% +0.00% 16 → 16 ok
ParseError/tokenize/parse -0.52% 0.409 +0.17% 1.03% +0.00% 4 → 4 ok
ParseError/tokenize/validate -0.16% 0.797 +0.82% 2.68% +0.00% 21 → 21 ok
ParseError/long_prefix/parse -0.40% 0.383 +0.44% 2.81% +0.00% 219 → 219 ok
ParseError/long_prefix/validate -0.32% 0.820 +0.90% 3.51% +0.00% 219 → 219 ok
geomean -0.17% 0.174 +0.11%

time and A/A' are Hodges-Lehmann shifts over the per-layout medians. spread: the base arm's robust standard deviation across its layouts (1.4826 x MAD, relative), i.e. how much this benchmark moves between builds that differ only in function placement, plus run-to-run noise; a change much smaller than it cannot be resolved in one run.

A/A' control (base revision, disjoint layout seeds): 0 of 52 benchmarks moved more than 3%; 0 would have been flagged by the time rule; suite geomean +0.11%, p 0.678.

Low power

4 benchmark(s) have under 80% estimated power to be flagged on their own for a +5% slowdown (their spread across layouts is too wide for 20 layouts at the Benjamini-Hochberg level alpha/m = 0.000192). A slowdown below the last column usually goes unflagged there; instructions/op, allocs/op and the suite geomean still guard them.

benchmark spread power at +5% slowdown caught 80% of the time
LintRule/L010 17.74% 0% +30.0%
LintRW/snowflake 4.60% 33% +7.0%
ParseError/long_prefix/validate 3.51% 72% +5.3%
LintRW/clickhouse 3.33% 79% +5.1%

Power is estimated with the normal approximation for the U test (Noether): power = Phi(ln(1+shift)/s * sqrt(K/2) * sqrt(3/pi) - z(1 - alpha/(2m))), with s the spread and K the layouts per arm.

Instructions per operation (cmd/perfdriver)

case instructions/op status
e2e/aggregate +0.03% ok
e2e/complex -0.03% ok
e2e/cte +0.00% ok
e2e/delete +0.05% ok
e2e/insert -0.03% ok
e2e/join -0.01% ok
e2e/select_where -0.00% ok
e2e/simple_select +0.03% ok
e2e/subquery +0.09% ok
e2e/update +0.09% ok
e2e/window +0.08% ok
rw/postgresql/medium -0.02% ok
Secondary metric: default GC, GOMAXPROCS=1 (informational)
benchmark time p
ParseE2E/simple_select +1.75% 0.011
ParseE2E/select_where +0.48% 0.427
ParseE2E/join +1.05% 0.173
ParseE2E/aggregate -0.47% 0.353
ParseE2E/subquery +0.40% 0.529
ParseE2E/cte +0.48% 0.796
ParseE2E/window +1.14% 0.257
ParseE2E/complex -0.48% 0.353
ParseE2E/insert +0.06% 0.940
ParseE2E/update -0.29% 0.496
ParseE2E/delete +1.22% 0.290
ParseRW/postgresql/medium -0.04% 0.971
ParseRW/mysql/medium -0.02% 0.912
ParseRW/mariadb/medium -0.32% 0.853
ParseRW/sqlserver/medium -0.26% 0.684
ParseRW/oracle/medium +0.53% 0.481
ParseRW/sqlite/medium +0.25% 0.436
ParseRW/snowflake/medium +0.25% 0.631
ParseRW/clickhouse/medium -0.08% 1.000
ParseFresh/simple_select +0.20% 0.853
ParseFresh/join -0.89% 0.280
ParseFresh/complex -0.10% 0.971
PoolGetPut/serial +0.01% 1.000
Tokenize/scratch/join +0.57% 0.496
Tokenize/scratch/complex +0.75% 0.256
Tokenize/scratch/insert +1.40% 0.481
Normalize/simple_select +0.17% 0.734
Normalize/join -0.23% 0.631
Normalize/complex +0.15% 0.853
TransformParse/simple_select -1.11% 0.096
TransformParse/join +0.24% 0.734
TransformParse/complex -0.11% 0.791
LintParallel/rules +0.79% 0.579
LintParallel/lint +0.18% 0.684
LintRW/postgresql +1.06% 0.007
LintRW/mysql +0.34% 0.123
LintRW/mariadb +0.37% 0.393
LintRW/sqlserver +0.69% 0.393
LintRW/oracle +0.84% 0.123
LintRW/sqlite +1.00% 0.089
LintRW/snowflake +3.07% 0.052
LintRW/clickhouse +0.57% 0.315
LintRule/L007 -2.43% 0.023
LintRule/L010 +0.34% 0.393
ParseError/syntax_mid/parse -0.72% 0.427
ParseError/syntax_mid/validate +0.28% 0.850
ParseError/syntax_end/parse +0.35% 0.450
ParseError/syntax_end/validate +0.41% 0.450
ParseError/tokenize/parse -0.04% 1.000
ParseError/tokenize/validate -0.47% 0.529
ParseError/long_prefix/parse -1.44% 0.075
ParseError/long_prefix/validate +0.85% 0.190
geomean +0.24%
Environment
date:        2026-11-06T21:23:03Z
base:        888940264f803d7fd1df46132b21e09807e0a26d
head:        working tree of 0da59249f30ea3879b930ffed766372e55386034
cpu model:   AMD EPYC 7763 64-Core Processor (x86_64)
go:          go version go1.26.9 linux/amd64
kernel:      Linux 7.0.0-1017-azure x86_64
layouts:     20 per arm, -ldflags=-randlayout seeds 422958208822..422958208841 (base, head), 422958208842..422958208861 (A/A')
pinning:     pinned to CPU 3 (SMT siblings 2-3) with taskset
gcoff env:   GOGC=off GOMEMLIMIT=64MiB
clocksource: tsc
load:        8.20, 3.19, 1.18
instr count: cachegrind
perf probe:  Error: No supported events found. The instructions:u event is not supported. 

Architecture:                            x86_64
CPU(s):                                  4
Model name:                              AMD EPYC 7763 64-Core Processor
Thread(s) per core:                      2
Core(s) per socket:                      2
Socket(s):                               1
Hypervisor vendor:                       Microsoft
L1d cache:                               64 KiB (2 instances)
L1i cache:                               64 KiB (2 instances)
L2 cache:                                1 MiB (2 instances)
L3 cache:                                32 MiB (1 instance)
benchstat (primary metric, samples pooled across layouts: informational, the verdict uses the per-layout test)
goos: linux
goarch: amd64
pkg: github.com/ajitpratap0/GoSQLX/pkg/fingerprint
cpu: AMD EPYC 7763 64-Core Processor                
                        │    base     │                head                │
                        │   sec/op    │   sec/op     vs base               │
Normalize/simple_select   2.340µ ± 1%   2.333µ ± 1%       ~ (p=0.984 n=20)
Normalize/join            7.163µ ± 1%   7.165µ ± 1%       ~ (p=0.805 n=20)
Normalize/complex         19.76µ ± 1%   19.72µ ± 1%       ~ (p=0.883 n=20)
geomean                   6.919µ        6.908µ       -0.16%

                        │     base     │                 head                  │
                        │     B/op     │     B/op      vs base                 │
Normalize/simple_select     896.0 ± 0%     896.0 ± 0%       ~ (p=1.000 n=20) ¹
Normalize/join            2.211Ki ± 0%   2.211Ki ± 0%       ~ (p=1.000 n=20) ¹
Normalize/complex         6.117Ki ± 0%   6.117Ki ± 0%       ~ (p=1.000 n=20) ¹
geomean                   2.279Ki        2.279Ki       +0.00%
¹ all samples are equal

                        │    base    │                head                 │
                        │ allocs/op  │ allocs/op   vs base                 │
Normalize/simple_select   7.000 ± 0%   7.000 ± 0%       ~ (p=1.000 n=20) ¹
Normalize/join            23.00 ± 0%   23.00 ± 0%       ~ (p=1.000 n=20) ¹
Normalize/complex         68.00 ± 0%   68.00 ± 0%       ~ (p=1.000 n=20) ¹
geomean                   22.20        22.20       +0.00%
¹ all samples are equal

pkg: github.com/ajitpratap0/GoSQLX/pkg/gosqlx
                                │    base     │                head                │
                                │   sec/op    │   sec/op     vs base               │
ParseE2E/simple_select            1.621µ ± 2%   1.635µ ± 1%       ~ (p=0.218 n=20)
ParseE2E/select_where             3.461µ ± 1%   3.440µ ± 0%       ~ (p=0.119 n=20)
ParseE2E/join                     4.622µ ± 1%   4.594µ ± 1%       ~ (p=0.317 n=20)
ParseE2E/aggregate                3.437µ ± 1%   3.448µ ± 1%       ~ (p=0.433 n=20)
ParseE2E/subquery                 3.104µ ± 1%   3.118µ ± 1%       ~ (p=0.654 n=20)
ParseE2E/cte                      4.445µ ± 1%   4.439µ ± 1%       ~ (p=0.877 n=20)
ParseE2E/window                   2.916µ ± 1%   2.898µ ± 1%       ~ (p=0.116 n=20)
ParseE2E/complex                  12.17µ ± 1%   12.09µ ± 1%       ~ (p=0.327 n=20)
ParseE2E/insert                   2.173µ ± 1%   2.152µ ± 1%       ~ (p=0.085 n=20)
ParseE2E/update                   1.935µ ± 1%   1.928µ ± 1%       ~ (p=0.203 n=20)
ParseE2E/delete                   1.246µ ± 2%   1.237µ ± 1%       ~ (p=0.569 n=20)
ParseRW/postgresql/medium         169.0µ ± 1%   169.4µ ± 1%       ~ (p=0.820 n=20)
ParseRW/mysql/medium              96.47µ ± 1%   96.48µ ± 1%       ~ (p=0.974 n=20)
ParseRW/mariadb/medium            137.4µ ± 1%   138.2µ ± 1%       ~ (p=0.192 n=20)
ParseRW/sqlserver/medium          274.3µ ± 2%   274.0µ ± 1%       ~ (p=0.174 n=20)
ParseRW/oracle/medium             325.3µ ± 1%   324.4µ ± 1%       ~ (p=0.253 n=20)
ParseRW/sqlite/medium             72.35µ ± 3%   72.39µ ± 2%       ~ (p=0.995 n=20)
ParseRW/snowflake/medium          190.1µ ± 1%   188.8µ ± 1%       ~ (p=0.026 n=20)
ParseRW/clickhouse/medium         89.18µ ± 2%   89.41µ ± 3%       ~ (p=0.678 n=20)
ParseFresh/simple_select          7.102µ ± 2%   7.032µ ± 1%       ~ (p=0.344 n=20)
ParseFresh/join                   11.48µ ± 1%   11.39µ ± 1%       ~ (p=0.107 n=20)
ParseFresh/complex                20.61µ ± 1%   20.53µ ± 1%       ~ (p=0.317 n=20)
PoolGetPut/serial                 67.23n ± 1%   67.03n ± 2%       ~ (p=0.218 n=20)
ParseError/syntax_mid/parse       2.419µ ± 1%   2.413µ ± 1%       ~ (p=0.229 n=20)
ParseError/syntax_mid/validate    2.166µ ± 1%   2.155µ ± 1%       ~ (p=0.213 n=20)
ParseError/syntax_end/parse       2.799µ ± 1%   2.782µ ± 1%       ~ (p=0.317 n=20)
ParseError/syntax_end/validate    2.632µ ± 2%   2.616µ ± 2%       ~ (p=0.625 n=20)
ParseError/tokenize/parse         910.9n ± 1%   907.5n ± 1%       ~ (p=0.410 n=20)
ParseError/tokenize/validate      2.823µ ± 2%   2.820µ ± 1%       ~ (p=0.794 n=20)
ParseError/long_prefix/parse      60.02µ ± 2%   59.68µ ± 1%       ~ (p=0.383 n=20)
ParseError/long_prefix/validate   56.29µ ± 3%   56.23µ ± 1%       ~ (p=0.820 n=20)
geomean                           9.512µ        9.486µ       -0.28%

                                │     base     │                head                 │
                                │     B/s      │     B/s       vs base               │
ParseE2E/simple_select            15.30Mi ± 2%   15.16Mi ± 1%       ~ (p=0.208 n=20)
ParseE2E/select_where             28.38Mi ± 1%   28.55Mi ± 0%       ~ (p=0.126 n=20)
ParseE2E/join                     26.00Mi ± 1%   26.16Mi ± 1%       ~ (p=0.311 n=20)
ParseE2E/aggregate                23.31Mi ± 1%   23.23Mi ± 1%       ~ (p=0.410 n=20)
ParseE2E/subquery                 25.19Mi ± 1%   25.09Mi ± 1%       ~ (p=0.635 n=20)
ParseE2E/cte                      26.60Mi ± 1%   26.64Mi ± 1%       ~ (p=0.878 n=20)
ParseE2E/window                   30.74Mi ± 1%   30.93Mi ± 1%       ~ (p=0.109 n=20)
ParseE2E/complex                  29.63Mi ± 1%   29.83Mi ± 1%       ~ (p=0.331 n=20)
ParseE2E/insert                   33.35Mi ± 1%   33.68Mi ± 1%       ~ (p=0.087 n=20)
ParseE2E/update                   27.10Mi ± 1%   27.21Mi ± 1%       ~ (p=0.199 n=20)
ParseE2E/delete                   39.81Mi ± 2%   40.10Mi ± 1%       ~ (p=0.578 n=20)
ParseRW/postgresql/medium         21.23Mi ± 1%   21.18Mi ± 1%       ~ (p=0.815 n=20)
ParseRW/mysql/medium              28.06Mi ± 1%   28.05Mi ± 1%       ~ (p=0.952 n=20)
ParseRW/mariadb/medium            25.80Mi ± 1%   25.67Mi ± 1%       ~ (p=0.189 n=20)
ParseRW/sqlserver/medium          24.25Mi ± 2%   24.28Mi ± 1%       ~ (p=0.172 n=20)
ParseRW/oracle/medium             25.77Mi ± 1%   25.84Mi ± 1%       ~ (p=0.250 n=20)
ParseRW/sqlite/medium             28.55Mi ± 3%   28.53Mi ± 2%       ~ (p=0.995 n=20)
ParseRW/snowflake/medium          26.75Mi ± 1%   26.93Mi ± 1%       ~ (p=0.027 n=20)
ParseRW/clickhouse/medium         25.27Mi ± 2%   25.21Mi ± 3%       ~ (p=0.678 n=20)
ParseError/syntax_mid/parse       18.93Mi ± 1%   18.96Mi ± 1%       ~ (p=0.250 n=20)
ParseError/syntax_mid/validate    21.13Mi ± 1%   21.24Mi ± 1%       ~ (p=0.213 n=20)
ParseError/syntax_end/parse       13.29Mi ± 1%   13.37Mi ± 1%       ~ (p=0.317 n=20)
ParseError/syntax_end/validate    14.13Mi ± 2%   14.22Mi ± 2%       ~ (p=0.635 n=20)
ParseError/tokenize/parse         48.17Mi ± 1%   48.34Mi ± 1%       ~ (p=0.410 n=20)
ParseError/tokenize/validate      15.54Mi ± 2%   15.55Mi ± 1%       ~ (p=0.773 n=20)
ParseError/long_prefix/parse      38.49Mi ± 2%   38.70Mi ± 1%       ~ (p=0.380 n=20)
ParseError/long_prefix/validate   41.04Mi ± 3%   41.08Mi ± 1%       ~ (p=0.825 n=20)
geomean                           25.50Mi        25.56Mi       +0.23%

                                │      base      │                 head                  │
                                │      B/op      │     B/op      vs base                 │
ParseE2E/simple_select              816.0 ± 0%       816.0 ± 0%       ~ (p=1.000 n=20) ¹
ParseE2E/select_where             1.523Ki ± 0%     1.523Ki ± 0%       ~ (p=1.000 n=20) ¹
ParseE2E/join                     1.836Ki ± 0%     1.836Ki ± 0%       ~ (p=1.000 n=20) ¹
ParseE2E/aggregate                1.812Ki ± 0%     1.812Ki ± 0%       ~ (p=1.000 n=20) ¹
ParseE2E/subquery                 1.828Ki ± 0%     1.828Ki ± 0%       ~ (p=1.000 n=20) ¹
ParseE2E/cte                      2.336Ki ± 0%     2.336Ki ± 0%       ~ (p=1.000 n=20) ¹
ParseE2E/window                   1.281Ki ± 0%     1.281Ki ± 0%       ~ (p=1.000 n=20) ¹
ParseE2E/complex                  5.025Ki ± 0%     5.025Ki ± 0%       ~ (p=1.000 n=20) ¹
ParseE2E/insert                     824.0 ± 0%       824.0 ± 0%       ~ (p=1.000 n=20) ¹
ParseE2E/update                     736.0 ± 0%       736.0 ± 0%       ~ (p=1.000 n=20) ¹
ParseE2E/delete                     400.0 ± 0%       400.0 ± 0%       ~ (p=1.000 n=20) ¹
ParseRW/postgresql/medium         65.91Ki ± 0%     65.91Ki ± 0%       ~ (p=0.955 n=20)
ParseRW/mysql/medium              42.37Ki ± 0%     42.37Ki ± 0%       ~ (p=1.000 n=20)
ParseRW/mariadb/medium            60.61Ki ± 0%     60.61Ki ± 0%       ~ (p=0.546 n=20)
ParseRW/sqlserver/medium          83.68Ki ± 0%     83.68Ki ± 0%       ~ (p=0.011 n=20)
ParseRW/oracle/medium             104.8Ki ± 0%     104.8Ki ± 0%       ~ (p=0.418 n=20)
ParseRW/sqlite/medium             38.12Ki ± 0%     38.12Ki ± 0%       ~ (p=1.000 n=20) ¹
ParseRW/snowflake/medium          77.63Ki ± 0%     77.63Ki ± 0%       ~ (p=0.480 n=20)
ParseRW/clickhouse/medium         34.82Ki ± 0%     34.82Ki ± 0%       ~ (p=1.000 n=20) ¹
ParseFresh/simple_select            896.0 ± 0%       896.0 ± 0%       ~ (p=1.000 n=20) ¹
ParseFresh/join                   1.914Ki ± 0%     1.914Ki ± 0%       ~ (p=1.000 n=20) ¹
ParseFresh/complex                5.102Ki ± 0%     5.102Ki ± 0%       ~ (p=1.000 n=20) ¹
PoolGetPut/serial                   0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=20) ¹
ParseError/syntax_mid/parse         680.0 ± 0%       680.0 ± 0%       ~ (p=1.000 n=20) ¹
ParseError/syntax_mid/validate      680.0 ± 0%       680.0 ± 0%       ~ (p=1.000 n=20) ¹
ParseError/syntax_end/parse       1.430Ki ± 0%     1.430Ki ± 0%       ~ (p=1.000 n=20) ¹
ParseError/syntax_end/validate    1.430Ki ± 0%     1.430Ki ± 0%       ~ (p=1.000 n=20) ¹
ParseError/tokenize/parse           272.0 ± 0%       272.0 ± 0%       ~ (p=1.000 n=20) ¹
ParseError/tokenize/validate      1.758Ki ± 0%     1.758Ki ± 0%       ~ (p=1.000 n=20) ¹
ParseError/long_prefix/parse      22.75Ki ± 0%     22.75Ki ± 0%       ~ (p=0.332 n=20)
ParseError/long_prefix/validate   22.68Ki ± 0%     22.68Ki ± 0%       ~ (p=1.000 n=20) ¹
geomean                                        ²                 -0.00%                ²
¹ all samples are equal
² summaries must be >0 to compute geomean

                                │     base      │                 head                 │
                                │   allocs/op   │  allocs/op   vs base                 │
ParseE2E/simple_select             5.000 ± 0%      5.000 ± 0%       ~ (p=1.000 n=20) ¹
ParseE2E/select_where              18.00 ± 0%      18.00 ± 0%       ~ (p=1.000 n=20) ¹
ParseE2E/join                      17.00 ± 0%      17.00 ± 0%       ~ (p=1.000 n=20) ¹
ParseE2E/aggregate                 18.00 ± 0%      18.00 ± 0%       ~ (p=1.000 n=20) ¹
ParseE2E/subquery                  14.00 ± 0%      14.00 ± 0%       ~ (p=1.000 n=20) ¹
ParseE2E/cte                       21.00 ± 0%      21.00 ± 0%       ~ (p=1.000 n=20) ¹
ParseE2E/window                    11.00 ± 0%      11.00 ± 0%       ~ (p=1.000 n=20) ¹
ParseE2E/complex                   49.00 ± 0%      49.00 ± 0%       ~ (p=1.000 n=20) ¹
ParseE2E/insert                    17.00 ± 0%      17.00 ± 0%       ~ (p=1.000 n=20) ¹
ParseE2E/update                    13.00 ± 0%      13.00 ± 0%       ~ (p=1.000 n=20) ¹
ParseE2E/delete                    5.000 ± 0%      5.000 ± 0%       ~ (p=1.000 n=20) ¹
ParseRW/postgresql/medium          646.0 ± 0%      646.0 ± 0%       ~ (p=1.000 n=20) ¹
ParseRW/mysql/medium               368.0 ± 0%      368.0 ± 0%       ~ (p=1.000 n=20) ¹
ParseRW/mariadb/medium             528.0 ± 0%      528.0 ± 0%       ~ (p=1.000 n=20) ¹
ParseRW/sqlserver/medium           927.0 ± 0%      927.0 ± 0%       ~ (p=1.000 n=20) ¹
ParseRW/oracle/medium             1.090k ± 0%     1.090k ± 0%       ~ (p=1.000 n=20) ¹
ParseRW/sqlite/medium              347.0 ± 0%      347.0 ± 0%       ~ (p=1.000 n=20) ¹
ParseRW/snowflake/medium           776.0 ± 0%      776.0 ± 0%       ~ (p=1.000 n=20) ¹
ParseRW/clickhouse/medium          383.0 ± 0%      383.0 ± 0%       ~ (p=1.000 n=20) ¹
ParseFresh/simple_select           6.000 ± 0%      6.000 ± 0%       ~ (p=1.000 n=20) ¹
ParseFresh/join                    18.00 ± 0%      18.00 ± 0%       ~ (p=1.000 n=20) ¹
ParseFresh/complex                 50.00 ± 0%      50.00 ± 0%       ~ (p=1.000 n=20) ¹
PoolGetPut/serial                  0.000 ± 0%      0.000 ± 0%       ~ (p=1.000 n=20) ¹
ParseError/syntax_mid/parse        12.00 ± 0%      12.00 ± 0%       ~ (p=1.000 n=20) ¹
ParseError/syntax_mid/validate     12.00 ± 0%      12.00 ± 0%       ~ (p=1.000 n=20) ¹
ParseError/syntax_end/parse        16.00 ± 0%      16.00 ± 0%       ~ (p=1.000 n=20) ¹
ParseError/syntax_end/validate     16.00 ± 0%      16.00 ± 0%       ~ (p=1.000 n=20) ¹
ParseError/tokenize/parse          4.000 ± 0%      4.000 ± 0%       ~ (p=1.000 n=20) ¹
ParseError/tokenize/validate       21.00 ± 0%      21.00 ± 0%       ~ (p=1.000 n=20) ¹
ParseError/long_prefix/parse       219.0 ± 0%      219.0 ± 0%       ~ (p=1.000 n=20) ¹
ParseError/long_prefix/validate    219.0 ± 0%      219.0 ± 0%       ~ (p=1.000 n=20) ¹
geomean                                       ²                +0.00%                ²
¹ all samples are equal
² summaries must be >0 to compute geomean

                          │    base     │                head                │
                          │  sec/stmt   │  sec/stmt    vs base               │
ParseRW/postgresql/medium   14.09µ ± 1%   14.12µ ± 1%       ~ (p=0.805 n=20)
ParseRW/mysql/medium        12.06µ ± 1%   12.06µ ± 1%       ~ (p=0.984 n=20)
ParseRW/mariadb/medium      15.27µ ± 1%   15.35µ ± 1%       ~ (p=0.194 n=20)
ParseRW/sqlserver/medium    13.06µ ± 2%   13.05µ ± 1%       ~ (p=0.167 n=20)
ParseRW/oracle/medium       13.56µ ± 1%   13.52µ ± 1%       ~ (p=0.253 n=20)
ParseRW/sqlite/medium       12.06µ ± 3%   12.06µ ± 2%       ~ (p=0.995 n=20)
ParseRW/snowflake/medium    14.62µ ± 1%   14.52µ ± 1%       ~ (p=0.026 n=20)
ParseRW/clickhouse/medium   12.74µ ± 2%   12.77µ ± 3%       ~ (p=0.678 n=20)
geomean                     13.39µ        13.39µ       -0.00%

pkg: github.com/ajitpratap0/GoSQLX/pkg/linter
                   │     base     │                head                 │
                   │    sec/op    │    sec/op     vs base               │
LintParallel/rules   19.71m ±  2%   19.84m ±  2%       ~ (p=0.495 n=20)
LintParallel/lint    39.01m ±  1%   39.02m ±  2%       ~ (p=0.841 n=20)
LintRW/postgresql    5.081m ±  1%   5.046m ±  1%       ~ (p=0.060 n=20)
LintRW/mysql         5.410m ±  1%   5.417m ±  2%       ~ (p=0.165 n=20)
LintRW/mariadb       4.885m ±  2%   4.925m ±  3%       ~ (p=0.925 n=20)
LintRW/sqlserver     4.664m ±  1%   4.645m ±  1%       ~ (p=0.640 n=20)
LintRW/oracle        5.599m ±  1%   5.585m ±  1%       ~ (p=0.369 n=20)
LintRW/sqlite        4.555m ±  1%   4.539m ±  2%       ~ (p=0.779 n=20)
LintRW/snowflake     4.762m ±  3%   4.744m ±  3%       ~ (p=0.968 n=20)
LintRW/clickhouse    5.249m ±  3%   5.329m ±  2%       ~ (p=0.369 n=20)
LintRule/L007        2.719m ±  2%   2.712m ±  1%       ~ (p=0.758 n=20)
LintRule/L010        791.2µ ± 12%   883.7µ ± 21%       ~ (p=0.678 n=20)
geomean              5.433m         5.486m        +0.99%

                  │     base     │                head                 │
                  │     B/s      │     B/s       vs base               │
LintRW/postgresql   5.574Mi ± 1%   5.612Mi ± 1%       ~ (p=0.049 n=20)
LintRW/mysql        6.046Mi ± 1%   6.037Mi ± 2%       ~ (p=0.158 n=20)
LintRW/mariadb      6.247Mi ± 2%   6.194Mi ± 3%       ~ (p=0.878 n=20)
LintRW/sqlserver    6.642Mi ± 1%   6.671Mi ± 1%       ~ (p=0.587 n=20)
LintRW/oracle       7.095Mi ± 1%   7.110Mi ± 1%       ~ (p=0.394 n=20)
LintRW/sqlite       6.299Mi ± 1%   6.323Mi ± 2%       ~ (p=0.743 n=20)
LintRW/snowflake    6.547Mi ± 3%   6.576Mi ± 3%       ~ (p=0.984 n=20)
LintRW/clickhouse   6.185Mi ± 3%   6.094Mi ± 2%       ~ (p=0.350 n=20)
geomean             6.315Mi        6.313Mi       -0.04%

                   │      base      │                 head                  │
                   │      B/op      │     B/op      vs base                 │
LintParallel/rules   5.559Mi ± 0%     5.559Mi ± 0%       ~ (p=0.474 n=20)
LintParallel/lint    18.19Mi ± 0%     18.19Mi ± 0%       ~ (p=0.815 n=20)
LintRW/postgresql    1.992Mi ± 0%     1.992Mi ± 0%       ~ (p=0.931 n=20)
LintRW/mysql         2.538Mi ± 0%     2.538Mi ± 0%       ~ (p=0.733 n=20)
LintRW/mariadb       2.312Mi ± 0%     2.312Mi ± 0%       ~ (p=0.498 n=20)
LintRW/sqlserver     1.996Mi ± 0%     1.996Mi ± 0%       ~ (p=0.106 n=20)
LintRW/oracle        2.469Mi ± 0%     2.469Mi ± 0%       ~ (p=0.053 n=20)
LintRW/sqlite        2.206Mi ± 0%     2.205Mi ± 0%       ~ (p=0.026 n=20)
LintRW/snowflake     2.203Mi ± 0%     2.203Mi ± 0%       ~ (p=0.663 n=20)
LintRW/clickhouse    2.476Mi ± 0%     2.476Mi ± 0%       ~ (p=0.292 n=20)
LintRule/L007        92.98Ki ± 0%     92.98Ki ± 0%       ~ (p=1.000 n=20) ¹
LintRule/L010          0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=20) ¹
geomean                           ²                 +0.00%                ²
¹ all samples are equal
² summaries must be >0 to compute geomean

                   │     base      │                 head                 │
                   │   allocs/op   │  allocs/op   vs base                 │
LintParallel/rules   68.93k ± 0%     68.93k ± 0%       ~ (p=0.760 n=20)
LintParallel/lint    133.2k ± 0%     133.2k ± 0%       ~ (p=0.914 n=20)
LintRW/postgresql    14.80k ± 0%     14.80k ± 0%       ~ (p=0.661 n=20)
LintRW/mysql         18.25k ± 0%     18.25k ± 0%       ~ (p=0.661 n=20)
LintRW/mariadb       16.56k ± 0%     16.56k ± 0%       ~ (p=0.527 n=20)
LintRW/sqlserver     14.53k ± 0%     14.53k ± 0%       ~ (p=1.000 n=20)
LintRW/oracle        17.80k ± 0%     17.80k ± 0%       ~ (p=1.000 n=20) ¹
LintRW/sqlite        16.52k ± 0%     16.52k ± 0%       ~ (p=0.231 n=20)
LintRW/snowflake     16.11k ± 0%     16.11k ± 0%       ~ (p=1.000 n=20) ¹
LintRW/clickhouse    18.66k ± 0%     18.66k ± 0%       ~ (p=0.661 n=20)
LintRule/L007        1.194k ± 0%     1.194k ± 0%       ~ (p=1.000 n=20) ¹
LintRule/L010         0.000 ± 0%      0.000 ± 0%       ~ (p=1.000 n=20) ¹
geomean                          ²                -0.00%                ²
¹ all samples are equal
² summaries must be >0 to compute geomean

                  │     base     │                head                 │
                  │   sec/stmt   │   sec/stmt    vs base               │
LintRW/postgresql   16.66µ ±  1%   16.54µ ±  1%       ~ (p=0.053 n=20)
LintRW/mysql        13.07µ ±  1%   13.09µ ±  2%       ~ (p=0.159 n=20)
LintRW/mariadb      12.85µ ±  2%   12.96µ ±  3%       ~ (p=0.910 n=20)
LintRW/sqlserver    16.84µ ±  1%   16.77µ ±  1%       ~ (p=0.640 n=20)
LintRW/oracle       15.21µ ±  1%   15.18µ ±  1%       ~ (p=0.369 n=20)
LintRW/sqlite       13.09µ ±  1%   13.04µ ±  2%       ~ (p=0.773 n=20)
LintRW/snowflake    14.56µ ±  3%   14.51µ ±  3%       ~ (p=0.968 n=20)
LintRW/clickhouse   13.32µ ±  3%   13.53µ ±  2%       ~ (p=0.365 n=20)
LintRule/L007       966.7n ±  2%   964.1n ±  1%       ~ (p=0.758 n=20)
LintRule/L010       281.3n ± 12%   314.1n ± 21%       ~ (p=0.625 n=20)
geomean             7.404µ         7.487µ        +1.12%

pkg: github.com/ajitpratap0/GoSQLX/pkg/sql/tokenizer
                         │    base     │                head                │
                         │   sec/op    │   sec/op     vs base               │
Tokenize/scratch/join      1.476µ ± 1%   1.482µ ± 1%       ~ (p=0.507 n=20)
Tokenize/scratch/complex   3.906µ ± 2%   3.938µ ± 3%       ~ (p=0.279 n=20)
Tokenize/scratch/insert    732.3n ± 2%   741.2n ± 2%       ~ (p=0.433 n=20)
geomean                    1.616µ        1.629µ       +0.80%

                         │     base     │                head                 │
                         │     B/s      │     B/s       vs base               │
Tokenize/scratch/join      81.42Mi ± 1%   81.12Mi ± 1%       ~ (p=0.512 n=20)
Tokenize/scratch/complex   92.31Mi ± 2%   91.55Mi ± 3%       ~ (p=0.292 n=20)
Tokenize/scratch/insert    98.98Mi ± 2%   97.78Mi ± 2%       ~ (p=0.433 n=20)
geomean                    90.61Mi        89.89Mi       -0.80%

                         │     base     │                head                 │
                         │     B/op     │    B/op     vs base                 │
Tokenize/scratch/join      0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=20) ¹
Tokenize/scratch/complex   0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=20) ¹
Tokenize/scratch/insert    0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=20) ¹
geomean                               ²               +0.00%                ²
¹ all samples are equal
² summaries must be >0 to compute geomean

                         │     base     │                head                 │
                         │  allocs/op   │ allocs/op   vs base                 │
Tokenize/scratch/join      0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=20) ¹
Tokenize/scratch/complex   0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=20) ¹
Tokenize/scratch/insert    0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=20) ¹
geomean                               ²               +0.00%                ²
¹ all samples are equal
² summaries must be >0 to compute geomean

pkg: github.com/ajitpratap0/GoSQLX/pkg/transform
                             │    base     │                head                │
                             │   sec/op    │   sec/op     vs base               │
TransformParse/simple_select   1.534µ ± 2%   1.543µ ± 2%       ~ (p=0.387 n=20)
TransformParse/join            4.985µ ± 1%   4.984µ ± 1%       ~ (p=0.635 n=20)
TransformParse/complex         13.11µ ± 1%   13.09µ ± 1%       ~ (p=0.738 n=20)
geomean                        4.646µ        4.652µ       +0.13%

                             │     base     │                 head                  │
                             │     B/op     │     B/op      vs base                 │
TransformParse/simple_select     816.0 ± 0%     816.0 ± 0%       ~ (p=1.000 n=20) ¹
TransformParse/join            1.836Ki ± 0%   1.836Ki ± 0%       ~ (p=1.000 n=20) ¹
TransformParse/complex         5.023Ki ± 0%   5.023Ki ± 0%       ~ (p=1.000 n=20) ¹
geomean                        1.944Ki        1.944Ki       +0.00%
¹ all samples are equal

                             │    base    │                head                 │
                             │ allocs/op  │ allocs/op   vs base                 │
TransformParse/simple_select   5.000 ± 0%   5.000 ± 0%       ~ (p=1.000 n=20) ¹
TransformParse/join            17.00 ± 0%   17.00 ± 0%       ~ (p=1.000 n=20) ¹
TransformParse/complex         49.00 ± 0%   49.00 ± 0%       ~ (p=1.000 n=20) ¹
geomean                        16.09        16.09       +0.00%
¹ all samples are equal

Run, raw data and benchstat

@github-actions

github-actions Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

Claude finished @ajitpratap0's task in 24s —— View job


Review of PR #947 (token classification move into internal/tokclass)

I read tokclass.go, the new preprocess.go diff, and the removed code it replaces. I did not run the build or tests. I skimmed remap.go, compound.go and the large test files, so the notes below on those files are not backed by a full read.

Summary: This is a clean move. preprocess.go shrinks to the loop. The rules now sit in one package that imports only pkg/models and strings. The loop in preprocessTokensInto keeps the same logic as before.

What looks good

  • Gate, NormalizeInPlace and AppendCompound are small, so they should inline. The perf-gate agrees: allocs/op and B/op are unchanged on all 52 rows, and instructions/op are within ±0.1%.
  • preprocessTokensInto deliberately repeats the body of tokclass.AppendReady. A comment says so, and TestPreprocessFastPath_EveryTokenType and TestPreprocessFastPath_Corpus check the two agree. I'd keep this unless a benchmark shows the compiler inlines AppendReady anyway. In that case, call it directly and drop the duplicate.
  • The tests cover the right risks: TestGateIsHoleFree, the differential harness against a frozen legacy pass, and the tokenizer coupling test.
  • "Breaking Changes: None" is accurate, since the package is internal.

Minor suggestions (none block the merge)

  1. CompoundParts linearly scans 11 entries for every generic keyword token. The length check makes it cheap. The benchmarks show no change, so leave it unless profiling points here.
  2. CompoundParts returns a shared slice. The comments say not to mutate it, and AppendCompound copies the elements. Because the package is internal, the risk stays contained. Add a test that fails if a table entry changes after a parse, if you don't already have one.
  3. NormalizeInPlace has a subtle guard, Start.Line != 0 && Start.Line == End.Line, before the backtick-width rule. The legacy differential probably covers it. If it doesn't, add a direct case for a zero-line span and for a multi-line span.
  4. legacy_preprocess_test.go (638 lines) and tokstream_equiv_test.go (727 lines) are large. Delete or repurpose the frozen legacy copy once W3-03b lands. Otherwise it will drift and become maintenance weight.
  5. The CTE timing smoke test flaked under load in a Codex run. Don't loosen its threshold. If it flakes in CI, investigate the cause instead.

Performance: The perf-gate (comment 6612455785) says PASS. The suite geomean is -0.08% (p 0.620), and the A/A' control was quiet. The gate does not cover the PLAN target benchmarks ParseStage/preprocess and PreprocessTokens. The local benchstat shows them flat (geomean +0.02%).

Security: No concerns. The change has no I/O, no unsafe code and no new input surface.

Test coverage: Strong. It includes table tests, gate completeness, a parser-mode differential test and a tokenizer coupling test. The race and norace files handle the build-tag split.

Verdict: Looks good to merge once task check is green in CI. I found nothing that blocks it.

@github-actions

github-actions Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

Claude finished @ajitpratap0's task in 31s —— View job


Review of PR #947 (token classification move into internal/tokclass)

I read the preprocess.go diff and the commit list. I did not build or run tests, and I did not read remap.go, compound.go or the large test files in full. The perf-gate numbers below come from the gate comment, not from my own runs.

New perf-gate result: REGRESSION on one metric. This run is on head f69cf6d against base b1d8625, and it replaces the earlier PASS. It runs in shadow mode, so it doesn't fail the check, but the repo rules say a missed target must be reported rather than hidden.

  • Flagged: e2e/complex instructions/op is +7.14%, over the 1.5% limit. It is the only flagged case.
  • Timing is flat: ParseE2E/complex is -0.84% (p 0.093). The suite geomean is -0.26%, and allocs/op and B/op are unchanged. The A/A' control was quiet (0 of 52 benchmarks moved more than 3%).
  • The other instruction counts look inconsistent: e2e/cte is -1.88%, and the other 9 cases are within ±0.1%. A refactor that only moves the same calls into another package would not be expected to add 7% instructions to one case and remove 1.9% from another. A real cost in the shared loop would also show up in rw/postgresql/medium and in the other e2e cases. They are flat.
  • Likely cause: this looks like a measurement artifact, or an effect of the merges from main since the earlier PASS (the instruction counter has a single sample per case). I can't confirm that from here.
  • Suggested check: rerun the gate, or run cmd/perfdriver for e2e/complex on base and head several times. If +7% reproduces, compare inlining decisions with go build -gcflags=-m ./pkg/sql/parser | grep -E 'tokclass|preprocessTokensInto'. The likeliest culprits are tokclass.NormalizeInPlace or AppendCompound no longer inlining, or Gate not folding into the loop. The complex query probably has the most compound and remapped tokens, so it would be the first to show that cost. If it is real, it is more likely a hot-path cost than noise, and the right fix is in the code, not a looser threshold.

Code quality

  • The package boundary is clean. preprocess.go is now just the loop, and tokclass has no dependency on the parser.
  • preprocessTokensInto repeats the body of tokclass.AppendReady on purpose. A comment says so, and the fast-path equivalence tests check the two agree. Given the instruction-count flag, keep the duplicate for now. Call AppendReady directly only if the inlining check shows it is free.
  • CompoundParts hands out shared slices, which are read-only by convention. A test that the tables are unchanged after parsing would guard that.
  • The Start.Line != 0 && Start.Line == End.Line guard in NormalizeInPlace is subtle. Make sure the differential harness covers a zero-line span and a multi-line span.
  • legacy_preprocess_test.go (638 lines) and tokstream_equiv_test.go (727 lines) are large. Remove or repurpose them once W3-03b lands.

Security: No concerns. There is no I/O, no unsafe code and no new input surface.

Test coverage: Strong: tables, gate completeness, a differential harness against the frozen legacy pass, and a tokenizer coupling test. Don't loosen the CTE timing smoke test if it flakes again. Investigate it instead.

Verdict: The code looks fine to merge. Before merging, resolve the e2e/complex +7.14% instructions/op flag by rerunning the gate to show it was noise. If it reproduces, fix the cause.
· branch perf/w3-03a1-tokclass

@github-actions

github-actions Bot commented Nov 6, 2026 •

Copy link
Copy Markdown

Claude finished @ajitpratap0's task in 24s —— View job


Review of PR #947 (token classification move into internal/tokclass)

I read the current preprocess.go and the commit list. The head is now 4b58a19, which is a merge of main. I did not build or run tests, and I did not re-read remap.go, compound.go or the large test files in full.

Summary: The refactor is clean. preprocess.go is reduced to the loop, and the classification rules live in a package that imports only pkg/models and strings. preprocessTokensInto has the same logic and the same call sequence as before. Nothing I read suggests a behaviour change.

Perf gate

  • The latest gate run is the PASS comment on head 733ae45. Suite geomean is -0.33% (p 0.277), the A/A' control was quiet, and allocs/op and B/op are unchanged. Every e2e/* instructions/op case is within ±0.06%, and e2e/complex is +0.00%.
  • The earlier REGRESSION comment (e2e/complex +7.14% instructions/op, e2e/cte -1.88%, on head f69cf6d) did not reproduce on this run. The code was not touched in between, only merges from main. That points to a measurement artifact or a main-side effect, and I could not verify the cause from here. The newer gate run is the better evidence.
  • Make sure the gate runs on the final head after this merge commit before merging.

Code quality

  • The package boundary is good. The tables are read-only, so the package is safe for concurrent use.
  • preprocessTokensInto repeats tokclass.AppendReady on purpose. The comment says so, and TestPreprocessFastPath_EveryTokenType and TestPreprocessFastPath_Corpus check the two agree. Given the earlier instruction-count scare, keep the duplicate unless go build -gcflags=-m shows AppendReady inlines at no cost.
  • CompoundParts returns a shared slice, so a caller that mutated it would corrupt global state. The package is internal and AppendCompound copies. A test that the tables are unchanged after a parse would be a cheap guard.
  • NormalizeInPlace has a subtle guard (Start.Line != 0 && Start.Line == End.Line) before the backtick-width rule. Check that the differential harness has direct cases for a zero-line span and a multi-line span.
  • legacy_preprocess_test.go (638 lines) and tokstream_equiv_test.go (727 lines) are large. Delete or repurpose the frozen legacy copy once W3-03b lands, so it doesn't drift.

Security: No concerns. There is no I/O, no unsafe code and no new input surface.

Test coverage: Strong. It covers the tables, gate completeness, a parser-mode differential test against the frozen legacy pass, and a tokenizer coupling test. The race and norace files handle the build-tag split. If the CTE timing smoke test flakes in CI, investigate it. Don't loosen its threshold.

Verdict: The code looks fine to merge once task check is green on the final head and the gate is clean there. Nothing blocks it.
· branch perf/w3-03a1-tokclass

@ajitpratap0

Copy link
Copy Markdown
Owner Author

Perf gate re-run on exact head 4b58a19 (workflow_dispatch run 42320036752, layout-randomized, 20 layouts per arm): PASS. Suite geomean -0.02% (p 0.841), A/A' control quiet (0 of 52 moved >3%), allocs/op +0.00%, B/op +0.00%. 2 benchmarks in the Low power list; allocs/op, B/op and instructions/op carry the verdict there. Opus diff review: pure move, no findings.

🤖 Generated with Claude Code

This branch was successfully deployed

1 active deployment
Preview — 4b58a190 Deployed Nov 6, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation parser tokenizer Tokenizer / lexer changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant