W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
Rust支持基準(zhǔn)測(cè)試來(lái)測(cè)試用戶代碼的性能。我們來(lái)看一下 src/lib.rs
的性能如何。
`#![feature(test)]
extern crate test;
pub fn add_two(a: i32) -> i32 {
a + 2
}
#[cfg(test)]
mod tests {
use super::*;
use test::Bencher;
#[test]
fn it_works() {
assert_eq!(4, add_two(2));
}
#[bench]
fn bench_add_two(b: &mut Bencher) {
b.iter(|| add_two(2));
}
}`
注意上面代碼中的 test
的功能聲明,這表示這并不是一個(gè)穩(wěn)定的功能。
用戶需要引入 test
的封裝,來(lái)使得基準(zhǔn)測(cè)試得以支持。通過(guò) bench
屬性的使用,我們可以實(shí)現(xiàn)一個(gè)新的函數(shù)。與不能有參數(shù)的常規(guī)測(cè)試不同,這里的基準(zhǔn)測(cè)試使用 &mut Bencher
來(lái)改善這個(gè)情況。這里的 Bencher
提供了一個(gè)閉包的 iter 方法。這個(gè)閉包就包含了需要進(jìn)行基準(zhǔn)測(cè)試的代碼。
用戶通過(guò) cargo bench
指令來(lái)執(zhí)行基準(zhǔn)測(cè)試:
$ cargo bench
Compiling adder v0.0.1 (file:///home/steve/tmp/adder)
Running target/release/adder-91b3e234d4ed382a
running 2 tests
test tests::it_works ... ignored
test tests::bench_add_two ... bench: 1 ns/iter (+/- 0)
test result: ok. 0 passed; 0 failed; 1 ignored; 1 measured
我們的非基準(zhǔn)測(cè)試可以被忽略掉。用戶也許會(huì)注意到 cargo bench
比 cargo test
長(zhǎng)一個(gè)比特。這是因?yàn)?Rust 會(huì)多次執(zhí)行基準(zhǔn)測(cè)試,然后會(huì)取一個(gè)平均值。因?yàn)樵谶@個(gè)例子中,只是實(shí)現(xiàn)了一些簡(jiǎn)單的功能,所以我們有一個(gè) ns/iter (+/- 0)
,但是這會(huì)展示出結(jié)果的方差。
如下是編寫基準(zhǔn)測(cè)試的建議:
iter
循環(huán)之外,只是將用戶希望進(jìn)行測(cè)試的代碼放到 iter
循環(huán)內(nèi)。iter
循環(huán)體內(nèi)容的代碼更精簡(jiǎn),然后使得基準(zhǔn)測(cè)試運(yùn)行起來(lái)更快捷,使得校準(zhǔn)器可以以更高精度的來(lái)校準(zhǔn)。iter
循環(huán)體內(nèi)的代碼更簡(jiǎn)單,以幫助查明性能改進(jìn)的地方(或回歸)。在基準(zhǔn)測(cè)試程序的編寫方面還存在一些辣手的問(wèn)題:優(yōu)化編譯后的基準(zhǔn)測(cè)試代碼可能會(huì)被優(yōu)化器篡改,這樣使得基準(zhǔn)測(cè)試可能就不再是用戶希望的測(cè)試對(duì)象了。比如,編譯器可能會(huì)重新組織一些代碼,因?yàn)檫@些代碼并沒(méi)有什么作用,甚至?xí)⑺縿h除。
#![feature(test)]
extern crate test;
use test::Bencher;
#[bench]
fn bench_xor_1000_ints(b: &mut Bencher) {
b.iter(|| {
(0..1000).fold(0, |old, new| old ^ new);
});
}
上述代碼會(huì)出現(xiàn)下述結(jié)果:
running 1 test
test bench_xor_1000_ints ... bench: 0 ns/iter (+/- 0)
test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured
為了避免上述問(wèn)題,基準(zhǔn)測(cè)試的執(zhí)行者會(huì)采用兩個(gè)方法。iter
方法可以獲得一個(gè)閉包,它可以返回一個(gè)任意值來(lái)迫使優(yōu)化器考慮這個(gè)結(jié)果,來(lái)保證優(yōu)化器不會(huì)更改基準(zhǔn)測(cè)試代碼。下面的例子就是來(lái)展示如何校準(zhǔn) b.iter
.
`b.iter(|| {
// note lack of `;` (could also use an explicit `return`).
(0..1000).fold(0, |old, new| old ^ new)
});`
另一種方法是通用的 test::black_box
函數(shù),它對(duì)優(yōu)化器就是一個(gè)“黑盒”,可以迫使優(yōu)化器考慮更多的參數(shù)。
#![feature(test)]
extern crate test;
b.iter(|| {
let n = test::black_box(1000);
(0..n).fold(0, |a, b| a ^ b)
})
這些并不會(huì)讀取和更改這個(gè)值。較大的值可以直接降低開銷。
`black_box(&huge_struct)`
執(zhí)行上述任何一種變化提供了以下基準(zhǔn)測(cè)試結(jié)果。
running 1 test
test bench_xor_1000_ints ... bench: 131 ns/iter (+/- 3)
test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured
即使使用上述方式,優(yōu)化器仍然會(huì)以不可想象的方式來(lái)修改測(cè)試用例。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: