Skip to content

Commit edd113e

Browse files
committed
Refactor cachegrind diff generation
1 parent 35741d5 commit edd113e

File tree

3 files changed

+63
-55
lines changed

3 files changed

+63
-55
lines changed

collector/src/bin/collector.rs

Lines changed: 4 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use std::io::BufWriter;
2323
use std::io::Write;
2424
use std::path::{Path, PathBuf};
2525
use std::process;
26-
use std::process::{Command, Stdio};
26+
use std::process::Command;
2727
use std::time::Duration;
2828
use std::{str, time::Instant};
2929
use tokio::runtime::Runtime;
@@ -39,7 +39,8 @@ use collector::runtime::{profile_runtime, RuntimeCompilationOpts};
3939
use collector::toolchain::{
4040
create_toolchain_from_published_version, get_local_toolchain, Sysroot, Toolchain,
4141
};
42-
use collector::utils::wait_for_future;
42+
use collector::utils::cachegrind::cachegrind_diff;
43+
use collector::utils::{is_installed, wait_for_future};
4344

4445
fn n_normal_benchmarks_remaining(n: usize) -> String {
4546
let suffix = if n == 1 { "" } else { "s" };
@@ -123,10 +124,6 @@ fn check_installed(name: &str) -> anyhow::Result<()> {
123124
Ok(())
124125
}
125126

126-
fn is_installed(name: &str) -> bool {
127-
Command::new(name).output().is_ok()
128-
}
129-
130127
fn generate_cachegrind_diffs(
131128
id1: &str,
132129
id2: &str,
@@ -161,15 +158,9 @@ fn generate_cachegrind_diffs(
161158
let id_diff = format!("{}-{}", id1, id2);
162159
let cgout1 = out_dir.join(filename("cgout", id1));
163160
let cgout2 = out_dir.join(filename("cgout", id2));
164-
let cgfilt_diff = out_dir.join(filename("cgfilt-diff", &id_diff));
165161
let cgann_diff = out_dir.join(filename("cgann-diff", &id_diff));
166162

167-
if let Err(e) = cg_diff(&cgout1, &cgout2, &cgfilt_diff) {
168-
errors.incr();
169-
eprintln!("collector error: {:?}", e);
170-
continue;
171-
}
172-
if let Err(e) = cg_annotate(&cgfilt_diff, &cgann_diff) {
163+
if let Err(e) = cachegrind_diff(&cgout1, &cgout2, &cgann_diff) {
173164
errors.incr();
174165
eprintln!("collector error: {:?}", e);
175166
continue;
@@ -182,47 +173,6 @@ fn generate_cachegrind_diffs(
182173
annotated_diffs
183174
}
184175

185-
/// Compares two Cachegrind output files using cg_diff and writes result to path.
186-
fn cg_diff(cgout1: &Path, cgout2: &Path, path: &Path) -> anyhow::Result<()> {
187-
if !is_installed("cg_diff") {
188-
anyhow::bail!("`cg_diff` not installed.");
189-
}
190-
let output = Command::new("cg_diff")
191-
.arg(r"--mod-filename=s/\/rustc\/[^\/]*\///")
192-
.arg("--mod-funcname=s/[.]llvm[.].*//")
193-
.arg(cgout1)
194-
.arg(cgout2)
195-
.stderr(Stdio::inherit())
196-
.output()
197-
.context("failed to run `cg_diff`")?;
198-
199-
if !output.status.success() {
200-
anyhow::bail!("failed to generate cachegrind diff");
201-
}
202-
203-
fs::write(path, output.stdout).context("failed to write `cg_diff` output")?;
204-
205-
Ok(())
206-
}
207-
208-
/// Post process Cachegrind output file and writes resutl to path.
209-
fn cg_annotate(cgout: &Path, path: &Path) -> anyhow::Result<()> {
210-
let output = Command::new("cg_annotate")
211-
.arg("--show-percs=no")
212-
.arg(cgout)
213-
.stderr(Stdio::inherit())
214-
.output()
215-
.context("failed to run `cg_annotate`")?;
216-
217-
if !output.status.success() {
218-
anyhow::bail!("failed to annotate cachegrind output");
219-
}
220-
221-
fs::write(path, output.stdout).context("failed to write `cg_annotate` output")?;
222-
223-
Ok(())
224-
}
225-
226176
#[allow(clippy::too_many_arguments)]
227177
fn profile_compile(
228178
toolchain: &Toolchain,

collector/src/utils/cachegrind.rs

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1+
use crate::utils::is_installed;
12
use crate::utils::mangling::demangle_file;
23
use anyhow::Context;
34
use std::io::{BufRead, Write};
45
use std::path::Path;
5-
use std::process::Command;
6+
use std::process::{Command, Stdio};
67
use std::{fs, io};
78

89
/// Annotate and demangle the output of Cachegrind using the `cg_annotate` tool.
@@ -64,3 +65,54 @@ pub fn cachegrind_annotate(
6465
fs::write(cgann_output, cg_annotate_cmd.output()?.stdout)?;
6566
Ok(())
6667
}
68+
69+
/// Creates a diff between two `cgout` files, and annotates the diff.
70+
pub fn cachegrind_diff(cgout_a: &Path, cgout_b: &Path, output: &Path) -> anyhow::Result<()> {
71+
let cgout_diff = tempfile::NamedTempFile::new()?.into_temp_path();
72+
73+
run_cg_diff(cgout_a, cgout_b, &cgout_diff).context("Cannot run cg_diff")?;
74+
annotate_diff(&cgout_diff, output).context("Cannot run cg_annotate")?;
75+
76+
Ok(())
77+
}
78+
79+
/// Compares two Cachegrind output files using `cg_diff` and writes the result to `path`.
80+
fn run_cg_diff(cgout1: &Path, cgout2: &Path, path: &Path) -> anyhow::Result<()> {
81+
if !is_installed("cg_diff") {
82+
anyhow::bail!("`cg_diff` not installed.");
83+
}
84+
let output = Command::new("cg_diff")
85+
.arg(r"--mod-filename=s/\/rustc\/[^\/]*\///")
86+
.arg("--mod-funcname=s/[.]llvm[.].*//")
87+
.arg(cgout1)
88+
.arg(cgout2)
89+
.stderr(Stdio::inherit())
90+
.output()
91+
.context("failed to run `cg_diff`")?;
92+
93+
if !output.status.success() {
94+
anyhow::bail!("failed to generate cachegrind diff");
95+
}
96+
97+
fs::write(path, output.stdout).context("failed to write `cg_diff` output")?;
98+
99+
Ok(())
100+
}
101+
102+
/// Postprocess Cachegrind output file and writes the result to `path`.
103+
fn annotate_diff(cgout: &Path, path: &Path) -> anyhow::Result<()> {
104+
let output = Command::new("cg_annotate")
105+
.arg("--show-percs=no")
106+
.arg(cgout)
107+
.stderr(Stdio::inherit())
108+
.output()
109+
.context("failed to run `cg_annotate`")?;
110+
111+
if !output.status.success() {
112+
anyhow::bail!("failed to annotate cachegrind output");
113+
}
114+
115+
fs::write(path, output.stdout).context("failed to write `cg_annotate` output")?;
116+
117+
Ok(())
118+
}

collector/src/utils/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use std::future::Future;
2+
use std::process::Command;
23

34
pub mod cachegrind;
45
pub mod fs;
@@ -13,3 +14,8 @@ pub fn wait_for_future<F: Future<Output = R>, R>(f: F) -> R {
1314
.unwrap()
1415
.block_on(f)
1516
}
17+
18+
/// Checks if the given binary can be executed.
19+
pub fn is_installed(name: &str) -> bool {
20+
Command::new(name).output().is_ok()
21+
}

0 commit comments

Comments
 (0)