1use std::process::Command;
2
3use anyhow::Result;
4use clap::Args;
5
6use crate::util::{repository_root, run_cmd};
7
8#[derive(Debug, Args)]
10pub(super) struct BenchCmd {
11 #[clap(long, short = 'p')]
12 package: String,
13
14 #[clap(long)]
16 debug: bool,
17
18 #[clap(short = 't')]
20 template: Option<String>,
21
22 #[clap(long)]
23 no_lib: bool,
24
25 #[clap(long)]
26 benches: bool,
27
28 #[clap(long)]
29 bench: Option<String>,
30
31 #[clap(long)]
33 instrument: bool,
34
35 #[clap(long)]
37 samply: bool,
38
39 #[clap(long)]
40 features: Vec<String>,
41
42 args: Vec<String>,
43}
44
45impl BenchCmd {
46 pub fn run(self) -> Result<()> {
47 let mut cmd = self.build_cmd()?;
48
49 cmd.env("RUST_LOG", "off");
50 cmd.env("CARGO_PROFILE_RELEASE_DEBUG", "true");
51 cmd.env("CARGO_PROFILE_BENCH_DEBUG", "true");
52
53 run_cmd(&mut cmd)
54 }
55
56 fn build_cmd(&self) -> Result<Command> {
57 let mut cmd = if self.samply {
58 let mut cmd = Command::new("ddt");
60 cmd.arg("profile").arg("samply").arg("cargo");
61
62 if !self.debug {
63 cmd.arg("--release");
64 }
65
66 cmd
67 } else if self.instrument {
68 let mut cmd = Command::new("ddt");
70 cmd.arg("profile").arg("instruments").arg("cargo");
71 cmd.arg("-t")
72 .arg(self.template.as_deref().unwrap_or("time"));
73
74 if !self.debug {
75 cmd.arg("--release");
76 }
77
78 cmd
79 } else {
80 let mut cmd = Command::new("cargo");
81 cmd.arg("bench");
82
83 if self.debug {
84 cmd.arg("--debug");
85 }
86
87 cmd
88 };
89
90 cmd.arg("--package").arg(&self.package);
91
92 if self.benches {
93 cmd.arg("--benches");
94 }
95
96 if let Some(b) = &self.bench {
97 cmd.arg("--bench").arg(b);
98 }
99
100 for f in self.features.iter() {
101 cmd.arg("--features").arg(f);
102 }
103
104 if self.samply || self.instrument {
105 cmd.arg("--").arg("--bench").args(&self.args);
106 } else {
107 cmd.arg("--").args(&self.args);
108 }
109
110 cmd.current_dir(repository_root()?.join("crates").join(&self.package));
112
113 Ok(cmd)
114 }
115}