The state's change map and its walks on the fast hasher ac03130a2b95
State's map of change metadata used SipHash on 32-byte keys, which are BLAKE3 hashes already; it now uses the seeded fast hasher the graphs use (crate::fasthash), as do the walks over it: maximal's set of what lies below, and heads' set of what is depended on. Each walks the whole closure, several times per commit. VS Code at 19,978 commits, alternating builds, nine one-file commits each: median 308 ms to 294 ms; within one, loading the base 66 to 47 ms, extending the state 36 to 23 ms, validating 9 to 5 ms. refs #93
- Author
- Andy McCall @andymccall <[email protected]>
- When
- · 2026-10-10 03:33 UTC
- Signature
- ✔ signed by Andy McCall
- Hash
ac03130a2b951553a9b9524225563c396ad72694f8e5ca36cdf995d25fcfa798- Depends on
- 07eb99be126e 4cce912a0953 75167672ebcd 982864068a59 f6451fbbae3f f9575918477f ff0af1ee299d
- Depended on by
- 74b4a3c62ea4 bf0247ee3590
- In bookmarks
- bare-hashes carried-not-removed carry-identical doctor-trust identical-sides keyless-tags main merge-remote-bookmark only-help-103 paths-for-resolutions-and-amend push-notes show-stat subrepo-pin-state switch-says
- In tags
- v0.10.0 v0.11.0 v0.4.3 v0.4.4 v0.4.5 v0.4.6 v0.5.0 v0.5.1 v0.6.0 v0.7.0 v0.8.0 v0.9.0
- Edits
- 8 atoms, 0 tree operations, 2 files
Browse the tree at this change
modified crates/oxy-core/src/repo/mod.rs +1 −1
| … | 1167 unchanged lines |
||
| 1168 | 1168 | /// heads), read without the rest of the index. |
|
| 1169 | 1169 | pub(crate) fn read_state_index_changes( |
|
| 1170 | 1170 | &self, |
|
| 1171 | - | ) -> Option<std::collections::HashMap<ChangeHash, std::sync::Arc<crate::state::ChangeMeta>>> |
|
| 1171 | + | ) -> Option<crate::fasthash::FastMap<ChangeHash, std::sync::Arc<crate::state::ChangeMeta>>> |
|
| 1172 | 1172 | { |
|
| 1173 | 1173 | use std::io::Read; |
|
| 1174 | 1174 | let _t = crate::timing::phase("load: state index changes"); |
|
| … | 778 unchanged lines |
modified crates/oxy-core/src/state.rs +6 −5
| … | 56 unchanged lines |
||
| 57 | 57 | pub struct State { |
|
| 58 | 58 | /// Shared between clones, like `files` and `deferred`: a state kept |
|
| 59 | 59 | /// beside another that differs by a few changes shares the rest. |
|
| 60 | - | changes: HashMap<ChangeHash, Arc<ChangeMeta>>, |
|
| 60 | + | changes: crate::fasthash::FastMap<ChangeHash, Arc<ChangeMeta>>, |
|
| 61 | 61 | tree: TreeGraph, |
|
| 62 | 62 | /// Shared between clones: a clone copies a graph only when an edit |
|
| 63 | 63 | /// changes it (`Arc::make_mut`), so keeping several states that differ |
|
| … | 286 unchanged lines |
||
| 350 | 350 | /// take without the rest (the log needs no more). |
|
| 351 | 351 | pub fn read_index_changes( |
|
| 352 | 352 | bytes: &[u8], |
|
| 353 | - | ) -> Result<HashMap<ChangeHash, Arc<ChangeMeta>>, ObjectError> { |
|
| 353 | + | ) -> Result<crate::fasthash::FastMap<ChangeHash, Arc<ChangeMeta>>, ObjectError> { |
|
| 354 | 354 | use crate::flat::Reader; |
|
| 355 | 355 | let mut r = Reader::new(bytes); |
|
| 356 | 356 | if r.fixed::<18>()?.as_slice() != Self::INDEX_MAGIC { |
|
| 357 | 357 | return Err(ObjectError::Schema("state index: not a state index".into())); |
|
| 358 | 358 | } |
|
| 359 | 359 | let n = r.count()?; |
|
| 360 | - | let mut changes = HashMap::with_capacity(n); |
|
| 360 | + | let mut changes = crate::fasthash::FastMap::default(); |
|
| 361 | + | changes.reserve(n); |
|
| 361 | 362 | for _ in 0..n { |
|
| 362 | 363 | let h = r.object()?; |
|
| 363 | 364 | let change_id = crate::ids::ChangeId(r.fixed::<16>()?); |
|
| … | 1092 unchanged lines |
||
| 1456 | 1457 | ||
| 1457 | 1458 | /// Changes that no other change depends on directly, sorted. |
|
| 1458 | 1459 | pub fn heads(&self) -> Vec<ChangeHash> { |
|
| 1459 | - | let depended: HashSet<&ChangeHash> = |
|
| 1460 | + | let depended: crate::fasthash::FastSet<&ChangeHash> = |
|
| 1460 | 1461 | self.changes.values().flat_map(|c| c.deps.iter()).collect(); |
|
| 1461 | 1462 | let mut heads: Vec<ChangeHash> = self |
|
| 1462 | 1463 | .changes |
|
| … | 12 unchanged lines |
||
| 1475 | 1476 | /// of heads, which a bookmark of independent changes has many of. |
|
| 1476 | 1477 | pub fn maximal(&self, hashes: &[ChangeHash]) -> Vec<ChangeHash> { |
|
| 1477 | 1478 | let set: BTreeSet<ChangeHash> = hashes.iter().copied().collect(); |
|
| 1478 | - | let mut below: HashSet<ChangeHash> = HashSet::new(); |
|
| 1479 | + | let mut below: crate::fasthash::FastSet<ChangeHash> = Default::default(); |
|
| 1479 | 1480 | let mut stack: Vec<ChangeHash> = set |
|
| 1480 | 1481 | .iter() |
|
| 1481 | 1482 | .filter_map(|h| self.changes.get(h)) |
|
| … | 980 unchanged lines |