about summary refs log tree commit diff
path: root/compiler/rustc_metadata/src
diff options
context:
space:
mode:
authorNicholas Nethercote <n.nethercote@gmail.com>2022-09-20 16:08:25 +1000
committerNicholas Nethercote <n.nethercote@gmail.com>2022-09-21 11:22:31 +1000
commita7b35b5618da9c557a8d318aa7839a96fecb4d05 (patch)
tree51573cef64569c65970848c19213271c992c93b4 /compiler/rustc_metadata/src
parentb7dc9341b5a57e120470f8bb0e4831bffab63c89 (diff)
downloadrust-a7b35b5618da9c557a8d318aa7839a96fecb4d05.tar.gz
rust-a7b35b5618da9c557a8d318aa7839a96fecb4d05.zip
Overhaul `-Zmeta-stats` output.
It's now much more like the `-Zhir-stats` output.
- Each line is preceded with `meta-stats`, which makes the provenance
  clearer and allows filtering of the output.
- Sections are now sorted in reverse order of size.
- Column headings avoid the need to repeat the word "bytes" on every line.
- Long numbers now have `_` separators for easier reading.
- Consistent use of '-' within section labels, rather than a mix of '-',
  '_', and ' '.

The code itself is shorter and easier to read thanks to:
- the `stat` macro, which encapsulates each section's encoding, avoids
  some boilerplate, and removes the need for some low-value comments;
- the `stats` vector, which replaces dozens of local variables.
Diffstat (limited to 'compiler/rustc_metadata/src')
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs344
1 files changed, 142 insertions, 202 deletions
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 2bc958df4a7..67c28461ce5 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -28,6 +28,7 @@ use rustc_middle::ty::codec::TyEncoder;
 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};
@@ -554,78 +555,56 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
 
     fn encode_crate_root(&mut self) -> LazyValue<CrateRoot> {
         let tcx = self.tcx;
-        let mut i = 0;
-        let preamble_bytes = self.position() - i;
-
-        // 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;
-
-        // Encode the lib features.
-        i = self.position();
-        let lib_features = self.encode_lib_features();
-        let lib_feature_bytes = self.position() - i;
-
-        // Encode the stability implications.
-        i = self.position();
-        let stability_implications = self.encode_stability_implications();
-        let stability_implications_bytes = self.position() - i;
-
-        // 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;
-
-        // Encode the diagnostic items.
-        i = self.position();
-        let diagnostic_items = self.encode_diagnostic_items();
-        let diagnostic_item_bytes = self.position() - i;
-
-        // Encode the native libraries used
-        i = self.position();
-        let native_libraries = self.encode_native_libraries();
-        let native_lib_bytes = self.position() - i;
-
-        i = self.position();
-        let foreign_modules = self.encode_foreign_modules();
-        let foreign_modules_bytes = self.position() - i;
-
-        // Encode DefPathTable
-        i = self.position();
-        self.encode_def_path_table();
-        let def_path_table_bytes = self.position() - i;
+        let mut stats: Vec<(&'static str, usize)> = Vec::with_capacity(32);
+
+        macro_rules! stat {
+            ($label:literal, $f:expr) => {{
+                let orig_pos = self.position();
+                let res = $f();
+                stats.push(($label, self.position() - orig_pos));
+                res
+            }};
+        }
+
+        // We have already encoded some things. Get their combined size from the current position.
+        stats.push(("preamble", self.position()));
+
+        let (crate_deps, dylib_dependency_formats) =
+            stat!("dep", || (self.encode_crate_deps(), self.encode_dylib_dependency_formats()));
+
+        let lib_features = stat!("lib-features", || self.encode_lib_features());
+
+        let stability_implications =
+            stat!("stability-implications", || self.encode_stability_implications());
+
+        let (lang_items, lang_items_missing) = stat!("lang-items", || {
+            (self.encode_lang_items(), self.encode_lang_items_missing())
+        });
+
+        let diagnostic_items = stat!("diagnostic-items", || self.encode_diagnostic_items());
+
+        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;
-
-        i = self.position();
-        let incoherent_impls = self.encode_incoherent_impls();
-        let incoherent_impls_bytes = self.position() - i;
-
-        // Encode MIR.
-        i = self.position();
-        self.encode_mir();
-        let mir_bytes = self.position() - i;
-
-        // Encode the items.
-        i = self.position();
-        self.encode_def_ids();
-        self.encode_info_for_items();
-        let item_bytes = self.position() - i;
-
-        // Encode the allocation index
-        i = self.position();
-        let interpret_alloc_index = {
+        let impls = stat!("impls", || self.encode_impls());
+
+        let incoherent_impls = stat!("incoherent-impls", || self.encode_incoherent_impls());
+
+        _ = stat!("mir", || self.encode_mir());
+
+        _ = stat!("items", || {
+            self.encode_def_ids();
+            self.encode_info_for_items();
+        });
+
+        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,125 +625,90 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                 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;
+        let exported_symbols = stat!("exported-symbols", || {
+            self.encode_exported_symbols(&tcx.exported_symbols(LOCAL_CRATE))
+        });
 
-        // Encode the hygiene data,
+        // 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 (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() {
@@ -782,42 +726,38 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             }
             assert_eq!(self.opaque.file().stream_position().unwrap(), pos_before_rewind);
 
+            stats.sort_by_key(|&(_, usize)| usize);
+
+            let prefix = "meta-stats";
             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));
-            };
 
-            eprintln!("");
+            eprintln!("{} METADATA STATS", prefix);
+            eprintln!("{} {:<23}{:>10}", prefix, "Section", "Size");
+            eprintln!(
+                "{} ----------------------------------------------------------------",
+                prefix
+            );
+            for (label, size) in stats {
+                eprintln!(
+                    "{} {:<23}{:>10} ({:4.1}%)",
+                    prefix,
+                    label,
+                    to_readable_str(size),
+                    perc(size)
+                );
+            }
+            eprintln!(
+                "{} ----------------------------------------------------------------",
+                prefix
+            );
             eprintln!(
-                "{} metadata bytes, of which {} bytes ({:.1}%) are zero",
-                total_bytes,
-                zero_bytes,
+                "{} {:<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