Skip to content

Commit 0ee39a2

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 0ee39a2

File tree

1 file changed

+38
-2
lines changed

1 file changed

+38
-2
lines changed

Diff for: lintcheck/src/main.rs

+38-2
Original file line numberDiff line numberDiff line change
@@ -120,14 +120,16 @@ impl Crate {
120120

121121
if config.perf {
122122
cmd = Command::new("perf");
123+
let perf_data_filename = get_perf_data_filename(&self.path);
123124
cmd.args(&[
124125
"record",
125126
"-e",
126127
"instructions", // Only count instructions
127128
"-g", // Enable call-graph, useful for flamegraphs and produces richer reports
128129
"--quiet", // Do not tamper with lintcheck's normal output
130+
"--compression-level=22",
129131
"-o",
130-
"perf.data",
132+
&perf_data_filename,
131133
"--",
132134
"cargo",
133135
]);
@@ -165,7 +167,7 @@ impl Crate {
165167
return Vec::new();
166168
}
167169

168-
if !config.fix {
170+
if !config.fix && !config.perf {
169171
cmd.arg("--message-format=json");
170172
}
171173

@@ -203,6 +205,11 @@ impl Crate {
203205
return Vec::new();
204206
}
205207

208+
// We don't want to keep target directories if benchmarking
209+
if config.perf {
210+
let _ = fs::remove_dir_all(&shared_target_dir);
211+
}
212+
206213
// get all clippy warnings and ICEs
207214
let mut entries: Vec<ClippyCheckOutput> = Message::parse_stream(stdout.as_bytes())
208215
.filter_map(|msg| match msg {
@@ -441,6 +448,35 @@ fn lintcheck(config: LintcheckConfig) {
441448
fs::write(&config.lintcheck_results_path, text).unwrap();
442449
}
443450

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

0 commit comments

Comments
 (0)