Skip to content

perf(builder): fast path for uniform-shape InsertRecords - #60

Open
VojtechVitek wants to merge 2 commits into
masterfrom
perf-insertrecords-uniform
Open

perf(builder): fast path for uniform-shape InsertRecords#60
VojtechVitek wants to merge 2 commits into
masterfrom
perf-insertrecords-uniform

Conversation

@VojtechVitek

Copy link
Copy Markdown
Member

What

InsertRecords supports mixed-shape batches (rows with different columns) by unioning columns and emitting DEFAULT for gaps. To do that it allocates a map[string]any and a padded []any per row. When every record has the same columns — the common case — that work is wasted.

Now: Map every record once, then compare column slices. If all rows share row 0's columns, take a fast path that feeds each row's values straight to the builder (no per-row map, no padding). Mixed-shape batches fall back to the existing union+DEFAULT path, reusing the already-mapped columns (no second Map pass). Generated SQL and args are byte-for-byte identical.

Commits

  1. test(builder)BenchmarkInsertRecords on a uniform batch (10 and 100 rows), incl. ToSql. Baseline. Pure, no DB.
  2. perf(builder) — the fast path.

Perf change, not a bug fix — CI stays green on both commits. Behavior is pinned by the existing TestInsertRecords_* suite (uniform, mixed-shape union/DEFAULT, omitzero/omitempty mixed, all-empty rejected, map records), which passes on both. benchstat proves the win.

Result

BenchmarkInsertRecords, count=8, all p=0.000:

Metric (100 rows) Baseline Improved Δ
time 117.5µs 102.0µs −13%
B/op 167.1 KiB 132.2 KiB −21%
allocs/op 3007 2702 −10%

Smallest of the batch — squirrel's ToSql dominates the absolute cost — but removes N map + N slice allocations per batch, scaling with row count.

Testing

  • Full suite incl. Postgres-backed ./tests/... passes.
  • go build ./..., go vet ./ clean.

🤖 Generated with Claude Code

VojtechVitek and others added 2 commits July 31, 2026 17:48
InsertRecords supports mixed-shape batches by unioning columns across
rows, which costs a map[string]any plus a padded []any per row. A
uniform batch (every record has the same columns — the common case)
pays that for nothing. This benchmarks the uniform case as the baseline
for the fast path in the next commit. Pure, no database.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
InsertRecords supports mixed-shape batches by unioning columns across
rows, allocating a map[string]any and a padded []any per row. When every
record has the same columns (the common case) that work is wasted.

Map every record once, then compare column slices: if all rows share
row 0's columns, take a fast path that feeds each row's values straight
to the builder — no per-row map, no padding. Mixed-shape batches fall
back to the existing union+DEFAULT path, reusing the already-mapped
columns (no second Map pass). Generated SQL and args are identical; the
shared no-columns error is factored into noColumnsErr.

BenchmarkInsertRecords, count=8, p=0.000:

  rows=100   time  117.5µs -> 102.0µs  (-13%)
             B/op  167.1Ki -> 132.2Ki  (-21%)
             allocs   3007 ->    2702  (-10%)

Behavior pinned by the existing TestInsertRecords_* suite (uniform,
mixed-shape union/DEFAULT, omitzero/omitempty, all-empty, maps).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant