|
|
@@ -1,193 +0,0 @@
|
|
|
-# 性能优化总结
|
|
|
-
|
|
|
-## 优化概述
|
|
|
-
|
|
|
-针对数据处理卡顿问题,实施了三项关键优化:
|
|
|
-
|
|
|
-### 优化2: 数据库批量写入 ✅
|
|
|
-
|
|
|
-**问题**: 每次策略执行都立即写入数据库,高频数据推送导致每秒数百次数据库操作
|
|
|
-
|
|
|
-**解决方案**:
|
|
|
-- 修改 `database.py` 添加缓冲区机制
|
|
|
-- 新增 `record_price_data()` 方法将数据添加到缓冲区而不是立即写入
|
|
|
-- 新增 `flush_price_data()` 方法批量写入缓冲区数据
|
|
|
-
|
|
|
-**性能提升**:
|
|
|
-- 从每秒100次单条写入 → 每秒1次批量写入(100条)
|
|
|
-- 减少数据库锁定时间
|
|
|
-- 减少磁盘I/O操作
|
|
|
-
|
|
|
-**代码变更**:
|
|
|
-```python
|
|
|
-# 旧方式:每次都commit
|
|
|
-cursor.execute(INSERT_SQL, data)
|
|
|
-self.connection.commit() # 立即提交
|
|
|
-
|
|
|
-# 新方式:缓冲后批量提交
|
|
|
-self._price_data_buffer.append(data)
|
|
|
-# 后台任务定期调用 flush_price_data()
|
|
|
-cursor.executemany(INSERT_SQL, self._price_data_buffer)
|
|
|
-self.connection.commit() # 一次提交100条
|
|
|
-```
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-### 优化3: 账户查询改为后台任务 ✅
|
|
|
-
|
|
|
-**问题**: 在 `do_strategy()` 中每秒查询一次账户信息,阻塞策略执行
|
|
|
-
|
|
|
-**解决方案**:
|
|
|
-- 从 `do_strategy()` 中移除账户查询逻辑
|
|
|
-- 新增 `_periodic_account_update()` 后台任务
|
|
|
-- 新增 `_periodic_db_flush()` 后台任务
|
|
|
-- 在 `main.py` 中启动这两个后台任务
|
|
|
-
|
|
|
-**性能提升**:
|
|
|
-- 策略执行不再被账户API调用阻塞
|
|
|
-- 账户信息独立更新,不影响策略逻辑
|
|
|
-- 数据库写入独立进行,不占用策略执行时间
|
|
|
-
|
|
|
-**代码变更**:
|
|
|
-```python
|
|
|
-# 旧方式:在策略中同步查询
|
|
|
-async def do_strategy(self, market_data):
|
|
|
- # ... 策略逻辑
|
|
|
- account_response = await self.account_api.account(...) # 阻塞
|
|
|
-
|
|
|
-# 新方式:后台定期更新
|
|
|
-async def _periodic_account_update(self):
|
|
|
- while True:
|
|
|
- await asyncio.sleep(1)
|
|
|
- account_response = await self.account_api.account(...)
|
|
|
- self.account_info = account_response
|
|
|
-
|
|
|
-# 在main中启动
|
|
|
-await trading_strategy.start_background_tasks()
|
|
|
-```
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-### 优化4: OrderBook缓存机制 ✅
|
|
|
-
|
|
|
-**问题**: 每次获取排序后的订单簿都需要排序,高频更新导致大量排序操作
|
|
|
-
|
|
|
-**解决方案**:
|
|
|
-- 添加缓存机制:`_bids_cache`, `_asks_cache`, `_cache_valid`
|
|
|
-- 只在数据更新时标记缓存失效
|
|
|
-- 获取排序数据时使用缓存,避免重复排序
|
|
|
-
|
|
|
-**性能提升**:
|
|
|
-- 缓存命中时: 3倍加速(0.0136ms → 0.0045ms)
|
|
|
-- 减少CPU使用率
|
|
|
-- 特别是在高频数据推送时效果显著
|
|
|
-
|
|
|
-**代码变更**:
|
|
|
-```python
|
|
|
-# 旧方式:每次都排序
|
|
|
-def get_sorted_bids(self, limit=10):
|
|
|
- sorted_bids = sorted(self.bids.items(), key=lambda x: x[0], reverse=True)
|
|
|
- return sorted_bids[:limit]
|
|
|
-
|
|
|
-# 新方式:使用缓存
|
|
|
-def get_sorted_bids(self, limit=10):
|
|
|
- if not self._cache_valid:
|
|
|
- self._bids_cache = sorted(self.bids.items(), key=lambda x: x[0], reverse=True)
|
|
|
- self._cache_valid = True
|
|
|
- return self._bids_cache[:limit]
|
|
|
-
|
|
|
-# 更新时标记缓存失效
|
|
|
-def update(self, order_book_data, offset):
|
|
|
- self._cache_valid = False # 标记缓存失效
|
|
|
- # ... 更新数据
|
|
|
-```
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## 测试结果
|
|
|
-
|
|
|
-### 测试2: 数据库批量写入
|
|
|
-```
|
|
|
-添加100条价格数据到缓冲区...
|
|
|
-缓冲区中的数据: 100 条
|
|
|
-批量写入数据库: 100 条
|
|
|
-数据库中的数据: 100 条
|
|
|
-✓ 测试通过
|
|
|
-```
|
|
|
-
|
|
|
-### 测试4: OrderBook缓存机制
|
|
|
-```
|
|
|
-第一次调用 get_sorted_bids: 0.0136ms (包含排序)
|
|
|
-第二次调用 get_sorted_bids: 0.0045ms (使用缓存)
|
|
|
-更新后调用 get_sorted_bids: 0.0134ms (重新排序)
|
|
|
-✓ 缓存机制工作正常,缓存加速: 3.0x
|
|
|
-```
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## 预期效果
|
|
|
-
|
|
|
-### 数据处理流程优化前后对比
|
|
|
-
|
|
|
-**优化前**:
|
|
|
-```
|
|
|
-数据推送(100次/秒)
|
|
|
- → trigger_strategy_update()(100次/秒)
|
|
|
- → do_strategy()(100次/秒)
|
|
|
- → 账户API查询(1次/秒,阻塞)
|
|
|
- → 数据库写入(100次/秒,阻塞)
|
|
|
- → 预签名订单(可能高频)
|
|
|
-```
|
|
|
-
|
|
|
-**优化后**:
|
|
|
-```
|
|
|
-数据推送(100次/秒)
|
|
|
- → trigger_strategy_update()(100次/秒)
|
|
|
- → do_strategy()(100次/秒)
|
|
|
- → 价格数据添加到缓冲区(非阻塞)
|
|
|
- → 预签名订单(可能高频)
|
|
|
-
|
|
|
-后台任务:
|
|
|
- → 账户更新(1次/秒,独立)
|
|
|
- → 数据库刷新(1次/秒,批量100条)
|
|
|
-```
|
|
|
-
|
|
|
-### 性能改进指标
|
|
|
-
|
|
|
-| 指标 | 优化前 | 优化后 | 改进 |
|
|
|
-|------|------|------|------|
|
|
|
-| 数据库写入次数/秒 | 100 | 1 | 100倍 ↓ |
|
|
|
-| 策略执行阻塞时间 | 高 | 低 | 显著 ↓ |
|
|
|
-| OrderBook排序次数 | 每次都排 | 缓存命中时0次 | 3倍 ↑ |
|
|
|
-| CPU使用率 | 高 | 低 | 显著 ↓ |
|
|
|
-| 内存占用 | 低 | 低 | 无变化 |
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## 文件修改清单
|
|
|
-
|
|
|
-1. **src/leadlag/database.py**
|
|
|
- - 修改 `record_price_data()` 使用缓冲区
|
|
|
- - 新增 `flush_price_data()` 批量写入方法
|
|
|
-
|
|
|
-2. **src/leadlag/strategy.py**
|
|
|
- - 移除 `do_strategy()` 中的账户查询
|
|
|
- - 新增 `start_background_tasks()` 启动后台任务
|
|
|
- - 新增 `_periodic_account_update()` 后台账户更新
|
|
|
- - 新增 `_periodic_db_flush()` 后台数据库刷新
|
|
|
-
|
|
|
-3. **src/leadlag/main.py**
|
|
|
- - 修改 `OrderBook` 类添加缓存机制
|
|
|
- - 优化 `_maintain_order_book()` 方法
|
|
|
- - 优化 `get_sorted_bids()` 和 `get_sorted_asks()` 使用缓存
|
|
|
- - 在 `main()` 中启动后台任务
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## 后续建议
|
|
|
-
|
|
|
-1. **监控数据库缓冲区大小**: 如果缓冲区持续增长,可能需要调整刷新间隔
|
|
|
-2. **调整刷新间隔**: 根据实际数据量调整 `_periodic_db_flush()` 的间隔
|
|
|
-3. **添加性能监控**: 记录策略执行时间、数据库写入时间等指标
|
|
|
-4. **考虑限流**: 如果数据推送频率过高,可以添加限流机制(建议2)
|
|
|
-
|