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());