mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
Improve performance of flex column layouts by caching (#34461)
* Obey min and max properties when computing main size of column flex When laying out a column flex container with an auto preferred main size, we were resolving the used main size to the intrinsic max-content size. However, we weren't clamping this amount between the min and max sizes. Co-authored-by: Martin Robinson <mrobinson@igalia.com> Signed-off-by: Oriol Brufau <obrufau@igalia.com> * Improve performance of flex column layouts by caching We were already using a cache for layout_for_block_content_size(), but we were only storing the intrinsic block size. Thus when laying out the flex items for real, we would perform new layouts, triggering an exponential complexity in case of nested flexboxes. Now we cache the entire layout result so that we can avoid doing the work again. This improves the results of flexbox-deeply-nested-column-flow.html (a Blink perf test) from ~40 runs/second to ~500 runs/second on my PC. Co-authored-by: Martin Robinson <mrobinson@igalia.com> Signed-off-by: Oriol Brufau <obrufau@igalia.com> --------- Signed-off-by: Oriol Brufau <obrufau@igalia.com> Co-authored-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
parent
ad448da7de
commit
0be5209003
2 changed files with 34 additions and 17 deletions
|
@ -1717,8 +1717,6 @@ impl InitialFlexLineLayout<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
let _ = item.item.box_.block_content_size_cache.borrow_mut().take();
|
||||
|
||||
let baseline = item.get_or_synthesize_baseline_with_cross_size(used_cross_size);
|
||||
if matches!(
|
||||
item.item.align_self.0.value(),
|
||||
|
@ -1875,9 +1873,6 @@ impl FlexItem<'_> {
|
|||
used_cross_size_override: Option<Au>,
|
||||
non_stretch_layout_result: Option<&mut FlexItemLayoutResult>,
|
||||
) -> Option<FlexItemLayoutResult> {
|
||||
// Clear any layout cache information so that it doesn't persist until the next layout.
|
||||
self.box_.block_content_size_cache.borrow_mut().take();
|
||||
|
||||
let containing_block = flex_context.containing_block;
|
||||
let mut positioning_context = PositioningContext::new_for_style(self.box_.style())
|
||||
.unwrap_or_else(|| {
|
||||
|
@ -2040,18 +2035,27 @@ impl FlexItem<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
let cache = self.box_.block_content_size_cache.borrow_mut().take();
|
||||
let layout = if let Some(cache) = cache.filter(|cache| {
|
||||
cache.compatible_with_item_as_containing_block(&item_as_containing_block)
|
||||
}) {
|
||||
positioning_context = cache.positioning_context;
|
||||
cache.layout
|
||||
} else {
|
||||
non_replaced.layout(
|
||||
flex_context.layout_context,
|
||||
&mut positioning_context,
|
||||
&item_as_containing_block,
|
||||
containing_block,
|
||||
)
|
||||
};
|
||||
let IndependentLayout {
|
||||
fragments,
|
||||
content_block_size,
|
||||
baselines: content_box_baselines,
|
||||
depends_on_block_constraints,
|
||||
..
|
||||
} = non_replaced.layout(
|
||||
flex_context.layout_context,
|
||||
&mut positioning_context,
|
||||
&item_as_containing_block,
|
||||
containing_block,
|
||||
);
|
||||
} = layout;
|
||||
let depends_on_block_constraints = depends_on_block_constraints ||
|
||||
(flex_axis == FlexAxis::Row && self.stretches());
|
||||
|
||||
|
@ -2806,10 +2810,10 @@ impl FlexItemBox {
|
|||
block_size: AuOrAuto::Auto,
|
||||
style: &non_replaced.style,
|
||||
};
|
||||
let mut content_block_size = || {
|
||||
let content_block_size = || {
|
||||
if let Some(cache) = &*self.block_content_size_cache.borrow() {
|
||||
if inline_size == cache.containing_block_inline_size {
|
||||
return cache.content_block_size;
|
||||
return cache.layout.content_block_size;
|
||||
} else {
|
||||
#[cfg(feature = "tracing")]
|
||||
tracing::warn!(
|
||||
|
@ -2833,7 +2837,8 @@ impl FlexItemBox {
|
|||
*self.block_content_size_cache.borrow_mut() =
|
||||
Some(CachedBlockSizeContribution {
|
||||
containing_block_inline_size: item_as_containing_block.inline_size,
|
||||
content_block_size: layout.content_block_size,
|
||||
layout,
|
||||
positioning_context,
|
||||
});
|
||||
content_block_size
|
||||
};
|
||||
|
|
|
@ -20,9 +20,10 @@ use crate::construct_modern::{ModernContainerBuilder, ModernItemKind};
|
|||
use crate::context::LayoutContext;
|
||||
use crate::dom::{LayoutBox, NodeExt};
|
||||
use crate::dom_traversal::{NodeAndStyleInfo, NonReplacedContents};
|
||||
use crate::formatting_contexts::IndependentFormattingContext;
|
||||
use crate::formatting_contexts::{IndependentFormattingContext, IndependentLayout};
|
||||
use crate::fragment_tree::BaseFragmentInfo;
|
||||
use crate::positioned::AbsolutelyPositionedBox;
|
||||
use crate::positioned::{AbsolutelyPositionedBox, PositioningContext};
|
||||
use crate::ContainingBlock;
|
||||
|
||||
mod geom;
|
||||
mod layout;
|
||||
|
@ -180,5 +181,16 @@ impl FlexItemBox {
|
|||
|
||||
struct CachedBlockSizeContribution {
|
||||
containing_block_inline_size: Au,
|
||||
content_block_size: Au,
|
||||
layout: IndependentLayout,
|
||||
positioning_context: PositioningContext,
|
||||
}
|
||||
|
||||
impl CachedBlockSizeContribution {
|
||||
fn compatible_with_item_as_containing_block(
|
||||
&self,
|
||||
item_as_containing_block: &ContainingBlock,
|
||||
) -> bool {
|
||||
item_as_containing_block.inline_size == self.containing_block_inline_size &&
|
||||
item_as_containing_block.block_size.is_auto()
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue