Mac CPU Tools

这段时间有一次顺手优化了一块代码之后,发现性能提升远比我预期的要多。事情是这样的,我摘取了一个最小浮现代码,最后发现自己写错了。按我之前朴素的理解,这里提升应该在 3.5 倍左右。性能提高了固然好,但是这个地方怎么说呢,如果是非预期的性能提升,后面可能藏着 bug,比如我优化前后逻辑不一致了,如果预期性能 x3,但是实际 x10 的话,我当然要检查这里 (1) 是不是优化的时候藏了 bug (2) 如果没有 bug,这个性能提升怎么来的?答案是写出了 bug,这点再次说明了 (1) 应该让 ai 做 code review (2) 无论优化还是劣化,都应该让它符合预期。超过预期的事情需要尽早清理。

火焰图

cargo flamegraph 工具可以看到 flamegraph。https://github.com/flamegraph-rs/flamegraph 。注意 cargo flamegraph 会自己采样的。所以你开着 cargo flamegraph,另一个进程采 perf 的话,会不如您所愿的。

我们先跑起来 benchmark

1
RUSTFLAGS="-C force-frame-pointers=yes" cargo bench

用 Instrument 采样旧代码,我们可以看到

img

这里逻辑大致上是合理的。

看看 Instruments

那差异是怎么来的呢?我在 Mac 上跑了一下 Instrument,我们来看看。下面两个是采样30秒的结果

img

旧代码:

1
2
3
4
5
Useful 41.66%
Instruction Processing Bottleneck 48.92%
Instruction Delivery Bottleneck 8.43%
Discarded Bottleneck 0.98%
Cycles 102,154,391,043

新代码:

1
2
3
4
5
Useful 86.75%  
Instruction Processing Bottleneck 2.55%
Instruction Delivery Bottleneck 7.31%
Discarded Bottleneck 3.2%
Cycles 101,718,418,431

看看汇编

接下来我们看看汇编差异。我使用的是:https://github.com/pacak/cargo-show-asm 工具。这样对比一下可以看到一边少做了很多事情。

小插曲

Perf 采集 benchmark?

我当然在 cargo bench 生成了结果,但是这中间还是经历了一些波折。

  1. Cargo flamegraph?
    1. 你在 perf 的时候如果开 cargo flamegraph,你会发现这个进程会经常在自己调用一些 stacktrace 之类的,对于火焰图来说这个很科学,但是你自己调用的时候…开什么玩笑。所以这里应该就自己跑跑 benchmark 就行
  2. Benchmark 的长度?
    1. 你可以看到,我这里上面为了结果能尽快跑出来,设置了 row_size = 1024,我们假设你设置 1024,这里测试能很快跑完,但是 perf 观测到的东西可能就会包含 benchmark 框架上的东西了,结果难免有一些失真。这里我们可以把 row_size 设置成一个比较大的值,让这里进程能长期做有意义的事情,perf 观测到的能够尽量不包含这些不该有的状态。
    2. 在这里我又碰到个小插曲,我个人 Mac Air 为 16G 内存(穷鬼是这样的)(对了我为什么不用 PC 测我傻逼吗)。

总结

总结:这个问题其实分析完是个特别简单的问题,感觉意识到了之后好像就特别好理解,和呼吸一样自然。

看到的一些材料