OXYGENHUB

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