|
| 1 | +//! Criterion benchmark for `fbuild_header_scan::scan` throughput. |
| 2 | +//! |
| 3 | +//! P-03 of FastLED/fbuild#205: capture single-thread MB/s on three input |
| 4 | +//! sizes (tiny / medium / large) so future PRs can regress against a |
| 5 | +//! recorded baseline. The aspirational threshold is ≥ 50 MB/s |
| 6 | +//! single-thread; this harness records the number but does not gate CI. |
| 7 | +
|
| 8 | +use criterion::{black_box, criterion_group, criterion_main, Criterion, Throughput}; |
| 9 | +use fbuild_header_scan::scan; |
| 10 | + |
| 11 | +/// Generate a synthetic C++ source string at least `target_bytes` long. |
| 12 | +/// |
| 13 | +/// The template intentionally exercises the scanner's adversary paths: |
| 14 | +/// angled + quoted `#include`, line and multi-line block comments |
| 15 | +/// containing fake `#include`s, string and raw-string literals with |
| 16 | +/// embedded `#include` payloads, identifiers ending in `R` / `L` |
| 17 | +/// (which must NOT be treated as raw-string prefixes), and a char |
| 18 | +/// literal containing `#`. Repeated until we hit the byte budget. |
| 19 | +fn fixture(target_bytes: usize) -> String { |
| 20 | + let template = "\ |
| 21 | + #include <a.h>\n\ |
| 22 | + // comment with #include <not_real.h>\n\ |
| 23 | + const char* s = \"#include <also_not_real.h>\";\n\ |
| 24 | + const char* r = R\"(#include <not_real_either.h>)\";\n\ |
| 25 | + auto FooR = 0; // identifier ending in R, NOT a raw string\n\ |
| 26 | + auto FooL = 1; // identifier ending in L, NOT a wide-string prefix\n\ |
| 27 | + /* block\n #include <inside_block.h>\n*/\n\ |
| 28 | + char c = '#';\n\ |
| 29 | + #include \"b.h\"\n\ |
| 30 | + "; |
| 31 | + let mut s = String::with_capacity(target_bytes + template.len()); |
| 32 | + while s.len() < target_bytes { |
| 33 | + s.push_str(template); |
| 34 | + } |
| 35 | + s |
| 36 | +} |
| 37 | + |
| 38 | +fn bench_scanner(c: &mut Criterion) { |
| 39 | + let mut group = c.benchmark_group("scan"); |
| 40 | + for (name, size) in [ |
| 41 | + ("tiny", 64usize), |
| 42 | + ("medium", 100 * 1024), |
| 43 | + ("large", 2 * 1024 * 1024), |
| 44 | + ] { |
| 45 | + let src = fixture(size); |
| 46 | + let actual_len = src.len(); |
| 47 | + group.throughput(Throughput::Bytes(actual_len as u64)); |
| 48 | + group.bench_function(name, |b| { |
| 49 | + b.iter(|| { |
| 50 | + let refs = scan(black_box(&src)); |
| 51 | + black_box(refs); |
| 52 | + }); |
| 53 | + }); |
| 54 | + } |
| 55 | + group.finish(); |
| 56 | +} |
| 57 | + |
| 58 | +criterion_group!(benches, bench_scanner); |
| 59 | +criterion_main!(benches); |
0 commit comments