test: record bounded gateway benchmark evidence
This commit is contained in:
parent
bb4b205aa0
commit
2124523cef
@ -116,7 +116,7 @@ flowchart LR
|
|||||||
|
|
||||||
## 当前完成度
|
## 当前完成度
|
||||||
|
|
||||||
截至 **2026-08-07**,实施计划中可直接勾选的检查项为 **70 / 75(93.3%)**。详情见
|
截至 **2026-08-07**,实施计划中可直接勾选的检查项为 **71 / 75(94.7%)**。详情见
|
||||||
[实施计划](docs/development/implementation-plan.md)和
|
[实施计划](docs/development/implementation-plan.md)和
|
||||||
[交付完成度审计](docs/requirements/completion-audit.md)。
|
[交付完成度审计](docs/requirements/completion-audit.md)。
|
||||||
|
|
||||||
@ -160,11 +160,15 @@ Secret 分离管理。
|
|||||||
go run ./deploy/tools/configcheck deploy/config/local.yaml
|
go run ./deploy/tools/configcheck deploy/config/local.yaml
|
||||||
./scripts/verify.ps1
|
./scripts/verify.ps1
|
||||||
./scripts/package-docs.ps1
|
./scripts/package-docs.ps1
|
||||||
|
./scripts/benchmark-gateway.ps1
|
||||||
```
|
```
|
||||||
|
|
||||||
`package-docs.ps1` 默认生成被忽略的 `dist/proxy-pool-docs-v1.0.zip`;包内包含 README、
|
`package-docs.ps1` 默认生成被忽略的 `dist/proxy-pool-docs-v1.0.zip`;包内包含 README、
|
||||||
`docs/`、图表、OpenAPI 和 Proto 契约,并以 `manifest.json` 记录 Git revision、文件大小和
|
`docs/`、图表、OpenAPI 和 Proto 契约,并以 `manifest.json` 记录 Git revision、文件大小和
|
||||||
SHA-256。可使用 `-Version vMAJOR.MINOR[.PATCH]` 与 `-OutputPath OUTPUT.zip` 生成指定交付物。
|
SHA-256。可使用 `-Version vMAJOR.MINOR[.PATCH]` 与 `-OutputPath OUTPUT.zip` 生成指定交付物。
|
||||||
|
`benchmark-gateway.ps1` 固定执行一次 100k 索引调度、Routing Round Robin 和 Snapshot Apply
|
||||||
|
微基准,并把版本与原始输出写入 `dist/gateway-benchmarks.txt`;它用于回归比较,不构成
|
||||||
|
网络转发或 100k QPS 集群容量证明。
|
||||||
|
|
||||||
Redis、PostgreSQL 和 Controller fixture 脚本会使用 Docker 启动隔离依赖:
|
Redis、PostgreSQL 和 Controller fixture 脚本会使用 Docker 启动隔离依赖:
|
||||||
|
|
||||||
|
|||||||
@ -395,7 +395,11 @@ CI 另有独立 Deployment job,在占位凭据下渲染 Compose,并使用 `k
|
|||||||
- [x] Map every requirement ID to code, test, contract, document, or verified runtime evidence.
|
- [x] Map every requirement ID to code, test, contract, document, or verified runtime evidence.
|
||||||
- [ ] Run `gofmt`, `go vet`, unit tests, race tests, builds, contract validation, and
|
- [ ] Run `gofmt`, `go vet`, unit tests, race tests, builds, contract validation, and
|
||||||
documentation link/example validation.
|
documentation link/example validation.
|
||||||
- [ ] Run bounded local performance benchmarks; label 100k QPS as unverified until a
|
- [x] Run bounded local performance benchmarks; label 100k QPS as unverified until a
|
||||||
representative cluster load run exists.
|
representative cluster load run exists.
|
||||||
|
|
||||||
|
`scripts/benchmark-gateway.ps1` 固定使用 `-count=1 -benchtime=1x` 分别执行 100k 索引调度、
|
||||||
|
Round Robin 和 Snapshot Apply 基准,并将 Git revision 与原始输出保存到 `dist/`。该基线不包含
|
||||||
|
网络、TLS、上游 RTT、真实连接或多 Worker 协调,不能替代代表性集群报告。
|
||||||
- [ ] Confirm no TODO/TBD/placeholders, secrets, unbounded queues, high-cardinality metric
|
- [ ] Confirm no TODO/TBD/placeholders, secrets, unbounded queues, high-cardinality metric
|
||||||
labels, extraction Lease APIs, or conflicting maxSize semantics remain.
|
labels, extraction Lease APIs, or conflicting maxSize semantics remain.
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -18,6 +19,36 @@ type docsPackageManifest struct {
|
|||||||
} `json:"files"`
|
} `json:"files"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGatewayBenchmarkScriptIsBoundedAndWritesEvidence(t *testing.T) {
|
||||||
|
pwsh, err := exec.LookPath("pwsh")
|
||||||
|
if err != nil {
|
||||||
|
t.Skip("pwsh is required to exercise the gateway benchmark script")
|
||||||
|
}
|
||||||
|
repositoryRoot := repositoryRoot(t)
|
||||||
|
outputPath := filepath.Join(t.TempDir(), "gateway-benchmarks.txt")
|
||||||
|
command := exec.Command(pwsh, "-NoProfile", "-NonInteractive", "-File", filepath.Join(repositoryRoot, "scripts", "benchmark-gateway.ps1"), "-OutputPath", outputPath)
|
||||||
|
command.Dir = repositoryRoot
|
||||||
|
if output, err := command.CombinedOutput(); err != nil {
|
||||||
|
t.Fatalf("run gateway benchmarks: %v\n%s", err, output)
|
||||||
|
}
|
||||||
|
payload, err := os.ReadFile(outputPath)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("read benchmark evidence: %v", err)
|
||||||
|
}
|
||||||
|
evidence := string(payload)
|
||||||
|
for _, required := range []string{
|
||||||
|
"BenchmarkAcquire100k(Indexed|RoutingRoundRobin)",
|
||||||
|
"BenchmarkStoreApply100k",
|
||||||
|
"-benchtime=1x",
|
||||||
|
"-count=1",
|
||||||
|
"revision:",
|
||||||
|
} {
|
||||||
|
if !strings.Contains(evidence, required) {
|
||||||
|
t.Errorf("benchmark evidence does not contain %q", required)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestPackageDocsCreatesTraceableArchive(t *testing.T) {
|
func TestPackageDocsCreatesTraceableArchive(t *testing.T) {
|
||||||
pwsh, err := exec.LookPath("pwsh")
|
pwsh, err := exec.LookPath("pwsh")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@ -96,6 +96,7 @@ docker compose config PASS
|
|||||||
kubectl kustomize PASS
|
kubectl kustomize PASS
|
||||||
configuration examples 21/21 PASS
|
configuration examples 21/21 PASS
|
||||||
Mermaid blocks 35
|
Mermaid blocks 35
|
||||||
|
bounded gateway microbenchmarks PASS (local baseline only)
|
||||||
```
|
```
|
||||||
|
|
||||||
Windows 环境为 `CGO_ENABLED=0` 且没有 C 编译器,`go test -race` 在本机未执行;
|
Windows 环境为 `CGO_ENABLED=0` 且没有 C 编译器,`go test -race` 在本机未执行;
|
||||||
|
|||||||
@ -83,13 +83,19 @@ soak 测试单独标记,不混入快速单测。
|
|||||||
|
|
||||||
## 5. 当前本地微基准
|
## 5. 当前本地微基准
|
||||||
|
|
||||||
2026-07-30,Windows/amd64、Intel Core Ultra 7 155H:
|
2026-08-07,Windows/amd64、Go 1.26.4、Intel Core Ultra 7 155H,以固定
|
||||||
|
`-count=1 -benchtime=1x` 运行:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
BenchmarkAcquire100kIndexed-22 1000000-1867125 893.9-1047 ns/op 256 B/op 2 allocs/op
|
BenchmarkAcquire100kIndexed-22 1 13100 ns/op 256 B/op 2 allocs/op
|
||||||
BenchmarkStoreApply100k-22 1 518.7 ms/op 540 MB/op 3000887 allocs/op
|
BenchmarkAcquire100kRoutingRoundRobin-22 1 45200 ns/op 13680 B/op 81 allocs/op
|
||||||
|
BenchmarkStoreApply100k-22 1 539017100 ns/op 684677920 B/op 3001735 allocs/op
|
||||||
```
|
```
|
||||||
|
|
||||||
|
使用 `./scripts/benchmark-gateway.ps1` 可复现该固定单次基线,输出写入被 Git 忽略的
|
||||||
|
`dist/gateway-benchmarks.txt` 并附带 revision。单次基准存在运行噪声,应只用于发现明显回归;
|
||||||
|
性能比较需要在同规格环境增加多次迭代后另行保存原始证据。
|
||||||
|
|
||||||
`Acquire` 已使用 scheme/upstream/tag 索引,结果只代表本地选择和容量预留。
|
`Acquire` 已使用 scheme/upstream/tag 索引,结果只代表本地选择和容量预留。
|
||||||
`Store.Apply` 属于冷路径且当前内存开销较高;运行态为防止旧快照在途连接超配,
|
`Store.Apply` 属于冷路径且当前内存开销较高;运行态为防止旧快照在途连接超配,
|
||||||
暂不自动回收曾出现过的 Proxy ID,但注册表有 1,000,000 项硬上限,达到上限时
|
暂不自动回收曾出现过的 Proxy ID,但注册表有 1,000,000 项硬上限,达到上限时
|
||||||
|
|||||||
53
scripts/benchmark-gateway.ps1
Normal file
53
scripts/benchmark-gateway.ps1
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
param(
|
||||||
|
[string]$OutputPath = ""
|
||||||
|
)
|
||||||
|
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
|
$repositoryRoot = Split-Path -Parent $PSScriptRoot
|
||||||
|
if ([string]::IsNullOrWhiteSpace($OutputPath)) {
|
||||||
|
$OutputPath = Join-Path $repositoryRoot "dist/gateway-benchmarks.txt"
|
||||||
|
}
|
||||||
|
elseif (-not [System.IO.Path]::IsPathRooted($OutputPath)) {
|
||||||
|
$OutputPath = Join-Path $repositoryRoot $OutputPath
|
||||||
|
}
|
||||||
|
$OutputPath = [System.IO.Path]::GetFullPath($OutputPath)
|
||||||
|
if ([System.IO.Path]::GetExtension($OutputPath) -ne ".txt") {
|
||||||
|
throw "OutputPath must end in .txt"
|
||||||
|
}
|
||||||
|
|
||||||
|
$revision = (& git -C $repositoryRoot rev-parse --verify HEAD 2>$null).Trim()
|
||||||
|
if ($LASTEXITCODE -ne 0 -or [string]::IsNullOrWhiteSpace($revision)) {
|
||||||
|
throw "could not resolve the current Git revision"
|
||||||
|
}
|
||||||
|
|
||||||
|
$outputDirectory = Split-Path -Parent $OutputPath
|
||||||
|
New-Item -ItemType Directory -Force -Path $outputDirectory | Out-Null
|
||||||
|
@(
|
||||||
|
"proxy-pool gateway microbenchmarks",
|
||||||
|
"revision: $revision",
|
||||||
|
"generated_at_utc: $([DateTime]::UtcNow.ToString('O'))",
|
||||||
|
"go_version: $((& go version).Trim())",
|
||||||
|
""
|
||||||
|
) | Set-Content -LiteralPath $OutputPath -Encoding utf8
|
||||||
|
|
||||||
|
function Invoke-Benchmark {
|
||||||
|
param(
|
||||||
|
[string]$Package,
|
||||||
|
[string]$Pattern
|
||||||
|
)
|
||||||
|
|
||||||
|
$arguments = @("test", "-count=1", "-run", "^$", "-bench", $Pattern, "-benchtime=1x", "-benchmem", $Package)
|
||||||
|
"==> go $($arguments -join ' ')" | Tee-Object -FilePath $OutputPath -Append
|
||||||
|
$lines = & go @arguments 2>&1
|
||||||
|
$exitCode = $LASTEXITCODE
|
||||||
|
$lines | Tee-Object -FilePath $OutputPath -Append
|
||||||
|
if ($exitCode -ne 0) {
|
||||||
|
throw "benchmark failed with exit code $exitCode"
|
||||||
|
}
|
||||||
|
"" | Tee-Object -FilePath $OutputPath -Append
|
||||||
|
}
|
||||||
|
|
||||||
|
Invoke-Benchmark -Package "./internal/gateway/dispatch" -Pattern "BenchmarkAcquire100k(Indexed|RoutingRoundRobin)"
|
||||||
|
Invoke-Benchmark -Package "./internal/gateway/snapshot" -Pattern "^BenchmarkStoreApply100k$"
|
||||||
|
Write-Host "benchmark evidence: $OutputPath"
|
||||||
Loading…
Reference in New Issue
Block a user