Files
map-client-vue/PERFORMANCE_ANALYSIS.md
2025-10-14 21:52:11 +08:00

375 lines
9.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 性能追踪分析指南
## 已添加的性能追踪点
### 1. 总体流程追踪
```
用户发送消息
[chatStore.sendMessageStream]
[chatService.sendMessageStream] ⏱️ callModelStream总耗时
├─ [chatService.callModel] ⏱️ callModel总耗时
│ ├─ 准备消息 ⏱️ 准备消息耗时
│ ├─ 服务匹配
│ ├─ [modelServiceManager.sendChatRequest] ⏱️ 请求耗时
│ │ ├─ 准备 ⏱️ 准备耗时
│ │ └─ [makeChatRequest] ⏱️ makeChatRequest总耗时
│ │ ├─ 构建请求 ⏱️ 构建请求耗时
│ │ ├─ 网络请求 ⏱️ 网络请求耗时 ← 通常最慢的部分
│ │ └─ 解析响应 ⏱️ 解析响应耗时
│ └─ 解析响应 ⏱️ 解析响应耗时
└─ 模拟流式输出 ⏱️ 模拟流式输出耗时
```
### 2. 关键性能指标
#### 控制台日志格式
```javascript
// 开始
⏱️ [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配额限制
**解决方案**:
```javascript
// 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
```
**原因**:
```javascript
// 每个块延迟30ms
await new Promise(resolve => setTimeout(resolve, 30))
// 80块 × 30ms = 2400ms
```
**解决方案**:
```javascript
// 方案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
```
**原因**: 消息数量太多
**解决方案**:
```javascript
// 限制消息历史
const MAX_MESSAGES = 20
const messages = conversation.messages
.filter(m => m.status === 'success')
.slice(-MAX_MESSAGES) // 只保留最近20条
```
#### 4. 响应解析慢 (>100ms)
**症状**:
```
⏱️ [makeChatRequest] 解析响应耗时: 250.00 ms
```
**原因**: 响应体太大
**解决方案**:
```javascript
// 检查响应大小
console.log('响应大小:', JSON.stringify(result).length, '字节')
// 如果太大,考虑:
// 1. 限制 max_tokens
body = {
model,
messages,
max_tokens: 1000 // 限制输出长度
}
```
## 性能优化建议
### 优先级1: 启用真正的流式API
**当前实现** (假流式):
```typescript
// 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)) // 人工延迟
}
```
**优化后** (真流式):
```typescript
// 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: 减少请求体大小
```typescript
// 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: 优化模拟流式的参数
```typescript
// 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: 添加超时控制
```typescript
// 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行:
```typescript
// 原来
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行:
```typescript
// 原来
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+