test/scripts/benchmark/reporters/markdown_reporter.py

125 lines
4.1 KiB
Python

# -*- coding: utf-8 -*-
"""
Markdown 报告生成器
"""
from datetime import datetime
from pathlib import Path
from typing import List, Optional
from ..metrics.models import AggregatedMetrics
class MarkdownReporter:
"""Markdown 报告生成器"""
def generate(
self,
asr_results: List[AggregatedMetrics],
output_path: Path,
config_info: Optional[dict] = None,
) -> None:
"""
生成 Markdown 报告
Args:
asr_results: ASR 测试结果
output_path: 输出文件路径
config_info: 配置信息
"""
lines = []
# 标题
lines.append("# Qwen3-ASR 并发性能测试报告")
lines.append("")
lines.append(f"**测试时间:** {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
if config_info:
lines.append(f"**服务器:** {config_info.get('host', 'localhost')}:{config_info.get('port', 8000)}")
lines.append(f"**并发级别:** {', '.join(map(str, config_info.get('concurrency_levels', [])))}")
lines.append("")
lines.append("---")
lines.append("")
# ASR 结果
if asr_results:
lines.extend(self._generate_asr_section(asr_results))
# 结论
lines.extend(self._generate_conclusions(asr_results))
# 写入文件
output_path.parent.mkdir(parents=True, exist_ok=True)
output_path.write_text("\n".join(lines), encoding="utf-8")
def _generate_asr_section(self, results: List[AggregatedMetrics]) -> List[str]:
"""生成 ASR 结果部分"""
lines = []
lines.append("## ASR 性能测试结果")
lines.append("")
# 延迟指标表格
lines.append("### 延迟指标 (毫秒)")
lines.append("")
lines.append("| 并发数 | 首次响应 (Avg) | 首次响应 (P95) | 总时间 (Avg) | 总时间 (P95) | 总时间 (Max) |")
lines.append("|--------|---------------|---------------|-------------|-------------|-------------|")
for r in results:
lines.append(
f"| {r.concurrency_level} | "
f"{r.first_latency_avg:.1f} | "
f"{r.first_latency_p95:.1f} | "
f"{r.total_time_avg:.1f} | "
f"{r.total_time_p95:.1f} | "
f"{r.total_time_max:.1f} |"
)
lines.append("")
# RTF 和吞吐量表格
lines.append("### RTF 和吞吐量")
lines.append("")
lines.append("| 并发数 | RTF (Avg) | RTF (P95) | 吞吐量 (req/s) | 成功率 |")
lines.append("|--------|----------|----------|---------------|--------|")
for r in results:
lines.append(
f"| {r.concurrency_level} | "
f"{r.rtf_avg:.3f} | "
f"{r.rtf_p95:.3f} | "
f"{r.throughput:.3f} | "
f"{r.success_rate:.1f}% |"
)
lines.append("")
return lines
def _generate_conclusions(
self,
asr_results: List[AggregatedMetrics],
) -> List[str]:
"""生成结论部分"""
lines = []
lines.append("## 结论")
lines.append("")
if asr_results:
max_level = max(asr_results, key=lambda x: x.concurrency_level)
lines.append(f"- **ASR 最大并发 ({max_level.concurrency_level}) RTF:** {max_level.rtf_avg:.3f}")
lines.append(f"- **ASR 最大并发吞吐量:** {max_level.throughput:.3f} req/s")
# 找到 RTF 超过 1.0 的并发级别
stable_levels = [r for r in asr_results if r.rtf_avg <= 1.0]
if stable_levels:
max_stable = max(stable_levels, key=lambda x: x.concurrency_level)
lines.append(f"- **ASR 稳定并发上限 (RTF < 1.0):** {max_stable.concurrency_level}")
lines.append("")
lines.append("---")
lines.append("")
lines.append("*RTF (Real-Time Factor): 处理时间与音频时长的比值,小于 1.0 表示处理速度快于实时*")
lines.append("")
return lines