##// END OF EJS Templates
rust-index: implement faster retain heads using a vec instead of a hashset...
Raphaël Gomès -
r52152:ed6683d4 default
parent child Browse files
Show More
@@ -13,7 +13,7 b''
13 //! - Similarly *relative roots* of a collection of `Revision`, we mean those
13 //! - Similarly *relative roots* of a collection of `Revision`, we mean those
14 //! whose parents, if any, don't belong to the collection.
14 //! whose parents, if any, don't belong to the collection.
15 use super::{Graph, GraphError, Revision, NULL_REVISION};
15 use super::{Graph, GraphError, Revision, NULL_REVISION};
16 use crate::ancestors::AncestorsIterator;
16 use crate::{ancestors::AncestorsIterator, BaseRevision};
17 use std::collections::{BTreeSet, HashSet};
17 use std::collections::{BTreeSet, HashSet};
18
18
19 fn remove_parents<S: std::hash::BuildHasher>(
19 fn remove_parents<S: std::hash::BuildHasher>(
@@ -81,6 +81,32 b' pub fn retain_heads<S: std::hash::BuildH'
81 Ok(())
81 Ok(())
82 }
82 }
83
83
84 /// Optimized version of `retain_heads` that expects an zeroed array of the size
85 /// of the graph, to act as a faster but less space-efficient `HashSet`.
86 ///
87 /// # Panics
88 ///
89 /// Can panic if `not_heads` is shorten than the length of graph.
90 pub fn retain_heads_fast(
91 graph: &impl Graph,
92 not_heads: &mut [bool],
93 filtered_revs: &HashSet<Revision>,
94 ) -> Result<(), GraphError> {
95 for idx in (0..not_heads.len()).rev() {
96 let rev = Revision(idx as BaseRevision);
97 if !not_heads[idx] && filtered_revs.contains(&rev) {
98 not_heads[idx] = true;
99 continue;
100 }
101 for parent in graph.parents(rev)?.iter() {
102 if *parent != NULL_REVISION {
103 not_heads[parent.0 as usize] = true;
104 }
105 }
106 }
107 Ok(())
108 }
109
84 /// Roots of `revs`, passed as a `HashSet`
110 /// Roots of `revs`, passed as a `HashSet`
85 ///
111 ///
86 /// They are returned in arbitrary order
112 /// They are returned in arbitrary order
@@ -1,4 +1,3 b''
1 use std::collections::hash_map::RandomState;
2 use std::collections::{HashMap, HashSet};
1 use std::collections::{HashMap, HashSet};
3 use std::fmt::Debug;
2 use std::fmt::Debug;
4 use std::ops::Deref;
3 use std::ops::Deref;
@@ -565,32 +564,24 b' impl Index {'
565 return Ok(self_head_revs.to_owned());
564 return Ok(self_head_revs.to_owned());
566 }
565 }
567 }
566 }
568 let mut revs: HashSet<Revision, RandomState> =
567
569 if filtered_revs.is_empty() {
568 let as_vec = if self.is_empty() {
570 (0..self.len())
569 vec![NULL_REVISION]
571 .into_iter()
570 } else {
572 .map(|i| Revision(i as BaseRevision))
571 let mut not_heads = vec![false; self.len()];
573 .collect()
572 dagops::retain_heads_fast(self, &mut not_heads, filtered_revs)?;
574 } else {
573 not_heads
575 (0..self.len())
574 .into_iter()
576 .into_iter()
575 .enumerate()
577 .filter_map(|i| {
576 .filter_map(|(idx, is_not_head)| {
578 let r = Revision(i as BaseRevision);
577 if is_not_head {
579 if filtered_revs.contains(&r) {
578 None
580 None
579 } else {
581 } else {
580 Some(Revision(idx as BaseRevision))
582 Some(r)
581 }
583 }
582 })
584 })
583 .collect()
585 .collect()
584 };
586 };
587 dagops::retain_heads(self, &mut revs)?;
588 if self.is_empty() {
589 revs.insert(NULL_REVISION);
590 }
591 let mut as_vec: Vec<Revision> =
592 revs.into_iter().map(Into::into).collect();
593 as_vec.sort_unstable();
594 *self
585 *self
595 .head_revs
586 .head_revs
596 .write()
587 .write()
General Comments 0
You need to be logged in to leave comments. Login now