Compute a state's tree view once 206c76cad4bf
A snapshot built its base's tree view twice, once for the graph keys and once to render, each time working out every node's placements, modes and path (0.4 s on the Linux tree). The tree graph now keeps its view once computed, cleared by any change to it, and hands out clones. A status with one file changed on the Linux tip takes 2.3 s (from 2.5 s). refs #35
- Author
- Andy McCall @andymccall <[email protected]>
- When
- · 2026-09-29 23:05 UTC
- Signature
- ✔ signed by Andy McCall
- Hash
206c76cad4bf2b61af35e9d48236b2e395a56aa73cd863c2bcd4a9610d580f10- Depends on
- 1d360c91a289 8b276e0106d1 ff0af1ee299d
- Depended on by
- e83354cdac22 2306a4d24779
- In bookmarks
- agents-in-readme 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.1.0 v0.10.0 v0.11.0 v0.2.0 v0.3.0 v0.3.1 v0.4.0 v0.4.1 v0.4.2 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, 2 files
Browse the tree at this change
modified crates/oxy-core/src/tree.rs +9 −0
| … | 28 unchanged lines |
||
| 29 | 29 | deleted_modes: HashMap<OpKey, BTreeSet<ChangeHash>>, |
|
| 30 | 30 | placements_of: HashMap<NodeId, BTreeSet<OpKey>>, |
|
| 31 | 31 | modes_of: HashMap<NodeId, BTreeSet<OpKey>>, |
|
| 32 | + | /// The view, once computed; cleared by every change to the graph. |
|
| 33 | + | view_cache: std::sync::OnceLock<TreeView>, |
|
| 32 | 34 | } |
|
| 33 | 35 | ||
| 34 | 36 | #[derive(Clone, Debug, PartialEq, Eq)] |
|
| … | 54 unchanged lines |
||
| 89 | 91 | ||
| 90 | 92 | /// Apply tree op `index` of `change`; `OpRef` self references must already be resolved. |
|
| 91 | 93 | pub fn apply(&mut self, change: ChangeHash, index: u32, op: &TreeOp) { |
|
| 94 | + | self.view_cache = std::sync::OnceLock::new(); |
|
| 92 | 95 | let key = (change, index); |
|
| 93 | 96 | match op { |
|
| 94 | 97 | TreeOp::AddNode { |
|
| … | 109 unchanged lines |
||
| 204 | 207 | } |
|
| 205 | 208 | ||
| 206 | 209 | /// Resolve the tree: assign paths, find conflicts. |
|
| 210 | + | /// The materialized tree (spec §7.1): computed once per graph and |
|
| 211 | + | /// cloned for each caller. |
|
| 207 | 212 | pub fn view(&self) -> TreeView { |
|
| 213 | + | self.view_cache.get_or_init(|| self.compute_view()).clone() |
|
| 214 | + | } |
|
| 215 | + | ||
| 216 | + | fn compute_view(&self) -> TreeView { |
|
| 208 | 217 | let mut view = TreeView::default(); |
|
| 209 | 218 | ||
| 210 | 219 | // Live placements grouped by parent. |
|
| … | 623 unchanged lines |
modified docs/benchmarks.md +3 −1
| … | 351 unchanged lines |
||
| 352 | 352 | file's stat is carried from the walk into the manifest. It now takes |
|
| 353 | 353 | 2.5 s: the base's history 0.5 s, its tree view and graph keys 0.38 s, |
|
| 354 | 354 | the walk 0.35 s, rendering the changed file 0.47 s, the diff 0.18 s, |
|
| 355 | - | and the manifest 0.14 s. (Git: 0.23 s.) |
|
| 355 | + | and the manifest 0.14 s. (Git: 0.23 s.) The tree view is now computed once per |
|
| 356 | + | state and cloned for each use, which brings rendering to 0.2 s and the |
|
| 357 | + | status to 2.3 s. |
|
| 356 | 358 |