lolly/.github/workflows/benchmark.yml
xfy f46b0dee07 feat(benchmark): 新增分层性能回归检测策略
- PR 趋势监控使用宽松阈值,仅警告不阻塞合并
- 定期完整检测使用严格阈值,生成统计报告
- 新增阈值配置文件支持分环境配置
- 回归检测脚本支持 YAML 配置和环境参数
- 新增方差分析脚本用于推导阈值
2026-04-08 18:25:22 +08:00

193 lines
5.6 KiB
YAML

# Benchmark CI Workflow
# 分层策略:
# - PR 趋势监控: 宽松阈值,不阻塞合并
# - 定期完整检测: 严格阈值,生成报告
#
# 作者: xfy
name: Benchmark
on:
push:
branches: [master]
pull_request:
branches: [master]
schedule:
# 每周一凌晨 2 点运行完整检测
- cron: '0 2 * * 1'
workflow_dispatch:
inputs:
full:
description: 'Run full benchmark suite'
required: false
default: 'false'
env:
GO_VERSION: '1.23'
BENCH_COUNT: 10
jobs:
# PR 趋势监控 - 宽松阈值,仅警告
benchmark-pr:
name: PR Benchmark
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
- name: Run core benchmarks
id: bench
run: |
# 运行核心模块基准测试
go test -bench='Benchmark(Variable|Compression|RateLimiter|SlidingWindow|AccessLog|Static|Cache|Proxy|LoadBalance)' \
-benchmem -count=${{ env.BENCH_COUNT }} -timeout=10m ./... 2>&1 | tee benchmark-pr.txt
# 统计测试数量
echo "test_count=$(grep -c 'ns/op' benchmark-pr.txt || echo 0)" >> $GITHUB_OUTPUT
- name: Check regression (warning only)
run: |
# 宽松阈值 ±20%,仅作警告
python3 scripts/check_regression.py \
--warning-threshold 20 \
--block-threshold 30 \
benchmark-pr.txt || \
echo "::warning::Potential performance change detected (±20% threshold)"
- name: Comment on PR
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const output = fs.readFileSync('benchmark-pr.txt', 'utf8');
const lines = output.split('\n').filter(l => l.includes('ns/op')).slice(0, 25);
const body = `## 📊 Benchmark Results
\`\`\`
${lines.join('\n')}
\`\`\`
- Tests run: ${{ steps.bench.outputs.test_count }}
- Threshold: ±20% (warning only)
`;
github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: body
});
- name: Upload results
uses: actions/upload-artifact@v4
with:
name: benchmark-pr-results
path: benchmark-pr.txt
retention-days: 7
# 定期完整检测 - 严格阈值
benchmark-weekly:
name: Weekly Full Benchmark
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
- name: Install benchstat
run: go install golang.org/x/perf/cmd/benchstat@latest
- name: Run full benchmarks
id: bench
run: |
echo "Running full benchmark suite..."
go test -bench=. -benchmem -count=20 -timeout=25m ./... 2>&1 | tee benchmark-full.txt
# 生成统计报告
benchstat benchmark-full.txt > benchmark-stat.txt || true
echo "test_count=$(grep -c 'ns/op' benchmark-full.txt || echo 0)" >> $GITHUB_OUTPUT
- name: Check regression with config
run: |
if [ -f .benchmark-thresholds.yaml ]; then
python3 scripts/check_regression.py \
--config .benchmark-thresholds.yaml \
--environment ci \
benchmark-full.txt || true
else
python3 scripts/check_regression.py \
--warning-threshold 15 \
--block-threshold 25 \
benchmark-full.txt || true
fi
- name: Upload baseline
uses: actions/upload-artifact@v4
with:
name: benchmark-baseline
path: benchmark-full.txt
retention-days: 30
- name: Upload report
uses: actions/upload-artifact@v4
with:
name: benchmark-report
path: |
benchmark-stat.txt
retention-days: 90
- name: Create issue on regression
if: failure()
uses: actions/github-script@v7
with:
script: |
github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: `🚨 Performance Regression Detected - ${new Date().toISOString().split('T')[0]}`,
body: `Weekly benchmark detected performance regression.\n\nSee [workflow run](${process.env.GITHUB_SERVER_URL}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId})`,
labels: ['performance', 'regression']
});
# 保存基准线
benchmark-save:
name: Save Benchmark Baseline
if: github.ref == 'refs/heads/master'
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
- name: Run benchmarks
run: |
go test -bench=. -benchmem -count=${{ env.BENCH_COUNT }} ./... > benchmark-main.txt
- name: Upload baseline
uses: actions/upload-artifact@v4
with:
name: benchmark-baseline-main
path: benchmark-main.txt
retention-days: 90