diff options
author | Aleksey Kladov <[email protected]> | 2021-02-09 16:29:40 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2021-02-09 17:25:39 +0000 |
commit | 4b1279d0b160d98c1429ca1a52b37aa7a0af5775 (patch) | |
tree | 8b71d80a070120904b76fca78d8db45b3000e9b3 /crates/test_utils/src | |
parent | 9ea2c96ddd0ad8c8898f1c65667a57a78ba2218c (diff) |
Infra for "unit" benchmarking
Diffstat (limited to 'crates/test_utils/src')
-rw-r--r-- | crates/test_utils/src/bench_fixture.rs | 28 | ||||
-rw-r--r-- | crates/test_utils/src/lib.rs | 43 |
2 files changed, 71 insertions, 0 deletions
diff --git a/crates/test_utils/src/bench_fixture.rs b/crates/test_utils/src/bench_fixture.rs new file mode 100644 index 000000000..41fcca635 --- /dev/null +++ b/crates/test_utils/src/bench_fixture.rs | |||
@@ -0,0 +1,28 @@ | |||
1 | //! Generates large snippets of Rust code for usage in the benchmarks. | ||
2 | |||
3 | use stdx::format_to; | ||
4 | |||
5 | pub fn big_struct() -> String { | ||
6 | let n = 1_000; | ||
7 | |||
8 | let mut buf = "pub struct RegisterBlock {".to_string(); | ||
9 | for i in 0..n { | ||
10 | format_to!(buf, " /// Doc comment for {}.\n", i); | ||
11 | format_to!(buf, " pub s{}: S{},\n", i, i); | ||
12 | } | ||
13 | buf.push_str("}\n\n"); | ||
14 | for i in 0..n { | ||
15 | format_to!( | ||
16 | buf, | ||
17 | " | ||
18 | |||
19 | #[repr(transparent)] | ||
20 | struct S{} {{ | ||
21 | field: u32, | ||
22 | }}", | ||
23 | i | ||
24 | ); | ||
25 | } | ||
26 | |||
27 | buf | ||
28 | } | ||
diff --git a/crates/test_utils/src/lib.rs b/crates/test_utils/src/lib.rs index e19d2ad61..5be4a64fc 100644 --- a/crates/test_utils/src/lib.rs +++ b/crates/test_utils/src/lib.rs | |||
@@ -8,6 +8,7 @@ | |||
8 | 8 | ||
9 | #[macro_use] | 9 | #[macro_use] |
10 | pub mod mark; | 10 | pub mod mark; |
11 | pub mod bench_fixture; | ||
11 | mod fixture; | 12 | mod fixture; |
12 | 13 | ||
13 | use std::{ | 14 | use std::{ |
@@ -16,6 +17,7 @@ use std::{ | |||
16 | path::PathBuf, | 17 | path::PathBuf, |
17 | }; | 18 | }; |
18 | 19 | ||
20 | use profile::StopWatch; | ||
19 | use serde_json::Value; | 21 | use serde_json::Value; |
20 | use stdx::lines_with_ends; | 22 | use stdx::lines_with_ends; |
21 | use text_size::{TextRange, TextSize}; | 23 | use text_size::{TextRange, TextSize}; |
@@ -406,3 +408,44 @@ pub fn format_diff(chunks: Vec<dissimilar::Chunk>) -> String { | |||
406 | } | 408 | } |
407 | buf | 409 | buf |
408 | } | 410 | } |
411 | |||
412 | /// Utility for writing benchmark tests. | ||
413 | /// | ||
414 | /// A benchmark test looks like this: | ||
415 | /// | ||
416 | /// ``` | ||
417 | /// #[test] | ||
418 | /// fn benchmark_foo() { | ||
419 | /// if skip_slow_tests() { return; } | ||
420 | /// | ||
421 | /// let data = bench_fixture::some_fixture(); | ||
422 | /// let analysis = some_setup(); | ||
423 | /// | ||
424 | /// let hash = { | ||
425 | /// let _b = bench("foo"); | ||
426 | /// actual_work(analysis) | ||
427 | /// }; | ||
428 | /// assert_eq!(hash, 92); | ||
429 | /// } | ||
430 | /// ``` | ||
431 | /// | ||
432 | /// * We skip benchmarks by default, to save time. | ||
433 | /// Ideal benchmark time is 800 -- 1500 ms in debug. | ||
434 | /// * We don't count preparation as part of the benchmark | ||
435 | /// * The benchmark itself returns some kind of numeric hash. | ||
436 | /// The hash is used as a sanity check that some code is actually run. | ||
437 | /// Otherwise, it's too easy to win the benchmark by just doing nothing. | ||
438 | pub fn bench(label: &'static str) -> impl Drop { | ||
439 | struct Bencher { | ||
440 | sw: StopWatch, | ||
441 | label: &'static str, | ||
442 | } | ||
443 | |||
444 | impl Drop for Bencher { | ||
445 | fn drop(&mut self) { | ||
446 | eprintln!("{}: {}", self.label, self.sw.elapsed()) | ||
447 | } | ||
448 | } | ||
449 | |||
450 | Bencher { sw: StopWatch::start(), label } | ||
451 | } | ||