about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--lintcheck/src/config.rs5
-rw-r--r--lintcheck/src/main.rs41
2 files changed, 40 insertions, 6 deletions
diff --git a/lintcheck/src/config.rs b/lintcheck/src/config.rs
index af243f94274..7fa4fb7c034 100644
--- a/lintcheck/src/config.rs
+++ b/lintcheck/src/config.rs
@@ -46,6 +46,11 @@ pub(crate) struct LintcheckConfig {
     /// Run clippy on the dependencies of crates specified in crates-toml
     #[clap(long, conflicts_with("max_jobs"))]
     pub recursive: bool,
+    /// Also produce a `perf.data` file, implies --jobs=1,
+    /// the `perf.data` file can be found at
+    /// `target/lintcheck/sources/<package>-<version>/perf.data`
+    #[clap(long)]
+    pub perf: bool,
     #[command(subcommand)]
     pub subcommand: Option<Commands>,
 }
diff --git a/lintcheck/src/main.rs b/lintcheck/src/main.rs
index e88d9f427be..0438ff40ed1 100644
--- a/lintcheck/src/main.rs
+++ b/lintcheck/src/main.rs
@@ -116,7 +116,25 @@ impl Crate {
 
         clippy_args.extend(lint_levels_args.iter().map(String::as_str));
 
-        let mut cmd = Command::new("cargo");
+        let mut cmd;
+
+        if config.perf {
+            cmd = Command::new("perf");
+            cmd.args(&[
+                "record",
+                "-e",
+                "instructions", // Only count instructions
+                "-g",           // Enable call-graph, useful for flamegraphs and produces richer reports
+                "--quiet",      // Do not tamper with lintcheck's normal output
+                "-o",
+                "perf.data",
+                "--",
+                "cargo",
+            ]);
+        } else {
+            cmd = Command::new("cargo");
+        }
+
         cmd.arg(if config.fix { "fix" } else { "check" })
             .arg("--quiet")
             .current_dir(&self.path)
@@ -234,9 +252,15 @@ fn normalize_diag(
 }
 
 /// Builds clippy inside the repo to make sure we have a clippy executable we can use.
-fn build_clippy() -> String {
+fn build_clippy(release_build: bool) -> String {
     let output = Command::new("cargo")
-        .args(["run", "--bin=clippy-driver", "--", "--version"])
+        .args([
+            "run",
+            "--bin=clippy-driver",
+            if release_build { "-r" } else { "" },
+            "--",
+            "--version",
+        ])
         .stderr(Stdio::inherit())
         .output()
         .unwrap();
@@ -270,13 +294,18 @@ fn main() {
 
 #[allow(clippy::too_many_lines)]
 fn lintcheck(config: LintcheckConfig) {
-    let clippy_ver = build_clippy();
-    let clippy_driver_path = fs::canonicalize(format!("target/debug/clippy-driver{EXE_SUFFIX}")).unwrap();
+    let clippy_ver = build_clippy(config.perf);
+    let clippy_driver_path = fs::canonicalize(format!(
+        "target/{}/clippy-driver{EXE_SUFFIX}",
+        if config.perf { "release" } else { "debug" }
+    ))
+    .unwrap();
 
     // assert that clippy is found
     assert!(
         clippy_driver_path.is_file(),
-        "target/debug/clippy-driver binary not found! {}",
+        "target/{}/clippy-driver binary not found! {}",
+        if config.perf { "release" } else { "debug" },
         clippy_driver_path.display()
     );