迭代 127 - 性能优化 8

背景

基于 performance_profile_development_20260117_141659.log 分析,当前总执行时间 343.38 秒

性能分析

主要热点函数 (按 tottime 排序)

| 排名 | 函数 | tottime | 调用次数 | per call |

|——|——|———|———-|———-|

| 1 | lineseries.__setattr__() | 14.34s | 21.3M | 0.67μs |

| 2 | linebuffer.forward() | 11.73s | 10.7M | 1.09μs |

| 3 | linebuffer.__setitem__() | 8.60s | 10.7M | 0.81μs |

| 4 | linebuffer.__getitem__() | 7.67s | 19M | 0.40μs |

| 5 | builtins.len | 7.63s | 38.7M | 0.20μs |

| 6 | dateintern.num2date() | 7.46s | 2.2M | 3.35μs |

| 7 | drawdown.next() | 6.82s | 688K | 9.91μs |

| 8 | linebuffer.advance() | 6.02s | 9.1M | 0.66μs |

| 9 | linebuffer.set_idx | 5.56s | 23.3M | 0.24μs |

| 10 | strategy._notify() | 5.51s | 688K | 8.01μs |

高调用次数函数

| 函数 | 调用次数 | tottime |

|——|———-|———|

| builtins.len | 38.7M | 7.63s |

| linebuffer.get_idx | 30.5M | 3.42s |

| builtins.getattr | 27.5M | 5.16s |

| linebuffer.set_idx | 23.3M | 5.56s |

| builtins.hasattr | 18.7M | 3.99s |

| str.startswith | 17.3M | 2.67s |

优化建议

Phase 1: 立即实施 (低风险)

1.1 linebuffer.py:set_idx/get_idx - 使用属性替代方法调用

  • 问题*: set_idxget_idx 是非常简单的方法,但被调用了 53.8M 次,方法调用开销显著。

  • 当前代码*:

def get_idx(self):
    return self.idx

def set_idx(self, idx):
    self.idx = idx

```bash

- *优化方案**: 使用 `@property` 或直接访问 `self.idx` 属性

- *预期收益**: 减少方法调用开销节省约 2-3 

#### 1.2 `linebuffer.py:__getitem__()` - 简化快速路径

- *问题**: `__getitem__` 被调用 19M 每次都有多重条件判断

- *优化方案**: 对最常见的 `ago=0` 情况添加快速路径

- *预期收益**: 减少条件判断节省约 1-2 

#### 1.3 `linebuffer.py:__setitem__()` - 减少边界检查

- *问题**: `__setitem__` 被调用 10.7M 边界检查开销大

- *优化方案**: 对常见情况简化边界检查

- *预期收益**: 减少计算节省约 1 

### Phase 2: 中等风险优化

#### 2.1 `dateintern.py:num2date()` - 添加 LRU 缓存

- *问题**: `num2date` 被调用 2.2M 每次都进行日期转换计算

- *优化方案**: 使用 `functools.lru_cache` 缓存常见日期转换

- *预期收益**: 减少重复计算节省约 3-4 

#### 2.2 `drawdown.py:next()` - 优化计算逻辑

- *问题**: `drawdown.next()` 被调用 688K tottime 6.82s

- *优化方案**: 缓存中间计算结果减少重复访问

- *预期收益**: 节省约 2 

### Phase 3: 高风险优化 (需要仔细测试)

#### 3.1 减少 `hasattr` 调用

- *问题**: `hasattr` 被调用 18.7M 耗时 3.99s

- *优化方案**: 使用 `getattr(obj, attr, None)` 替代 `hasattr` + 访问

#### 3.2 减少 `len()` 调用

- *问题**: `len()` 被调用 38.7M 耗时 7.63s

- *优化方案**: 缓存长度值避免重复计算

## 测试验证

每次优化后需要运行:

```bash

# 1. 安装更新并运行测试

pip install -U . && pytest tests -n 8

# 2. 代码格式检查

./scripts/optimize_code.sh

# 3. 性能测试

python scripts/profile_performance.py

```bash

## 实施记录

| 日期 | 优化项 | 状态 | 效果 |

|------|--------|------|------|

| | | | |