Skip to content

Commit 95d8589

Browse files
committed
Add more measurements to the CGU debug printing.
For example, we go from this: ``` FINAL (4059 items, total_size=232342; 16 CGUs, max_size=39608, min_size=5468, max_size/min_size=7.2): - CGU[0] regex.f2ff11e98f8b05c7-cgu.0 (318 items, size=39608): - fn ... - fn ... ``` to this: ``` FINAL - unique items: 2726 (1459 root + 1267 inlined), unique size: 201214 (146046 root + 55168 inlined) - placed items: 4059 (1459 root + 2600 inlined), placed size: 232342 (146046 root + 86296 inlined) - placed/unique items ratio: 1.49, placed/unique size ratio: 1.15 - CGUs: 16, mean size: 14521.4, sizes: [39608, 31122, 20318, 20236, 16268, 13777, 12310, 10531, 10205, 9810, 9250, 9065 (x2), 7785, 7524, 5468] - CGU[0] - regex.f2ff11e98f8b05c7-cgu.0, size: 39608 - items: 318, mean size: 124.6, sizes: [28395, 3418, 558, 485, 259, 228, 176, 166, 146, 118, 117 (x3), 114 (x5), 113 (x3), 101, 84, 82, 77, 76, 72, 71 (x2), 66, 65, 62, 61, 59 (x2), 57, 55, 54 (x2), 53 (x4), 52 (x5), 51 (x4), 50, 48, 47, 46, 45 (x3), 44, 43 (x5), 42, 40, 38 (x4), 37, 35, 34 (x2), 32 (x2), 31, 30, 28 (x2), 27 (x2), 26 (x3), 24 (x2), 23 (x3), 22 (x2), 21, 20, 16 (x4), 15, 13 (x7), 12 (x3), 11 (x6), 10, 9 (x2), 8 (x4), 7 (x8), 6 (x38), 5 (x21), 4 (x7), 3 (x45), 2 (x63), 1 (x13)] - fn ... - fn ... ``` This is a lot more information, distinguishing between root items and inlined items, showing how much duplication there is of inlined items, plus the full range of sizes for CGUs and items within CGUs. All of which is really helpful when analyzing this stuff and trying different CGU formation algorithms.
1 parent 5182151 commit 95d8589

File tree

1 file changed

+134
-23
lines changed

1 file changed

+134
-23
lines changed

compiler/rustc_monomorphize/src/partitioning.rs

+134-23
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,11 @@ struct PlacedRootMonoItems<'tcx> {
129129
codegen_units: Vec<CodegenUnit<'tcx>>,
130130

131131
internalization_candidates: FxHashSet<MonoItem<'tcx>>,
132+
133+
/// These must be obtained when the iterator in `partition` runs. They
134+
/// can't be obtained later because some inlined functions might not be
135+
/// reachable.
136+
unique_inlined_stats: (usize, usize),
132137
}
133138

134139
// The output CGUs are sorted by name.
@@ -147,7 +152,7 @@ where
147152
// In the first step, we place all regular monomorphizations into their
148153
// respective 'home' codegen unit. Regular monomorphizations are all
149154
// functions and statics defined in the local crate.
150-
let PlacedRootMonoItems { mut codegen_units, internalization_candidates } = {
155+
let PlacedRootMonoItems { mut codegen_units, internalization_candidates, unique_inlined_stats } = {
151156
let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_place_roots");
152157
place_root_mono_items(cx, mono_items)
153158
};
@@ -156,15 +161,15 @@ where
156161
cgu.create_size_estimate(tcx);
157162
}
158163

159-
debug_dump(tcx, "INITIAL PARTITIONING", &codegen_units);
164+
debug_dump(tcx, "ROOTS", &codegen_units, unique_inlined_stats);
160165

161166
// Merge until we have at most `max_cgu_count` codegen units.
162167
// `merge_codegen_units` is responsible for updating the CGU size
163168
// estimates.
164169
{
165170
let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_merge_cgus");
166171
merge_codegen_units(cx, &mut codegen_units);
167-
debug_dump(tcx, "POST MERGING", &codegen_units);
172+
debug_dump(tcx, "MERGE", &codegen_units, unique_inlined_stats);
168173
}
169174

170175
// In the next step, we use the inlining map to determine which additional
@@ -180,7 +185,7 @@ where
180185
cgu.create_size_estimate(tcx);
181186
}
182187

183-
debug_dump(tcx, "POST INLINING", &codegen_units);
188+
debug_dump(tcx, "INLINE", &codegen_units, unique_inlined_stats);
184189

