性能分析
在优化程序时,你也需要一种方法来确定程序的哪些部分是“热点”(被频繁执行以影响运行时)并且值得修改。这最好通过性能分析来完成。
性能分析工具
有许多不同的性能分析工具可用,每种都有其优点和缺点。以下是已成功用于 Rust 程序的性能分析工具的不完全列表。
- perf 是一种使用硬件性能计数器的通用性能分析工具。Hotspot 和 Firefox Profiler 适用于查看 perf 记录的数据。它在 Linux 上运行。
- Instruments 是一种通用性能分析工具,随 Xcode 一起提供在 macOS 上。
- Intel VTune Profiler 是一种通用性能分析工具。它在 Windows、Linux 和 macOS 上运行。
- AMD μProf 是一种通用性能分析工具。它在 Windows 和 Linux 上运行。
- samply 是一种采样分析器,可生成可以在 Firefox Profiler 中查看的分析文件。它在 Mac 和 Linux 上运行。
- flamegraph 是一个 Cargo 命令,使用 perf/DTrace 来分析您的代码,然后在火焰图中显示结果。它在 Linux 上运行,以及支持 DTrace 的所有平台(macOS、FreeBSD、NetBSD 和可能的 Windows)。
- Cachegrind 和 Callgrind 提供全局、每个函数和每个源代码行的指令计数以及模拟缓存和分支预测数据。它们在 Linux 和其他一些 Unix 上运行。
- DHAT 适用于查找代码中哪些部分导致了大量分配,并提供有关峰值内存使用情况的见解。它还可以用于识别对
memcpy
的热点调用。它在 Linux 和其他一些 Unix 上运行。dhat-rs 是一个实验性的替代方案,功能稍弱,需要对您的 Rust 程序进行轻微更改,但在所有平台上都运行。 - heaptrack 和 bytehound 是堆分析工具。它们在 Linux 上运行。
counts
支持即时分析,将eprintln!
语句与基于频率的后处理结合使用,非常适合获取对代码部分的领域特定见解。它在所有平台上运行。- Coz 执行因果分析以测量优化潜力,并通过 coz-rs 支持 Rust。它在 Linux 上运行。
调试信息
为了有效地对发布版本进行性能分析,您可能需要启用源代码行调试信息。要做到这一点,请将以下行添加到您的 Cargo.toml
文件中:
[profile.release]
debug = 1
有关 debug
设置的更多详细信息,请参阅 Cargo 文档。
不幸的是,即使执行了上述步骤,您也不会得到有关标准库代码的详细性能分析信息。这是因为 Rust 标准库的发布版本未使用调试信息构建。
绕过这个问题最可靠的方法是构建您自己版本的编译器和标准库,按照 这些说明 进行操作,并将以下行添加到 config.toml
文件中:
[rust]
debuginfo-level = 1
虽然这很麻烦,但在某些情况下可能值得一试。
另外,不稳定的 build-std 功能允许您将标准库作为程序的正常编译的一部分进行编译,并使用相同的构建配置。然而,标准库调试信息中的文件名不会指向源代码文件,因为此功能不会下载标准库源代码。因此,这种方法不会帮助像 Cachegrind 和 Samply 这样需要源代码才能完全运行的性能分析工具。
符号解析
Rust 使用一种名称编码形式来在编译代码中编码函数名称。如果性能分析工具不了解这一点,其输出可能包含以 _ZN
或 _R
开头的符号名称,例如 _ZN3foo3barE
或 _ZN28_$u7b$$u7b$closure$u7d$$u7d$E
或 _RMCsno73SFvQKx_1cINtB0_3StrKRe616263_E
类似这样的名称可以使用 [rustfilt
] 手动解析。
如果在性能分析时遇到符号解析的问题,将默认的旧版格式更改为新版 v0 格式可能值得一试。
要从命令行使用 v0 格式,可以使用 -C symbol-mangling-version=v0
标志。例如:
RUSTFLAGS="-C symbol-mangling-version=v0" cargo build --release
或者,要求在 config.toml
文件中(对于一个或多个项目)添加以下指令:
[build]
rustflags = ["-C", "symbol-mangling-version=v0"]