forked from nnethercote/perf-book
-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
0b15c98
commit 061c21a
Showing
7 changed files
with
362 additions
and
106 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
modified: .github/workflows/ci.yml | ||
modified: .gitignore | ||
modified: src/benchmarking.md | ||
new file: src/bounds-checks.md | ||
modified: src/build-configuration.md | ||
modified: src/compile-times.md | ||
modified: src/general-tips.md | ||
modified: src/hashing.md | ||
modified: src/heap-allocations.md | ||
modified: src/inlining.md | ||
modified: src/introduction.md | ||
modified: src/io.md | ||
modified: src/iterators.md | ||
modified: src/linting.md | ||
modified: src/logging-and-debugging.md | ||
modified: src/machine-code.md | ||
modified: src/profiling.md | ||
modified: src/standard-library-types.md | ||
modified: src/type-sizes.md |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,21 +1,30 @@ | ||
# Benchmarking | ||
|
||
在优化一个程序时,你需要一种方法来可靠地回答 "这个改变是否加快了程序?"这个问题。这个过程有时被称为基准测试(benchmarking)。基准测试是一个复杂的话题,彻底的覆盖范围超出了本书的范围,但以下是基本的内容。 | ||
基准测试通常涉及比较执行相同任务的两个或多个程序的性能。有时可能涉及比较两个或多个不同的程序,例如 `Firefox` vs `Safari` vs `Chrome`。有时涉及比较同一程序的两个不同版本。后一种情况让我们能够可靠地回答问题“这个变化是否加快了速度?” | ||
|
||
首先,你需要工作负载来衡量。理想情况下,你会有各种工作负载,代表你的程序的实际使用情况。使用真实世界输入的工作负载是最好的,但[microbenchmarks]和[压力测试(stress tests)]在适度的情况下也是有用的。 | ||
基准测试是一个复杂的主题,全面覆盖超出了本书的范围,但以下是基础知识。 | ||
|
||
首先,您需要工作负载来进行测量。理想情况下,您会有各种代表程序实际使用情况的工作负载。使用真实世界输入的工作负载最好,但[microbenchmarks]和[压力测试]在适度的情况下也是有用的。 | ||
|
||
[microbenchmarks]: https://stackoverflow.com/questions/2842695/what-is-microbenchmarking | ||
[压力测试(stress tests)]: https://en.wikipedia.org/wiki/Stress_testing_(software) | ||
[压力测试]: https://en.wikipedia.org/wiki/Stress_testing_(software) | ||
|
||
其次,您需要一种运行工作负载的方式,这也将决定所使用的度量标准。 | ||
|
||
其次,你需要一种运行工作负载的方法,这也将决定使用的指标。Rust内置的[基准测试(benchmark tests)]是一个简单的起点。[Criterion]是一个更复杂的选择。自定义benchmarking harnesses也是可能的。例如,[rustc-perf]就是用来对Rust编译器进行基准测试的harnesses。 | ||
Rust 内置的[benchmark tests]是一个简单的起点,但它们使用不稳定的功能,因此仅适用于夜间版的 Rust。 | ||
[Criterion] 和 [Divan] 是更复杂的替代方案。 | ||
[Hyperfine] 是一个出色的通用基准测试工具。 | ||
也可以使用自定义基准测试工具。例如,[rustc-perf] 是用于对 Rust 编译器进行基准测试的工具。 | ||
|
||
[基准测试(benchmark tests)]: https://doc.rust-lang.org/1.7.0/book/benchmark-tests.html | ||
[benchmark tests]: https://doc.rust-lang.org/nightly/unstable-book/library-features/test.html | ||
[Criterion]: https://github.com/bheisler/criterion.rs | ||
[Divan]: https://github.com/nvzqz/divan | ||
[Hyperfine]: https://github.com/sharkdp/hyperfine | ||
[rustc-perf]: https://github.com/rust-lang/rustc-perf/ | ||
|
||
当涉及到度量时,有许多选择,正确的选择将取决于被基准化的程序的性质。例如,对批处理程序有意义的指标可能对交互式程序没有意义。在许多情况下,Wall-time是一个显而易见的选择,因为它与用户的感知相对应。然而,它可能会受到大幅变化的影响。特别是,内存布局的微小变化可能会导致显著但短暂的性能波动。因此,方差较小的其他指标(如周期或指令数)可能是一个合理的选择。 | ||
在度量标准方面,有许多选择,选择合适的度量标准取决于正在进行基准测试的程序的性质。例如,对于`批处理程序`(batch program)有意义的度量标准可能对`交互式程序`(interactive program)没有意义。在许多情况下,`Wall-time`是一个显而易见的选择,因为它对应于用户的感知。然而,它可能受到高方差的影响。特别是,内存布局中微小的变化可能导致显著但短暂的性能波动。因此,具有较低方差的其他度量标准(如周期cycles或指令计数)可能是一个合理的替代方案。 | ||
|
||
从多个工作负载中总结测量结果也是一个挑战,尽管有多种方法,但并没有一种方法是最完美的。 | ||
总结来自多个工作负载的测量结果也是一个挑战,有许多方法可以做到这一点,没有一种方法显然是最好的。 | ||
|
||
良好好的基准测试是很难实现的。总而言之,不要过于强调拥有一个完美的基准测试设置,特别是当你开始优化一个程序的时候。一个平庸的设置比没有设置要好得多。对你正在测量的东西保持开放的心态,随着时间的推移,你可以在了解你的程序的性能特点后进行基准测试改进。 | ||
良好的基准测试很困难。话虽如此,在拟进行程序优化时,不要过分强调拥有完美的基准测试设置,尤其是在开始优化程序时。一般的基准测试要比没有基准测试好得多。保持对您正在测量的内容开放的态度,随着时间的推移,您可以根据了解到的程序性能特征进行基准测试改进。 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# Bounds Checks | ||
|
||
默认情况下,在 Rust 中,对切片和向量等容器类型的访问涉及边界检查。这可能会影响性能,例如在热循环中,尽管发生的频率可能不如您所预期的那样频繁。 | ||
|
||
有几种安全的方法可以更改代码,以便编译器了解容器的长度并优化掉边界检查。 | ||
|
||
- 在循环中,通过迭代替换直接元素访问。 | ||
- 在循环中,不要对 Vec 进行索引,而是在循环之前创建 Vec 的切片,然后在循环中对切片进行索引。 | ||
- 在索引变量的范围上添加断言。 | ||
[**Example 1**](https://github.com/rust-random/rand/pull/960/commits/de9dfdd86851032d942eb583d8d438e06085867b), | ||
[**Example 2**](https://github.com/image-rs/jpeg-decoder/pull/167/files). | ||
|
||
让这些方法起作用可能有些棘手。[Bounds Check Cookbook]对这个主题进行了更详细的介绍 | ||
|
||
[Bounds Check Cookbook]: https://github.com/Shnatsel/bounds-check-cookbook/ | ||
|
||
作为最后的手段,还有不安全的方法 [get_unchecked] 和 [get_unchecked_mut]。 | ||
|
||
[`get_unchecked`]: https://doc.rust-lang.org/std/primitive.slice.html#method.get_unchecked | ||
[`get_unchecked_mut`]: https://doc.rust-lang.org/std/primitive.slice.html#method.get_unchecked_mut | ||
|
Oops, something went wrong.