9.8 KiB
9.8 KiB
性能追踪分析指南
已添加的性能追踪点
1. 总体流程追踪
用户发送消息
↓
[chatStore.sendMessageStream]
↓
[chatService.sendMessageStream] ⏱️ callModelStream总耗时
├─ [chatService.callModel] ⏱️ callModel总耗时
│ ├─ 准备消息 ⏱️ 准备消息耗时
│ ├─ 服务匹配
│ ├─ [modelServiceManager.sendChatRequest] ⏱️ 请求耗时
│ │ ├─ 准备 ⏱️ 准备耗时
│ │ └─ [makeChatRequest] ⏱️ makeChatRequest总耗时
│ │ ├─ 构建请求 ⏱️ 构建请求耗时
│ │ ├─ 网络请求 ⏱️ 网络请求耗时 ← 通常最慢的部分
│ │ └─ 解析响应 ⏱️ 解析响应耗时
│ └─ 解析响应 ⏱️ 解析响应耗时
└─ 模拟流式输出 ⏱️ 模拟流式输出耗时
2. 关键性能指标
控制台日志格式
// 开始
⏱️ [callModelStream] 开始流式处理
⏱️ [callModel] 开始处理 {model: "xxx", 对话消息数: 5}
⏱️ [callModel] 准备消息耗时: 0.50 ms 处理后消息数: 5
⏱️ [sendChatRequest] 开始请求 {serviceId: "xxx", model: "xxx", messages数量: 5}
// 网络请求阶段 (通常最慢)
⏱️ [sendChatRequest] 准备耗时: 0.10 ms
⏱️ [makeChatRequest] 构建请求耗时: 0.20 ms
🔍 [makeChatRequest] 请求体大小: 1024 字节
⏱️ [makeChatRequest] 网络请求耗时: 2500.00 ms ← 关键指标!
🔍 [makeChatRequest] 响应状态: 200 OK
// 解析阶段
⏱️ [makeChatRequest] 解析响应耗时: 5.00 ms
⏱️ [makeChatRequest] makeChatRequest总耗时: 2505.50 ms
⏱️ [sendChatRequest] 请求耗时: 2505.60 ms
⏱️ [sendChatRequest] 总耗时: 2505.70 ms
⏱️ [callModel] 服务调用耗时: 2505.80 ms
⏱️ [callModel] 解析响应耗时: 0.30 ms
⏱️ [callModel] callModel总耗时: 2507.00 ms
// 流式输出阶段
⏱️ [callModelStream] callModel耗时: 2507.10 ms
⏱️ [callModelStream] 模拟流式输出耗时: 1800.00 ms
⏱️ [callModelStream] 输出块数: 60 总字符数: 300
⏱️ [callModelStream] callModelStream总耗时: 4307.10 ms
性能瓶颈分析
常见的慢速原因
1. 网络请求慢 (2000-5000ms)
症状:
⏱️ [makeChatRequest] 网络请求耗时: 3500.00 ms
可能原因:
- API服务器响应慢
- 网络延迟高
- 请求体太大
- API配额限制
解决方案:
// 1. 检查请求体大小
🔍 [makeChatRequest] 请求体大小: 50000 字节 // 如果>10KB需要优化
// 2. 减少上下文消息数量
const messages = conversation.messages
.filter(m => m.status === 'success')
.slice(-10) // 只保留最近10条消息
// 3. 使用CDN或更近的API端点
// 火山引擎: https://ark.cn-beijing.volces.com (北京)
// 阿里云: https://dashscope.aliyuncs.com (杭州)
2. 模拟流式输出慢 (1000-3000ms)
症状:
⏱️ [callModelStream] 模拟流式输出耗时: 2400.00 ms
⏱️ [callModelStream] 输出块数: 80 总字符数: 400
原因:
// 每个块延迟30ms
await new Promise(resolve => setTimeout(resolve, 30))
// 80块 × 30ms = 2400ms
解决方案:
// 方案1: 减少延迟
await new Promise(resolve => setTimeout(resolve, 10)) // 30ms → 10ms
// 方案2: 增加块大小
const chunkSize = 10 // 5 → 10,减少块数
// 方案3: 使用真正的流式API (最佳)
// 火山引擎支持 stream: true
body = {
model,
messages,
stream: true // 启用流式
}
3. 消息准备慢 (>100ms)
症状:
⏱️ [callModel] 准备消息耗时: 150.00 ms 处理后消息数: 1000
原因: 消息数量太多
解决方案:
// 限制消息历史
const MAX_MESSAGES = 20
const messages = conversation.messages
.filter(m => m.status === 'success')
.slice(-MAX_MESSAGES) // 只保留最近20条
4. 响应解析慢 (>100ms)
症状:
⏱️ [makeChatRequest] 解析响应耗时: 250.00 ms
原因: 响应体太大
解决方案:
// 检查响应大小
console.log('响应大小:', JSON.stringify(result).length, '字节')
// 如果太大,考虑:
// 1. 限制 max_tokens
body = {
model,
messages,
max_tokens: 1000 // 限制输出长度
}
性能优化建议
优先级1: 启用真正的流式API
当前实现 (假流式):
// chatService.ts
const result = await this.callModel(conversation, model) // 等待完整响应
// 然后模拟流式输出
for (let i = 0; i < content.length; i += chunkSize) {
onChunk(chunk)
await new Promise(resolve => setTimeout(resolve, 30)) // 人工延迟
}
优化后 (真流式):
// modelServiceManager.ts - makeChatRequest
const response = await fetch(url, {
method: 'POST',
headers,
body: JSON.stringify({
model,
messages,
stream: true // ← 启用流式
})
})
// 读取流
const reader = response.body.getReader()
const decoder = new TextDecoder()
while (true) {
const { done, value } = await reader.read()
if (done) break
const chunk = decoder.decode(value)
const lines = chunk.split('\n')
for (const line of lines) {
if (line.startsWith('data: ')) {
const data = JSON.parse(line.slice(6))
if (data.choices[0].delta?.content) {
onChunk(data.choices[0].delta.content) // 实时输出
}
}
}
}
效果:
- ❌ 当前: 等待3000ms + 模拟2000ms = 5000ms总延迟
- ✅ 优化后: 实时流式 = 首字输出<500ms
优先级2: 减少请求体大小
// chatService.ts - callModel
const MAX_CONTEXT_MESSAGES = 10 // 最多10条上下文
const MAX_CONTENT_LENGTH = 2000 // 每条消息最多2000字符
const messages = conversation.messages
.filter(m => m.status === 'success')
.slice(-MAX_CONTEXT_MESSAGES) // 只保留最近N条
.map(m => ({
role: m.role,
content: m.content.slice(0, MAX_CONTENT_LENGTH) // 限制长度
}))
优先级3: 优化模拟流式的参数
// chatService.ts - callModelStream
const chunkSize = 20 // 5 → 20 (增大块,减少循环)
const delay = 10 // 30 → 10 (减少延迟)
for (let i = 0; i < content.length; i += chunkSize) {
const chunk = content.slice(i, i + chunkSize)
onChunk(chunk)
await new Promise(resolve => setTimeout(resolve, delay))
}
效果:
- 字符数: 300
- 块数: 300/20 = 15块 (原来60块)
- 总延迟: 15×10 = 150ms (原来1800ms)
- 提速12倍!
优先级4: 添加超时控制
// modelServiceManager.ts - makeChatRequest
const controller = new AbortController()
const timeoutId = setTimeout(() => controller.abort(), 30000) // 30秒超时
try {
const response = await fetch(url, {
method: 'POST',
headers,
body: JSON.stringify(body),
signal: controller.signal
})
clearTimeout(timeoutId)
// ...
} catch (error) {
clearTimeout(timeoutId)
if (error.name === 'AbortError') {
throw new Error('请求超时(30秒)')
}
throw error
}
使用方法
1. 打开浏览器控制台
按 F12 或 Cmd+Option+I (Mac)
2. 发送测试消息
在聊天界面输入简短消息,如 "你好"
3. 查看性能日志
在控制台搜索 ⏱️ 查看所有计时日志
4. 分析瓶颈
按照时间从大到小排序:
⏱️ [callModelStream] callModelStream总耗时: 4307.10 ms ← 总时间
├─ [callModel] callModel总耗时: 2507.00 ms
│ └─ [makeChatRequest] 网络请求耗时: 2500.00 ms ← 瓶颈1
└─ [callModelStream] 模拟流式输出耗时: 1800.00 ms ← 瓶颈2
5. 针对性优化
- 如果 网络请求耗时 > 2000ms → 检查网络/API
- 如果 模拟流式输出耗时 > 1000ms → 优化流式参数或启用真流式
- 如果 准备消息耗时 > 100ms → 限制消息历史数量
预期性能指标
理想情况 (真流式API + 优化)
⏱️ [callModel] 准备消息耗时: < 10 ms
⏱️ [makeChatRequest] 构建请求耗时: < 5 ms
⏱️ [makeChatRequest] 网络请求耗时: 500-1500 ms (首字输出)
⏱️ [callModelStream] 流式输出: 实时,无额外延迟
⏱️ 总体首字延迟: < 2000 ms
当前情况 (假流式)
⏱️ [callModel] 准备消息耗时: 0.5-2 ms ✅
⏱️ [makeChatRequest] 构建请求耗时: 0.2-1 ms ✅
⏱️ [makeChatRequest] 网络请求耗时: 2000-5000 ms ⚠️
⏱️ [callModelStream] 模拟流式输出: 1000-3000 ms ❌
⏱️ 总体延迟: 3000-8000 ms ❌
快速诊断清单
| 问题 | 检查项 | 正常值 | 解决方案 |
|---|---|---|---|
| 总体很慢 | callModelStream总耗时 | < 5000ms | 检查网络和流式 |
| 网络慢 | 网络请求耗时 | < 2000ms | 换更近的API端点 |
| 流式慢 | 模拟流式输出耗时 | < 500ms | 优化参数或启用真流式 |
| 准备慢 | 准备消息耗时 | < 10ms | 限制消息数量 |
| 解析慢 | 解析响应耗时 | < 10ms | 检查响应大小 |
立即可做的优化
快速优化1: 调整流式参数 (30秒)
编辑 /web/src/services/chatService.ts 第565行:
// 原来
const chunkSize = 5
await new Promise(resolve => setTimeout(resolve, 30))
// 改为
const chunkSize = 20
await new Promise(resolve => setTimeout(resolve, 10))
效果: 流式输出速度提升 6-12倍
快速优化2: 限制消息历史 (1分钟)
编辑 /web/src/services/chatService.ts 第500行:
// 原来
const messages = conversation.messages
.filter(m => m.status === 'success')
.map(m => ({ role: m.role, content: m.content }))
// 改为
const MAX_MESSAGES = 10
const messages = conversation.messages
.filter(m => m.status === 'success')
.slice(-MAX_MESSAGES) // 只保留最近10条
.map(m => ({ role: m.role, content: m.content }))
效果: 减少请求体大小,提升网络速度 10-30%
创建时间: 2025年10月14日
适用版本: mcp-client-vue v2.1+