23 个版本
0.5.3 | 2024 年 2 月 8 日 |
---|---|
0.5.2 | 2023 年 10 月 16 日 |
0.5.0 | 2023 年 6 月 1 日 |
0.4.0 | 2023 年 1 月 26 日 |
0.1.2 | 2021 年 3 月 2 日 |
#12 在 性能分析 中
260 每月下载量
在 15 crates 中使用
63KB
1K SLoC
Brunch
Brunch
是一个受 easybench
启发的非常简单的 Rust 微型基准测试运行器。它的依赖项比 criterion
少得多,不需要 nightly,并为每个基准维护一个(单)"上次运行"状态,允许它显示运行之间的相对变化。
(格式也非常美观。)
与所有 Rust 基准测试一样,有很多注意事项,结果可能人为地快或慢。为了获得最佳结果
- 编译优化;
- 收集大量样本;
- 重复相同的运行以了解自然变化;
Brunch
不能测量低于纳秒级别的时间,因此如果你正在尝试基准测试非常快的方法,你可能需要将它们包装在同时运行多个迭代的方法中。例如
use brunch::Bench;
///# Generate Strings to Test.
fn string_seeds() -> Vec<String> {
(0..10_000_usize).into_iter()
.map(|i| "x".repeat(i))
.collect()
}
///# Generate Strings to Test.
fn byte_seeds() -> Vec<Vec<u8>> {
(0..10_000_usize).into_iter()
.map(|i| "x".repeat(i).into_bytes())
.collect()
}
brunch::benches!(
Bench::new("String::len(_)")
.run_seeded_with(string_seeds, |vals| {
let mut len: usize = 0;
for v in vals {
len += v.len();
}
len
}),
Bench::new("Vec::len(_)")
.run_seeded_with(byte_seeds, |vals| {
let mut len: usize = 0;
for v in vals {
len += v.len();
}
len
}),
);
安装
将 brunch
添加到 Cargo.toml
中的 dev-dependencies
,如下所示
[dev-dependencies]
brunch = "0.5.*"
基准测试也应定义在 Cargo.toml
中。只需确保为每个设置 harness = false
[[bench]]
name = "encode"
harness = false
以下环境变量是可选的
变量 | 值 | 描述 | 默认值 |
---|---|---|---|
NO_BRUNCH_HISTORY |
1 |
禁用运行到运行的记录。 | |
BRUNCH_HISTORY |
历史文件路径。 | 从指定路径加载/保存运行到运行的记录。 | std::env::temp_dir()/__brunch.last |
用法
Brunch
的核心是 Bench
结构体,它定义了一个基准测试。不需要进行太多配置,但每个 Bench
都具有以下属性
数据 | 描述 | 默认值 |
---|---|---|
名称 | 一个唯一的标识符。这可以是任意的,但最好是将方法本身的字符串表示作为标识符,例如 foo::bar(10) |
|
样本 | 要收集的样本数量。 | 2500 |
超时 | 一个截止时间,以防止它无限运行。 | 10秒 |
方法 | 一个不断运行的方法! |
该结构体使用构建器风格的函数,允许在单个链中设置所有内容。您始终需要从 Bench::new
开始,并以一个运行者方法结束——Bench::run
、Bench::run_seeded
或 Bench::run_seeded_with
。如果您想更改样本或超时限制,可以在其中添加 Bench::with_samples
或 Bench::with_timeout
。
还有一个特殊的 Bench::spacer
方法,可以用于在结果中插入换行符。下面是一个示例。
示例
benches!
宏是运行 Brunch
基准测试的最简单方法。
只需传递一个逗号分隔的列表,列出您要运行的所有 Bench
对象,它将处理设置、运行、制表和最后给出一个很好的总结。
默认情况下,此宏还会生成 main()
入口点,但您可以通过将 "inline:" 作为第一个参数添加来抑制此操作。
无论如何,默认使用方法如下所示
use brunch::{Bench, benches};
// Example benchmark adding 2+2.
fn callback() -> Option<usize> { 2_usize.checked_add(2) }
// Example benchmark multiplying 2x2.
fn callback2() -> Option<usize> { 2_usize.checked_mul(2) }
// Let the macro handle everything for you.
benches!(
Bench::new("usize::checked_add(2)")
.run(callback),
Bench::new("usize::checked_mul(2)")
.run(callback2),
);
当声明自己的主入口点时,您需要在第一个参数中添加 "inline:"。然后,像往常一样,在后面添加 Bench
实例的列表。
use brunch::{Bench, benches};
/// # Custom Main.
fn main() {
// A typical use case for the "inline" variant would be to declare
// an owned variable for a benchmark that needs to return a reference
// (to e.g. keep Rust from complaining about lifetimes).
let v = vec![0_u8, 1, 2, 3, 4, 5];
// The macro call goes here!
benches!(
inline:
Bench::new("vec::as_slice()").run(|| v.as_slice()),
);
// You can also do other stuff afterwards if you want.
eprintln!("Done!");
}
为了获得更多控制流,跳过宏并直接使用 Benches
。
解释结果
如果您运行此存储库的示例基准测试,您应该看到以下类似的摘要
Method Mean Change Samples
------------------------------------------------------------
fibonacci_recursive(30) 2.22 ms +1.02% 2,408/2,500
fibonacci_loop(30) 56.17 ns --- 2,499/2,500
方法 列表不言自明,但数字需要一些解释
列 | 描述 |
---|---|
平均值 | 针对单次运行的调整后平均执行时间,以保持输出整洁的最适当时间单位进行缩放。 |
变化 | 与上次运行相比的相对差异,如果超过两个标准差。 |
样本 | 有效/总样本数,差异是异常值(5th 和 95th 分位数)不包括在内。 |
许可
另请参阅: CREDITS.md
版权 © 2024 Blobfolio, LLC <[email protected]>
本作品免费。您可以在 Do What The Fuck You Want To Public License,版本 2 的条款下重新分发或修改它。
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.
依赖关系
~555KB