Mercurial > hg
comparison rust/hg-core/src/revlog/index.rs @ 51259:ed6683d4cb29
rust-index: implement faster retain heads using a vec instead of a hashset
This is the same optimization that the C index does, we're only catching up
now because this showed up as slow in benchmarking.
author | Raphaël Gomès <rgomes@octobus.net> |
---|---|
date | Wed, 29 Nov 2023 10:04:41 -0500 |
parents | e74dd6d73cb5 |
children | c4f1a790bda8 |
comparison
equal
deleted
inserted
replaced
51258:8b89f7cc953a | 51259:ed6683d4cb29 |
---|---|
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; |
5 use std::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard}; | 4 use std::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard}; |
6 | 5 |
563 && filtered_revs == self_filtered_revs | 562 && filtered_revs == self_filtered_revs |
564 { | 563 { |
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() |
597 .expect("RwLock on Index.head_revs should not be poisoned") = | 588 .expect("RwLock on Index.head_revs should not be poisoned") = |
598 (as_vec.to_owned(), filtered_revs.to_owned()); | 589 (as_vec.to_owned(), filtered_revs.to_owned()); |