4 个版本 (2 个破坏性更新)
0.3.0 | 2023年6月12日 |
---|---|
0.2.0 | 2022年10月7日 |
0.1.1 | 2022年7月19日 |
0.1.0 | 2022年6月16日 |
#78 in 性能分析
每月下载量 1,215
用于 4 crates
65KB
1.5K SLoC
库
一个受 Criterion 启发的基准测试和计时库。
这里的“受启发”意味着复制 criterion 做得好的地方(我的确是指复制),比如结果的统计分析、简化代码,并省略了大部分的自定义性。
Criterion 采用 MIT 许可,请参阅该仓库的许可或 这里。
主要目标
- 可靠的结果
- 快速构建
- 无依赖
- 简单易读、理解、修改的代码
用途
有时你只需要计算某件事花费的时间。这个库旨在满足这一需求。
基准测试的目标是足够精确,以提供可靠的基准,同时占用最小空间,以便你可以轻松判断是否走错了路。
计时目标是为了提供一种方法,让你可以了解代码运行的时间,尽管它可能不如基准测试可靠。
注意事项
这个库的目标不是提供生产级的分析工具。它只是将数据打印到 stdout 以供指导。如果你需要高级分析,Criterion 提供了更适合的工具。
如果你需要找到应用程序花费时间的地方,flamegraph 可能更适合。
如果您需要在应用程序运行时追踪单个组件,那么追踪可能更适合。
最后,如果您需要更小的基准测试库,请查看benchmark-simple。
未实现
有几个统计指标很受欢迎,但受到该库使用方法的限制。
由于它可能运行数十亿次迭代,因此无法在不将数据缓存到磁盘的情况下,根据看到的所有迭代计算统计信息,例如中位数、标准差和百分位数。因此,像方差或中位数这样的指标前缀为"sample",因为它们与单个迭代时间无关,而是样本之间的比较。
该库没有arg-parsing或bench-matching,因此您不能运行cargo bench . 相反,用户需要将不同的bench放入函数中,并将这些函数添加/删除到bench main中。这样做的原因是,这些库是重量级的,并且可能需要一些宏来选择要运行的bench,这会降低可读性和可理解性。
示例
了解应用程序哪些部分耗时
"我有一个迭代器,我想知道它完成需要多长时间"
use std::time::Duration;
use tiny_bench::Timeable;
pub fn main() {
let v = (0..100)
.map(|a| {
my_expensive_call();
a
})
.timed()
.max();
assert_eq!(99, v.unwrap())
// prints:
// anonymous [100.0 iterations in 512.25ms]:
// elapsed [min mean max]: [5.06ms 5.12ms 5.20ms]
}
fn my_expensive_call() {
std::thread::sleep(Duration::from_millis(5));
}
"我有一个有副作用的重循环,我想测量其执行时间"
use tiny_bench::run_timed_from_iterator;
fn main() {
let generator = 0..100;
let mut spooky_calculation = 0;
let results = run_timed_from_iterator(generator, |i| {
spooky_calculation += i;
});
results.pretty_print();
assert_eq!(4950, spooky_calculation);
}
更复杂的比较
"我的算法相当愚蠢,但我只对最大长度为5的向量进行排序,所以在大局上可能没关系"
use tiny_bench::BenchmarkConfig;
fn main() {
let v = vec![10, 5, 3, 8, 7, 5];
tiny_bench::run_bench(&BenchmarkConfig::default(), || {
let sorted = bad_sort(v.clone());
assert_eq!(vec![3, 5, 5, 7, 8, 10], sorted);
})
// Prints:
// anonymous [2.5M iterations in 4.99s with 100.0 samples]:
// elapsed [min mean max]: [2.14µs 2.01µs 2.14µs]
}
fn bad_sort(mut v: Vec<u32>) -> Vec<u32> {
let mut sorted = Vec::with_capacity(v.len());
while !v.is_empty() {
let mut min_val = u32::MAX;
let mut min_index = 0;
for i in 0..v.len() {
if v[i] < min_val {
min_index = i;
min_val = v[i];
}
}
sorted.push(min_val);
v.remove(min_index);
}
sorted
}
"我想比较不同的实现之间的差异"
use tiny_bench::black_box;
fn main() {
// Results are compared by label
let label = "compare_functions";
tiny_bench::bench_labeled(label, my_slow_function);
tiny_bench::bench_labeled(label, my_faster_function);
// prints:
//compare_functions [30.3 thousand iterations in 5.24s with 100.0 samples]:
//elapsed [min mean max]: [246.33µs 175.51µs 246.33µs]
//compare_functions [60.6 thousand iterations in 5.24s with 100.0 samples]:
//elapsed [min mean max]: [87.67µs 86.42µs 87.67µs]
//change [min mean max]: [-49.6111% -50.7620% -64.4102%] (p = 0.00)
}
fn my_slow_function() {
let mut num_iters = 0;
for _ in 0..10_000 {
num_iters += black_box(1);
}
assert_eq!(10_000, black_box(num_iters))
}
fn my_faster_function() {
let mut num_iters = 0;
for _ in 0..5_000 {
num_iters += black_box(1);
}
assert_eq!(5_000, black_box(num_iters))
}
贡献
我们欢迎社区为本项目做出贡献。
请阅读我们的贡献指南以获取有关如何开始的更多信息。在您做出任何贡献之前,请阅读我们的贡献条款。
任何有意提交以包含在Embark Studios项目中的贡献,应遵守Rust标准许可模式(MIT OR Apache 2.0),因此以下列方式双许可,不附加任何额外条款或条件
许可
此贡献以下列之一双许可:
- Apache许可证版本2.0,(LICENSE-APACHE或http://www.apache.org/licenses/LICENSE-2.0)
- MIT许可证 (LICENSE-MIT或http://opensource.org/licenses/MIT)
任选其一。
为了清晰起见,“您的”指的是Embark或任何其他贡献者/许可方/用户。