Carry a widget's depth down the draw instead of walking up for it
Choosing which dirty widget to settle next asked every one of them how deep it was, and answering meant walking its ancestry to the root. At 130 of 260 widgets dirty that was 25.8% of the frame -- more than laying out or rendering. A widget's depth is known where it is drawn: its parent's plus one. So `Painter` carries it and `ActiveData` keeps it, and the choice reads a field. Being reused counts as being visited, so the two reuse paths keep it current too; only a subtree nothing looked at can hold an old one, and nothing under an unvisited subtree is being ordered. The order is unchanged, so nothing about the layout is: the five reference renders and the resize render are byte-identical. What the carried depth might get wrong is itself, so `depth` asserts it against the ancestry in debug builds, and the hundred-seed sweep passes with those assertions on -- including the reshuffles, which are what move a widget to another parent. Same load, 1000 frames, 130 of 260 dirty: 8.16M instructions per frame to 7.14M, median 0.813 ms to 0.639, and the choosing from 25.8% of the frame to 4.7%. What is left of it is iterating the dirty set itself, which a `HashSet` walks by capacity rather than by length. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
bf9438087a
commit
3f7cd8251b
4 files changed
+40
-5
No files matched your search
@@ -31,6 +31,7 @@ pub struct Painter<'a> {
|
||||
/// its parent placed it, otherwise the nearest ancestor that has one.
|
||||
pub(super) move_idx: MoveIdx,
|
||||
pub layer: usize,
|
||||
pub(super) depth: usize,
|
||||
pub(super) id: WidgetId,
|
||||
}
|
||||
|
||||
@@ -134,6 +135,7 @@ impl<'a> Painter<'a> {
|
||||
id.id(),
|
||||
region,
|
||||
Some(self.id),
|
||||
self.depth + 1,
|
||||
self.move_idx,
|
||||
slotted,
|
||||
self.mask,
|
||||
|
||||
Reference in new issue
Block a user