Mercurial > hg
changeset 51425:7c6d0b9dde37
rust-index: improve phase computation speed
While less memory efficient, using an array is *much* faster than using a
HashMap, especially with the default hasher. It even makes the code simpler,
so I'm not really sure what I was thinking in the first place, maybe it's more
obvious now.
This fix a significant performance regression when using the rust version of the
code. (however, the C code still outperform rust on this operation)
hg perf::phases on mozilla-try-2023-03-22
- 6.6.3: 0.451239 seconds
- before: 0.982495 seconds
- after: 0.265347 seconds
- C code: 0.183241 second
author | Raphaël Gomès <rgomes@octobus.net> |
---|---|
date | Thu, 22 Feb 2024 15:06:16 +0100 |
parents | 3cee8706f53b |
children | 3099f1c68afd |
files | rust/hg-core/src/revlog/index.rs |
diffstat | 1 files changed, 12 insertions(+), 19 deletions(-) [+] |
line wrap: on
line diff
--- a/rust/hg-core/src/revlog/index.rs Fri Feb 23 06:37:25 2024 +0100 +++ b/rust/hg-core/src/revlog/index.rs Thu Feb 22 15:06:16 2024 +0100 @@ -1026,7 +1026,7 @@ &self, roots: HashMap<Phase, Vec<Revision>>, ) -> Result<(usize, RootsPerPhase), GraphError> { - let mut phases = HashMap::new(); + let mut phases = vec![Phase::Public; self.len()]; let mut min_phase_rev = NULL_REVISION; for phase in Phase::non_public_phases() { @@ -1053,24 +1053,17 @@ let rev = Revision(rev); let [p1, p2] = self.parents(rev)?; - const DEFAULT_PHASE: &Phase = &Phase::Public; - if p1.0 >= 0 - && phases.get(&p1).unwrap_or(DEFAULT_PHASE) - > phases.get(&rev).unwrap_or(DEFAULT_PHASE) - { - phases.insert(rev, phases[&p1]); + if p1.0 >= 0 && phases[p1.0 as usize] > phases[rev.0 as usize] { + phases[rev.0 as usize] = phases[p1.0 as usize]; + } + if p2.0 >= 0 && phases[p2.0 as usize] > phases[rev.0 as usize] { + phases[rev.0 as usize] = phases[p2.0 as usize]; } - if p2.0 >= 0 - && phases.get(&p2).unwrap_or(DEFAULT_PHASE) - > phases.get(&rev).unwrap_or(DEFAULT_PHASE) - { - phases.insert(rev, phases[&p2]); - } - let set = match phases.get(&rev).unwrap_or(DEFAULT_PHASE) { + let set = match phases[rev.0 as usize] { Phase::Public => continue, - phase => &mut phase_sets[*phase as usize - 1], + phase => &mut phase_sets[phase as usize - 1], }; - set.insert(rev); + set.push(rev); } Ok((self.len(), phase_sets)) @@ -1079,13 +1072,13 @@ fn add_roots_get_min( &self, phase_roots: &[Revision], - phases: &mut HashMap<Revision, Phase>, + phases: &mut [Phase], phase: Phase, ) -> Revision { let mut min_rev = NULL_REVISION; for root in phase_roots { - phases.insert(*root, phase); + phases[root.0 as usize] = phase; if min_rev == NULL_REVISION || min_rev > *root { min_rev = *root; } @@ -1606,7 +1599,7 @@ } /// Set of roots of all non-public phases -pub type RootsPerPhase = [HashSet<Revision>; Phase::non_public_phases().len()]; +pub type RootsPerPhase = [Vec<Revision>; Phase::non_public_phases().len()]; #[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)] pub enum Phase {