mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
Rollup merge of #112155 - nnethercote:debug_dump, r=wesleywiser
Improve CGU debug printing. - Add more total and per-CGU measurements. - Ensure CGUs are sorted by name before the first `debug_dump` calls, for deterministic output. - Print items within CGUs in sorted-by-name order, for deterministic output. - Add some assertions and comments clarifying sortedness of CGUs at various points. An example, before: ``` INITIAL PARTITIONING (5 CodegenUnits, max=29, min=1, max/min=29.0): CodegenUnit scev95ysd7g4b0z estimated size 2: - fn <() as std::process::Termination>::report [(External, Hidden)] [h082b15a6d07338dcE] estimated size 2 CodegenUnit 1j0frgtl72rsz24q estimated size 29: - fn std::rt::lang_start::<()>::{closure#0} [(External, Hidden)] [h695c7b5d6a212565E] estimated size 17 - fn std::rt::lang_start::<()> [(External, Hidden)] [h4ca942948e9cb931E] estimated size 12 CodegenUnit 5dbzi1e5qm0d7kj2 estimated size 4: - fn <[closure@std::rt::lang_start<()>::{closure#0}] as std::ops::FnOnce<()>>::call_once - shim [(External, Hidden)] [h24eaa44f03b2b233E] estimated size 1 - fn <fn() as std::ops::FnOnce<()>>::call_once - shim(fn()) [(External, Hidden)] [hf338f5339c3711acE] estimated size 1 - fn <[closure@std::rt::lang_start<()>::{closure#0}] as std::ops::FnOnce<()>>::call_once - shim(vtable) [(External, Hidden)] [h595d414cbb7651d5E] estimated size 1 - fn std::ptr::drop_in_place::<[closure@std::rt::lang_start<()>::{closure#0}]> - shim(None) [(External, Hidden)] [h17a19dcdb40600daE] estimated size 1 CodegenUnit 220m1mqa2mlbg7r3 estimated size 1: - fn main [(External, Hidden)] [hb29587cdb6db5f42E] estimated size 1 CodegenUnit 4ulbh241f7tvyn7x estimated size 6: - fn std::sys_common::backtrace::__rust_begin_short_backtrace::<fn(), ()> [(External, Hidden)] [h41dada2c21a1259dE] estimated size 6 ``` and after: ``` INITIAL PARTITIONING (9 items, total_size=42; 5 CGUs, max_size=29, min_size=1, max_size/min_size=29.0): - CGU[0] 1j0frgtl72rsz24q (2 items, size=29): - fn std::rt::lang_start::<()> [(External, Hidden)] [h4ca942948e9cb931E] (size=12) - fn std::rt::lang_start::<()>::{closure#0} [(External, Hidden)] [h695c7b5d6a212565E] (size=17) - CGU[1] 220m1mqa2mlbg7r3 (1 items, size=1): - fn main [(External, Hidden)] [hb29587cdb6db5f42E] (size=1) - CGU[2] 4ulbh241f7tvyn7x (1 items, size=6): - fn std::sys_common::backtrace::__rust_begin_short_backtrace::<fn(), ()> [(External, Hidden)] [h41dada2c21a1259dE] (size=6) - CGU[3] 5dbzi1e5qm0d7kj2 (4 items, size=4): - fn <[closure@std::rt::lang_start<()>::{closure#0}] as std::ops::FnOnce<()>>::call_once - shim(vtable) [(External, Hidden)] [h595d414cbb7651d5E] (size=1) - fn <[closure@std::rt::lang_start<()>::{closure#0}] as std::ops::FnOnce<()>>::call_once - shim [(External, Hidden)] [h24eaa44f03b2b233E] (size=1) - fn <fn() as std::ops::FnOnce<()>>::call_once - shim(fn()) [(External, Hidden)] [hf338f5339c3711acE] (size=1) - fn std::ptr::drop_in_place::<[closure@std::rt::lang_start<()>::{closure#0}]> - shim(None) [(External, Hidden)] [h17a19dcdb40600daE] (size=1) - CGU[4] scev95ysd7g4b0z (1 items, size=2): - fn <() as std::process::Termination>::report [(External, Hidden)] [h082b15a6d07338dcE] (size=2) ``` r? ``@wesleywiser``
This commit is contained in:
commit
c6aec9459e
@ -291,10 +291,12 @@ impl<'tcx> CodegenUnit<'tcx> {
|
|||||||
self.primary = true;
|
self.primary = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The order of these items is non-determinstic.
|
||||||
pub fn items(&self) -> &FxHashMap<MonoItem<'tcx>, (Linkage, Visibility)> {
|
pub fn items(&self) -> &FxHashMap<MonoItem<'tcx>, (Linkage, Visibility)> {
|
||||||
&self.items
|
&self.items
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The order of these items is non-determinstic.
|
||||||
pub fn items_mut(&mut self) -> &mut FxHashMap<MonoItem<'tcx>, (Linkage, Visibility)> {
|
pub fn items_mut(&mut self) -> &mut FxHashMap<MonoItem<'tcx>, (Linkage, Visibility)> {
|
||||||
&mut self.items
|
&mut self.items
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#![feature(array_windows)]
|
#![feature(array_windows)]
|
||||||
|
#![feature(is_sorted)]
|
||||||
#![recursion_limit = "256"]
|
#![recursion_limit = "256"]
|
||||||
#![allow(rustc::potential_query_instability)]
|
#![allow(rustc::potential_query_instability)]
|
||||||
#![deny(rustc::untranslatable_diagnostic)]
|
#![deny(rustc::untranslatable_diagnostic)]
|
||||||
|
@ -126,11 +126,14 @@ struct PartitioningCx<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct PlacedRootMonoItems<'tcx> {
|
struct PlacedRootMonoItems<'tcx> {
|
||||||
|
/// The codegen units, sorted by name to make things deterministic.
|
||||||
codegen_units: Vec<CodegenUnit<'tcx>>,
|
codegen_units: Vec<CodegenUnit<'tcx>>,
|
||||||
|
|
||||||
roots: FxHashSet<MonoItem<'tcx>>,
|
roots: FxHashSet<MonoItem<'tcx>>,
|
||||||
internalization_candidates: FxHashSet<MonoItem<'tcx>>,
|
internalization_candidates: FxHashSet<MonoItem<'tcx>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The output CGUs are sorted by name.
|
||||||
fn partition<'tcx, I>(
|
fn partition<'tcx, I>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
mono_items: &mut I,
|
mono_items: &mut I,
|
||||||
@ -143,6 +146,7 @@ where
|
|||||||
let _prof_timer = tcx.prof.generic_activity("cgu_partitioning");
|
let _prof_timer = tcx.prof.generic_activity("cgu_partitioning");
|
||||||
|
|
||||||
let cx = &PartitioningCx { tcx, target_cgu_count: max_cgu_count, inlining_map };
|
let cx = &PartitioningCx { tcx, target_cgu_count: max_cgu_count, inlining_map };
|
||||||
|
|
||||||
// In the first step, we place all regular monomorphizations into their
|
// In the first step, we place all regular monomorphizations into their
|
||||||
// respective 'home' codegen unit. Regular monomorphizations are all
|
// respective 'home' codegen unit. Regular monomorphizations are all
|
||||||
// functions and statics defined in the local crate.
|
// functions and statics defined in the local crate.
|
||||||
@ -225,8 +229,8 @@ where
|
|||||||
dead_code_cgu.make_code_coverage_dead_code_cgu();
|
dead_code_cgu.make_code_coverage_dead_code_cgu();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally, sort by codegen unit name, so that we get deterministic results.
|
// Ensure CGUs are sorted by name, so that we get deterministic results.
|
||||||
codegen_units.sort_by(|a, b| a.name().as_str().cmp(b.name().as_str()));
|
assert!(codegen_units.is_sorted_by(|a, b| Some(a.name().as_str().cmp(b.name().as_str()))));
|
||||||
|
|
||||||
debug_dump(tcx, "FINAL", &codegen_units);
|
debug_dump(tcx, "FINAL", &codegen_units);
|
||||||
|
|
||||||
@ -301,27 +305,22 @@ where
|
|||||||
codegen_units.insert(codegen_unit_name, CodegenUnit::new(codegen_unit_name));
|
codegen_units.insert(codegen_unit_name, CodegenUnit::new(codegen_unit_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
let codegen_units = codegen_units.into_values().collect();
|
let mut codegen_units: Vec<_> = codegen_units.into_values().collect();
|
||||||
|
codegen_units.sort_by(|a, b| a.name().as_str().cmp(b.name().as_str()));
|
||||||
|
|
||||||
PlacedRootMonoItems { codegen_units, roots, internalization_candidates }
|
PlacedRootMonoItems { codegen_units, roots, internalization_candidates }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This function requires the CGUs to be sorted by name on input, and ensures
|
||||||
|
// they are sorted by name on return, for deterministic behaviour.
|
||||||
fn merge_codegen_units<'tcx>(
|
fn merge_codegen_units<'tcx>(
|
||||||
cx: &PartitioningCx<'_, 'tcx>,
|
cx: &PartitioningCx<'_, 'tcx>,
|
||||||
codegen_units: &mut Vec<CodegenUnit<'tcx>>,
|
codegen_units: &mut Vec<CodegenUnit<'tcx>>,
|
||||||
) {
|
) {
|
||||||
assert!(cx.target_cgu_count >= 1);
|
assert!(cx.target_cgu_count >= 1);
|
||||||
|
|
||||||
// Note that at this point in time the `codegen_units` here may not be
|
// A sorted order here ensures merging is deterministic.
|
||||||
// in a deterministic order (but we know they're deterministically the
|
assert!(codegen_units.is_sorted_by(|a, b| Some(a.name().as_str().cmp(b.name().as_str()))));
|
||||||
// same set). We want this merging to produce a deterministic ordering
|
|
||||||
// of codegen units from the input.
|
|
||||||
//
|
|
||||||
// Due to basically how we've implemented the merging below (merge the
|
|
||||||
// two smallest into each other) we're sure to start off with a
|
|
||||||
// deterministic order (sorted by name). This'll mean that if two cgus
|
|
||||||
// have the same size the stable sort below will keep everything nice
|
|
||||||
// and deterministic.
|
|
||||||
codegen_units.sort_by(|a, b| a.name().as_str().cmp(b.name().as_str()));
|
|
||||||
|
|
||||||
// This map keeps track of what got merged into what.
|
// This map keeps track of what got merged into what.
|
||||||
let mut cgu_contents: FxHashMap<Symbol, Vec<Symbol>> =
|
let mut cgu_contents: FxHashMap<Symbol, Vec<Symbol>> =
|
||||||
@ -400,6 +399,9 @@ fn merge_codegen_units<'tcx>(
|
|||||||
cgu.set_name(numbered_codegen_unit_name);
|
cgu.set_name(numbered_codegen_unit_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A sorted order here ensures what follows can be deterministic.
|
||||||
|
codegen_units.sort_by(|a, b| a.name().as_str().cmp(b.name().as_str()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// For symbol internalization, we need to know whether a symbol/mono-item is
|
/// For symbol internalization, we need to know whether a symbol/mono-item is
|
||||||
@ -859,36 +861,46 @@ fn default_visibility(tcx: TyCtxt<'_>, id: DefId, is_generic: bool) -> Visibilit
|
|||||||
_ => Visibility::Hidden,
|
_ => Visibility::Hidden,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn debug_dump<'a, 'tcx: 'a>(tcx: TyCtxt<'tcx>, label: &str, cgus: &[CodegenUnit<'tcx>]) {
|
fn debug_dump<'a, 'tcx: 'a>(tcx: TyCtxt<'tcx>, label: &str, cgus: &[CodegenUnit<'tcx>]) {
|
||||||
let dump = move || {
|
let dump = move || {
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
|
|
||||||
let num_cgus = cgus.len();
|
let num_cgus = cgus.len();
|
||||||
let max = cgus.iter().map(|cgu| cgu.size_estimate()).max().unwrap();
|
let num_items: usize = cgus.iter().map(|cgu| cgu.items().len()).sum();
|
||||||
let min = cgus.iter().map(|cgu| cgu.size_estimate()).min().unwrap();
|
let total_size: usize = cgus.iter().map(|cgu| cgu.size_estimate()).sum();
|
||||||
let ratio = max as f64 / min as f64;
|
let max_size = cgus.iter().map(|cgu| cgu.size_estimate()).max().unwrap();
|
||||||
|
let min_size = cgus.iter().map(|cgu| cgu.size_estimate()).min().unwrap();
|
||||||
|
let max_min_size_ratio = max_size as f64 / min_size as f64;
|
||||||
|
|
||||||
let s = &mut String::new();
|
let s = &mut String::new();
|
||||||
let _ = writeln!(
|
let _ = writeln!(
|
||||||
s,
|
s,
|
||||||
"{label} ({num_cgus} CodegenUnits, max={max}, min={min}, max/min={ratio:.1}):"
|
"{label} ({num_items} items, total_size={total_size}; {num_cgus} CGUs, \
|
||||||
|
max_size={max_size}, min_size={min_size}, max_size/min_size={max_min_size_ratio:.1}):"
|
||||||
);
|
);
|
||||||
for cgu in cgus {
|
for (i, cgu) in cgus.iter().enumerate() {
|
||||||
let _ =
|
let num_items = cgu.items().len();
|
||||||
writeln!(s, "CodegenUnit {} estimated size {}:", cgu.name(), cgu.size_estimate());
|
let _ = writeln!(
|
||||||
|
s,
|
||||||
|
"- CGU[{i}] {} ({num_items} items, size={}):",
|
||||||
|
cgu.name(),
|
||||||
|
cgu.size_estimate()
|
||||||
|
);
|
||||||
|
|
||||||
for (mono_item, linkage) in cgu.items() {
|
// The order of `cgu.items()` is non-deterministic; sort it by name
|
||||||
let symbol_name = mono_item.symbol_name(tcx).name;
|
// to give deterministic output.
|
||||||
|
let mut items: Vec<_> = cgu.items().iter().collect();
|
||||||
|
items.sort_by_key(|(item, _)| item.symbol_name(tcx).name);
|
||||||
|
for (item, linkage) in items {
|
||||||
|
let symbol_name = item.symbol_name(tcx).name;
|
||||||
let symbol_hash_start = symbol_name.rfind('h');
|
let symbol_hash_start = symbol_name.rfind('h');
|
||||||
let symbol_hash = symbol_hash_start.map_or("<no hash>", |i| &symbol_name[i..]);
|
let symbol_hash = symbol_hash_start.map_or("<no hash>", |i| &symbol_name[i..]);
|
||||||
|
|
||||||
|
let size = item.size_estimate(tcx);
|
||||||
let _ = with_no_trimmed_paths!(writeln!(
|
let _ = with_no_trimmed_paths!(writeln!(
|
||||||
s,
|
s,
|
||||||
" - {} [{:?}] [{}] estimated size {}",
|
" - {item} [{linkage:?}] [{symbol_hash}] (size={size})"
|
||||||
mono_item,
|
|
||||||
linkage,
|
|
||||||
symbol_hash,
|
|
||||||
mono_item.size_estimate(tcx)
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user