Log without walking history when the index is the closure bf0247ee3590
When every head asked for is in the workspace's state index and every head of the index is among them, their closure is exactly the index's changes, which is closed: metas_of takes them all without a walk. Under test it still walks the store and checks the two agree. VS Code at 19,978 commits, under load: log -n 20 about 45 ms to 38 ms (metadata 17 to 12 ms); the whole log unchanged. refs #94
- Author
- Andy McCall @andymccall <[email protected]>
- When
- · 2026-10-10 03:38 UTC
- Signature
- ✔ signed by Andy McCall
- Hash
bf0247ee3590fb9049d7f49b8c382753df9151d16636667a9f3a15cf7f9fff0f- Depends on
- 4cce912a0953 79b5a90ffd43 982864068a59 ac03130a2b95 f9575918477f
- Depended on by
- 74b4a3c62ea4
- 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
- 6 atoms, 0 tree operations, 1 file
Browse the tree at this change
modified crates/oxy-core/src/repo/mod.rs +39 −4
| … | 1504 unchanged lines |
||
| 1505 | 1505 | ||
| 1506 | 1506 | /// The changes of this workspace's state index (the closure of its |
|
| 1507 | 1507 | /// heads), read without the rest of the index. |
|
| 1508 | + | #[allow(clippy::type_complexity)] |
|
| 1508 | 1509 | pub(crate) fn read_state_index_changes( |
|
| 1509 | 1510 | &self, |
|
| 1510 | - | ) -> Option<crate::fasthash::FastMap<ChangeHash, std::sync::Arc<crate::state::ChangeMeta>>> |
|
| 1511 | - | { |
|
| 1511 | + | ) -> Option<( |
|
| 1512 | + | Vec<ChangeHash>, |
|
| 1513 | + | crate::fasthash::FastMap<ChangeHash, std::sync::Arc<crate::state::ChangeMeta>>, |
|
| 1514 | + | )> { |
|
| 1512 | 1515 | use std::io::Read; |
|
| 1513 | 1516 | let _t = crate::timing::phase("load: state index changes"); |
|
| 1514 | 1517 | let mut f = fs::File::open(self.state_indexes().first()?).ok()?; |
|
| … | 2 unchanged lines |
||
| 1517 | 1520 | let n = u32::from_le_bytes(word) as usize; |
|
| 1518 | 1521 | let mut head = vec![0u8; 32 * n + 64 + 4]; |
|
| 1519 | 1522 | f.read_exact(&mut head).ok()?; |
|
| 1523 | + | let heads: Vec<ChangeHash> = head[..32 * n] |
|
| 1524 | + | .chunks_exact(32) |
|
| 1525 | + | .map(|c| ObjectRef(c.try_into().unwrap())) |
|
| 1526 | + | .collect(); |
|
| 1520 | 1527 | let sum = &head[32 * n..32 * n + 32]; |
|
| 1521 | 1528 | let len = u32::from_le_bytes(head[32 * n + 64..].try_into().unwrap()) as usize; |
|
| 1522 | 1529 | let mut changes = vec![0u8; 4 + len]; |
|
| … | 7 unchanged lines |
||
| 1530 | 1537 | } |
|
| 1531 | 1538 | drop(checking); |
|
| 1532 | 1539 | let _decoding = crate::timing::phase("load: of which decoding"); |
|
| 1533 | - | State::read_index_changes(&changes[4..]).ok() |
|
| 1540 | + | Some((heads, State::read_index_changes(&changes[4..]).ok()?)) |
|
| 1534 | 1541 | } |
|
| 1535 | 1542 | ||
| 1536 | 1543 | /// Save `st`, the history-only state of `deps`, as this workspace's |
|
| … | 414 unchanged lines |
||
| 1951 | 1958 | // The state index holds the metadata of its heads' closure: a |
|
| 1952 | 1959 | // change found there is not read from the store (a change object |
|
| 1953 | 1960 | // can be as large as the tree it adds). |
|
| 1954 | - | let mut indexed = self.read_state_index_changes(); |
|
| 1961 | + | let read = self.read_state_index_changes(); |
|
| 1962 | + | // Every one of `heads` in the index, and every head of the index |
|
| 1963 | + | // among them: their closure is the index's changes, all of them |
|
| 1964 | + | // (it is closed), and no walk is needed to find it. |
|
| 1965 | + | if let Some((index_heads, all)) = &read { |
|
| 1966 | + | let asked: crate::fasthash::FastSet<&ChangeHash> = heads.iter().collect(); |
|
| 1967 | + | if heads.iter().all(|h| all.contains_key(h)) |
|
| 1968 | + | && index_heads.iter().all(|h| asked.contains(h)) |
|
| 1969 | + | { |
|
| 1970 | + | let (_, all) = read.expect("matched above"); |
|
| 1971 | + | #[cfg(test)] |
|
| 1972 | + | { |
|
| 1973 | + | // The walk the shortcut saves finds the same changes. |
|
| 1974 | + | let mut seen: HashSet<ChangeHash> = HashSet::new(); |
|
| 1975 | + | let mut stack = heads.to_vec(); |
|
| 1976 | + | while let Some(h) = stack.pop() { |
|
| 1977 | + | if seen.insert(h) { |
|
| 1978 | + | stack.extend(self.store.get_change_meta(&h)?.deps); |
|
| 1979 | + | } |
|
| 1980 | + | } |
|
| 1981 | + | assert_eq!(seen, all.keys().copied().collect::<HashSet<_>>()); |
|
| 1982 | + | } |
|
| 1983 | + | return Ok(all |
|
| 1984 | + | .into_iter() |
|
| 1985 | + | .map(|(h, m)| (h, std::sync::Arc::unwrap_or_clone(m))) |
|
| 1986 | + | .collect()); |
|
| 1987 | + | } |
|
| 1988 | + | } |
|
| 1989 | + | let mut indexed = read.map(|(_, all)| all); |
|
| 1955 | 1990 | let _walk = crate::timing::phase("metadata: walk"); |
|
| 1956 | 1991 | let (mut stored, mut from_store) = (0usize, std::time::Duration::ZERO); |
|
| 1957 | 1992 | let mut seen: crate::fasthash::FastSet<ChangeHash> = Default::default(); |
|
| … | 356 unchanged lines |