Skip to content

Commit 4e21bf3

Browse files
Merge pull request #1016 from Mark-Simulacrum/mono-items
mono-item profiler
2 parents fa4f2ee + 13d1110 commit 4e21bf3

File tree

4 files changed

+69
-2
lines changed

4 files changed

+69
-2
lines changed

collector/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,13 @@ The mandatory `<PROFILER>` argument must be one of the following.
359359
- **Output**. Human-readable output is written to files with an `ll` prefix.
360360
- **Notes**. Does not work with the `Check` build kind. Also does not work
361361
with the `IncrFull`, `IncrUnchanged`, and `IncrPatched` run kinds.
362+
- `mono-items`: Dump monomorphization items for each (merged) CGU in the crate.
363+
These are also post-processed from the raw format into per-file dumps.
364+
- **Purpose**. This is useful to investigate changes in CGU partionining.
365+
- **Slowdown**. Equivalent to normal compilation.
366+
- **Output**. File per CGU, currently, placed in a directory inside results.
367+
- **Notes**. Will likely work best with `Full` builds, on either Debug or Opt
368+
profiles.
362369

363370
The mandatory `<RUSTC>` argument is a patch to a rustc executable, similar to
364371
`bench_local`.

collector/src/execute.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use std::fmt;
1313
use std::fs::{self, File};
1414
use std::hash;
1515
use std::io::Read;
16+
use std::io::Write;
1617
use std::mem::ManuallyDrop;
1718
use std::path::{Path, PathBuf};
1819
use std::process::{self, Command};
@@ -178,6 +179,7 @@ pub enum Profiler {
178179
Massif,
179180
Eprintln,
180181
LlvmLines,
182+
MonoItems,
181183
}
182184

183185
impl Profiler {
@@ -198,6 +200,7 @@ impl Profiler {
198200
"massif" => Ok(Profiler::Massif),
199201
"eprintln" => Ok(Profiler::Eprintln),
200202
"llvm-lines" => Ok(Profiler::LlvmLines),
203+
"mono-items" => Ok(Profiler::MonoItems),
201204
_ => Err(anyhow!("'{}' is not a known profiler", name)),
202205
}
203206
}
@@ -218,6 +221,7 @@ impl Profiler {
218221
Profiler::Massif => "massif",
219222
Profiler::Eprintln => "eprintln",
220223
Profiler::LlvmLines => "llvm-lines",
224+
Profiler::MonoItems => "mono-items",
221225
}
222226
}
223227

@@ -237,6 +241,7 @@ impl Profiler {
237241
| Profiler::Callgrind
238242
| Profiler::DHAT
239243
| Profiler::Massif
244+
| Profiler::MonoItems
240245
| Profiler::Eprintln => {
241246
if build_kind == BuildKind::Doc {
242247
Some("rustdoc")
@@ -265,6 +270,7 @@ impl Profiler {
265270
| Profiler::Callgrind
266271
| Profiler::DHAT
267272
| Profiler::Massif
273+
| Profiler::MonoItems
268274
| Profiler::Eprintln => true,
269275
Profiler::LlvmLines => scenario_kind == ScenarioKind::Full,
270276
}
@@ -1132,6 +1138,51 @@ impl<'a> Processor for ProfileProcessor<'a> {
11321138
fs::copy(&tmp_eprintln_file, &eprintln_file)?;
11331139
}
11341140

1141+
// mono item results are redirected (via rustc-fake) to a file
1142+
// called `mono-items`. We copy it from the temp dir to the output
1143+
// dir, giving it a new name in the process.
1144+
Profiler::MonoItems => {
1145+
let tmp_file = filepath(data.cwd.as_ref(), "mono-items");
1146+
let out_dir = self.output_dir.join(&out_file("mono-items"));
1147+
let _ = fs::create_dir_all(&out_dir);
1148+
let result_file = filepath(&out_dir, "raw");
1149+
1150+
fs::copy(&tmp_file, &result_file)?;
1151+
1152+
let mut by_cgu: HashMap<&str, Vec<(&str, &str)>> = HashMap::new();
1153+
let mono_items = std::fs::read_to_string(&tmp_file)?;
1154+
for line in mono_items.lines() {
1155+
let line = if let Some(line) = line.strip_prefix("MONO_ITEM ") {
1156+
line
1157+
} else {
1158+
continue;
1159+
};
1160+
1161+
let (name, cgus) = if let Some(parts) = line.split_once(" @@ ") {
1162+
parts
1163+
} else {
1164+
continue;
1165+
};
1166+
1167+
for cgu in cgus.split(' ') {
1168+
let cgu_name_end = cgu.rfind('[').expect(&cgu);
1169+
let cgu_name = &cgu[..cgu_name_end];
1170+
let linkage = &cgu[cgu_name_end + 1..cgu.len() - 1];
1171+
by_cgu.entry(cgu_name).or_default().push((name, linkage));
1172+
}
1173+
}
1174+
1175+
for (cgu, items) in &by_cgu {
1176+
let cgu_file = filepath(&out_dir, cgu);
1177+
let mut file = std::io::BufWriter::new(
1178+
fs::File::create(&cgu_file).with_context(|| format!("{:?}", cgu_file))?,
1179+
);
1180+
for (name, linkage) in items {
1181+
writeln!(&mut file, "{} {}", name, linkage)?;
1182+
}
1183+
}
1184+
}
1185+
11351186
// `cargo llvm-lines` writes its output to stdout. We copy that
11361187
// output into a file in the output dir.
11371188
Profiler::LlvmLines => {

collector/src/main.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -674,7 +674,7 @@ fn main_result() -> anyhow::Result<i32> {
674674
(@arg PROFILER: +required +takes_value
675675
"One of: 'self-profile', 'time-passes', 'perf-record',\n\
676676
'oprofile', 'cachegrind', 'callgrind', 'dhat', 'massif',\n\
677-
'eprintln', 'llvm-lines'")
677+
'eprintln', 'llvm-lines', 'mono-items'")
678678
(@arg RUSTC: +required +takes_value "The path to the local rustc to benchmark")
679679
(@arg ID: +required +takes_value "Identifier to associate benchmark results with")
680680

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

collector/src/rustc-fake.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,15 @@ fn main() {
285285
assert!(cmd.status().expect("failed to spawn").success());
286286
}
287287

288+
"mono-items" => {
289+
// Lazy item collection is the default (i.e., without this
290+
// option)
291+
args.push("-Zprint-mono-items=lazy".into());
292+
let mut cmd = bash_command(tool, args, "1> mono-items");
293+
294+
assert!(cmd.status().expect("failed to spawn").success());
295+
}
296+
288297
_ => {
289298
panic!("unknown wrapper: {}", wrapper);
290299
}

0 commit comments

Comments
 (0)