layout: Report memory usage for fragment and box trees. (#36553)

Add memory reporter integration for the fragment and box trees that are
persisted in the layout thread.

Testing: Looked at the numbers for https://servo.org and
https://html.spec.whatwg.org/. The former was very small, but the latter
was 700mb.

---------

Signed-off-by: Josh Matthews <josh@joshmatthews.net>
This commit is contained in:
Josh Matthews 2025-04-18 16:05:15 -04:00 committed by GitHub
parent add8c51f47
commit c787688afc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
33 changed files with 230 additions and 69 deletions

View file

@ -3,6 +3,8 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use bitflags::bitflags;
use malloc_size_of::malloc_size_of_is_0;
use malloc_size_of_derive::MallocSizeOf;
use script_layout_interface::combine_id_with_fragment_type;
use style::dom::OpaqueNode;
use style::selector_parser::PseudoElement;
@ -10,7 +12,7 @@ use style::selector_parser::PseudoElement;
/// This data structure stores fields that are common to all non-base
/// Fragment types and should generally be the first member of all
/// concrete fragments.
#[derive(Clone, Debug)]
#[derive(Clone, Debug, MallocSizeOf)]
pub(crate) struct BaseFragment {
/// A tag which identifies the DOM node and pseudo element of this
/// Fragment's content. If this fragment is for an anonymous box,
@ -38,7 +40,7 @@ impl BaseFragment {
}
/// Information necessary to construct a new BaseFragment.
#[derive(Clone, Copy, Debug)]
#[derive(Clone, Copy, Debug, MallocSizeOf)]
pub(crate) struct BaseFragmentInfo {
/// The tag to use for the new BaseFragment, if it is not an anonymous Fragment.
pub tag: Option<Tag>,
@ -107,9 +109,11 @@ bitflags! {
}
}
malloc_size_of_is_0!(FragmentFlags);
/// A data structure used to hold DOM and pseudo-element information about
/// a particular layout object.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq)]
pub(crate) struct Tag {
pub(crate) node: OpaqueNode,
pub(crate) pseudo: Option<PseudoElement>,

View file

@ -5,6 +5,7 @@
use app_units::Au;
use atomic_refcell::AtomicRefCell;
use base::print_tree::PrintTree;
use malloc_size_of_derive::MallocSizeOf;
use servo_arc::Arc as ServoArc;
use style::Zero;
use style::computed_values::border_collapse::T as BorderCollapse;
@ -24,6 +25,7 @@ use crate::table::SpecificTableGridInfo;
use crate::taffy::SpecificTaffyGridInfo;
/// Describes how a [`BoxFragment`] paints its background.
#[derive(MallocSizeOf)]
pub(crate) enum BackgroundMode {
/// Draw the normal [`BoxFragment`] background as well as the extra backgrounds
/// based on the style and positioning rectangles in this data structure.
@ -36,12 +38,14 @@ pub(crate) enum BackgroundMode {
Normal,
}
#[derive(MallocSizeOf)]
pub(crate) struct ExtraBackground {
#[conditional_malloc_size_of]
pub style: ServoArc<ComputedValues>,
pub rect: PhysicalRect<Au>,
}
#[derive(Clone, Debug)]
#[derive(Clone, Debug, MallocSizeOf)]
pub(crate) enum SpecificLayoutInfo {
Grid(Box<SpecificTaffyGridInfo>),
TableCellWithCollapsedBorders,
@ -49,9 +53,11 @@ pub(crate) enum SpecificLayoutInfo {
TableWrapper,
}
#[derive(MallocSizeOf)]
pub(crate) struct BoxFragment {
pub base: BaseFragment,
#[conditional_malloc_size_of]
pub style: ServoArc<ComputedValues>,
pub children: Vec<Fragment>,

View file

@ -8,6 +8,7 @@ use app_units::Au;
use base::id::PipelineId;
use base::print_tree::PrintTree;
use fonts::{ByteIndex, FontMetrics, GlyphStore};
use malloc_size_of_derive::MallocSizeOf;
use range::Range as ServoRange;
use servo_arc::Arc as ServoArc;
use style::Zero;
@ -23,7 +24,7 @@ use crate::cell::ArcRefCell;
use crate::geom::{LogicalSides, PhysicalRect};
use crate::style_ext::ComputedValuesExt;
#[derive(Clone)]
#[derive(Clone, MallocSizeOf)]
pub(crate) enum Fragment {
Box(ArcRefCell<BoxFragment>),
/// Floating content. A floated fragment is very similar to a normal
@ -46,25 +47,28 @@ pub(crate) enum Fragment {
IFrame(ArcRefCell<IFrameFragment>),
}
#[derive(Clone)]
#[derive(Clone, MallocSizeOf)]
pub(crate) struct CollapsedBlockMargins {
pub collapsed_through: bool,
pub start: CollapsedMargin,
pub end: CollapsedMargin,
}
#[derive(Clone, Copy, Debug)]
#[derive(Clone, Copy, Debug, MallocSizeOf)]
pub(crate) struct CollapsedMargin {
max_positive: Au,
min_negative: Au,
}
#[derive(MallocSizeOf)]
pub(crate) struct TextFragment {
pub base: BaseFragment,
#[conditional_malloc_size_of]
pub parent_style: ServoArc<ComputedValues>,
pub rect: PhysicalRect<Au>,
pub font_metrics: FontMetrics,
pub font_key: FontInstanceKey,
#[conditional_malloc_size_of]
pub glyphs: Vec<Arc<GlyphStore>>,
/// A flag that represents the _used_ value of the text-decoration property.
@ -73,21 +77,26 @@ pub(crate) struct TextFragment {
/// Extra space to add for each justification opportunity.
pub justification_adjustment: Au,
pub selection_range: Option<ServoRange<ByteIndex>>,
#[conditional_malloc_size_of]
pub selected_style: ServoArc<ComputedValues>,
}
#[derive(MallocSizeOf)]
pub(crate) struct ImageFragment {
pub base: BaseFragment,
#[conditional_malloc_size_of]
pub style: ServoArc<ComputedValues>,
pub rect: PhysicalRect<Au>,
pub clip: PhysicalRect<Au>,
pub image_key: Option<ImageKey>,
}
#[derive(MallocSizeOf)]
pub(crate) struct IFrameFragment {
pub base: BaseFragment,
pub pipeline_id: PipelineId,
pub rect: PhysicalRect<Au>,
#[conditional_malloc_size_of]
pub style: ServoArc<ComputedValues>,
}

View file

@ -7,6 +7,7 @@ use base::print_tree::PrintTree;
use compositing_traits::display_list::AxesScrollSensitivity;
use euclid::default::{Point2D, Rect, Size2D};
use fxhash::FxHashSet;
use malloc_size_of_derive::MallocSizeOf;
use style::animation::AnimationSetKey;
use style::dom::OpaqueNode;
use webrender_api::units;
@ -16,6 +17,7 @@ use crate::display_list::StackingContext;
use crate::flow::CanvasBackground;
use crate::geom::{PhysicalPoint, PhysicalRect};
#[derive(MallocSizeOf)]
pub struct FragmentTree {
/// Fragments at the top-level of the tree.
///

View file

@ -3,6 +3,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use app_units::Au;
use malloc_size_of_derive::MallocSizeOf;
use style::logical_geometry::WritingMode;
use style::values::specified::align::AlignFlags;
@ -12,6 +13,7 @@ use crate::geom::{LogicalVec2, PhysicalRect, PhysicalVec};
/// A reference to a Fragment which is shared between `HoistedAbsolutelyPositionedBox`
/// and its placeholder `AbsoluteOrFixedPositionedFragment` in the original tree position.
/// This will be used later in order to paint this hoisted box in tree order.
#[derive(MallocSizeOf)]
pub(crate) struct HoistedSharedFragment {
pub fragment: Option<Fragment>,
/// The "static-position rect" of this absolutely positioned box. This is defined by the

View file

@ -4,6 +4,7 @@
use app_units::Au;
use base::print_tree::PrintTree;
use malloc_size_of_derive::MallocSizeOf;
use servo_arc::Arc as ServoArc;
use style::properties::ComputedValues;
@ -14,6 +15,7 @@ use crate::geom::PhysicalRect;
/// Can contain child fragments with relative coordinates, but does not contribute to painting
/// itself. [`PositioningFragment`]s may be completely anonymous, or just non-painting Fragments
/// generated by boxes.
#[derive(MallocSizeOf)]
pub(crate) struct PositioningFragment {
pub base: BaseFragment,
pub rect: PhysicalRect<Au>,
@ -22,6 +24,7 @@ pub(crate) struct PositioningFragment {
pub scrollable_overflow: PhysicalRect<Au>,
/// If this fragment was created with a style, the style of the fragment.
#[conditional_malloc_size_of]
pub style: Option<ServoArc<ComputedValues>>,
}