Skip to content

Commit d49b1ff

Browse files
committed
Implement --perf flag to lintcheck for benchmarking
Turns out I was completely overcomplicating myself, there was no need for an external tool such as becnhv2 or even the original becnh, we already had the benchmarking infrastructure right under our noses! This PR implements a new **lintcheck** option called --perf, using it as a flag will mean that lintcheck builds Clippy as a release package and hooks perf to it. The realization that lintcheck is already 90% of what a benchmarking tool needs came to me in a dream.
1 parent ad05bc0 commit d49b1ff

File tree

2 files changed

+40
-6
lines changed

2 files changed

+40
-6
lines changed

lintcheck/src/config.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ pub(crate) struct LintcheckConfig {
4646
/// Run clippy on the dependencies of crates specified in crates-toml
4747
#[clap(long, conflicts_with("max_jobs"))]
4848
pub recursive: bool,
49+
/// Also produce a `perf.data` file, implies --jobs=1,
50+
/// the `perf.data` file can be found at
51+
/// `target/lintcheck/sources/<package>-<version>/perf.data`
52+
#[clap(long)]
53+
pub perf: bool,
4954
#[command(subcommand)]
5055
pub subcommand: Option<Commands>,
5156
}

lintcheck/src/main.rs

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,25 @@ impl Crate {
116116

117117
clippy_args.extend(lint_levels_args.iter().map(String::as_str));
118118

119-
let mut cmd = Command::new("cargo");
119+
let mut cmd;
120+
121+
if config.perf {
122+
cmd = Command::new("perf");
123+
cmd.args(&[
124+
"record",
125+
"-e",
126+
"instructions", // Only count instructions
127+
"-g", // Enable call-graph, useful for flamegraphs and produces richer reports
128+
"--quiet", // Do not tamper with lintcheck's normal output
129+
"-o",
130+
"perf.data",
131+
"--",
132+
"cargo",
133+
]);
134+
} else {
135+
cmd = Command::new("cargo");
136+
}
137+
120138
cmd.arg(if config.fix { "fix" } else { "check" })
121139
.arg("--quiet")
122140
.current_dir(&self.path)
@@ -234,9 +252,15 @@ fn normalize_diag(
234252
}
235253

236254
/// Builds clippy inside the repo to make sure we have a clippy executable we can use.
237-
fn build_clippy() -> String {
255+
fn build_clippy(release_build: bool) -> String {
238256
let output = Command::new("cargo")
239-
.args(["run", "--bin=clippy-driver", "--", "--version"])
257+
.args([
258+
"run",
259+
"--bin=clippy-driver",
260+
if release_build { "-r" } else { "" },
261+
"--",
262+
"--version",
263+
])
240264
.stderr(Stdio::inherit())
241265
.output()
242266
.unwrap();
@@ -270,13 +294,18 @@ fn main() {
270294

271295
#[allow(clippy::too_many_lines)]
272296
fn lintcheck(config: LintcheckConfig) {
273-
let clippy_ver = build_clippy();
274-
let clippy_driver_path = fs::canonicalize(format!("target/debug/clippy-driver{EXE_SUFFIX}")).unwrap();
297+
let clippy_ver = build_clippy(config.perf);
298+
let clippy_driver_path = fs::canonicalize(format!(
299+
"target/{}/clippy-driver{EXE_SUFFIX}",
300+
if config.perf { "release" } else { "debug" }
301+
))
302+
.unwrap();
275303

276304
// assert that clippy is found
277305
assert!(
278306
clippy_driver_path.is_file(),
279-
"target/debug/clippy-driver binary not found! {}",
307+
"target/{}/clippy-driver binary not found! {}",
308+
if config.perf { "release" } else { "debug" },
280309
clippy_driver_path.display()
281310
);
282311

0 commit comments

Comments
 (0)