Skip to content

perf(router): cache-friendly static child lookup#3024

Open
vishr wants to merge 1 commit into
masterfrom
perf/router-static-child-lookup
Open

perf(router): cache-friendly static child lookup#3024
vishr wants to merge 1 commit into
masterfrom
perf/router-static-child-lookup

Conversation

@vishr

@vishr vishr commented Jun 19, 2026

Copy link
Copy Markdown
Member

Split out of #3023 at @aldas's request so the router and JSON changes land as independent PRs.

What

findStaticChild scanned []*node and dereferenced every child just to read its one-byte label — a pointer chase per static step on the routing hot path. This adds a parallel scLabels []byte (kept in sync in addStaticChild, newNode, the insert split, and Remove) and scans that contiguous slice instead, indexing into staticChildren only on a hit.

It also folds the is-leaf recomputation — previously duplicated across 5 sites, with the Remove copy subtly using len()==0 while the others used == nil — into a single refreshLeaf() helper that uses len(), so it is correct whether staticChildren is nil or an emptied-but-non-nil slice left after a removal.

Numbers

benchstat (n=6):
RouterStaticRoutes-14   8.49µs -> 8.01µs   -5.67%  (p=0.002)
RouterGitHubAPI-14      16.93µs -> 16.45µs  -2.86%  (p=0.002)
RouterParseAPI / GooglePlusAPI: neutral (param-heavy)
allocations: 0, unchanged

The companion ServeHTTP benchmark harness lands with #3023 (the JSON PR); routing benchmarks there exercise this change once both merge.

🤖 Generated with Claude Code

findStaticChild scanned []*node and dereferenced every child to read its
one-byte label — a pointer chase per static step. Maintain a parallel
scLabels []byte (kept in sync in addStaticChild, newNode, the insert
split, and Remove) and scan that contiguous slice instead, indexing into
staticChildren only on a hit.

  benchstat (n=6):
  RouterStaticRoutes-14   8.49µ -> 8.01µ   -5.67%  (p=0.002)
  RouterGitHubAPI-14      16.93µ -> 16.45µ  -2.86%  (p=0.002)
  RouterParseAPI / GooglePlusAPI: neutral (param-heavy)
  allocations: 0, unchanged

Also fold the is-leaf recomputation (duplicated across 5 sites, with the
Remove copy subtly using len()==0 vs == nil) into a single refreshLeaf()
helper that uses len() so it is correct whether staticChildren is nil or
an emptied-but-non-nil slice left after a removal.

Split out of #3023 so the router and JSON changes can be reviewed
independently (requested by @aldas).

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