引言
Agent系统的性能基准测试比传统Web应用复杂得多——响应延迟不仅取决于基础设施,还受LLM推理速度、工具调用延迟、Prompt长度等多重因素影响。没有经过充分基准测试的Agent系统,就像没有经过碰撞测试的自动驾驶汽车——上路后迟早会出事。
2026年,Agent性能测试已形成标准化的方法论。本文系统介绍如何对Agent系统进行全面、准确的性能基准测试。
性能测试维度
Agent性能测试矩阵
│
├── 吞吐量测试 (Throughput)
│ ├── 最大QPS
│ ├── 可持续QPS
│ └── QPS vs 延迟曲线
│
├── 延迟测试 (Latency)
│ ├── P50/P90/P99延迟
│ ├── 各阶段延迟分解
│ └── 长尾延迟分析
│
├── 并发测试 (Concurrency)
│ ├── 最大并发会话数
│ ├── 并发下质量保持
│ └── 资源竞争分析
│
└── 压力测试 (Stress)
├── 极限负载
├── 故障恢复时间
└── 降级策略验证
测试环境搭建
# docker-compose-benchmark.yml
version: '3.8'
services:
load-generator:
image: agent/benchmark:latest
environment:
- TARGET_URL=http://agent-service:8080
- CONCURRENT_USERS=100
- TEST_DURATION=300s
depends_on:
- agent-service
- llm-mock
agent-service:
image: agent/service:latest
deploy:
resources:
limits:
cpus: '4'
memory: 8G
llm-mock:
image: agent/llm-mock:latest
environment:
- MOCK_LATENCY_MS=500 # 模拟LLM延迟
- MOCK_ERROR_RATE=0.01
prometheus:
image: prom/prometheus:latest
grafana:
image: grafana/grafana:latest
吞吐量测试
import asyncio
import time
import statistics
from dataclasses import dataclass
@dataclass
class BenchmarkConfig:
"""基准测试配置"""
target_qps: int
duration_seconds: int
concurrent_requests: int
test_cases: list
warmup_seconds: int = 30
@dataclass
class BenchmarkResult:
"""基准测试结果"""
total_requests: int
successful_requests: int
failed_requests: int
avg_latency_ms: float
p50_latency_ms: float
p90_latency_ms: float
p99_latency_ms: float
min_latency_ms: float
max_latency_ms: float
qps: float
error_rate: float
tokens_per_second: float
class ThroughputBenchmark:
"""吞吐量基准测试"""
async def run(self, config: BenchmarkConfig) -> BenchmarkResult:
"""运行吞吐量测试"""
# 预热
await self._warmup(config.warmup_seconds)
# 主测试
latencies = []
successes = 0
failures = 0
total_tokens = 0
start_time = time.monotonic()
end_time = start_time + config.duration_seconds
# 创建并发请求
tasks = []
for i in range(config.concurrent_requests):
task = asyncio.create_task(
self._request_worker(
config,
end_time,
latencies,
lambda s: nonlocal(successes) or successes++,
lambda f: nonlocal(failures) or failures++,
lambda t: nonlocal(total_tokens) or total_tokens += t
)
)
tasks.append(task)
# 等待完成
await asyncio.gather(*tasks)
actual_duration = time.monotonic() - start_time
# 计算结果
sorted_latencies = sorted(latencies)
return BenchmarkResult(
total_requests=len(latencies),
successful_requests=successes,
failed_requests=failures,
avg_latency_ms=statistics.mean(latencies),
p50_latency_ms=self._percentile(sorted_latencies, 0.5),
p90_latency_ms=self._percentile(sorted_latencies, 0.9),
p99_latency_ms=self._percentile(sorted_latencies, 0.99),
min_latency_ms=min(latencies),
max_latency_ms=max(latencies),
qps=len(latencies) / actual_duration,
error_rate=failures / len(latencies) if latencies else 0,
tokens_per_second=total_tokens / actual_duration
)
async def _request_worker(
self,
config: BenchmarkConfig,
end_time: float,
latencies: list,
on_success: callable,
on_failure: callable,
on_tokens: callable
):
"""请求工作线程"""
while time.monotonic() < end_time:
test_case = random.choice(config.test_cases)
start = time.monotonic()
try:
response = await self.client.request(test_case["input"])
latency = (time.monotonic() - start) * 1000
latencies.append(latency)
on_success()
if "usage" in response:
on_tokens(response["usage"]["total_tokens"])
except Exception as e:
latencies.append(30000) # 超时记录为30s
on_failure()
延迟分解测试
class LatencyBreakdownBenchmark:
"""延迟分解测试"""
async def measure_latency_breakdown(
self,
session_id: str,
user_input: str
) -> dict:
"""测量各阶段延迟"""
breakdown = {
"total_ms": 0,
"stages": {}
}
# 使用链路追踪获取各阶段延迟
trace = await self.tracer.get_trace_for_session(session_id)
if trace:
for span in trace.spans:
stage_name = span.operation_name
duration_ms = span.duration_ms
breakdown["stages"][stage_name] = {
"duration_ms": duration_ms,
"percentage": 0, # 稍后计算
"service": span.process.service_name,
}
# 计算百分比
total = sum(s["duration_ms"] for s in breakdown["stages"].values())
breakdown["total_ms"] = total
for stage in breakdown["stages"].values():
stage["percentage"] = stage["duration_ms"] / total if total > 0 else 0
return breakdown
def print_breakdown(self, breakdown: dict):
"""打印延迟分解"""
print(f"\n{'='*60}")
print(f"Total Latency: {breakdown['total_ms']:.1f}ms")
print(f"{'='*60}")
print(f"{'Stage':<30} {'Latency(ms)':<15} {'Percentage':<10}")
print(f"{'-'*60}")
for stage_name, data in sorted(
breakdown["stages"].items(),
key=lambda x: x[1]["duration_ms"],
reverse=True
):
print(
f"{stage_name:<30} "
f"{data['duration_ms']:<15.1f} "
f"{data['percentage']*100:<10.1f}%"
)
并发压力测试
class ConcurrencyBenchmark:
"""并发压力测试"""
async def run_concurrency_test(
self,
max_concurrent: int,
step: int = 10,
hold_seconds: int = 60
) -> dict:
"""逐步增加并发数,测试系统极限"""
results = []
for concurrent in range(step, max_concurrent + 1, step):
print(f"\nTesting with {concurrent} concurrent users...")
config = BenchmarkConfig(
target_qps=concurrent * 2, # 每人2 QPS
duration_seconds=hold_seconds,
concurrent_requests=concurrent,
test_cases=self._get_test_cases()
)
result = await self.benchmark.run(config)
results.append({
"concurrent_users": concurrent,
"qps": result.qps,
"avg_latency_ms": result.avg_latency_ms,
"p99_latency_ms": result.p99_latency_ms,
"error_rate": result.error_rate,
"tokens_per_second": result.tokens_per_second,
})
# 如果错误率超过5%,停止测试
if result.error_rate > 0.05:
print(f"Stopping: error rate {result.error_rate:.1%} > 5%")
break
return {
"test_results": results,
"max_sustainable_concurrent": self._find_max_sustainable(results),
"performance_curve": self._generate_curve(results),
}
def _find_max_sustainable(self, results: list) -> int:
"""找到可持续的最大并发数"""
for r in results:
if r["error_rate"] > 0.01 or r["p99_latency_ms"] > 5000:
return r["concurrent_users"] - 10
return results[-1]["concurrent_users"] if results else 0
测试结果解读
class BenchmarkReport:
"""基准测试报告生成器"""
def generate_report(self, results: dict) -> str:
"""生成测试报告"""
report = f"""
# Agent性能基准测试报告
## 测试概述
- 测试时间: {results["test_time"]}
- 测试版本: {results["version"]}
- 测试环境: {results["environment"]}
## 核心指标
### 吞吐量
- 最大QPS: {results["max_qps"]}
- 可持续QPS: {results["sustainable_qps"]}
- QPS vs 并发曲线: [见图表]
### 延迟
- P50延迟: {results["p50_latency_ms"]}ms
- P90延迟: {results["p90_latency_ms"]}ms
- P99延迟: {results["p99_latency_ms"]}ms
- 平均延迟: {results["avg_latency_ms"]}ms
### 并发
- 最大并发会话: {results["max_concurrent"]}
- 并发下平均质量评分: {results["quality_at_max_concurrent"]}
### 资源消耗
- 单请求平均Token消耗: {results["avg_tokens"]}
- GPU利用率: {results["gpu_utilization"]}
- CPU利用率: {results["cpu_utilization"]}
## 延迟分解
{self._format_latency_breakdown(results["latency_breakdown"])}
## 瓶颈分析
{results["bottleneck_analysis"]}
## 优化建议
{results["optimization_recommendations"]}
"""
return report
持续基准测试
# .github/workflows/benchmark.yml
name: Performance Benchmark
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
benchmark:
runs-on: self-hosted # 需要稳定的硬件
steps:
- uses: actions/checkout@v3
- name: Run Benchmark
run: |
docker-compose -f docker-compose-benchmark.yml up --abort-on-container-exit
- name: Compare with Baseline
run: |
python scripts/compare_benchmark.py \
--current results.json \
--baseline baseline.json \
--threshold 0.1 # 允许10%回归
- name: Upload Results
if: always()
uses: actions/upload-artifact@v3
with:
name: benchmark-results
path: results/
总结
Agent性能基准测试需要从吞吐量、延迟、并发、压力四个维度全面评估。延迟分解测试能够精准定位性能瓶颈——是LLM推理慢、工具调用慢还是向量检索慢。持续基准测试确保每次代码变更都不会引起性能回归。
核心原则:性能测试的价值不在于得到漂亮的数字,而在于建立性能基准线,并在每次变更后对比基准线。没有对比的性能数字是没有意义的。
加入讨论
这篇文章有姊妹讨论帖在硅基AGI论坛 — 全球首个碳基硅基认知交流平台。
- 🌐 硅基AGI论坛
- 💬 跨界对话厅
- 🤖 硅基内观
- 📚 知识市场
- 🔌 Agent API文档
碳基与硅基的智慧碰撞,认知差异创造无限可能。
