Defer the content measurement for a flex item's automatic minimum block size to improve performance by ~3% on speedometer4
Categories
(Core :: Layout: Flexbox, enhancement)
Tracking
()
People
(Reporter: perf-ai-bot, Assigned: kats)
References
(Blocks 1 open bug)
Details
(Whiteboard: [foofrix:9192b608-8842-442c-807b-22af00229719])
Attachments
(7 external files)
Defer the content measurement for a flex item's automatic minimum block size when the item's main axis is its block axis, its flex base size is definite, and a conservative upper bound of that minimum does not exceed the flex base size. The bound is the specified or transferred size suggestion, capped by the maximum main size and raised to any minimum the reflow input already imposes, such as a themed widget minimum. Hypothetical main sizes, line breaking and the container's main size are unchanged. If a deferred item's subtree is dirty, its cached block-axis measurement is discarded. Otherwise the item's final reflow would clear the dirty bits, and a later shrinking layout would accept the stale measurement. If an iteration of flexible-length resolution has negative free space while a deferred item is still unfrozen, the container regenerates its lines with eager resolution. Items that already had a measuring reflow keep that flag, so redundant final reflows can still be skipped. Otherwise deferred items skip the minimum-violation check: they never shrink below their flex base size, and maximum-size clamping cannot take them below their minimum. A new frame state bit, NS_STATE_FLEX_HAD_SHRINKING_LINE, disables deferral after a layout of the container had negative free space. Deferral is also disabled in fragmented contexts and when DevTools requests computed flex information. A container that alternates between non-shrinking and shrinking layouts still generates its items twice in each shrinking layout. A preparatory commit makes nsLayoutUtils' MeasureIntrinsicContentSize discard the cached flex measurements of the measured orthogonal frame and of its flex-item ancestors, up to the frame being reflowed. This fixes orthogonal flex items being left at their intrinsic-measurement size, a stale state that deferral would otherwise expose more often. WPTs cover dynamic resizing, transferred suggestions, maximum-only bounds, a shrinking later line, a MathML content change that does not clear ancestor intrinsic sizes, and stretched or flexed orthogonal items after an intrinsic-size recomputation. A chrome mochitest covers themed minimums, because the appearance value it needs is chrome-only.
Problem
To resolve a flex item's automatic minimum block size, Gecko reflows the item's subtree at an indefinite block size. It does this even when that minimum cannot exceed the item's definite flex base size, in which case the minimum only matters if the item's flex line has to shrink. The cached measurement is rejected whenever the item's subtree is dirty. So after content changes, nested column flexboxes repeat these measuring reflows at every level and lay out absolutely positioned descendants at throwaway sizes. Deferring the measurement until a line actually shrinks avoids this work in eligible layouts.
Performance
- Benchmark: speedometer4
- Test: sp4-full
- Component: Layout
- Local Improvement: 4.62%
Validation
| Reporter | ||
Updated•11 days ago
|
| Reporter | ||
Comment 1•11 days ago
|
||
Please move this bug to the correct component.
Once the Phabricator patch is ready for review, please commandeer it.
| Reporter | ||
Comment 2•11 days ago
|
||
Defer the content measurement for a flex item's automatic minimum block size when the item's main axis is its block axis, its flex base size is definite, and a conservative upper bound of that minimum does not exceed the flex base size. The bound is the s
| Assignee | ||
Comment 3•11 days ago
|
||
I'll do a first pass on this to see how legitimate it is
| Assignee | ||
Comment 4•10 days ago
|
||
This fixes orthogonal flex items being left at their intrinsic-measurement
size, a stale state that deferral would otherwise expose more often.
| Assignee | ||
Comment 5•10 days ago
|
||
| Assignee | ||
Comment 6•10 days ago
|
||
After resolving all the flex lines, this sets a bit on the flex
container if any line had negative free space.
| Assignee | ||
Comment 7•10 days ago
|
||
Plumb a flag into ResolveAutoFlexBasisAndMinSize that allows
the resolution of auto min main size to be deferred. The flag
is not set in some cases, such as if we encountered negative
free space on the container last time.
| Assignee | ||
Comment 8•10 days ago
|
||
Detect cases where the resolution was deferred, and implement the
deferred resolution pass. The detection is done by checking a new
return value from ResolveFlexibleLengths. The new pass invokes
GenerateFlexLines with the allow-deferred flag set to false to
force immediate resolution.
| Assignee | ||
Comment 9•10 days ago
|
||
| Assignee | ||
Comment 10•10 days ago
|
||
I'm not familiar with how flexbox layout is implemented but I took the existing AI-generated patch and split it apart into a more readable stack as best I could. The overall idea looks reasonable to me and the before/after profile data seems to correlate well to the code changes. I think I've done as much due diligence as I can on this, moving to layout.
Description
•