Skip to content

Commit a81d754

Browse files
committed
Several improvements on lintcheck perf (desc.)
- Now lintcheck perf deletes target directory after benchmarking, benchmarking with a cache isn't very useful or telling of any precise outcome. - Support for benchmarking several times without having to do a cargo clean. Now we can benchmark a PR and master (or a single change in the same commit) without having to move the perf.data files into an external directory. - Compress perf.data to allow for allowing multiple stacks and occupy much less space
1 parent e0175f8 commit a81d754

File tree

1 file changed

+39
-2
lines changed

1 file changed

+39
-2
lines changed

lintcheck/src/main.rs

+39-2
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ use std::io::{self};
3737
use std::path::{Path, PathBuf};
3838
use std::process::{Command, Stdio};
3939
use std::sync::atomic::{AtomicUsize, Ordering};
40+
use std::ffi::OsStr;
4041
use std::{env, fs};
4142

4243
use cargo_metadata::Message;
@@ -120,14 +121,16 @@ impl Crate {
120121

121122
if config.perf {
122123
cmd = Command::new("perf");
124+
let perf_data_filename = get_perf_data_filename(&self.path);
123125
cmd.args(&[
124126
"record",
125127
"-e",
126128
"instructions", // Only count instructions
127129
"-g", // Enable call-graph, useful for flamegraphs and produces richer reports
128130
"--quiet", // Do not tamper with lintcheck's normal output
131+
"--compression-level=22",
129132
"-o",
130-
"perf.data",
133+
&perf_data_filename,
131134
"--",
132135
"cargo",
133136
]);
@@ -165,7 +168,7 @@ impl Crate {
165168
return Vec::new();
166169
}
167170

168-
if !config.fix {
171+
if !config.fix && !config.perf {
169172
cmd.arg("--message-format=json");
170173
}
171174

@@ -203,6 +206,11 @@ impl Crate {
203206
return Vec::new();
204207
}
205208

209+
// We don't want to keep target directories if benchmarking
210+
if config.perf {
211+
fs::remove_dir_all(&shared_target_dir);
212+
}
213+
206214
// get all clippy warnings and ICEs
207215
let mut entries: Vec<ClippyCheckOutput> = Message::parse_stream(stdout.as_bytes())
208216
.filter_map(|msg| match msg {
@@ -441,6 +449,35 @@ fn lintcheck(config: LintcheckConfig) {
441449
fs::write(&config.lintcheck_results_path, text).unwrap();
442450
}
443451

452+
/// Traverse a directory looking for `perf.data.<number>` files, and adds one
453+
/// to the most recent of those files, returning the new most recent `perf.data`
454+
/// file name.
455+
fn get_perf_data_filename(source_path: &Path) -> String {
456+
if source_path.join("perf.data").exists() {
457+
let mut max_number = 0;
458+
let read_dir = fs::read_dir(source_path)
459+
.unwrap()
460+
.filter_map(|path| path.ok())
461+
.filter(|path| {
462+
path.file_name()
463+
.as_os_str()
464+
.to_string_lossy() // We don't care about data loss, as we're checking for equality
465+
.starts_with("perf.data")
466+
})
467+
.for_each(|path| {
468+
let file_name = path.file_name();
469+
let file_name = file_name.as_os_str().to_str().unwrap().split('.').last().unwrap();
470+
if let Ok(parsed_file_name) = file_name.parse::<usize>() {
471+
if parsed_file_name >= max_number {
472+
max_number = parsed_file_name + 1
473+
}
474+
}
475+
});
476+
return format!("perf.data.{max_number}");
477+
}
478+
String::from("perf.data")
479+
}
480+
444481
/// Returns the path to the Clippy project directory
445482
#[must_use]
446483
fn clippy_project_root() -> &'static Path {

0 commit comments

Comments
 (0)