about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-03-22 22:36:44 +0000
committerbors <bors@rust-lang.org>2020-03-22 22:36:44 +0000
commite4b01c7791446b2f79a1b1d517223378df2bf5f2 (patch)
treefc02a84a46cc3ecc8a826e3b20b173a548c5cc37
parentd1e81ef234ff5c2e0e3a69cb4e8e5f5b0fe1fd83 (diff)
parent4168c25b0f8aadcfe38c8bdae7cc51c22c2f45d1 (diff)
downloadrust-e4b01c7791446b2f79a1b1d517223378df2bf5f2.tar.gz
rust-e4b01c7791446b2f79a1b1d517223378df2bf5f2.zip
Auto merge of #69778 - Marwes:dep_graph, r=davidtwco
perf(dep_graph): Avoid allocating a set on when the number reads are …

…small

`reserve_and_rehash` takes up 1.4% of the runtime on the `packed-simd`
benchmark which I believe is due to the number of reads are very low in
many cases (see https://github.com/rust-lang/rust/pull/50565 for
instance).

This avoids allocating the set until we start allocating the `reads`
`SmallVec` but it is possible that a lower limit might be better (not
tested since the improvement will be hard to spot either way).
-rw-r--r--src/librustc/dep_graph/graph.rs35
1 files changed, 24 insertions, 11 deletions
diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs
index 40192d072eb..dcb53a4fdef 100644
--- a/src/librustc/dep_graph/graph.rs
+++ b/src/librustc/dep_graph/graph.rs
@@ -328,12 +328,7 @@ impl DepGraph {
     {
         if let Some(ref data) = self.data {
             let (result, task_deps) = ty::tls::with_context(|icx| {
-                let task_deps = Lock::new(TaskDeps {
-                    #[cfg(debug_assertions)]
-                    node: None,
-                    reads: SmallVec::new(),
-                    read_set: Default::default(),
-                });
+                let task_deps = Lock::new(TaskDeps::default());
 
                 let r = {
                     let icx = ty::tls::ImplicitCtxt { task_deps: Some(&task_deps), ..icx.clone() };
@@ -953,7 +948,7 @@ pub enum WorkProductFileKind {
 #[derive(Clone)]
 struct DepNodeData {
     node: DepNode,
-    edges: SmallVec<[DepNodeIndex; 8]>,
+    edges: EdgesVec,
     fingerprint: Fingerprint,
 }
 
@@ -1078,7 +1073,7 @@ impl CurrentDepGraph {
     fn alloc_node(
         &self,
         dep_node: DepNode,
-        edges: SmallVec<[DepNodeIndex; 8]>,
+        edges: EdgesVec,
         fingerprint: Fingerprint,
     ) -> DepNodeIndex {
         debug_assert!(
@@ -1090,7 +1085,7 @@ impl CurrentDepGraph {
     fn intern_node(
         &self,
         dep_node: DepNode,
-        edges: SmallVec<[DepNodeIndex; 8]>,
+        edges: EdgesVec,
         fingerprint: Fingerprint,
     ) -> DepNodeIndex {
         match self.node_to_node_index.get_shard_by_value(&dep_node).lock().entry(dep_node) {
@@ -1113,11 +1108,25 @@ impl DepGraphData {
             let icx = if let Some(icx) = icx { icx } else { return };
             if let Some(task_deps) = icx.task_deps {
                 let mut task_deps = task_deps.lock();
+                let task_deps = &mut *task_deps;
                 if cfg!(debug_assertions) {
                     self.current.total_read_count.fetch_add(1, Relaxed);
                 }
-                if task_deps.read_set.insert(source) {
+
+                // As long as we only have a low number of reads we can avoid doing a hash
+                // insert and potentially allocating/reallocating the hashmap
+                let new_read = if task_deps.reads.len() < TASK_DEPS_READS_CAP {
+                    task_deps.reads.iter().all(|other| *other != source)
+                } else {
+                    task_deps.read_set.insert(source)
+                };
+                if new_read {
                     task_deps.reads.push(source);
+                    if task_deps.reads.len() == TASK_DEPS_READS_CAP {
+                        // Fill `read_set` with what we have so far so we can use the hashset next
+                        // time
+                        task_deps.read_set.extend(task_deps.reads.iter().copied());
+                    }
 
                     #[cfg(debug_assertions)]
                     {
@@ -1139,10 +1148,14 @@ impl DepGraphData {
     }
 }
 
+/// The capacity of the `reads` field `SmallVec`
+const TASK_DEPS_READS_CAP: usize = 8;
+type EdgesVec = SmallVec<[DepNodeIndex; TASK_DEPS_READS_CAP]>;
+#[derive(Default)]
 pub struct TaskDeps {
     #[cfg(debug_assertions)]
     node: Option<DepNode>,
-    reads: SmallVec<[DepNodeIndex; 8]>,
+    reads: EdgesVec,
     read_set: FxHashSet<DepNodeIndex>,
 }