185190
// Next we try to make as many symbols "internal" as possible, so LLVM has
186191
// more freedom to optimize.
@@ -224,7 +229,7 @@ where
224229
// Ensure CGUs are sorted by name, so that we get deterministic results.
225230
assert!(codegen_units.is_sorted_by(|a, b| Some(a.name().as_str().cmp(b.name().as_str()))));
226231

227-
debug_dump(tcx, "FINAL", &codegen_units);
232+
debug_dump(tcx, "FINAL", &codegen_units, unique_inlined_stats);
228233

229234
codegen_units
230235
}
@@ -250,10 +255,16 @@ where
250255
let cgu_name_builder = &mut CodegenUnitNameBuilder::new(cx.tcx);
251256
let cgu_name_cache = &mut FxHashMap::default();
252257

258+
let mut num_unique_inlined_items = 0;
259+
let mut unique_inlined_items_size = 0;
253260
for mono_item in mono_items {
254261
match mono_item.instantiation_mode(cx.tcx) {
255262
InstantiationMode::GloballyShared { .. } => {}
256-
InstantiationMode::LocalCopy => continue,
263+
InstantiationMode::LocalCopy => {
264+
num_unique_inlined_items += 1;
265+
unique_inlined_items_size += mono_item.size_estimate(cx.tcx);
266+
continue;
267+
}
257268
}
258269

259270
let characteristic_def_id = characteristic_def_id_of_mono_item(cx.tcx, mono_item);
@@ -298,7 +309,11 @@ where
298309
let mut codegen_units: Vec<_> = codegen_units.into_values().collect();
299310
codegen_units.sort_by(|a, b| a.name().as_str().cmp(b.name().as_str()));
300311

301-
PlacedRootMonoItems { codegen_units, internalization_candidates }
312+
PlacedRootMonoItems {
313+
codegen_units,
314+
internalization_candidates,
315+
unique_inlined_stats: (num_unique_inlined_items, unique_inlined_items_size),
316+
}
302317
}
303318

304319
// This function requires the CGUs to be sorted by name on input, and ensures
@@ -812,31 +827,91 @@ fn default_visibility(tcx: TyCtxt<'_>, id: DefId, is_generic: bool) -> Visibilit
812827
}
813828
}
814829

