From f5c2e87965d8e3eab783228f6045efe8838a035c Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sun, 13 Mar 2022 16:19:54 +0100 Subject: [PATCH] LibWeb: Sort stacking context tree once, after fully building it Instead of calling quick_sort() every time a StackingContext child is added to a parent, we now do a single pass of sorting work after the full StackingContext tree has been built. Before this change, the quick_sort() was ~13.5% of the profile while hovering links on GitHub in the Browser. After the change, it's down to ~0.6%. Pretty good! :^) --- .../LibWeb/Layout/InitialContainingBlock.cpp | 2 ++ .../LibWeb/Painting/StackingContext.cpp | 24 +++++++++++-------- .../LibWeb/Painting/StackingContext.h | 2 ++ 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/Userland/Libraries/LibWeb/Layout/InitialContainingBlock.cpp b/Userland/Libraries/LibWeb/Layout/InitialContainingBlock.cpp index 1f3cda61a5..f68b535d99 100644 --- a/Userland/Libraries/LibWeb/Layout/InitialContainingBlock.cpp +++ b/Userland/Libraries/LibWeb/Layout/InitialContainingBlock.cpp @@ -36,6 +36,8 @@ void InitialContainingBlock::build_stacking_context_tree() const_cast(box.paint_box())->set_stacking_context(make(box, parent_context)); return IterationDecision::Continue; }); + + const_cast(paint_box())->stacking_context()->sort(); } void InitialContainingBlock::paint_all_phases(PaintContext& context) diff --git a/Userland/Libraries/LibWeb/Painting/StackingContext.cpp b/Userland/Libraries/LibWeb/Painting/StackingContext.cpp index fb0dc9d51c..be08000159 100644 --- a/Userland/Libraries/LibWeb/Painting/StackingContext.cpp +++ b/Userland/Libraries/LibWeb/Painting/StackingContext.cpp @@ -26,18 +26,22 @@ StackingContext::StackingContext(Layout::Box& box, StackingContext* parent) , m_parent(parent) { VERIFY(m_parent != this); - if (m_parent) { + if (m_parent) m_parent->m_children.append(this); +} - // FIXME: Don't sort on every append.. - quick_sort(m_parent->m_children, [](auto& a, auto& b) { - auto a_z_index = a->m_box.computed_values().z_index().value_or(0); - auto b_z_index = b->m_box.computed_values().z_index().value_or(0); - if (a_z_index == b_z_index) - return a->m_box.is_before(b->m_box); - return a_z_index < b_z_index; - }); - } +void StackingContext::sort() +{ + quick_sort(m_children, [](auto& a, auto& b) { + auto a_z_index = a->m_box.computed_values().z_index().value_or(0); + auto b_z_index = b->m_box.computed_values().z_index().value_or(0); + if (a_z_index == b_z_index) + return a->m_box.is_before(b->m_box); + return a_z_index < b_z_index; + }); + + for (auto* child : m_children) + child->sort(); } void StackingContext::paint_descendants(PaintContext& context, Layout::Node& box, StackingContextPaintPhase phase) const diff --git a/Userland/Libraries/LibWeb/Painting/StackingContext.h b/Userland/Libraries/LibWeb/Painting/StackingContext.h index 0851a93984..b5cac7cd26 100644 --- a/Userland/Libraries/LibWeb/Painting/StackingContext.h +++ b/Userland/Libraries/LibWeb/Painting/StackingContext.h @@ -33,6 +33,8 @@ public: void dump(int indent = 0) const; + void sort(); + private: Layout::Box& m_box; StackingContext* const m_parent { nullptr };