引擎四处「算了没人要的东西」,append_bar 13.9ms → 6.6ms
服务端把增量上线后回传两个热点:add_indicators 为加一根重算全表(占 34%)、 cal_bi_list 整表重扫(51%)。顺着查下来四处都不是算法慢,是算了没人读的结果。 1. cal_trend 挂到 lean 下。它不是笔的依赖(bi.py:221 在它自己的循环里读自身 序列状态),服务端 verify_incr_parity 三币 1800 根已对拍定论。web 走非 lean,klc_trend 图层不受影响。 2. check_fx_pattern 删掉拼完就丢的字符串。它把 klu.to_string() 拼成 p 只为 一行注释掉的 print——2000 根上近 3 万次 f-string 加 6 万次 enum 格式化, 而且在 cal_bi_list 内层。klu.pattern 只被 cal_klu_pattern 自己的双K/三K 判定读,不出模块不进 web,所以整个调用在 lean 下也跳过。 3. ChanBI.add_klc 去二次方。去重原本线性扫 klc_list,且每加一根就把整笔所有 KLU 的 macdhist 重累一遍,往一笔加 k 根是 O(k²)。改成下标集合加 macd_hist/macd_div 惰性求值。这两个值只有背驰判定(bsp.py)读,lean 下 bsp 根本不算。 4. add_indicators 批量挂列。2001 行上 TA 计算合计只有 2.5ms,而 30 多次 df['x']= 要 3.6ms——开销大头是 BlockManager 逐列插入不是计算,改为一次 concat。cal_volume_ratio 里为算一列 rolling 而 copy() 整张 40 列表,一并去掉。 实测(本机,2001 根窗口。服务端基线 21.8ms 是另一台机器,别直接比绝对值): append_bar 13.9 → 6.6ms └ rebuild_bi_zs 8.7 → 2.8ms └ add_indicators 4.4 → 3.5ms TF_DF lean 49.8 → 32.9ms TF_DF full 72.7 → 64.9ms 对拍用 git worktree 检出改动前的提交,同一份 BTC 1m 4000 根跑 38 项指纹: full 模式 19 项全部一致(web 那条路没动);lean 模式差 2 项,正是设计要它差 的 klc.trend 和 klu.pattern,而 lean 下 bi/zs/seg/bsp/dataframe 全部一致—— 这就是「这两个字段没人读」的实测证据:打空它们,下游一位不变。 瓶颈已经换位置了。新增 probe_inner.py 拆 inner_ms 分档:本机 TF_DF 两条腿占 70%、build_htf_zones 13%、htf_fx_timeline 6%,而服务端报的是 chan 构建 22ms / 信号链 86ms,机器差解释不了这个四倍差距。曾怀疑是 payload 反序列化,实测 _rebuild 只有 1.0ms,假设不成立。两边跑同一探针对分档表才能定位。 HANDOFF 顺带修掉一处 5.6 重号(增量落地那节改为 5.7,本节挂 5.71)。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+51
-1
@@ -1556,7 +1556,7 @@ python step46_engine_parity.py --check --rows 200000 --out step46_baseline_big.j
|
||||
> 这处偏差值得记:它是读代码读出来的(把一个函数的内部自引用误当成外部
|
||||
> 依赖),而对拍一次就定论了。同类判断优先用对拍。
|
||||
|
||||
### 5.6 增量在影子路径上的落地(2026-08-28)
|
||||
### 5.7 增量在影子路径上的落地(2026-08-28)
|
||||
|
||||
`shadow_signal.compute` 已改为按 `(symbol, timeframe)` 缓存流式对象。
|
||||
|
||||
@@ -1585,6 +1585,56 @@ python step46_engine_parity.py --check --rows 200000 --out step46_baseline_big.j
|
||||
是 `build_htf_zones` / `find_fast_bsp3` / `attach_htf_context`。再压 chan
|
||||
构建收益有限,要继续压得看下游那三个。
|
||||
|
||||
#### 5.71 第二轮引擎优化(2026-08-28,服务端反馈驱动)
|
||||
|
||||
承上——§5.7 末尾点的那两个引擎侧热点(`add_indicators` 全表重算 34%、
|
||||
`cal_bi_list` 整表重扫 51%)。逐个查下来,**四处都是"算了没人要的东西",
|
||||
不是算法本身慢**:
|
||||
|
||||
| 改动 | 性质 |
|
||||
|---|---|
|
||||
| `cal_trend` 挂到 lean 下 | 见上面那条更正——它不是笔的依赖。web 走非 lean,`klc_trend` 图层不受影响 |
|
||||
| `check_fx_pattern` 删掉拼完就丢的字符串 | 它把 `klu.to_string()` 拼成 `p` 只为一行注释掉的 print。2000 根上近 3 万次 f-string + 6 万次 enum 格式化,在 `cal_bi_list` 内层。`klu.pattern` 只被 `cal_klu_pattern` 自己的双K/三K 判定读,不出模块、不进 web,故整个调用 lean 下也跳 |
|
||||
| `ChanBI.add_klc` 去二次方 | 去重原本线性扫 `klc_list`,且**每加一根就把整笔所有 KLU 的 macdhist 重累一遍** → 往一笔加 k 根是 O(k²)。改下标集合 + `macd_hist`/`macd_div` 惰性求值。这两个值只有背驰判定(`bsp.py`)读,lean 下 bsp 根本不算 |
|
||||
| `add_indicators` 批量挂列 | 2001 行上 TA 计算合计只有 2.5ms,而 30 多次 `df['x']=` 要 3.6ms——**开销大头是 BlockManager 逐列插入,不是计算**。改为一次 concat。`cal_volume_ratio` 里为算一列 rolling 而 `dataframe.copy()` 整张 40 列表,一并去掉 |
|
||||
|
||||
实测(本机,2001 根窗口)。**注意这组数和 §5.7 的 21.8ms 不同机**——本机基线
|
||||
就是 13.9ms,服务端约慢 1.4~1.6 倍,别把两边的绝对值直接比:
|
||||
|
||||
| | 改前 | 改后 |
|
||||
|---|---|---|
|
||||
| `append_bar` | 13.9ms | **6.6ms** |
|
||||
| └ `rebuild_bi_zs` | 8.7ms | 2.8ms |
|
||||
| └ `add_indicators` | 4.4ms | 3.5ms |
|
||||
| `TF_DF` lean | 49.8ms | **32.9ms** |
|
||||
| `TF_DF` full | 72.7ms | 64.9ms |
|
||||
|
||||
**对拍**(`git worktree` 检出改动前的提交,同一份 BTC 1m 4000 根,
|
||||
lean/full 两模式 × klc/klu/bi/zs/seg/bsp/指标列/列序,38 项指纹):
|
||||
|
||||
- **full 模式 19 项全部一致** → web 那条路一个字节没动。
|
||||
- **lean 模式差 2 项,且正是设计要它差的两项**:`klc.trend`(跳了
|
||||
`cal_trend`,现恒为 `UNKNOWN`)与 `klu.pattern`(跳了 `cal_klu_pattern`)。
|
||||
- **lean 下的 `bi`/`zs`/`seg`/`bsp`/`dataframe` 全部一致** ——
|
||||
这就是"这两个字段没人读"那句断言的实测证据:把它们打空,下游一位不变。
|
||||
|
||||
⚠️ 别把这写成"完全一致"。有两项按设计就该变,写成全等会掩盖掉真正要担保的
|
||||
那件事:**变的只有这两个已确认无人消费的字段。** full 模式的 `bsp_list` 是
|
||||
`macd_hist` 的唯一消费者,它没变才说明惰性求值是对的。
|
||||
|
||||
**剩下没做的:`add_indicators` 仍是全表重算**(为加一根算 2001 行)。
|
||||
EMA/MACD/ATR 是递推的、BB/SMA/量比是窗口的,理论上都能 O(1) 更新到精确值,
|
||||
但 Wilder RSI 需要额外维护 `avg_gain`/`avg_loss` 状态(从输出反推不出来)。
|
||||
做完 `append_bar` 可到 3~4ms。**风险在于一处不精确就静默换掉一批信号,
|
||||
要做必须先扩对拍。**
|
||||
|
||||
**瓶颈已经换位置了。** 本机分档(`research/live/probe_inner.py`,与服务端
|
||||
同口径):`TF_DF` 两条腿占 70%、`build_htf_zones` 13%、`htf_fx_timeline` 6%、
|
||||
`find_fast_bsp3`+ladder+attach 合计不到 2%。但服务端报的是 chan 构建 22ms /
|
||||
信号链 86ms,按机器差(×1.36)解释不了四倍差距。
|
||||
**曾怀疑是 payload 反序列化,实测 `_rebuild` 只有 1.0ms,假设不成立。**
|
||||
两边跑同一个探针对分档表,才能定位那 86ms。
|
||||
|
||||
---
|
||||
|
||||
## 6. 接下来要做的事(按优先级)
|
||||
|
||||
Reference in New Issue
Block a user