Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 4b7c596

Browse files
authoredSep 21, 2022
Rollup merge of #102041 - nnethercote:improve-meta-stats, r=bjorn3
Improve `-Zmeta-stats` some more A follow-up to #97384. r? ```@bjorn3```
2 parents 36e3972 + a7b35b5 commit 4b7c596

File tree

1 file changed

+152
-213
lines changed

1 file changed

+152
-213
lines changed
 

‎compiler/rustc_metadata/src/rmeta/encoder.rs

Lines changed: 152 additions & 213 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ use rustc_middle::ty::codec::TyEncoder;
2828
use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams};
2929
use rustc_middle::ty::query::Providers;
3030
use rustc_middle::ty::{self, SymbolName, Ty, TyCtxt};
31+
use rustc_middle::util::common::to_readable_str;
3132
use rustc_serialize::{opaque, Decodable, Decoder, Encodable, Encoder};
3233
use rustc_session::config::CrateType;
3334
use rustc_session::cstore::{ForeignModule, LinkagePreference, NativeLib};
@@ -261,10 +262,10 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Span {
261262
// This allows us to avoid loading the dependencies of proc-macro crates: all of
262263
// the information we need to decode `Span`s is stored in the proc-macro crate.
263264
let (tag, metadata_index) = if source_file.is_imported() && !s.is_proc_macro {
264-
// To simplify deserialization, we 'rebase' this span onto the crate it originally came from
265-
// (the crate that 'owns' the file it references. These rebased 'lo' and 'hi' values
266-
// are relative to the source map information for the 'foreign' crate whose CrateNum
267-
// we write into the metadata. This allows `imported_source_files` to binary
265+
// To simplify deserialization, we 'rebase' this span onto the crate it originally came
266+
// from (the crate that 'owns' the file it references. These rebased 'lo' and 'hi'
267+
// values are relative to the source map information for the 'foreign' crate whose
268+
// CrateNum we write into the metadata. This allows `imported_source_files` to binary
268269
// search through the 'foreign' crate's source map information, using the
269270
// deserialized 'lo' and 'hi' values directly.
270271
//
@@ -554,78 +555,56 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
554555

555556
fn encode_crate_root(&mut self) -> LazyValue<CrateRoot> {
556557
let tcx = self.tcx;
557-
let mut i = 0;
558-
let preamble_bytes = self.position() - i;
559-
560-
// Encode the crate deps
561-
i = self.position();
562-
let crate_deps = self.encode_crate_deps();
563-
let dylib_dependency_formats = self.encode_dylib_dependency_formats();
564-
let dep_bytes = self.position() - i;
565-
566-
// Encode the lib features.
567-
i = self.position();
568-
let lib_features = self.encode_lib_features();
569-
let lib_feature_bytes = self.position() - i;
570-
571-
// Encode the stability implications.
572-
i = self.position();
573-
let stability_implications = self.encode_stability_implications();
574-
let stability_implications_bytes = self.position() - i;
575-
576-
// Encode the language items.
577-
i = self.position();
578-
let lang_items = self.encode_lang_items();
579-
let lang_items_missing = self.encode_lang_items_missing();
580-
let lang_item_bytes = self.position() - i;
581-
582-
// Encode the diagnostic items.
583-
i = self.position();
584-
let diagnostic_items = self.encode_diagnostic_items();
585-
let diagnostic_item_bytes = self.position() - i;
586-
587-
// Encode the native libraries used
588-
i = self.position();
589-
let native_libraries = self.encode_native_libraries();
590-
let native_lib_bytes = self.position() - i;
591-
592-
i = self.position();
593-
let foreign_modules = self.encode_foreign_modules();
594-
let foreign_modules_bytes = self.position() - i;
595-
596-
// Encode DefPathTable
597-
i = self.position();
598-
self.encode_def_path_table();
599-
let def_path_table_bytes = self.position() - i;
558+
let mut stats: Vec<(&'static str, usize)> = Vec::with_capacity(32);
559+
560+
macro_rules! stat {
561+
($label:literal, $f:expr) => {{
562+
let orig_pos = self.position();
563+
let res = $f();
564+
stats.push(($label, self.position() - orig_pos));
565+
res
566+
}};
567+
}
568+
569+
// We have already encoded some things. Get their combined size from the current position.
570+
stats.push(("preamble", self.position()));
571+
572+
let (crate_deps, dylib_dependency_formats) =
573+
stat!("dep", || (self.encode_crate_deps(), self.encode_dylib_dependency_formats()));
574+
575+
let lib_features = stat!("lib-features", || self.encode_lib_features());
576+
577+
let stability_implications =
578+
stat!("stability-implications", || self.encode_stability_implications());
579+
580+
let (lang_items, lang_items_missing) = stat!("lang-items", || {
581+
(self.encode_lang_items(), self.encode_lang_items_missing())
582+
});
583+
584+
let diagnostic_items = stat!("diagnostic-items", || self.encode_diagnostic_items());
585+
586+
let native_libraries = stat!("native-libs", || self.encode_native_libraries());
587+
588+
let foreign_modules = stat!("foreign-modules", || self.encode_foreign_modules());
589+
590+
_ = stat!("def-path-table", || self.encode_def_path_table());
600591

601592
// Encode the def IDs of traits, for rustdoc and diagnostics.
602-
i = self.position();
603-
let traits = self.encode_traits();
604-
let traits_bytes = self.position() - i;
593+
let traits = stat!("traits", || self.encode_traits());
605594

606595
// Encode the def IDs of impls, for coherence checking.
607-
i = self.position();
608-
let impls = self.encode_impls();
609-
let impls_bytes = self.position() - i;
610-
611-
i = self.position();
612-
let incoherent_impls = self.encode_incoherent_impls();
613-
let incoherent_impls_bytes = self.position() - i;
614-
615-
// Encode MIR.
616-
i = self.position();
617-
self.encode_mir();
618-
let mir_bytes = self.position() - i;
619-
620-
// Encode the items.
621-
i = self.position();
622-
self.encode_def_ids();
623-
self.encode_info_for_items();
624-
let item_bytes = self.position() - i;
625-
626-
// Encode the allocation index
627-
i = self.position();
628-
let interpret_alloc_index = {
596+
let impls = stat!("impls", || self.encode_impls());
597+
598+
let incoherent_impls = stat!("incoherent-impls", || self.encode_incoherent_impls());
599+
600+
_ = stat!("mir", || self.encode_mir());
601+
602+
_ = stat!("items", || {
603+
self.encode_def_ids();
604+
self.encode_info_for_items();
605+
});
606+
607+
let interpret_alloc_index = stat!("interpret-alloc-index", || {
629608
let mut interpret_alloc_index = Vec::new();
630609
let mut n = 0;
631610
trace!("beginning to encode alloc ids");
@@ -646,126 +625,90 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
646625
n = new_n;
647626
}
648627
self.lazy_array(interpret_alloc_index)
649-
};
650-
let interpret_alloc_index_bytes = self.position() - i;
628+
});
651629

652-
// Encode the proc macro data. This affects 'tables',
653-
// so we need to do this before we encode the tables.
654-
// This overwrites def_keys, so it must happen after encode_def_path_table.
655-
i = self.position();
656-
let proc_macro_data = self.encode_proc_macros();
657-
let proc_macro_data_bytes = self.position() - i;
630+
// Encode the proc macro data. This affects `tables`, so we need to do this before we
631+
// encode the tables. This overwrites def_keys, so it must happen after
632+
// encode_def_path_table.
633+
let proc_macro_data = stat!("proc-macro-data", || self.encode_proc_macros());
658634

659-
i = self.position();
660-
let tables = self.tables.encode(&mut self.opaque);
661-
let tables_bytes = self.position() - i;
635+
let tables = stat!("tables", || self.tables.encode(&mut self.opaque));
662636

663-
i = self.position();
664-
let debugger_visualizers = self.encode_debugger_visualizers();
665-
let debugger_visualizers_bytes = self.position() - i;
637+
let debugger_visualizers =
638+
stat!("debugger-visualizers", || self.encode_debugger_visualizers());
666639

667640
// Encode exported symbols info. This is prefetched in `encode_metadata` so we encode
668641
// this as late as possible to give the prefetching as much time as possible to complete.
669-
i = self.position();
670-
let exported_symbols = tcx.exported_symbols(LOCAL_CRATE);
671-
let exported_symbols = self.encode_exported_symbols(&exported_symbols);
672-
let exported_symbols_bytes = self.position() - i;
673-
674-
// Encode the hygiene data,
675-
// IMPORTANT: this *must* be the last thing that we encode (other than `SourceMap`). The process
676-
// of encoding other items (e.g. `optimized_mir`) may cause us to load
677-
// data from the incremental cache. If this causes us to deserialize a `Span`,
678-
// then we may load additional `SyntaxContext`s into the global `HygieneData`.
679-
// Therefore, we need to encode the hygiene data last to ensure that we encode
680-
// any `SyntaxContext`s that might be used.
681-
i = self.position();
682-
let (syntax_contexts, expn_data, expn_hashes) = self.encode_hygiene();
683-
let hygiene_bytes = self.position() - i;
684-
685-
i = self.position();
686-
let def_path_hash_map = self.encode_def_path_hash_map();
687-
let def_path_hash_map_bytes = self.position() - i;
688-
689-
// Encode source_map. This needs to be done last,
690-
// since encoding `Span`s tells us which `SourceFiles` we actually
691-
// need to encode.
692-
i = self.position();
693-
let source_map = self.encode_source_map();
694-
let source_map_bytes = self.position() - i;
695-
696-
i = self.position();
697-
let attrs = tcx.hir().krate_attrs();
698-
let has_default_lib_allocator = tcx.sess.contains_name(&attrs, sym::default_lib_allocator);
699-
let root = self.lazy(CrateRoot {
700-
name: tcx.crate_name(LOCAL_CRATE),
701-
extra_filename: tcx.sess.opts.cg.extra_filename.clone(),
702-
triple: tcx.sess.opts.target_triple.clone(),
703-
hash: tcx.crate_hash(LOCAL_CRATE),
704-
stable_crate_id: tcx.def_path_hash(LOCAL_CRATE.as_def_id()).stable_crate_id(),
705-
required_panic_strategy: tcx.required_panic_strategy(LOCAL_CRATE),
706-
panic_in_drop_strategy: tcx.sess.opts.unstable_opts.panic_in_drop,
707-
edition: tcx.sess.edition(),
708-
has_global_allocator: tcx.has_global_allocator(LOCAL_CRATE),
709-
has_panic_handler: tcx.has_panic_handler(LOCAL_CRATE),
710-
has_default_lib_allocator,
711-
proc_macro_data,
712-
debugger_visualizers,
713-
compiler_builtins: tcx.sess.contains_name(&attrs, sym::compiler_builtins),
714-
needs_allocator: tcx.sess.contains_name(&attrs, sym::needs_allocator),
715-
needs_panic_runtime: tcx.sess.contains_name(&attrs, sym::needs_panic_runtime),
716-
no_builtins: tcx.sess.contains_name(&attrs, sym::no_builtins),
717-
panic_runtime: tcx.sess.contains_name(&attrs, sym::panic_runtime),
718-
profiler_runtime: tcx.sess.contains_name(&attrs, sym::profiler_runtime),
719-
symbol_mangling_version: tcx.sess.opts.get_symbol_mangling_version(),
720-
721-
crate_deps,
722-
dylib_dependency_formats,
723-
lib_features,
724-
stability_implications,
725-
lang_items,
726-
diagnostic_items,
727-
lang_items_missing,
728-
native_libraries,
729-
foreign_modules,
730-
source_map,
731-
traits,
732-
impls,
733-
incoherent_impls,
734-
exported_symbols,
735-
interpret_alloc_index,
736-
tables,
737-
syntax_contexts,
738-
expn_data,
739-
expn_hashes,
740-
def_path_hash_map,
642+
let exported_symbols = stat!("exported-symbols", || {
643+
self.encode_exported_symbols(&tcx.exported_symbols(LOCAL_CRATE))
644+
});
645+
646+
// Encode the hygiene data.
647+
// IMPORTANT: this *must* be the last thing that we encode (other than `SourceMap`). The
648+
// process of encoding other items (e.g. `optimized_mir`) may cause us to load data from
649+
// the incremental cache. If this causes us to deserialize a `Span`, then we may load
650+
// additional `SyntaxContext`s into the global `HygieneData`. Therefore, we need to encode
651+
// the hygiene data last to ensure that we encode any `SyntaxContext`s that might be used.
652+
let (syntax_contexts, expn_data, expn_hashes) = stat!("hygiene", || self.encode_hygiene());
653+
654+
let def_path_hash_map = stat!("def-path-hash-map", || self.encode_def_path_hash_map());
655+
656+
// Encode source_map. This needs to be done last, because encoding `Span`s tells us which
657+
// `SourceFiles` we actually need to encode.
658+
let source_map = stat!("source-map", || self.encode_source_map());
659+
660+
let root = stat!("final", || {
661+
let attrs = tcx.hir().krate_attrs();
662+
self.lazy(CrateRoot {
663+
name: tcx.crate_name(LOCAL_CRATE),
664+
extra_filename: tcx.sess.opts.cg.extra_filename.clone(),
665+
triple: tcx.sess.opts.target_triple.clone(),
666+
hash: tcx.crate_hash(LOCAL_CRATE),
667+
stable_crate_id: tcx.def_path_hash(LOCAL_CRATE.as_def_id()).stable_crate_id(),
668+
required_panic_strategy: tcx.required_panic_strategy(LOCAL_CRATE),
669+
panic_in_drop_strategy: tcx.sess.opts.unstable_opts.panic_in_drop,
670+
edition: tcx.sess.edition(),
671+
has_global_allocator: tcx.has_global_allocator(LOCAL_CRATE),
672+
has_panic_handler: tcx.has_panic_handler(LOCAL_CRATE),
673+
has_default_lib_allocator: tcx
674+
.sess
675+
.contains_name(&attrs, sym::default_lib_allocator),
676+
proc_macro_data,
677+
debugger_visualizers,
678+
compiler_builtins: tcx.sess.contains_name(&attrs, sym::compiler_builtins),
679+
needs_allocator: tcx.sess.contains_name(&attrs, sym::needs_allocator),
680+
needs_panic_runtime: tcx.sess.contains_name(&attrs, sym::needs_panic_runtime),
681+
no_builtins: tcx.sess.contains_name(&attrs, sym::no_builtins),
682+
panic_runtime: tcx.sess.contains_name(&attrs, sym::panic_runtime),
683+
profiler_runtime: tcx.sess.contains_name(&attrs, sym::profiler_runtime),
684+
symbol_mangling_version: tcx.sess.opts.get_symbol_mangling_version(),
685+
686+
crate_deps,
687+
dylib_dependency_formats,
688+
lib_features,
689+
stability_implications,
690+
lang_items,
691+
diagnostic_items,
692+
lang_items_missing,
693+
native_libraries,
694+
foreign_modules,
695+
source_map,
696+
traits,
697+
impls,
698+
incoherent_impls,
699+
exported_symbols,
700+
interpret_alloc_index,
701+
tables,
702+
syntax_contexts,
703+
expn_data,
704+
expn_hashes,
705+
def_path_hash_map,
706+
})
741707
});
742-
let final_bytes = self.position() - i;
743708

744709
let total_bytes = self.position();
745710

746-
let computed_total_bytes = preamble_bytes
747-
+ dep_bytes
748-
+ lib_feature_bytes
749-
+ stability_implications_bytes
750-
+ lang_item_bytes
751-
+ diagnostic_item_bytes
752-
+ native_lib_bytes
753-
+ foreign_modules_bytes
754-
+ def_path_table_bytes
755-
+ traits_bytes
756-
+ impls_bytes
757-
+ incoherent_impls_bytes
758-
+ mir_bytes
759-
+ item_bytes
760-
+ interpret_alloc_index_bytes
761-
+ proc_macro_data_bytes
762-
+ tables_bytes
763-
+ debugger_visualizers_bytes
764-
+ exported_symbols_bytes
765-
+ hygiene_bytes
766-
+ def_path_hash_map_bytes
767-
+ source_map_bytes
768-
+ final_bytes;
711+
let computed_total_bytes: usize = stats.iter().map(|(_, size)| size).sum();
769712
assert_eq!(total_bytes, computed_total_bytes);
770713

771714
if tcx.sess.meta_stats() {
@@ -783,42 +726,38 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
783726
}
784727
assert_eq!(self.opaque.file().stream_position().unwrap(), pos_before_rewind);
785728

729+
stats.sort_by_key(|&(_, usize)| usize);
730+
731+
let prefix = "meta-stats";
786732
let perc = |bytes| (bytes * 100) as f64 / total_bytes as f64;
787-
let p = |label, bytes| {
788-
eprintln!("{:>21}: {:>8} bytes ({:4.1}%)", label, bytes, perc(bytes));
789-
};
790733

791-
eprintln!("");
734+
eprintln!("{} METADATA STATS", prefix);
735+
eprintln!("{} {:<23}{:>10}", prefix, "Section", "Size");
736+
eprintln!(
737+
"{} ----------------------------------------------------------------",
738+
prefix
739+
);
740+
for (label, size) in stats {
741+
eprintln!(
742+
"{} {:<23}{:>10} ({:4.1}%)",
743+
prefix,
744+
label,
745+
to_readable_str(size),
746+
perc(size)
747+
);
748+
}
749+
eprintln!(
750+
"{} ----------------------------------------------------------------",
751+
prefix
752+
);
792753
eprintln!(
793-
"{} metadata bytes, of which {} bytes ({:.1}%) are zero",
794-
total_bytes,
795-
zero_bytes,
754+
"{} {:<23}{:>10} (of which {:.1}% are zero bytes)",
755+
prefix,
756+
"Total",
757+
to_readable_str(total_bytes),
796758
perc(zero_bytes)
797759
);
798-
p("preamble", preamble_bytes);
799-
p("dep", dep_bytes);
800-
p("lib feature", lib_feature_bytes);
801-
p("stability_implications", stability_implications_bytes);
802-
p("lang item", lang_item_bytes);
803-
p("diagnostic item", diagnostic_item_bytes);
804-
p("native lib", native_lib_bytes);
805-
p("foreign modules", foreign_modules_bytes);
806-
p("def-path table", def_path_table_bytes);
807-
p("traits", traits_bytes);
808-
p("impls", impls_bytes);
809-
p("incoherent_impls", incoherent_impls_bytes);
810-
p("mir", mir_bytes);
811-
p("item", item_bytes);
812-
p("interpret_alloc_index", interpret_alloc_index_bytes);
813-
p("proc-macro-data", proc_macro_data_bytes);
814-
p("tables", tables_bytes);
815-
p("debugger visualizers", debugger_visualizers_bytes);
816-
p("exported symbols", exported_symbols_bytes);
817-
p("hygiene", hygiene_bytes);
818-
p("def-path hashes", def_path_hash_map_bytes);
819-
p("source_map", source_map_bytes);
820-
p("final", final_bytes);
821-
eprintln!("");
760+
eprintln!("{}", prefix);
822761
}
823762

824763
root

0 commit comments

Comments
 (0)
Please sign in to comment.