← 全部文章

258 倍:热点不在你以为的地方,也不在 profiler 说的地方

2026-08-19约 3 分钟更新日志

一件冲孔板的分析要跑十几秒。我们打开 cProfile 找热点,改完,几乎没快。

profiler 自己就是负载

cProfile 对调用极频繁的小函数收的税特别重——每次调用都要记一笔。于是那些 调用次数百万级的函数在报告里被顶到最前面,而它们的真实占比远没有那么高。我们 按它的指引改了几处,实测收益微乎其微:报告里 4 倍的差距,真跑起来根本不存在。

换成靶向秒表之后才看清楚:在怀疑的那几段代码前后直接掐表,跑真实零件, 对比总时长。土办法,但它测的是真实执行,没有观测者效应。

第一大热点是一句 list()

edges = list(NCollection_List)   # 1290 ms

OCP(OCCT 的 Python 绑定)的迭代器每走一步都要跨一次 C++/Python 边界并做一次 类型分发。实测 1212 个两元素列表要 1290 ms。

换成直接问 Size / First / Last:

n = lst.Size()                   # 5 ms

258 倍。

它藏在建邻接表的循环里,每条边执行一次,是整件分析的第一大热点——冲孔板上占 整体的 24%。而它在 profiler 的报告里毫不起眼,因为它只是一次 list() 调用。

修法上有一条要说清楚:流形几何里一条边恰好属于两张面,所以 0 / 1 / 2 个 元素的快路径覆盖了实际全部情形;元素数 ≥ 3(非流形)时退回原来的慢迭代。快 路径不是赌,是有边界的:

逐边对照新旧两种取法,结果完全一致。

一条留给自己的纪律

性能这件事上我们踩过的坑,几乎都不是"算法选错了",而是测错了地方:

所以现在的做法很朴素:靶向秒表 + 真实零件 + 安静的机器。三样缺一样,测出来 的数就不值得据以改代码。

← 更早一篇同一份文件解析两次,必须给同一个答案