Skip to content

perf: generic LRU cache with struct key for prepared statement cache#824

Merged
dkropachev merged 1 commit intoscylladb:masterfrom
mykaul:perf/lru-struct-key
Apr 5, 2026
Merged

perf: generic LRU cache with struct key for prepared statement cache#824
dkropachev merged 1 commit intoscylladb:masterfrom
mykaul:perf/lru-struct-key

Conversation

@mykaul
Copy link
Copy Markdown

@mykaul mykaul commented Apr 5, 2026

Summary

  • Make internal/lru.Cache generic (Cache[K comparable]) to support typed keys
  • Replace the prepared statement cache's string-concatenation key with a stmtCacheKey struct, eliminating per-query allocation from fmt.Sprintf and fixing a theoretical key collision when host IDs or keyspace names contain the separator character
  • Update routingKeyInfoLRU to use the typed Cache[string]

Extracted from #779.

Benchmark results

Before (string-concatenation key) vs after (struct key) — 5 runs, Intel i7-1270P.

Lookup (hot path — cache hit)

ns/op B/op allocs/op
Before (StringKeyLookup) 13.7 ±3% 0 0
After (StructKeyLookup) 17.1 ±3% 0 0
Delta +25%

Struct key lookup is ~3ns slower due to comparing 3 fields vs one pre-built string. Both are zero-allocation. This is the steady-state path for repeated queries — the regression is negligible in absolute terms (~3ns).

Insert (cold path — cache miss, key construction + insertion)

ns/op B/op allocs/op
Before (StringKeyInsert) 315.6 ±2% 248 6
After (StructKeyInsert) 214.6 ±2% 168 4
Delta -32% -32% -33%

This is the path that matters for new queries: every new (host, keyspace, statement) tuple hits this on first use. The old approach allocated a concatenated string via fmt.Sprintf on every call. The struct key references the original strings without copying.

Net effect

The insert path (where the allocation overhead lived) improves by 32% across the board. The lookup regression of ~3ns is dwarfed by the real-world query execution time. Additionally, the struct key fixes a correctness issue: the old concatenation hostID + keyspace + statement could collide when field boundaries overlap (e.g., hostID="ab", keyspace="cd" vs hostID="a", keyspace="bcd").

Signed-off-by: Yaniv Kaul yaniv.kaul@scylladb.com

…atement cache

Make internal/lru.Cache generic (Cache[K comparable]) to support typed
keys. Replace the prepared statement cache's string-concatenation key
with a stmtCacheKey struct, eliminating ~100-500 bytes of allocation per
query from fmt.Sprintf and fixing a theoretical key collision when host
IDs or keyspace names contain the separator character.

Also update routingKeyInfoLRU to use the typed Cache[string].
@mykaul
Copy link
Copy Markdown
Author

mykaul commented Apr 5, 2026

CI failure seems to be #822 again.

@dkropachev dkropachev marked this pull request as ready for review April 5, 2026 21:40
@dkropachev dkropachev merged commit a2bae78 into scylladb:master Apr 5, 2026
8 of 9 checks passed
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.

2 participants