Commit 2677c1f
perf: faster model resolution, JSON decoding, and request snapshotting (#413)
* perf: faster model resolution, JSON decoding, and request snapshotting
Reduce per-request CPU and allocations on the gateway hot path. Changes are
behavior-preserving for all valid input; the one intentional difference is
documented and tested.
Model resolution (O(1)):
- Add a lazy provider-selector index to the registry (qualifiedByName /
qualifiedByType), invalidated at the existing single cache-invalidation point.
- Route qualified-selector resolution through it via an optional
qualifiedSelectorResolver interface, with the catalog scan kept as a fallback
for non-indexed lookups and raw slash-shaped model IDs.
- Resolution is now O(1) and constant in catalog size (was O(N), copying the
full catalog several times per request): ~31us/164KB -> ~0.8us/0.3KB at 300
models. Deduplicated the redundant name/type scans in resolveQualifiedSelector.
JSON decoding (goccy/go-json):
- Migrate internal/ + cmd/ from encoding/json to github.com/goccy/go-json
(drop-in; package is named json). gjson is unchanged.
- ~3.8x faster realistic chat-body decode with fewer allocations.
- goccy is slightly more lenient than encoding/json on a couple of malformed
inputs (leading-zero numbers; malformed values in skipped passthrough fields).
Accepted under the gateway's accept-generously principle and pinned by
TestDecoderLeniencyIsBounded.
- Drop the redundant gjson.ValidBytes walk in extractUnknownJSONFields (callers
already validate via the preceding Unmarshal).
Request snapshot allocations:
- Add NewRequestSnapshotWithOwnedMaps so ingress capture owns the freshly built
route/query/trace maps and body, cloning only the live header map.
- Add HeadersView (zero-copy) and route read-only callers to it.
- Remove the now-superseded NewRequestSnapshotWithOwnedBody constructor.
Perf harness:
- Make the gateway hot-path benchmark exercise the real Router + populated
catalog (it previously bypassed routing, giving false confidence) and add a
guard case for it. Add a resolution micro-benchmark.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* test(perf): tighten hot-path allocation guard thresholds
CI (linux/amd64) and local (darwin/arm64) produce identical allocation counts
and near-identical byte counts, confirming these are deterministic. Tighten the
ceilings from "intentionally generous" to ~10% over the measured baseline so the
guard catches smaller regressions while still absorbing Go/dependency drift:
hot_path: 125 -> 120 allocs (baseline 113)
routed: 160 -> 150 allocs, 18->16 KB (baseline 137 / ~14.7 KB)
responses_stream: 310 -> 222 allocs, 25->22 KB (baseline 202 / ~19.6 KB)
shared_observers: unchanged (already tight, no headroom to trim)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(providers): address PR review on selector index and benchmarks
- registry: trim publicName/ProviderType when building the qualified-selector
index and skip empty keys, matching the trimmed lookup inputs and the previous
catalog scan (which compared trimmed fields on both sides). Prevents the O(1)
fast path from missing when provider metadata carries whitespace padding.
- resolve_bench_test: build exactly totalModels (round-robin across providers)
instead of providersN*(n/6); the models=50/1000 cases previously benchmarked
48/996 models due to integer truncation. Add benchSelector helper.
- request_snapshot_test: extend the owned-maps test to assert route/query/trace
maps are owned (not cloned) while headers are still defensively cloned.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>1 parent 9025183 commit 2677c1f
126 files changed
Lines changed: 666 additions & 178 deletions
File tree
- cmd
- gomodel
- recordapi
- internal
- admin
- aliases
- anthropicapi
- app
- auditlog
- batch
- cache/modelcache
- conversationstore
- core
- embedding
- gateway
- guardrails
- live
- llmclient
- modeldata
- modeloverrides
- pricingoverrides
- providers
- anthropic
- bailian
- bedrock
- deepseek
- gemini
- googlecommon
- ollama
- openai
- vertex
- xai
- xiaomi
- responsecache
- responsestore
- server
- streaming
- usage
- workflows
- tests/perf
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
5 | | - | |
6 | 5 | | |
7 | 6 | | |
8 | 7 | | |
| |||
11 | 10 | | |
12 | 11 | | |
13 | 12 | | |
| 13 | + | |
| 14 | + | |
14 | 15 | | |
15 | 16 | | |
16 | 17 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
12 | | - | |
13 | 12 | | |
14 | 13 | | |
15 | 14 | | |
| |||
18 | 17 | | |
19 | 18 | | |
20 | 19 | | |
| 20 | + | |
| 21 | + | |
21 | 22 | | |
22 | 23 | | |
23 | 24 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
| 13 | + | |
13 | 14 | | |
14 | 15 | | |
15 | 16 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
83 | 83 | | |
84 | 84 | | |
85 | 85 | | |
| 86 | + | |
| 87 | + | |
86 | 88 | | |
87 | 89 | | |
88 | 90 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
4 | | - | |
5 | 4 | | |
6 | 5 | | |
7 | 6 | | |
8 | 7 | | |
| 8 | + | |
| 9 | + | |
9 | 10 | | |
10 | 11 | | |
11 | 12 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
4 | | - | |
5 | 4 | | |
6 | 5 | | |
7 | 6 | | |
8 | 7 | | |
9 | 8 | | |
10 | 9 | | |
| 10 | + | |
| 11 | + | |
11 | 12 | | |
12 | 13 | | |
13 | 14 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
5 | | - | |
6 | 5 | | |
7 | 6 | | |
8 | 7 | | |
| 8 | + | |
| 9 | + | |
9 | 10 | | |
10 | 11 | | |
11 | 12 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
5 | | - | |
6 | 5 | | |
7 | 6 | | |
8 | 7 | | |
9 | 8 | | |
| 9 | + | |
| 10 | + | |
10 | 11 | | |
11 | 12 | | |
12 | 13 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
5 | | - | |
6 | 5 | | |
7 | 6 | | |
| 7 | + | |
| 8 | + | |
8 | 9 | | |
9 | 10 | | |
10 | 11 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
6 | | - | |
7 | 6 | | |
8 | 7 | | |
| 8 | + | |
| 9 | + | |
9 | 10 | | |
10 | 11 | | |
11 | 12 | | |
| |||
0 commit comments