815-
fn debug_dump<'a, 'tcx: 'a>(tcx: TyCtxt<'tcx>, label: &str, cgus: &[CodegenUnit<'tcx>]) {
830+
fn debug_dump<'a, 'tcx: 'a>(
831+
tcx: TyCtxt<'tcx>,
832+
label: &str,
833+
cgus: &[CodegenUnit<'tcx>],
834+
(unique_inlined_items, unique_inlined_size): (usize, usize),
835+
) {
816836
let dump = move || {
817837
use std::fmt::Write;
818838

819-
let num_cgus = cgus.len();
820-
let num_items: usize = cgus.iter().map(|cgu| cgu.items().len()).sum();
821-
let total_size: usize = cgus.iter().map(|cgu| cgu.size_estimate()).sum();
822-
let max_size = cgus.iter().map(|cgu| cgu.size_estimate()).max().unwrap();
823-
let min_size = cgus.iter().map(|cgu| cgu.size_estimate()).min().unwrap();
824-
let max_min_size_ratio = max_size as f64 / min_size as f64;
839+
let mut num_cgus = 0;
840+
let mut all_cgu_sizes = Vec::new();
841+
842+
// Note: every unique root item is placed exactly once, so the number
843+
// of unique root items always equals the number of placed root items.
844+
845+
let mut root_items = 0;
846+
// unique_inlined_items is passed in above.
847+
let mut placed_inlined_items = 0;
848+
849+
let mut root_size = 0;
850+
// unique_inlined_size is passed in above.
851+
let mut placed_inlined_size = 0;
852+
853+
for cgu in cgus.iter() {
854+
num_cgus += 1;
855+
all_cgu_sizes.push(cgu.size_estimate());
856+
857+
for (item, _) in cgu.items() {
858+
match item.instantiation_mode(tcx) {
859+
InstantiationMode::GloballyShared { .. } => {
860+
root_items += 1;
861+
root_size += item.size_estimate(tcx);
862+
}
863+
InstantiationMode::LocalCopy => {
864+
placed_inlined_items += 1;
865+
placed_inlined_size += item.size_estimate(tcx);
866+
}
867+
}
868+
}
869+
}
870+
871+
all_cgu_sizes.sort_unstable_by_key(|&n| cmp::Reverse(n));
872+
873+
let unique_items = root_items + unique_inlined_items;
874+
let placed_items = root_items + placed_inlined_items;
875+
let items_ratio = placed_items as f64 / unique_items as f64;
876+
877+
let unique_size = root_size + unique_inlined_size;
878+
let placed_size = root_size + placed_inlined_size;
879+
let size_ratio = placed_size as f64 / unique_size as f64;
880+
881+
let mean_cgu_size = placed_size as f64 / num_cgus as f64;
882+
883+
assert_eq!(placed_size, all_cgu_sizes.iter().sum::<usize>());
825884

826885
let s = &mut String::new();
886+
let _ = writeln!(s, "{label}");
827887
let _ = writeln!(
828888
s,
829-
"{label} ({num_items} items, total_size={total_size}; {num_cgus} CGUs, \
830-
max_size={max_size}, min_size={min_size}, max_size/min_size={max_min_size_ratio:.1}):"
889+
"- unique items: {unique_items} ({root_items} root + {unique_inlined_items} inlined), \
890+
unique size: {unique_size} ({root_size} root + {unique_inlined_size} inlined)\n\
891+
- placed items: {placed_items} ({root_items} root + {placed_inlined_items} inlined), \
892+
placed size: {placed_size} ({root_size} root + {placed_inlined_size} inlined)\n\
893+
- placed/unique items ratio: {items_ratio:.2}, \
894+
placed/unique size ratio: {size_ratio:.2}\n\
895+
- CGUs: {num_cgus}, mean size: {mean_cgu_size:.1}, sizes: {}",
896+
list(&all_cgu_sizes),
831897
);
898+
let _ = writeln!(s);
899+
832900
for (i, cgu) in cgus.iter().enumerate() {
901+
let name = cgu.name();
902+
let size = cgu.size_estimate();
833903
let num_items = cgu.items().len();
834-
let _ = writeln!(
835-
s,
836-
"- CGU[{i}] {} ({num_items} items, size={}):",
837-
cgu.name(),
838-
cgu.size_estimate()
839-
);
904+
let mean_size = size as f64 / num_items as f64;
905+
906+
let mut placed_item_sizes: Vec<_> =
907+
cgu.items().iter().map(|(item, _)| item.size_estimate(tcx)).collect();
908+
placed_item_sizes.sort_unstable_by_key(|&n| cmp::Reverse(n));
909+
let sizes = list(&placed_item_sizes);
910+
911+
let _ = writeln!(s, "- CGU[{i}]");
912+
let _ = writeln!(s, " - {name}, size: {size}");
913+
let _ =
914+
writeln!(s, " - items: {num_items}, mean size: {mean_size:.1}, sizes: {sizes}",);
840915

841916
for (item, linkage) in cgu.items_in_deterministic_order(tcx) {
842917
let symbol_name = item.symbol_name(tcx).name;
@@ -852,7 +927,43 @@ fn debug_dump<'a, 'tcx: 'a>(tcx: TyCtxt<'tcx>, label: &str, cgus: &[CodegenUnit<
852927
let _ = writeln!(s);
853928
}
854929

855-
std::mem::take(s)
930+
return std::mem::take(s);
931+
932+
// Converts a slice to a string, capturing repetitions to save space.
933+
// E.g. `[4, 4, 4, 3, 2, 1, 1, 1, 1, 1]` -> "[4 (x3), 3, 2, 1 (x5)]".
934+
fn list(ns: &[usize]) -> String {
935+
let mut v = Vec::new();
936+
if ns.is_empty() {
937+
return "[]".to_string();
938+
}
939+
940+
let mut elem = |curr, curr_count| {
941+
if curr_count == 1 {
942+
v.push(format!("{curr}"));
943+
} else {
944+
v.push(format!("{curr} (x{curr_count})"));
945+
}
946+
};
947+
948+
let mut curr = ns[0];
949+
let mut curr_count = 1;
950+
951+
for &n in &ns[1..] {
952+
if n != curr {
953+
elem(curr, curr_count);
954+
curr = n;
955+
curr_count = 1;
956+
} else {
957+
curr_count += 1;
958+
}
959+
}
960+
elem(curr, curr_count);
961+
962+
let mut s = "[".to_string();
963+
s.push_str(&v.join(", "));
964+
s.push_str("]");
965+
s
966+
}
856967
};
857968

858969
debug!("{}", dump());

0 commit comments

Comments
 (0)