Files
xyzw_web_helper/MD说明文件夹/性能优化-700Token并发100优化方案v3.11.9.md
2025-10-17 20:56:50 +08:00

617 lines
14 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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.

# 性能优化700Token并发100优化方案 v3.11.9
## 📋 文档时间
2025-10-08
## 🎯 场景说明
**实际需求:**
- 总token数**700+个**
- 并发执行:**100个同时运行**
- 总批次:**7批**700 ÷ 100 = 7
- 关键目标:**降低CPU和内存开销**
## 📊 当前问题分析
### 性能瓶颈
#### 1⃣ 内存开销(最严重)
```javascript
// 100个并发token的内存占用估算
100个WebSocket连接 ~500-1000MB
100个token状态对象 ~50-100MB
100个Vue响应式代理 ~100-200MB
100个UI卡片DOM ~200-300MB
执行进度数据 ~50-100MB
日志数据 ~100-200MB
------------------------------------------
预估总内存 1000-1900MB1-2GB)⚠️
// 加上浏览器基础占用约500MB
总计 1.5-2.5GB
```
**问题:** 浏览器可能崩溃或极度卡顿
#### 2⃣ CPU开销
```javascript
// CPU占用来源
1. 100个WebSocket消息处理 主要
2. 100个Vue响应式更新 主要
3. 100个UI卡片渲染 主要
4. 日志输出console.log 次要
5. 任务进度计算 次要
6. CSS动画 次要
预估CPU占用40-60% 多核情况下)⚠️
```
#### 3⃣ UI渲染压力
```javascript
// 100个token卡片同时更新
每秒更新次数100 × 2/ = 200/
触发重排/重绘频繁
滚动性能卡顿
动画效果掉帧
结果界面卡顿严重 ⚠️
```
---
## ✅ 优化方案(七大维度)
### 🎯 方案1虚拟滚动最重要
#### 问题
```
100个token卡片全部渲染在DOM中
→ 大量DOM节点
→ 内存和渲染压力巨大
```
#### 解决方案
```javascript
// 实现虚拟滚动,只渲染可见区域
屏幕可见 约15-20个卡片
预加载 上下各5个
实际渲染 约25-30个卡片
内存节省 70%100 30
渲染性能提升 3-5
```
#### 实现建议
```javascript
// 使用 vue-virtual-scroller 或 vue-virtual-scroll-list
// 或自己实现简单版本
// 核心思路:
1. 计算可见区域viewport
2. 只渲染可见+预加载的卡片
3. 监听滚动动态更新渲染列表
4. 使用 transform 而非 top/margin 定位
```
**预期效果:**
- 内存1.5GB → **800MB** ⬇️ 减少47%
- CPU50% → **25%** ⬇️ 减少50%
- 渲染:卡顿 → **流畅**
---
### 🔇 方案2禁用/优化日志输出
#### 问题
```javascript
// 100个token × 每秒10条日志 = 1000条/秒
console.log() 非常消耗性能
每条日志都会触发浏览器渲染
```
#### 解决方案
```javascript
// 方案A生产模式禁用日志推荐
const DEBUG_MODE = false // 批量任务时设为false
if (DEBUG_MODE) {
console.log(...)
}
// 方案B限制日志级别
只保留 error warn
禁用 info debug
// 方案C批量输出日志
每100条日志合并输出一次
而不是每条都立即输出
```
**预期效果:**
- CPU-10-15%
- 渲染流畅度:明显提升
---
### ⚡ 方案3UI更新节流
#### 问题
```javascript
// 100个token每500ms更新一次进度
// 每秒触发200次Vue响应式更新
taskProgress.value[tokenId].progress = 50 // 触发更新
```
#### 解决方案
```javascript
// 使用节流throttle限制更新频率
// 当前:每个任务完成就更新
// 优化每1-2秒批量更新一次
const updateBatch = new Map()
let updateTimer = null
function throttledUpdate(tokenId, updates) {
updateBatch.set(tokenId, { ...updateBatch.get(tokenId), ...updates })
if (!updateTimer) {
updateTimer = setTimeout(() => {
// 批量应用所有更新
updateBatch.forEach((updates, id) => {
Object.assign(taskProgress.value[id], updates)
})
updateBatch.clear()
updateTimer = null
}, 1000) // 每秒更新一次
}
}
```
**预期效果:**
- Vue响应式更新200次/秒 → **20次/秒** ⬇️
- CPU-5-10%
---
### 🎨 方案4禁用动画和过渡
#### 问题
```javascript
// CSS动画和过渡效果消耗GPU/CPU
.card {
transition: all 0.3s;
animation: pulse 2s infinite;
}
```
#### 解决方案
```javascript
// 在批量任务执行时禁用所有动画
// 方案A添加CSS类
.batch-executing {
* {
animation: none !important;
transition: none !important;
}
}
// 方案BJavaScript控制
document.body.classList.add('disable-animations')
```
**预期效果:**
- GPU占用-20-30%
- 页面流畅度:提升
---
### 💾 方案5优化内存管理
#### 5.1 限制历史记录
```javascript
// 问题:保留所有执行历史
executionHistory.value.unshift(historyItem)
// 优化:只保留最近的
if (executionHistory.value.length > 5) { // 改为5
executionHistory.value = executionHistory.value.slice(0, 5)
}
```
#### 5.2 清理已完成的token数据
```javascript
// 问题已完成的token仍保留完整数据
// 优化:只保留摘要信息
function compactCompletedToken(tokenId) {
const progress = taskProgress.value[tokenId]
if (progress.status === 'completed' || progress.status === 'failed') {
// 只保留关键信息,清理详细数据
progress.result = null // 清理任务结果详情
progress.error = progress.error ? '错误已记录' : null
}
}
```
#### 5.3 WebSocket连接及时断开
```javascript
// 确保任务完成后立即断开连接
// 当前已实现,但要确保没有泄漏
finally {
if (tokenStore.wsConnections[tokenId]) {
tokenStore.closeWebSocketConnection(tokenId)
}
}
```
**预期效果:**
- 内存占用:-200-400MB
---
### 🔧 方案6优化WebSocket消息处理
#### 问题
```javascript
// 每条消息都触发复杂的响应式更新
socket.onmessage = (event) => {
const data = parseMessage(event.data)
// 触发多层响应式更新
store.messages.push(data) // 触发更新
store.unreadCount++ // 触发更新
updateUI() // 触发更新
}
```
#### 解决方案
```javascript
// 使用 nextTick 批量处理消息
const messageQueue = []
socket.onmessage = (event) => {
messageQueue.push(event.data)
// 使用 requestIdleCallback 在空闲时处理
requestIdleCallback(() => {
const batch = messageQueue.splice(0, 100)
processBatch(batch)
})
}
```
**预期效果:**
- 消息处理效率提升30-50%
- CPU尖刺减少
---
### ⏱️ 方案7进一步缩短延迟时间
#### 当前配置
```javascript
连接稳定等待: 2000ms
任务间隔: 500ms
连接间隔: 500ms
```
#### 优化配置100并发专用
```javascript
连接稳定等待: 300ms ⬇️(并发高时可以更短
任务间隔: 200ms ⬇️
连接间隔: 300ms ⬇️
子任务延迟: 50-100ms ⬇️
```
**原理:**
- 100个并发时等待时间可以重叠
- 不需要每个都等足2秒
- 通过并发实现"虚拟等待"
**预期效果:**
- 每个token节省3-5秒
- 总时间节省100个 × 4秒 = 400秒
---
## 🔧 具体代码实施
### 优先级1立即实施核心优化
#### ✅ 1. 禁用日志输出
`src/stores/batchTaskStore.js` 顶部添加:
```javascript
// 批量任务性能优化:禁用日志
const ENABLE_BATCH_LOGS = false // 改为false
// 包装所有console.log
const batchLog = ENABLE_BATCH_LOGS ? console.log.bind(console) : () => {}
// 替换所有 console.log 为 batchLog
// 搜索console.log
// 替换batchLog
```
#### ✅ 2. 缩短延迟时间
```javascript
// 第348行连接稳定等待
await new Promise(resolve => setTimeout(resolve, 2000))
// 改为
await new Promise(resolve => setTimeout(resolve, 300))
// 第401行任务间隔
await new Promise(resolve => setTimeout(resolve, 500))
// 改为
await new Promise(resolve => setTimeout(resolve, 200))
// 第259行连接间隔
const delayMs = connectionIndex * 500
// 改为
const delayMs = connectionIndex * 300
```
#### ✅ 3. 限制历史记录
```javascript
// 第1689行
if (executionHistory.value.length > 10) {
executionHistory.value = executionHistory.value.slice(0, 10)
}
// 改为
if (executionHistory.value.length > 3) {
executionHistory.value = executionHistory.value.slice(0, 3)
}
```
#### ✅ 4. UI更新节流
`src/stores/batchTaskStore.js` 中添加:
```javascript
// 更新进度节流
let updateThrottleTimer = null
const pendingUpdates = new Map()
const updateTaskProgressThrottled = (tokenId, updates) => {
pendingUpdates.set(tokenId, { ...pendingUpdates.get(tokenId), ...updates })
if (!updateThrottleTimer) {
updateThrottleTimer = setTimeout(() => {
pendingUpdates.forEach((updates, id) => {
if (taskProgress.value[id]) {
Object.assign(taskProgress.value[id], updates)
}
})
pendingUpdates.clear()
updateThrottleTimer = null
}, 500) // 每500ms更新一次
}
}
// 在非关键更新处使用 updateTaskProgressThrottled
// 关键更新(开始、结束、失败)仍使用 updateTaskProgress
```
---
### 优先级2重要优化需要更多工作
#### ⭐ 虚拟滚动实现
这需要修改 `TaskProgressCard` 组件的渲染逻辑。
**简单方案:**
```vue
<template>
<div class="token-list-container" @scroll="handleScroll">
<div class="token-list-spacer" :style="{ height: totalHeight + 'px' }">
<div class="token-list-visible" :style="{ transform: `translateY(${offsetY}px)` }">
<TaskProgressCard
v-for="token in visibleTokens"
:key="token.id"
:token="token"
/>
</div>
</div>
</div>
</template>
<script setup>
const CARD_HEIGHT = 200 // 每个卡片高度
const VISIBLE_COUNT = 20 // 可见数量
const BUFFER_COUNT = 5 // 缓冲数量
const visibleTokens = computed(() => {
const start = Math.max(0, scrollTop.value - BUFFER_COUNT)
const end = Math.min(tokens.length, start + VISIBLE_COUNT + BUFFER_COUNT * 2)
return tokens.slice(start, end)
})
const totalHeight = computed(() => tokens.length * CARD_HEIGHT)
const offsetY = computed(() => scrollTop.value * CARD_HEIGHT)
</script>
```
**预期效果:**
- 内存:-800MB
- CPU-25%
- 渲染:流畅
---
## 📊 优化效果预估
### 内存占用对比
| 项目 | 优化前 | 优化后 | 节省 |
|------|--------|--------|------|
| **DOM渲染** | 1000MB | 300MB | **-700MB** ⬇️ |
| **日志数据** | 200MB | 20MB | **-180MB** ⬇️ |
| **历史记录** | 100MB | 30MB | **-70MB** ⬇️ |
| **其他** | 500MB | 450MB | -50MB |
| **总计** | **1800MB** | **800MB** | **-1000MB (55%)** ⬇️ |
### CPU占用对比
| 项目 | 优化前 | 优化后 | 节省 |
|------|--------|--------|------|
| **UI渲染** | 20% | 5% | **-15%** ⬇️ |
| **日志输出** | 10% | 1% | **-9%** ⬇️ |
| **Vue更新** | 15% | 5% | **-10%** ⬇️ |
| **WS消息** | 10% | 8% | -2% |
| **任务逻辑** | 5% | 5% | 0% |
| **总计** | **60%** | **24%** | **-36% (60%)** ⬇️ |
### 执行时间对比700个token
| 方案 | 批次 | 单批时间 | 总时间 |
|------|------|---------|--------|
| **优化前** | 7批 | 3-4分钟 | **21-28分钟** |
| **优化后** | 7批 | 1.5-2分钟 | **10.5-14分钟** ⬇️ |
| **节省** | - | 1.5-2分钟 | **10-14分钟 (50%)** ⬇️ |
---
## ⚠️ 实施建议
### 分阶段实施
#### 阶段1立即可做30分钟
```
1. ✅ 禁用日志输出
2. ✅ 缩短延迟时间
3. ✅ 限制历史记录
4. ✅ 测试50个token
预期效果:内存-300MBCPU-15%
```
#### 阶段2重要优化2小时
```
1. ⭐ 实现虚拟滚动
2. ✅ UI更新节流
3. ✅ 禁用动画
4. ✅ 测试100个token
预期效果:内存-800MBCPU-35%
```
#### 阶段3全面测试1天
```
1. 测试100并发
2. 测试700全量7批
3. 监控性能指标
4. 调优参数
```
---
### 测试检查清单
**启动前检查:**
- [ ] 关闭其他浏览器标签页
- [ ] 关闭不必要的应用程序
- [ ] 确保内存 >4GB 可用
- [ ] 确保网络稳定
**运行中监控:**
- [ ] 任务管理器监控内存(目标<2GB
- [ ] 任务管理器监控CPU目标<40%
- [ ] 浏览器控制台无错误
- [ ] 页面可以正常滚动
**完成后检查:**
- [ ] 成功率 >85%
- [ ] 浏览器未崩溃
- [ ] 内存正常释放
- [ ] 记录实际数据
---
## 💡 额外建议
### 1. 分批策略优化
**不建议:** 一次100个 × 7批
**建议:**
```
方案A50个 × 14批更稳定
方案B70个 × 10批平衡
方案C100个 × 7批激进需全面优化
```
### 2. 时间分散
**建议:**
```
- 不要一口气跑完700个
- 分成早中晚3次每次跑230个
- 避免长时间高负载
```
### 3. 备用方案
如果浏览器仍然吃不消:
**方案A使用多个浏览器实例**
```
浏览器1运行350个token并发50
浏览器2运行350个token并发50
```
**方案B使用Headless模式**
```
使用Puppeteer/Playwright
无UI运行内存占用更小
```
---
## 📝 需要我立即实施的代码修改
我可以马上帮您修改:
### ✅ 核心优化(推荐立即实施)
1. 禁用日志输出
2. 缩短延迟时间300ms/200ms/300ms
3. 限制历史记录10条→3条
4. UI更新节流每500ms
**预期效果:**
- 内存1800MB → **1200MB** ⬇️
- CPU60% → **35%** ⬇️
- 时间21分钟 → **14分钟** ⬇️
### ⭐ 重要优化(需要更多时间)
5. 虚拟滚动需要1-2小时
6. 禁用动画
7. WebSocket消息批处理
**预期效果:**
- 内存1200MB → **800MB** ⬇️
- CPU35% → **24%** ⬇️
- 时间14分钟 → **10.5分钟** ⬇️
---
## 🚀 请确认
**您希望我现在:**
1. ✅ 立即实施核心优化4项修改
2. ⭐ 同时实施虚拟滚动(需要更多时间)?
3. 📋 还是先提供完整修改清单,您自行决定?
**或者您想先测试:**
- 调整并发数到50或70看看现状能否承受
请告诉我您的选择! 🎯