Skip to content

mono-item profiler #1016

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions collector/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,13 @@ The mandatory `<PROFILER>` argument must be one of the following.
- **Output**. Human-readable output is written to files with an `ll` prefix.
- **Notes**. Does not work with the `Check` build kind. Also does not work
with the `IncrFull`, `IncrUnchanged`, and `IncrPatched` run kinds.
- `mono-items`: Dump monomorphization items for each (merged) CGU in the crate.
These are also post-processed from the raw format into per-file dumps.
- **Purpose**. This is useful to investigate changes in CGU partionining.
- **Slowdown**. Equivalent to normal compilation.
- **Output**. File per CGU, currently, placed in a directory inside results.
- **Notes**. Will likely work best with `Full` builds, on either Debug or Opt
profiles.

The mandatory `<RUSTC>` argument is a patch to a rustc executable, similar to
`bench_local`.
Expand Down
51 changes: 51 additions & 0 deletions collector/src/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use std::fmt;
use std::fs::{self, File};
use std::hash;
use std::io::Read;
use std::io::Write;
use std::mem::ManuallyDrop;
use std::path::{Path, PathBuf};
use std::process::{self, Command};
Expand Down Expand Up @@ -178,6 +179,7 @@ pub enum Profiler {
Massif,
Eprintln,
LlvmLines,
MonoItems,
}

impl Profiler {
Expand All @@ -198,6 +200,7 @@ impl Profiler {
"massif" => Ok(Profiler::Massif),
"eprintln" => Ok(Profiler::Eprintln),
"llvm-lines" => Ok(Profiler::LlvmLines),
"mono-items" => Ok(Profiler::MonoItems),
_ => Err(anyhow!("'{}' is not a known profiler", name)),
}
}
Expand All @@ -218,6 +221,7 @@ impl Profiler {
Profiler::Massif => "massif",
Profiler::Eprintln => "eprintln",
Profiler::LlvmLines => "llvm-lines",
Profiler::MonoItems => "mono-items",
}
}

Expand All @@ -237,6 +241,7 @@ impl Profiler {
| Profiler::Callgrind
| Profiler::DHAT
| Profiler::Massif
| Profiler::MonoItems
| Profiler::Eprintln => {
if build_kind == BuildKind::Doc {
Some("rustdoc")
Expand Down Expand Up @@ -265,6 +270,7 @@ impl Profiler {
| Profiler::Callgrind
| Profiler::DHAT
| Profiler::Massif
| Profiler::MonoItems
| Profiler::Eprintln => true,
Profiler::LlvmLines => scenario_kind == ScenarioKind::Full,
}
Expand Down Expand Up @@ -1132,6 +1138,51 @@ impl<'a> Processor for ProfileProcessor<'a> {
fs::copy(&tmp_eprintln_file, &eprintln_file)?;
}

// mono item results are redirected (via rustc-fake) to a file
// called `mono-items`. We copy it from the temp dir to the output
// dir, giving it a new name in the process.
Profiler::MonoItems => {
let tmp_file = filepath(data.cwd.as_ref(), "mono-items");
let out_dir = self.output_dir.join(&out_file("mono-items"));
let _ = fs::create_dir_all(&out_dir);
let result_file = filepath(&out_dir, "raw");

fs::copy(&tmp_file, &result_file)?;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these result files severed from the site or is this currently only useable locally?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are all just usable locally, the perf collector server doesn't hit this function at all, I believe.

Eventually I'd like to surface this specific profile in the site - potentially integrated with the recently added codegen schedule graphs - but that's future work.


let mut by_cgu: HashMap<&str, Vec<(&str, &str)>> = HashMap::new();
let mono_items = std::fs::read_to_string(&tmp_file)?;
for line in mono_items.lines() {
let line = if let Some(line) = line.strip_prefix("MONO_ITEM ") {
line
} else {
continue;
};

let (name, cgus) = if let Some(parts) = line.split_once(" @@ ") {
parts
} else {
continue;
};

for cgu in cgus.split(' ') {
let cgu_name_end = cgu.rfind('[').expect(&cgu);
let cgu_name = &cgu[..cgu_name_end];
let linkage = &cgu[cgu_name_end + 1..cgu.len() - 1];
by_cgu.entry(cgu_name).or_default().push((name, linkage));
}
}

for (cgu, items) in &by_cgu {
let cgu_file = filepath(&out_dir, cgu);
let mut file = std::io::BufWriter::new(
fs::File::create(&cgu_file).with_context(|| format!("{:?}", cgu_file))?,
);
for (name, linkage) in items {
writeln!(&mut file, "{} {}", name, linkage)?;
}
}
}

// `cargo llvm-lines` writes its output to stdout. We copy that
// output into a file in the output dir.
Profiler::LlvmLines => {
Expand Down
4 changes: 2 additions & 2 deletions collector/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -674,7 +674,7 @@ fn main_result() -> anyhow::Result<i32> {
(@arg PROFILER: +required +takes_value
"One of: 'self-profile', 'time-passes', 'perf-record',\n\
'oprofile', 'cachegrind', 'callgrind', 'dhat', 'massif',\n\
'eprintln', 'llvm-lines'")
'eprintln', 'llvm-lines', 'mono-items'")
(@arg RUSTC: +required +takes_value "The path to the local rustc to benchmark")
(@arg ID: +required +takes_value "Identifier to associate benchmark results with")

Expand Down Expand Up @@ -703,7 +703,7 @@ fn main_result() -> anyhow::Result<i32> {
(@arg PROFILER: +required +takes_value
"One of: 'self-profile', 'time-passes', 'perf-record',\n\
'oprofile', 'cachegrind', 'callgrind', 'dhat', 'massif',\n\
'eprintln', 'llvm-lines'")
'eprintln', 'llvm-lines', 'mono-items'")
(@arg RUSTC_BEFORE: +required +takes_value "The path to the local rustc to benchmark")
(@arg RUSTC_AFTER: +required +takes_value "The path to the local rustc to benchmark")

Expand Down
9 changes: 9 additions & 0 deletions collector/src/rustc-fake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,15 @@ fn main() {
assert!(cmd.status().expect("failed to spawn").success());
}

"mono-items" => {
// Lazy item collection is the default (i.e., without this
// option)
args.push("-Zprint-mono-items=lazy".into());
let mut cmd = bash_command(tool, args, "1> mono-items");

assert!(cmd.status().expect("failed to spawn").success());
}

_ => {
panic!("unknown wrapper: {}", wrapper);
}
Expand Down