替换哈希集合后,为何cargo flamegraph比cargo run快45倍?
核心原因可以拆解为三点:
哈希算法的性能差距
std的HashMap/HashSet采用SipHash加密哈希算法,虽能抵御哈希碰撞攻击,但计算开销远高于rustc_hash的Fx系列——Fx使用专为性能优化设计的非加密哈希算法,哈希计算、插入、查找等操作的耗时仅为SipHash的几分之一到几十分之一。如果你的程序有大量哈希表操作,这部分性能提升本身就非常显著。Profiling采样与哈希表行为的叠加效应
cargo flamegraph依赖perf工具进行CPU采样,采样过程本身会带来一定运行开销(比如定时中断、上下文切换)。使用std哈希表时,程序大量时间消耗在SipHash的复杂计算上,perf会捕获更多采样点,采样开销与哈希计算耗时叠加,导致整体运行略慢于纯release模式的cargo run。
换成Fx哈希表后,哈希计算的CPU耗时骤降,程序整体运行时间大幅缩短,perf需要采样的次数也随之减少,采样的相对开销被极大稀释。你看到的45倍差距,本质是原std版本在flamegraph下的慢态和Fx版本在flamegraph下的快态之间的对比,核心是Fx哈希表的性能提升加上采样开销的大幅降低。编译优化与调试信息的影响
cargo flamegraph会在release编译基础上添加-g调试信息,这可能导致std库中部分代码的内联优化被取消(比如SipHash的核心计算函数),进一步拉低std哈希表的性能。而Fx哈希表的实现更简洁,对调试信息的兼容性更好,即使在带调试信息的release编译模式下,也能保持接近最优的优化效果。
内容的提问来源于stack exchange,提问作者Dave

