|
| 1 | +use std::{ |
| 2 | + process::Command, |
| 3 | + sync::{LazyLock, Once}, |
| 4 | +}; |
| 5 | + |
| 6 | +use gungraun::{ |
| 7 | + BinaryBenchmarkConfig, Callgrind, FlamegraphConfig, binary_benchmark, binary_benchmark_group, |
| 8 | + main, |
| 9 | +}; |
| 10 | + |
| 11 | +static BUILD: Once = Once::new(); |
| 12 | +static EXT_TARGET_DIR: LazyLock<String> = LazyLock::new(|| { |
| 13 | + let mut dir = std::env::current_dir().expect("Could not get cwd"); |
| 14 | + dir.pop(); |
| 15 | + dir.push("target"); |
| 16 | + dir.push("release"); |
| 17 | + dir.display().to_string() |
| 18 | +}); |
| 19 | + |
| 20 | +fn setup() { |
| 21 | + BUILD.call_once(|| { |
| 22 | + let mut command = Command::new("cargo"); |
| 23 | + command.arg("build"); |
| 24 | + |
| 25 | + command.arg("--release"); |
| 26 | + |
| 27 | + // Build features list dynamically based on compiled features |
| 28 | + // Note: Using vec_init_then_push pattern here is intentional due to conditional compilation |
| 29 | + #[allow(clippy::vec_init_then_push)] |
| 30 | + { |
| 31 | + let mut features = vec![]; |
| 32 | + #[cfg(feature = "enum")] |
| 33 | + features.push("enum"); |
| 34 | + #[cfg(feature = "closure")] |
| 35 | + features.push("closure"); |
| 36 | + #[cfg(feature = "anyhow")] |
| 37 | + features.push("anyhow"); |
| 38 | + #[cfg(feature = "runtime")] |
| 39 | + features.push("runtime"); |
| 40 | + #[cfg(feature = "static")] |
| 41 | + features.push("static"); |
| 42 | + |
| 43 | + if !features.is_empty() { |
| 44 | + command.arg("--no-default-features"); |
| 45 | + command.arg("--features").arg(features.join(",")); |
| 46 | + } |
| 47 | + } |
| 48 | + |
| 49 | + let result = command.output().expect("failed to execute cargo build"); |
| 50 | + |
| 51 | + assert!( |
| 52 | + result.status.success(), |
| 53 | + "Extension build failed:\nstdout: {}\nstderr: {}", |
| 54 | + String::from_utf8_lossy(&result.stdout), |
| 55 | + String::from_utf8_lossy(&result.stderr) |
| 56 | + ); |
| 57 | + }); |
| 58 | +} |
| 59 | + |
| 60 | +#[binary_benchmark] |
| 61 | +#[bench::single_function_call(args = ("benches/function_call.php", 1))] |
| 62 | +#[bench::multiple_function_calls(args = ("benches/function_call.php", 10))] |
| 63 | +#[bench::lots_of_function_calls(args = ("benches/function_call.php", 100_000))] |
| 64 | +fn function_calls(path: &str, cnt: usize) -> gungraun::Command { |
| 65 | + setup(); |
| 66 | + |
| 67 | + gungraun::Command::new("php") |
| 68 | + .arg(format!("-dextension={}/libbenches.so", *EXT_TARGET_DIR)) |
| 69 | + .arg(path) |
| 70 | + .arg(cnt.to_string()) |
| 71 | + .build() |
| 72 | +} |
| 73 | + |
| 74 | +binary_benchmark_group!( |
| 75 | + name = function; |
| 76 | + benchmarks = function_calls |
| 77 | +); |
| 78 | + |
| 79 | +main!( |
| 80 | + config = BinaryBenchmarkConfig::default() |
| 81 | + .tool(Callgrind::with_args(["--instr-atstart=no", "--I1=32768,8,64", "--D1=32768,8,64", "--LL=67108864,16,64"]) |
| 82 | + .flamegraph(FlamegraphConfig::default())); |
| 83 | + binary_benchmark_groups = function |
| 84 | +); |
0 commit comments