Rollup merge of #102041 - nnethercote:improve-meta-stats, r=bjorn3

Improve `-Zmeta-stats` some more

A follow-up to #97384.

r? ```@bjorn3```
This commit is contained in:
Dylan DPC 2022-09-21 19:01:08 +05:30 committed by GitHub
commit 4b7c596b3a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -28,6 +28,7 @@
use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams};
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, SymbolName, Ty, TyCtxt};
use rustc_middle::util::common::to_readable_str;
use rustc_serialize::{opaque, Decodable, Decoder, Encodable, Encoder};
use rustc_session::config::CrateType;
use rustc_session::cstore::{ForeignModule, LinkagePreference, NativeLib};
@ -261,10 +262,10 @@ fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
// This allows us to avoid loading the dependencies of proc-macro crates: all of
// the information we need to decode `Span`s is stored in the proc-macro crate.
let (tag, metadata_index) = if source_file.is_imported() && !s.is_proc_macro {
// To simplify deserialization, we 'rebase' this span onto the crate it originally came from
// (the crate that 'owns' the file it references. These rebased 'lo' and 'hi' values
// are relative to the source map information for the 'foreign' crate whose CrateNum
// we write into the metadata. This allows `imported_source_files` to binary
// To simplify deserialization, we 'rebase' this span onto the crate it originally came
// from (the crate that 'owns' the file it references. These rebased 'lo' and 'hi'
// values are relative to the source map information for the 'foreign' crate whose
// CrateNum we write into the metadata. This allows `imported_source_files` to binary
// search through the 'foreign' crate's source map information, using the
// deserialized 'lo' and 'hi' values directly.
//
@ -554,78 +555,56 @@ fn encode_source_map(&mut self) -> LazyTable<u32, LazyValue<rustc_span::SourceFi
fn encode_crate_root(&mut self) -> LazyValue<CrateRoot> {
let tcx = self.tcx;
let mut i = 0;
let preamble_bytes = self.position() - i;
let mut stats: Vec<(&'static str, usize)> = Vec::with_capacity(32);
// Encode the crate deps
i = self.position();
let crate_deps = self.encode_crate_deps();
let dylib_dependency_formats = self.encode_dylib_dependency_formats();
let dep_bytes = self.position() - i;
macro_rules! stat {
($label:literal, $f:expr) => {{
let orig_pos = self.position();
let res = $f();
stats.push(($label, self.position() - orig_pos));
res
}};
}
// Encode the lib features.
i = self.position();
let lib_features = self.encode_lib_features();
let lib_feature_bytes = self.position() - i;
// We have already encoded some things. Get their combined size from the current position.
stats.push(("preamble", self.position()));
// Encode the stability implications.
i = self.position();
let stability_implications = self.encode_stability_implications();
let stability_implications_bytes = self.position() - i;
let (crate_deps, dylib_dependency_formats) =
stat!("dep", || (self.encode_crate_deps(), self.encode_dylib_dependency_formats()));
// Encode the language items.
i = self.position();
let lang_items = self.encode_lang_items();
let lang_items_missing = self.encode_lang_items_missing();
let lang_item_bytes = self.position() - i;
let lib_features = stat!("lib-features", || self.encode_lib_features());
// Encode the diagnostic items.
i = self.position();
let diagnostic_items = self.encode_diagnostic_items();
let diagnostic_item_bytes = self.position() - i;
let stability_implications =
stat!("stability-implications", || self.encode_stability_implications());
// Encode the native libraries used
i = self.position();
let native_libraries = self.encode_native_libraries();
let native_lib_bytes = self.position() - i;
let (lang_items, lang_items_missing) = stat!("lang-items", || {
(self.encode_lang_items(), self.encode_lang_items_missing())
});
i = self.position();
let foreign_modules = self.encode_foreign_modules();
let foreign_modules_bytes = self.position() - i;
let diagnostic_items = stat!("diagnostic-items", || self.encode_diagnostic_items());
// Encode DefPathTable
i = self.position();
self.encode_def_path_table();
let def_path_table_bytes = self.position() - i;
let native_libraries = stat!("native-libs", || self.encode_native_libraries());
let foreign_modules = stat!("foreign-modules", || self.encode_foreign_modules());
_ = stat!("def-path-table", || self.encode_def_path_table());
// Encode the def IDs of traits, for rustdoc and diagnostics.
i = self.position();
let traits = self.encode_traits();
let traits_bytes = self.position() - i;
let traits = stat!("traits", || self.encode_traits());
// Encode the def IDs of impls, for coherence checking.
i = self.position();
let impls = self.encode_impls();
let impls_bytes = self.position() - i;
let impls = stat!("impls", || self.encode_impls());
i = self.position();
let incoherent_impls = self.encode_incoherent_impls();
let incoherent_impls_bytes = self.position() - i;
let incoherent_impls = stat!("incoherent-impls", || self.encode_incoherent_impls());
// Encode MIR.
i = self.position();
self.encode_mir();
let mir_bytes = self.position() - i;
_ = stat!("mir", || self.encode_mir());
// Encode the items.
i = self.position();
self.encode_def_ids();
self.encode_info_for_items();
let item_bytes = self.position() - i;
_ = stat!("items", || {
self.encode_def_ids();
self.encode_info_for_items();
});
// Encode the allocation index
i = self.position();
let interpret_alloc_index = {
let interpret_alloc_index = stat!("interpret-alloc-index", || {
let mut interpret_alloc_index = Vec::new();
let mut n = 0;
trace!("beginning to encode alloc ids");
@ -646,126 +625,90 @@ fn encode_crate_root(&mut self) -> LazyValue<CrateRoot> {
n = new_n;
}
self.lazy_array(interpret_alloc_index)
};
let interpret_alloc_index_bytes = self.position() - i;
});
// Encode the proc macro data. This affects 'tables',
// so we need to do this before we encode the tables.
// This overwrites def_keys, so it must happen after encode_def_path_table.
i = self.position();
let proc_macro_data = self.encode_proc_macros();
let proc_macro_data_bytes = self.position() - i;
// Encode the proc macro data. This affects `tables`, so we need to do this before we
// encode the tables. This overwrites def_keys, so it must happen after
// encode_def_path_table.
let proc_macro_data = stat!("proc-macro-data", || self.encode_proc_macros());
i = self.position();
let tables = self.tables.encode(&mut self.opaque);
let tables_bytes = self.position() - i;
let tables = stat!("tables", || self.tables.encode(&mut self.opaque));
i = self.position();
let debugger_visualizers = self.encode_debugger_visualizers();
let debugger_visualizers_bytes = self.position() - i;
let debugger_visualizers =
stat!("debugger-visualizers", || self.encode_debugger_visualizers());
// Encode exported symbols info. This is prefetched in `encode_metadata` so we encode
// this as late as possible to give the prefetching as much time as possible to complete.
i = self.position();
let exported_symbols = tcx.exported_symbols(LOCAL_CRATE);
let exported_symbols = self.encode_exported_symbols(&exported_symbols);
let exported_symbols_bytes = self.position() - i;
// Encode the hygiene data,
// IMPORTANT: this *must* be the last thing that we encode (other than `SourceMap`). The process
// of encoding other items (e.g. `optimized_mir`) may cause us to load
// data from the incremental cache. If this causes us to deserialize a `Span`,
// then we may load additional `SyntaxContext`s into the global `HygieneData`.
// Therefore, we need to encode the hygiene data last to ensure that we encode
// any `SyntaxContext`s that might be used.
i = self.position();
let (syntax_contexts, expn_data, expn_hashes) = self.encode_hygiene();
let hygiene_bytes = self.position() - i;
i = self.position();
let def_path_hash_map = self.encode_def_path_hash_map();
let def_path_hash_map_bytes = self.position() - i;
// Encode source_map. This needs to be done last,
// since encoding `Span`s tells us which `SourceFiles` we actually
// need to encode.
i = self.position();
let source_map = self.encode_source_map();
let source_map_bytes = self.position() - i;
i = self.position();
let attrs = tcx.hir().krate_attrs();
let has_default_lib_allocator = tcx.sess.contains_name(&attrs, sym::default_lib_allocator);
let root = self.lazy(CrateRoot {
name: tcx.crate_name(LOCAL_CRATE),
extra_filename: tcx.sess.opts.cg.extra_filename.clone(),
triple: tcx.sess.opts.target_triple.clone(),
hash: tcx.crate_hash(LOCAL_CRATE),
stable_crate_id: tcx.def_path_hash(LOCAL_CRATE.as_def_id()).stable_crate_id(),
required_panic_strategy: tcx.required_panic_strategy(LOCAL_CRATE),
panic_in_drop_strategy: tcx.sess.opts.unstable_opts.panic_in_drop,
edition: tcx.sess.edition(),
has_global_allocator: tcx.has_global_allocator(LOCAL_CRATE),
has_panic_handler: tcx.has_panic_handler(LOCAL_CRATE),
has_default_lib_allocator,
proc_macro_data,
debugger_visualizers,
compiler_builtins: tcx.sess.contains_name(&attrs, sym::compiler_builtins),
needs_allocator: tcx.sess.contains_name(&attrs, sym::needs_allocator),
needs_panic_runtime: tcx.sess.contains_name(&attrs, sym::needs_panic_runtime),
no_builtins: tcx.sess.contains_name(&attrs, sym::no_builtins),
panic_runtime: tcx.sess.contains_name(&attrs, sym::panic_runtime),
profiler_runtime: tcx.sess.contains_name(&attrs, sym::profiler_runtime),
symbol_mangling_version: tcx.sess.opts.get_symbol_mangling_version(),
crate_deps,
dylib_dependency_formats,
lib_features,
stability_implications,
lang_items,
diagnostic_items,
lang_items_missing,
native_libraries,
foreign_modules,
source_map,
traits,
impls,
incoherent_impls,
exported_symbols,
interpret_alloc_index,
tables,
syntax_contexts,
expn_data,
expn_hashes,
def_path_hash_map,
let exported_symbols = stat!("exported-symbols", || {
self.encode_exported_symbols(&tcx.exported_symbols(LOCAL_CRATE))
});
// Encode the hygiene data.
// IMPORTANT: this *must* be the last thing that we encode (other than `SourceMap`). The
// process of encoding other items (e.g. `optimized_mir`) may cause us to load data from
// the incremental cache. If this causes us to deserialize a `Span`, then we may load
// additional `SyntaxContext`s into the global `HygieneData`. Therefore, we need to encode
// the hygiene data last to ensure that we encode any `SyntaxContext`s that might be used.
let (syntax_contexts, expn_data, expn_hashes) = stat!("hygiene", || self.encode_hygiene());
let def_path_hash_map = stat!("def-path-hash-map", || self.encode_def_path_hash_map());
// Encode source_map. This needs to be done last, because encoding `Span`s tells us which
// `SourceFiles` we actually need to encode.
let source_map = stat!("source-map", || self.encode_source_map());
let root = stat!("final", || {
let attrs = tcx.hir().krate_attrs();
self.lazy(CrateRoot {
name: tcx.crate_name(LOCAL_CRATE),
extra_filename: tcx.sess.opts.cg.extra_filename.clone(),
triple: tcx.sess.opts.target_triple.clone(),
hash: tcx.crate_hash(LOCAL_CRATE),
stable_crate_id: tcx.def_path_hash(LOCAL_CRATE.as_def_id()).stable_crate_id(),
required_panic_strategy: tcx.required_panic_strategy(LOCAL_CRATE),
panic_in_drop_strategy: tcx.sess.opts.unstable_opts.panic_in_drop,
edition: tcx.sess.edition(),
has_global_allocator: tcx.has_global_allocator(LOCAL_CRATE),
has_panic_handler: tcx.has_panic_handler(LOCAL_CRATE),
has_default_lib_allocator: tcx
.sess
.contains_name(&attrs, sym::default_lib_allocator),
proc_macro_data,
debugger_visualizers,
compiler_builtins: tcx.sess.contains_name(&attrs, sym::compiler_builtins),
needs_allocator: tcx.sess.contains_name(&attrs, sym::needs_allocator),
needs_panic_runtime: tcx.sess.contains_name(&attrs, sym::needs_panic_runtime),
no_builtins: tcx.sess.contains_name(&attrs, sym::no_builtins),
panic_runtime: tcx.sess.contains_name(&attrs, sym::panic_runtime),
profiler_runtime: tcx.sess.contains_name(&attrs, sym::profiler_runtime),
symbol_mangling_version: tcx.sess.opts.get_symbol_mangling_version(),
crate_deps,
dylib_dependency_formats,
lib_features,
stability_implications,
lang_items,
diagnostic_items,
lang_items_missing,
native_libraries,
foreign_modules,
source_map,
traits,
impls,
incoherent_impls,
exported_symbols,
interpret_alloc_index,
tables,
syntax_contexts,
expn_data,
expn_hashes,
def_path_hash_map,
})
});
let final_bytes = self.position() - i;
let total_bytes = self.position();
let computed_total_bytes = preamble_bytes
+ dep_bytes
+ lib_feature_bytes
+ stability_implications_bytes
+ lang_item_bytes
+ diagnostic_item_bytes
+ native_lib_bytes
+ foreign_modules_bytes
+ def_path_table_bytes
+ traits_bytes
+ impls_bytes
+ incoherent_impls_bytes
+ mir_bytes
+ item_bytes
+ interpret_alloc_index_bytes
+ proc_macro_data_bytes
+ tables_bytes
+ debugger_visualizers_bytes
+ exported_symbols_bytes
+ hygiene_bytes
+ def_path_hash_map_bytes
+ source_map_bytes
+ final_bytes;
let computed_total_bytes: usize = stats.iter().map(|(_, size)| size).sum();
assert_eq!(total_bytes, computed_total_bytes);
if tcx.sess.meta_stats() {
@ -783,42 +726,38 @@ fn encode_crate_root(&mut self) -> LazyValue<CrateRoot> {
}
assert_eq!(self.opaque.file().stream_position().unwrap(), pos_before_rewind);
let perc = |bytes| (bytes * 100) as f64 / total_bytes as f64;
let p = |label, bytes| {
eprintln!("{:>21}: {:>8} bytes ({:4.1}%)", label, bytes, perc(bytes));
};
stats.sort_by_key(|&(_, usize)| usize);
eprintln!("");
let prefix = "meta-stats";
let perc = |bytes| (bytes * 100) as f64 / total_bytes as f64;
eprintln!("{} METADATA STATS", prefix);
eprintln!("{} {:<23}{:>10}", prefix, "Section", "Size");
eprintln!(
"{} metadata bytes, of which {} bytes ({:.1}%) are zero",
total_bytes,
zero_bytes,
"{} ----------------------------------------------------------------",
prefix
);
for (label, size) in stats {
eprintln!(
"{} {:<23}{:>10} ({:4.1}%)",
prefix,
label,
to_readable_str(size),
perc(size)
);
}
eprintln!(
"{} ----------------------------------------------------------------",
prefix
);
eprintln!(
"{} {:<23}{:>10} (of which {:.1}% are zero bytes)",
prefix,
"Total",
to_readable_str(total_bytes),
perc(zero_bytes)
);
p("preamble", preamble_bytes);
p("dep", dep_bytes);
p("lib feature", lib_feature_bytes);
p("stability_implications", stability_implications_bytes);
p("lang item", lang_item_bytes);
p("diagnostic item", diagnostic_item_bytes);
p("native lib", native_lib_bytes);
p("foreign modules", foreign_modules_bytes);
p("def-path table", def_path_table_bytes);
p("traits", traits_bytes);
p("impls", impls_bytes);
p("incoherent_impls", incoherent_impls_bytes);
p("mir", mir_bytes);
p("item", item_bytes);
p("interpret_alloc_index", interpret_alloc_index_bytes);
p("proc-macro-data", proc_macro_data_bytes);
p("tables", tables_bytes);
p("debugger visualizers", debugger_visualizers_bytes);
p("exported symbols", exported_symbols_bytes);
p("hygiene", hygiene_bytes);
p("def-path hashes", def_path_hash_map_bytes);
p("source_map", source_map_bytes);
p("final", final_bytes);
eprintln!("");
eprintln!("{}", prefix);
}
root