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
@@ -45,7 +45,7 @@ pub(crate) enum Counter {
|
||||
ResizeChecks,
|
||||
ResizeCheckChildren,
|
||||
QueuePops,
|
||||
DepthSteps,
|
||||
DepthReads,
|
||||
EagerReaderRedraws,
|
||||
LocalRedraws,
|
||||
SizeChanges,
|
||||
@@ -82,7 +82,7 @@ impl Counter {
|
||||
"resize checks",
|
||||
"resize children checked",
|
||||
"redraw queue pops",
|
||||
"depth steps",
|
||||
"depth reads",
|
||||
"eager reader redraws",
|
||||
"local redraws",
|
||||
"size changes",
|
||||
|
||||
Reference in new issue
Block a user