8个版本 (5个破坏性更新)
0.6.0 | 2023年9月18日 |
---|---|
0.5.0 | 2022年8月26日 |
0.4.1 | 2019年9月8日 |
0.4.0 | 2019年4月14日 |
0.1.0 | 2017年7月7日 |
#963 in 密码学
每月45次下载
33KB
489 行
dudect-bencher
这个crate实现了测试函数是否为常时函数的DudeCT统计方法。它是基于bencher
基准测试框架的。
通常,不可能证明一个函数总是以常时运行。这个工具的目的在于找到存在非常时的情况。这并不容易,需要用户非常仔细地思考非常时可能存在的地方。
导入和功能
要导入此crate,请在您的Cargo.toml
文件中添加以下行
dudect-bencher = "0.6"
此crate暴露的功能标志
core-hint-black-box
(默认)— 启用一个新的最佳努力优化屏障(core::hint::black_box
)。如果您使用的Rust版本小于1.66,则无法编译。
使用方法
此框架构建了一个独立的二进制文件。因此,您必须定义一个main.rs
文件,或您的src/bin
目录中的一个文件,或者一个单独的二进制crate,该crate包含您要测试的库。
在高级上,您通过首先定义两个输入集到函数f
,称为Right和Left来测试函数f
。您选择这些输入的方式非常主观。您需要已经有一个关于可能引起非常时行为的想法。然后,您填充Left和Right集合,使得(您认为)f(l)
和f(r)
将花费不同的平均时间运行,其中l
来自Left,r
来自Right。最后,运行基准测试并标记哪个集合是哪个。
以下是一个测试等价函数的例子:v == u
,其中v
和u
是相同长度的Vec<u8>
。这显然不是一个常数时间函数。我们定义左分配为一个集合(v, u)
,其中v == u
,右分配是集合(v, u)
,其中v[6] != u[6]
。
use dudect_bencher::{ctbench_main, BenchRng, Class, CtRunner};
use rand::{Rng, RngCore};
// Return a random vector of length len
fn rand_vec(len: usize, rng: &mut BenchRng) -> Vec<u8> {
let mut arr = vec![0u8; len];
rng.fill(arr.as_mut_slice());
arr
}
// Benchmark for equality of vectors. This does an early return when it finds an
// inequality, so it should be very much not constant-time
fn vec_eq(runner: &mut CtRunner, rng: &mut BenchRng) {
// Make vectors of size 100
let vlen = 100;
let mut inputs: Vec<(Vec<u8>, Vec<u8>)> = Vec::new();
let mut classes = Vec::new();
// Make 100,000 random pairs of vectors
for _ in 0..100_000 {
// Flip a coin. If true, make a pair of vectors that are equal to each
// other and put it in the Left distribution
if rng.gen::<bool>() {
let v1 = rand_vec(vlen, rng);
let v2 = v1.clone();
inputs.push((v1, v2));
classes.push(Class::Left);
}
// Otherwise, make a pair of vectors that differ at the 6th element and
// put it in the right distribution
else {
let v1 = rand_vec(vlen, rng);
let mut v2 = v1.clone();
v2[5] = 7;
inputs.push((v1, v2));
classes.push(Class::Right);
}
}
for (class, (u, v)) in classes.into_iter().zip(inputs.into_iter()) {
// Now time how long it takes to do a vector comparison
runner.run_one(class, || u == v);
}
}
// Crate the main function to include the bench for vec_eq
ctbench_main!(vec_eq);
这是examples/ctbench-foo.rs
示例代码的一部分。要运行示例,请执行
cargo run --release --example ctbench-foo
更多命令行参数见下文
基准测试输出
程序输出如下
bench array_eq ... : n == +0.046M, max t = +61.61472, max tau = +0.28863, (5/tau)^2 = 300
解释如下。首先请注意,运行时分布在不同百分位数被裁剪,并进行了大约100次t检验。在这些t检验中,产生最大绝对t值的那个打印为max_t
。其他打印的值包括
n
,表示计算此t值使用的样本数量max_tau
,这是根据样本大小缩放的t值(正式上,max_tau = max_t / sqrt(n)
)(5/tau)^2
,表示区分两个分布需要测量的数量,其中t > 5
大于5的t值通常被认为是函数不是常数时间的良好指标。小于5的t值并不一定意味着函数是常数时间,因为在某些输入分布下,函数的行为可能显著不同。
命令行参数
--filter
运行包含特定字符串的基准测试子集。例如
cargo run --release --example ctbench-foo -- --filter ar
将只运行包含子字符串ar
的基准测试,即arith
,而不是vec_eq
。
--continuous
持续运行基准测试,随着运行收集更多样本。例如
cargo run --release --example ctbench-foo -- --continuous vec_eq
将连续运行vec_eq
基准测试。
--out
以CSV格式输出原始运行时间。例如
cargo run --release --example ctbench-foo -- --out data.csv
将输出所有在ctbench-foo.rs
中的基准测试到data.csv
。
许可证
根据您的选择,许可以下其中之一
- Apache许可证2.0版本,(LICENSE-APACHE)
- MIT许可证(LICENSE-MIT)
。
依赖项
~2–10MB
~89K SLoC