about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-12-28 20:02:23 +0000
committerbors <bors@rust-lang.org>2018-12-28 20:02:23 +0000
commit60e825389db3cb7421afb7015b28cb9436c79bba (patch)
tree473d532205d35689c3ce0b47a5278278fed3750e
parent3cda631ea45bac643ed9e4968f9292b0244a5b82 (diff)
parent0257c5adca83a4670772e8ed27cb9d9ee0aada13 (diff)
downloadrust-60e825389db3cb7421afb7015b28cb9436c79bba.tar.gz
rust-60e825389db3cb7421afb7015b28cb9436c79bba.zip
Auto merge of #57118 - Zoxc:query-stats, r=wesleywiser
Add a command line flag to print some query stats

r? @michaelwoerister
-rw-r--r--src/librustc/session/config.rs2
-rw-r--r--src/librustc/ty/context.rs2
-rw-r--r--src/librustc/ty/query/mod.rs1
-rw-r--r--src/librustc/ty/query/plumbing.rs105
-rw-r--r--src/librustc_driver/driver.rs4
5 files changed, 112 insertions, 2 deletions
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index 8dcf140cd2a..e58c9d75a9d 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -1279,6 +1279,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
         "emit Retagging MIR statements, interpreted e.g., by miri; implies -Zmir-opt-level=0"),
     perf_stats: bool = (false, parse_bool, [UNTRACKED],
         "print some performance-related statistics"),
+    query_stats: bool = (false, parse_bool, [UNTRACKED],
+        "print some statistics about the query system"),
     hir_stats: bool = (false, parse_bool, [UNTRACKED],
         "print some statistics about AST and HIR"),
     always_encode_mir: bool = (false, parse_bool, [TRACKED],
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 289ef4da992..ea69d466ba6 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -903,7 +903,7 @@ pub struct GlobalCtxt<'tcx> {
     /// as well as all upstream crates. Only populated in incremental mode.
     pub def_path_hash_to_def_id: Option<FxHashMap<DefPathHash, DefId>>,
 
-    pub(crate) queries: query::Queries<'tcx>,
+    pub queries: query::Queries<'tcx>,
 
     // Records the free variables referenced by every closure
     // expression. Do not track deps for this, just recompute it from
diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs
index cbdec2ef2ba..22bd1cd90a7 100644
--- a/src/librustc/ty/query/mod.rs
+++ b/src/librustc/ty/query/mod.rs
@@ -53,6 +53,7 @@ use rustc_target::spec::PanicStrategy;
 use std::borrow::Cow;
 use std::ops::Deref;
 use std::sync::Arc;
+use std::intrinsics::type_name;
 use syntax_pos::{Span, DUMMY_SP};
 use syntax_pos::symbol::InternedString;
 use syntax::attr;
diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs
index 99da77491ca..5d23ee0994a 100644
--- a/src/librustc/ty/query/plumbing.rs
+++ b/src/librustc/ty/query/plumbing.rs
@@ -27,6 +27,8 @@ use syntax::source_map::DUMMY_SP;
 pub struct QueryCache<'tcx, D: QueryConfig<'tcx> + ?Sized> {
     pub(super) results: FxHashMap<D::Key, QueryValue<D::Value>>,
     pub(super) active: FxHashMap<D::Key, QueryResult<'tcx>>,
+    #[cfg(debug_assertions)]
+    pub(super) cache_hits: usize,
 }
 
 pub(super) struct QueryValue<T> {
@@ -50,6 +52,8 @@ impl<'tcx, M: QueryConfig<'tcx>> Default for QueryCache<'tcx, M> {
         QueryCache {
             results: FxHashMap::default(),
             active: FxHashMap::default(),
+            #[cfg(debug_assertions)]
+            cache_hits: 0,
         }
     }
 }
@@ -114,6 +118,10 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> {
                 });
 
                 let result = Ok((value.value.clone(), value.index));
