diff options
| author | bors <bors@rust-lang.org> | 2020-03-22 22:36:44 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2020-03-22 22:36:44 +0000 |
| commit | e4b01c7791446b2f79a1b1d517223378df2bf5f2 (patch) | |
| tree | fc02a84a46cc3ecc8a826e3b20b173a548c5cc37 | |
| parent | d1e81ef234ff5c2e0e3a69cb4e8e5f5b0fe1fd83 (diff) | |
| parent | 4168c25b0f8aadcfe38c8bdae7cc51c22c2f45d1 (diff) | |
| download | rust-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.rs | 35 |
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>, } |
