┌─────────────────────────────────────────────────────────────┐
│ 用户界面层 │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ run_all.sh │ │ Makefile │ │ CLI Args │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ 测试执行层 │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ api_perf_test.py │ │
│ │ ┌─────────────┐ ┌──────────────┐ ┌────────────┐ │ │
│ │ │StabilityTest│ │PerfOutputParser│ │TestResult │ │ │
│ │ └─────────────┘ └──────────────┘ └────────────┘ │ │
│ └──────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ 数据持久层 │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ JSON 文件 │ │ 日志文件 │ │ 配置文件 │ │
│ │test_results │ │ .log │ │config.json │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ 报告生成层 │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ generate_report.py │ │
│ │ ┌─────────────┐ ┌──────────────┐ ┌────────────┐ │ │
│ │ │JSON Loader │ │Data Processor│ │HTML Builder│ │ │
│ │ └─────────────┘ └──────────────┘ └────────────┘ │ │
│ └──────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ 可视化展示层 │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ HTML 报告 │ │ Chart.js │ │ 统计卡片 │ │
│ │ report.html │ │ 图表 │ │ 指标展示 │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────┘
职责:执行 evalscope perf 测试并收集结果
核心类:
-
StabilityTest: 主测试控制器- 构建测试命令
- 执行测试循环
- 管理测试状态
-
PerfOutputParser: 输出解析器- 正则表达式匹配性能指标
- 提取表格数据
-
TestResult: 测试结果容器- 存储单次测试数据
- 序列化为 JSON
数据流:
配置 → 命令构建 → subprocess 执行 → 输出捕获 → 解析 → 存储
职责:将测试结果转换为可视化 HTML 报告
核心类:
HTMLReportGenerator: 报告生成器- 加载 JSON 数据
- 提取时间序列
- 计算统计指标
- 生成 HTML
数据处理流程:
JSON → 时间序列提取 → 统计计算 → 图表数据准备 → HTML 渲染
配置文件结构:
{
"api": "openai", // API 类型
"url": "...", // API URL
"api_key": "...", // API Key
"model": "...", // 模型名称
"parallel": 8, // 并发数
"number": 50, // 请求数
"test_schedule": { // 测试计划
"total_tests": 48, // 总次数
"interval_seconds": 1800 // 间隔
}
}使用正则表达式解析 evalscope perf 的表格输出:
METRICS_PATTERN = re.compile(
r'│\s*(\d+)\s*│\s*(\S+)\s*│\s*([\d.]+)\s*│\s*'
r'([\d.]+)\s*│\s*([\d.]+)\s*│\s*'
r'([\d.]+)\s*│\s*([\d.]+)\s*│\s*'
r'([\d.]+)\s*│\s*([\d.]+)\s*│\s*'
r'([\d.]+)\s*│\s*([\d.]+)%\s*│'
)匹配的指标:
- Concurrency (并发数)
- Rate (速率)
- RPS (每秒请求数)
- Avg Latency (平均延迟)
- P99 Latency (P99 延迟)
- Avg TTFT (平均首字延迟)
- P99 TTFT (P99 首字延迟)
- Avg TPOT (平均每 token 时间)
- P99 TPOT (P99 每 token 时间)
- Gen. toks/s (生成速度)
- Success Rate (成功率)
从多次测试结果中提取时间序列:
def _extract_time_series_data(self):
time_series = {
'test_index': [],
'start_time': [],
'avg_latency': [],
# ... 其他指标
}
for result in self.data['results']:
if result['success'] and result['metrics']:
metrics = result['metrics'][0] # 取第一个并发级别
time_series['avg_latency'].append(metrics['avg_latency'])
# ... 提取其他指标计算每个指标的最小值、最大值、平均值:
def _calculate_statistics(self, time_series):
stats = {}
for key in metrics_keys:
values = [v for v in time_series[key] if v > 0]
stats[key] = {
'min': min(values),
'max': max(values),
'avg': sum(values) / len(values)
}使用 Python f-string 模板生成 HTML:
html_content = f'''<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
</head>
<body>
<canvas id="chart"></canvas>
<script>
new Chart(ctx, {{
type: 'line',
data: {{
labels: {json.dumps(labels)},
datasets: [{{
label: 'Latency',
data: {json.dumps(data)}
}}]
}}
}});
</script>
</body>
</html>'''┌──────────┐
│ 配置文件 │
└────┬─────┘
│
↓
┌──────────────┐
│ 测试执行器 │
│ │
│ ┌──────────┐ │
│ │构建命令 │ │
│ └──────────┘ │
│ ┌──────────┐ │
│ │执行测试 │ │
│ └──────────┘ │
│ ┌──────────┐ │
│ │解析输出 │ │
│ └──────────┘ │
└──────┬───────┘
│
↓
┌──────────────┐
│ JSON 结果 │
│ test_results │
└──────┬───────┘
│
↓
┌──────────────┐
│ 报告生成器 │
│ │
│ ┌──────────┐ │
│ │加载数据 │ │
│ └──────────┘ │
│ ┌──────────┐ │
│ │提取序列 │ │
│ └──────────┘ │
│ ┌──────────┐ │
│ │计算统计 │ │
│ └──────────┘ │
│ ┌──────────┐ │
│ │生成 HTML │ │
│ └──────────┘ │
└──────┬───────┘
│
↓
┌──────────────┐
│ HTML 报告 │
│ report.html │
└──────────────┘
- 模块化: 每个组件职责单一,易于维护
- 可配置: 通过配置文件灵活调整参数
- 可扩展: 易于添加新的指标和图表
- 容错性: 处理测试失败,保存中间结果
- 可读性: 清晰的代码结构和注释
在 PerfMetrics 类中添加新字段,更新正则表达式。
在 HTMLReportGenerator 中添加新的 Chart.js 配置。
继承 StabilityTest 类,重写 build_command 和解析逻辑。
添加 CSV、Excel 等格式的导出功能。
- 内存: 使用流式处理,避免一次性加载大量日志
- 并发: 测试间隔使用
time.sleep(),不占用 CPU - 存储: JSON 文件使用增量保存,避免数据丢失
- 渲染: HTML 使用 CDN 加载 Chart.js,减少本地资源
- API Key: 不记录到日志文件,仅存储在 JSON 结果中
- 配置文件: 提供
.example模板,避免提交敏感信息 - 输入验证: 检查配置参数的有效性