+                #[cfg(debug_assertions)]
+                {
+                    lock.cache_hits += 1;
+                }
                 return TryGetJob::JobCompleted(result);
             }
             let job = match lock.active.entry((*key).clone()) {
@@ -752,6 +760,101 @@ macro_rules! define_queries_inner {
 
                 jobs
             }
+
+            pub fn print_stats(&self) {
+                let mut queries = Vec::new();
+
+                #[derive(Clone)]
+                struct QueryStats {
+                    name: &'static str,
+                    cache_hits: usize,
+                    key_size: usize,
+                    key_type: &'static str,
+                    value_size: usize,
+                    value_type: &'static str,
+                    entry_count: usize,
+                }
+
+                fn stats<'tcx, Q: QueryConfig<'tcx>>(
+                    name: &'static str,
+                    map: &QueryCache<'tcx, Q>
+                ) -> QueryStats {
+                    QueryStats {
+                        name,
+                        #[cfg(debug_assertions)]
+                        cache_hits: map.cache_hits,
+                        #[cfg(not(debug_assertions))]
+                        cache_hits: 0,
+                        key_size: mem::size_of::<Q::Key>(),
+                        key_type: unsafe { type_name::<Q::Key>() },
+                        value_size: mem::size_of::<Q::Value>(),
+                        value_type: unsafe { type_name::<Q::Value>() },
+                        entry_count: map.results.len(),
+                    }
+                }
+
+                $(
+                    queries.push(stats::<queries::$name<'_>>(
+                        stringify!($name),
+                        &*self.$name.lock()
+                    ));
+                )*
+
+                if cfg!(debug_assertions) {
+                    let hits: usize = queries.iter().map(|s| s.cache_hits).sum();
+                    let results: usize = queries.iter().map(|s| s.entry_count).sum();
+                    println!("\nQuery cache hit rate: {}", hits as f64 / (hits + results) as f64);
+                }
+
+                let mut query_key_sizes = queries.clone();
+                query_key_sizes.sort_by_key(|q| q.key_size);
+                println!("\nLarge query keys:");
+                for q in query_key_sizes.iter().rev()
+                                        .filter(|q| q.key_size > 8) {
+                    println!(
+                        "   {} - {} x {} - {}",
+                        q.name,
+                        q.key_size,
+                        q.entry_count,
+                        q.key_type
+                    );
+                }
+
+                let mut query_value_sizes = queries.clone();
+                query_value_sizes.sort_by_key(|q| q.value_size);
+                println!("\nLarge query values:");
+                for q in query_value_sizes.iter().rev()
+                                          .filter(|q| q.value_size > 8) {
+                    println!(
+                        "   {} - {} x {} - {}",
+                        q.name,
+                        q.value_size,
+                        q.entry_count,
+                        q.value_type
+                    );
+                }
+
+                if cfg!(debug_assertions) {
+                    let mut query_cache_hits = queries.clone();
+                    query_cache_hits.sort_by_key(|q| q.cache_hits);
+                    println!("\nQuery cache hits:");
+                    for q in query_cache_hits.iter().rev() {
+                        println!(
+                            "   {} - {} ({}%)",
+                            q.name,
+                            q.cache_hits,
+                            q.cache_hits as f64 / (q.cache_hits + q.entry_count) as f64
+                        );
+                    }
+                }
+
+                let mut query_value_count = queries.clone();
+                query_value_count.sort_by_key(|q| q.entry_count);
+                println!("\nQuery value count:");
+                for q in query_value_count.iter().rev() {
+                    println!("   {} - {}", q.name, q.entry_count);
+                }
+            }
         }
 
         #[allow(nonstandard_style)]
@@ -940,7 +1043,7 @@ macro_rules! define_queries_inner {
 macro_rules! define_queries_struct {
     (tcx: $tcx:tt,
      input: ($(([$($modifiers:tt)*] [$($attr:tt)*] [$name:ident]))*)) => {
-        pub(crate) struct Queries<$tcx> {
+        pub struct Queries<$tcx> {
             /// This provides access to the incr. comp. on-disk cache for query results.
             /// Do not access this directly. It is only meant to be used by
             /// `DepGraph::try_mark_green()` and the query infrastructure.
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index 62dc8691e65..9b232edc11d 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -328,6 +328,10 @@ pub fn compile_input(
                     }
                 }
 
+                if tcx.sess.opts.debugging_opts.query_stats {
+                    tcx.queries.print_stats();
+                }
+
                 Ok((outputs.clone(), ongoing_codegen, tcx.dep_graph.clone()))
             },
         )??