Skip to content

perf(builder): replace fmt.Sprintf with string concatenation in hot paths - #59

Open
VojtechVitek wants to merge 2 commits into
masterfrom
perf-string-concat
Open

perf(builder): replace fmt.Sprintf with string concatenation in hot paths#59
VojtechVitek wants to merge 2 commits into
masterfrom
perf-string-concat

Conversation

@VojtechVitek

Copy link
Copy Markdown
Member

What

fmt.Sprintf runs a format-string parser and boxes each arg into interface{} (one alloc apiece). For the fixed "col ORDER" and "$N" shapes, plain concatenation is several times cheaper. Replaced in three query-building hot paths:

Path File Change
Sort.String() page.go fmt.Sprintf("%s %s", ...)col + " " + order
Paginator.getOrder() page.go same
RawSQL.Prepare() querier.go fmt.Sprintf("$%d", ...)strconv.Itoa; bytes.Bufferstrings.Builder (zero-copy String())

Output strings are unchanged.

Commits

  1. test(builder) — benchmarks for Sort.String() and RawQuery/Prepare, plus TestStringConcatOutputUnchanged pinning the exact output strings.
  2. perf(builder) — the concatenation change.

Perf change, not a bug fix — CI stays green on both commits. The output test in commit 1 is the behavior guard (green before and after); benchstat proves the speedup.

Result

count=8, all p=0.000:

Benchmark time allocs
SortString 124.9ns → 68.4ns (−45%) 5 → 2 (−60%)
RawQueryPrepare 322ns → 145ns (−55%) 9 → 4 (−56%)

Sort.String() runs once per ORDER BY column on every paginated/keyset query build.

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:44
Add benchmarks for Sort.String() (one call per ORDER BY column on every
paginated/keyset build) and RawQuery/RawSQL.Prepare (the ?->$N rewrite),
plus a test pinning their exact output strings.

Baselines for the fmt.Sprintf -> string-concatenation change in the next
commit; the output test must stay green across it. Pure, no database.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
fmt.Sprintf runs a format-string parser and boxes its args into
interface{} (one alloc each); for fixed "col ORDER" / "$N" shapes plain
concatenation is several times cheaper. Replace it in three hot paths:

  - Sort.String()          (page.go)   fmt.Sprintf("%s %s", ...) -> +
  - Paginator.getOrder()   (page.go)   same
  - RawSQL.Prepare()       (querier.go) fmt.Sprintf("$%d", ...) -> strconv;
                                        bytes.Buffer -> strings.Builder
                                        (zero-copy String())

Output strings are unchanged (pinned by TestStringConcatOutputUnchanged).

Benchmarks, count=8, p=0.000:

  SortString        124.9ns -> 68.4ns  (-45%)   5 -> 2 allocs
  RawQueryPrepare    322ns  -> 145ns   (-55%)   9 -> 4 allocs

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