Measure the UA cache.

ServoStyleSetSizes now has two uses, one for the Stylist, and one for the UA
cache, and so the patch removes 'Stylist' from the field names.

Example output from about:memory:

> +----1,359,608 B (00.55%) -- layout
> |    +----756,488 B (00.31%) -- style-sheet-cache [2]
> |    +----393,968 B (00.16%) -- servo-ua-cache
> |    |    +--234,496 B (00.10%) -- element-and-pseudos-maps
> |    |    +---59,648 B (00.02%) -- revalidation-selectors
> |    |    +---58,320 B (00.02%) -- invalidation-map
> |    |    +---30,752 B (00.01%) -- other
> |    |    +---10,752 B (00.00%) -- precomputed-pseudos
This commit is contained in:
Nicholas Nethercote 2017-09-20 08:50:21 +10:00
parent c6381c66a0
commit f7023a120e
7 changed files with 114 additions and 84 deletions

View file

@ -36,6 +36,7 @@ const SOURCE_ORDER_MASK: u32 = (1 << SOURCE_ORDER_BITS) - 1;
const SOURCE_ORDER_MAX: u32 = SOURCE_ORDER_MASK; const SOURCE_ORDER_MAX: u32 = SOURCE_ORDER_MASK;
/// Stores the source order of a block and the cascade level it belongs to. /// Stores the source order of a block and the cascade level it belongs to.
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[derive(Clone, Copy, Eq, PartialEq)] #[derive(Clone, Copy, Eq, PartialEq)]
struct SourceOrderAndCascadeLevel(u32); struct SourceOrderAndCascadeLevel(u32);
@ -75,10 +76,12 @@ impl Debug for SourceOrderAndCascadeLevel {
/// ///
/// This represents the declarations in a given declaration block for a given /// This represents the declarations in a given declaration block for a given
/// importance. /// importance.
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub struct ApplicableDeclarationBlock { pub struct ApplicableDeclarationBlock {
/// The style source, either a style rule, or a property declaration block. /// The style source, either a style rule, or a property declaration block.
#[cfg_attr(feature = "gecko", ignore_malloc_size_of = "contains Arcs")]
#[cfg_attr(feature = "servo", ignore_heap_size_of = "Arc")] #[cfg_attr(feature = "servo", ignore_heap_size_of = "Arc")]
pub source: StyleSource, pub source: StyleSource,
/// The source order of the block, and the cascade level it belongs to. /// The source order of the block, and the cascade level it belongs to.

View file

@ -2089,6 +2089,11 @@ extern "C" {
set: set:
RawServoStyleSetBorrowed); RawServoStyleSetBorrowed);
} }
extern "C" {
pub fn Servo_UACache_AddSizeOf(malloc_size_of: MallocSizeOf,
malloc_enclosing_size_of: MallocSizeOf,
sizes: *mut ServoStyleSetSizes);
}
extern "C" { extern "C" {
pub fn Servo_StyleContext_AddRef(ctx: ServoStyleContextBorrowed); pub fn Servo_StyleContext_AddRef(ctx: ServoStyleContextBorrowed);
} }

View file

@ -4947,17 +4947,16 @@ pub mod root {
#[repr(C)] #[repr(C)]
#[derive(Debug, Copy)] #[derive(Debug, Copy)]
pub struct ServoStyleSetSizes { pub struct ServoStyleSetSizes {
pub mStylistRuleTree: usize, pub mRuleTree: usize,
pub mStylistPrecomputedPseudos: usize, pub mPrecomputedPseudos: usize,
pub mStylistElementAndPseudosMaps: usize, pub mElementAndPseudosMaps: usize,
pub mStylistInvalidationMap: usize, pub mInvalidationMap: usize,
pub mStylistRevalidationSelectors: usize, pub mRevalidationSelectors: usize,
pub mStylistOther: usize,
pub mOther: usize, pub mOther: usize,
} }
#[test] #[test]
fn bindgen_test_layout_ServoStyleSetSizes() { fn bindgen_test_layout_ServoStyleSetSizes() {
assert_eq!(::std::mem::size_of::<ServoStyleSetSizes>() , 56usize , assert_eq!(::std::mem::size_of::<ServoStyleSetSizes>() , 48usize ,
concat ! ( concat ! (
"Size of: " , stringify ! ( ServoStyleSetSizes ) )); "Size of: " , stringify ! ( ServoStyleSetSizes ) ));
assert_eq! (::std::mem::align_of::<ServoStyleSetSizes>() , 8usize assert_eq! (::std::mem::align_of::<ServoStyleSetSizes>() , 8usize
@ -4966,49 +4965,42 @@ pub mod root {
)); ));
assert_eq! (unsafe { assert_eq! (unsafe {
& ( * ( 0 as * const ServoStyleSetSizes ) ) . & ( * ( 0 as * const ServoStyleSetSizes ) ) .
mStylistRuleTree as * const _ as usize } , 0usize , mRuleTree as * const _ as usize } , 0usize , concat !
(
"Alignment of field: " , stringify ! (
ServoStyleSetSizes ) , "::" , stringify ! ( mRuleTree
) ));
assert_eq! (unsafe {
& ( * ( 0 as * const ServoStyleSetSizes ) ) .
mPrecomputedPseudos as * const _ as usize } , 8usize ,
concat ! ( concat ! (
"Alignment of field: " , stringify ! ( "Alignment of field: " , stringify ! (
ServoStyleSetSizes ) , "::" , stringify ! ( ServoStyleSetSizes ) , "::" , stringify ! (
mStylistRuleTree ) )); mPrecomputedPseudos ) ));
assert_eq! (unsafe { assert_eq! (unsafe {
& ( * ( 0 as * const ServoStyleSetSizes ) ) . & ( * ( 0 as * const ServoStyleSetSizes ) ) .
mStylistPrecomputedPseudos as * const _ as usize } , mElementAndPseudosMaps as * const _ as usize } ,
8usize , concat ! ( 16usize , concat ! (
"Alignment of field: " , stringify ! ( "Alignment of field: " , stringify ! (
ServoStyleSetSizes ) , "::" , stringify ! ( ServoStyleSetSizes ) , "::" , stringify ! (
mStylistPrecomputedPseudos ) )); mElementAndPseudosMaps ) ));
assert_eq! (unsafe { assert_eq! (unsafe {
& ( * ( 0 as * const ServoStyleSetSizes ) ) . & ( * ( 0 as * const ServoStyleSetSizes ) ) .
mStylistElementAndPseudosMaps as * const _ as usize } mInvalidationMap as * const _ as usize } , 24usize ,
, 16usize , concat ! (
"Alignment of field: " , stringify ! (
ServoStyleSetSizes ) , "::" , stringify ! (
mStylistElementAndPseudosMaps ) ));
assert_eq! (unsafe {
& ( * ( 0 as * const ServoStyleSetSizes ) ) .
mStylistInvalidationMap as * const _ as usize } ,
24usize , concat ! (
"Alignment of field: " , stringify ! (
ServoStyleSetSizes ) , "::" , stringify ! (
mStylistInvalidationMap ) ));
assert_eq! (unsafe {
& ( * ( 0 as * const ServoStyleSetSizes ) ) .
mStylistRevalidationSelectors as * const _ as usize }
, 32usize , concat ! (
"Alignment of field: " , stringify ! (
ServoStyleSetSizes ) , "::" , stringify ! (
mStylistRevalidationSelectors ) ));
assert_eq! (unsafe {
& ( * ( 0 as * const ServoStyleSetSizes ) ) .
mStylistOther as * const _ as usize } , 40usize ,
concat ! ( concat ! (
"Alignment of field: " , stringify ! ( "Alignment of field: " , stringify ! (
ServoStyleSetSizes ) , "::" , stringify ! ( ServoStyleSetSizes ) , "::" , stringify ! (
mStylistOther ) )); mInvalidationMap ) ));
assert_eq! (unsafe {
& ( * ( 0 as * const ServoStyleSetSizes ) ) .
mRevalidationSelectors as * const _ as usize } ,
32usize , concat ! (
"Alignment of field: " , stringify ! (
ServoStyleSetSizes ) , "::" , stringify ! (
mRevalidationSelectors ) ));
assert_eq! (unsafe { assert_eq! (unsafe {
& ( * ( 0 as * const ServoStyleSetSizes ) ) . mOther & ( * ( 0 as * const ServoStyleSetSizes ) ) . mOther
as * const _ as usize } , 48usize , concat ! ( as * const _ as usize } , 40usize , concat ! (
"Alignment of field: " , stringify ! ( "Alignment of field: " , stringify ! (
ServoStyleSetSizes ) , "::" , stringify ! ( mOther ) ServoStyleSetSizes ) , "::" , stringify ! ( mOther )
)); ));

View file

@ -4867,17 +4867,16 @@ pub mod root {
#[repr(C)] #[repr(C)]
#[derive(Debug, Copy)] #[derive(Debug, Copy)]
pub struct ServoStyleSetSizes { pub struct ServoStyleSetSizes {
pub mStylistRuleTree: usize, pub mRuleTree: usize,
pub mStylistPrecomputedPseudos: usize, pub mPrecomputedPseudos: usize,
pub mStylistElementAndPseudosMaps: usize, pub mElementAndPseudosMaps: usize,
pub mStylistInvalidationMap: usize, pub mInvalidationMap: usize,
pub mStylistRevalidationSelectors: usize, pub mRevalidationSelectors: usize,
pub mStylistOther: usize,
pub mOther: usize, pub mOther: usize,
} }
#[test] #[test]
fn bindgen_test_layout_ServoStyleSetSizes() { fn bindgen_test_layout_ServoStyleSetSizes() {
assert_eq!(::std::mem::size_of::<ServoStyleSetSizes>() , 56usize , assert_eq!(::std::mem::size_of::<ServoStyleSetSizes>() , 48usize ,
concat ! ( concat ! (
"Size of: " , stringify ! ( ServoStyleSetSizes ) )); "Size of: " , stringify ! ( ServoStyleSetSizes ) ));
assert_eq! (::std::mem::align_of::<ServoStyleSetSizes>() , 8usize assert_eq! (::std::mem::align_of::<ServoStyleSetSizes>() , 8usize
@ -4886,49 +4885,42 @@ pub mod root {
)); ));
assert_eq! (unsafe { assert_eq! (unsafe {
& ( * ( 0 as * const ServoStyleSetSizes ) ) . & ( * ( 0 as * const ServoStyleSetSizes ) ) .
mStylistRuleTree as * const _ as usize } , 0usize , mRuleTree as * const _ as usize } , 0usize , concat !
(
"Alignment of field: " , stringify ! (
ServoStyleSetSizes ) , "::" , stringify ! ( mRuleTree
) ));
assert_eq! (unsafe {
& ( * ( 0 as * const ServoStyleSetSizes ) ) .
mPrecomputedPseudos as * const _ as usize } , 8usize ,
concat ! ( concat ! (
"Alignment of field: " , stringify ! ( "Alignment of field: " , stringify ! (
ServoStyleSetSizes ) , "::" , stringify ! ( ServoStyleSetSizes ) , "::" , stringify ! (
mStylistRuleTree ) )); mPrecomputedPseudos ) ));
assert_eq! (unsafe { assert_eq! (unsafe {
& ( * ( 0 as * const ServoStyleSetSizes ) ) . & ( * ( 0 as * const ServoStyleSetSizes ) ) .
mStylistPrecomputedPseudos as * const _ as usize } , mElementAndPseudosMaps as * const _ as usize } ,
8usize , concat ! ( 16usize , concat ! (
"Alignment of field: " , stringify ! ( "Alignment of field: " , stringify ! (
ServoStyleSetSizes ) , "::" , stringify ! ( ServoStyleSetSizes ) , "::" , stringify ! (
mStylistPrecomputedPseudos ) )); mElementAndPseudosMaps ) ));
assert_eq! (unsafe { assert_eq! (unsafe {
& ( * ( 0 as * const ServoStyleSetSizes ) ) . & ( * ( 0 as * const ServoStyleSetSizes ) ) .
mStylistElementAndPseudosMaps as * const _ as usize } mInvalidationMap as * const _ as usize } , 24usize ,
, 16usize , concat ! (
"Alignment of field: " , stringify ! (
ServoStyleSetSizes ) , "::" , stringify ! (
mStylistElementAndPseudosMaps ) ));
assert_eq! (unsafe {
& ( * ( 0 as * const ServoStyleSetSizes ) ) .
mStylistInvalidationMap as * const _ as usize } ,
24usize , concat ! (
"Alignment of field: " , stringify ! (
ServoStyleSetSizes ) , "::" , stringify ! (
mStylistInvalidationMap ) ));
assert_eq! (unsafe {
& ( * ( 0 as * const ServoStyleSetSizes ) ) .
mStylistRevalidationSelectors as * const _ as usize }
, 32usize , concat ! (
"Alignment of field: " , stringify ! (
ServoStyleSetSizes ) , "::" , stringify ! (
mStylistRevalidationSelectors ) ));
assert_eq! (unsafe {
& ( * ( 0 as * const ServoStyleSetSizes ) ) .
mStylistOther as * const _ as usize } , 40usize ,
concat ! ( concat ! (
"Alignment of field: " , stringify ! ( "Alignment of field: " , stringify ! (
ServoStyleSetSizes ) , "::" , stringify ! ( ServoStyleSetSizes ) , "::" , stringify ! (
mStylistOther ) )); mInvalidationMap ) ));
assert_eq! (unsafe {
& ( * ( 0 as * const ServoStyleSetSizes ) ) .
mRevalidationSelectors as * const _ as usize } ,
32usize , concat ! (
"Alignment of field: " , stringify ! (
ServoStyleSetSizes ) , "::" , stringify ! (
mRevalidationSelectors ) ));
assert_eq! (unsafe { assert_eq! (unsafe {
& ( * ( 0 as * const ServoStyleSetSizes ) ) . mOther & ( * ( 0 as * const ServoStyleSetSizes ) ) . mOther
as * const _ as usize } , 48usize , concat ! ( as * const _ as usize } , 40usize , concat ! (
"Alignment of field: " , stringify ! ( "Alignment of field: " , stringify ! (
ServoStyleSetSizes ) , "::" , stringify ! ( mOther ) ServoStyleSetSizes ) , "::" , stringify ! ( mOther )
)); ));

View file

@ -112,6 +112,7 @@ pub trait ElementExt: Element<Impl=SelectorImpl> + Debug {
} }
/// A per-functional-pseudo map, from a given pseudo to a `T`. /// A per-functional-pseudo map, from a given pseudo to a `T`.
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct PerPseudoElementMap<T> { pub struct PerPseudoElementMap<T> {
entries: [Option<T>; SIMPLE_PSEUDO_COUNT], entries: [Option<T>; SIMPLE_PSEUDO_COUNT],

View file

@ -17,6 +17,8 @@ use invalidation::element::invalidation_map::InvalidationMap;
use invalidation::media_queries::{EffectiveMediaQueryResults, ToMediaListKey}; use invalidation::media_queries::{EffectiveMediaQueryResults, ToMediaListKey};
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
use malloc_size_of::{MallocShallowSizeOf, MallocSizeOf, MallocSizeOfOps}; use malloc_size_of::{MallocShallowSizeOf, MallocSizeOf, MallocSizeOfOps};
#[cfg(feature = "gecko")]
use malloc_size_of::MallocUnconditionalShallowSizeOf;
use media_queries::Device; use media_queries::Device;
use properties::{self, CascadeFlags, ComputedValues}; use properties::{self, CascadeFlags, ComputedValues};
use properties::{AnimationRules, PropertyDeclarationBlock}; use properties::{AnimationRules, PropertyDeclarationBlock};
@ -133,6 +135,23 @@ impl UserAgentCascadeDataCache {
fn clear(&mut self) { fn clear(&mut self) {
self.entries.clear(); self.entries.clear();
} }
#[cfg(feature = "gecko")]
pub fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
sizes.mOther += self.entries.shallow_size_of(ops);
for arc in self.entries.iter() {
// These are primary Arc references that can be measured
// unconditionally.
sizes.mOther += arc.unconditional_shallow_size_of(ops);
arc.add_size_of(ops, sizes);
}
}
}
/// Measure heap usage of UA_CASCADE_DATA_CACHE.
#[cfg(feature = "gecko")]
pub fn add_size_of_ua_cache(ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
UA_CASCADE_DATA_CACHE.lock().unwrap().add_size_of(ops, sizes);
} }
type PrecomputedPseudoElementDeclarations = type PrecomputedPseudoElementDeclarations =
@ -151,6 +170,14 @@ struct UserAgentCascadeData {
precomputed_pseudo_element_decls: PrecomputedPseudoElementDeclarations, precomputed_pseudo_element_decls: PrecomputedPseudoElementDeclarations,
} }
impl UserAgentCascadeData {
#[cfg(feature = "gecko")]
fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
self.cascade_data.add_size_of_children(ops, sizes);
sizes.mPrecomputedPseudos += self.precomputed_pseudo_element_decls.size_of(ops);
}
}
/// All the computed information for a stylesheet. /// All the computed information for a stylesheet.
#[derive(Default)] #[derive(Default)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
@ -304,9 +331,6 @@ impl DocumentCascadeData {
pub fn add_size_of_children(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) { pub fn add_size_of_children(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
self.user.add_size_of_children(ops, sizes); self.user.add_size_of_children(ops, sizes);
self.author.add_size_of_children(ops, sizes); self.author.add_size_of_children(ops, sizes);
// FIXME(emilio): UA_CASCADE_DATA_CACHE is shared, we should do whatever
// we do for RuleProcessorCache in Gecko.
} }
} }
@ -1500,7 +1524,7 @@ impl Stylist {
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
pub fn add_size_of_children(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) { pub fn add_size_of_children(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
self.cascade_data.add_size_of_children(ops, sizes); self.cascade_data.add_size_of_children(ops, sizes);
sizes.mStylistRuleTree += self.rule_tree.size_of(ops); sizes.mRuleTree += self.rule_tree.size_of(ops);
// We may measure other fields in the future if DMD says it's worth it. // We may measure other fields in the future if DMD says it's worth it.
} }
@ -2194,22 +2218,22 @@ impl CascadeData {
/// Measures heap usage. /// Measures heap usage.
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
pub fn add_size_of_children(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) { pub fn add_size_of_children(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
sizes.mStylistElementAndPseudosMaps += self.element_map.size_of(ops); sizes.mElementAndPseudosMaps += self.element_map.size_of(ops);
for elem in self.pseudos_map.iter() { for elem in self.pseudos_map.iter() {
if let Some(ref elem) = *elem { if let Some(ref elem) = *elem {
sizes.mStylistElementAndPseudosMaps += <Box<_> as MallocSizeOf>::size_of(elem, ops); sizes.mElementAndPseudosMaps += <Box<_> as MallocSizeOf>::size_of(elem, ops);
} }
} }
sizes.mStylistOther += self.animations.size_of(ops); sizes.mOther += self.animations.size_of(ops);
sizes.mStylistInvalidationMap += self.invalidation_map.size_of(ops); sizes.mInvalidationMap += self.invalidation_map.size_of(ops);
sizes.mStylistRevalidationSelectors += self.selectors_for_cache_revalidation.size_of(ops); sizes.mRevalidationSelectors += self.selectors_for_cache_revalidation.size_of(ops);
sizes.mStylistOther += self.effective_media_query_results.size_of(ops); sizes.mOther += self.effective_media_query_results.size_of(ops);
sizes.mStylistOther += self.extra_data.size_of(ops); sizes.mOther += self.extra_data.size_of(ops);
} }
} }

View file

@ -131,7 +131,7 @@ use style::stylesheets::{StylesheetContents, SupportsRule};
use style::stylesheets::StylesheetLoader as StyleStylesheetLoader; use style::stylesheets::StylesheetLoader as StyleStylesheetLoader;
use style::stylesheets::keyframes_rule::{Keyframe, KeyframeSelector, KeyframesStepValue}; use style::stylesheets::keyframes_rule::{Keyframe, KeyframeSelector, KeyframesStepValue};
use style::stylesheets::supports_rule::parse_condition_or_declaration; use style::stylesheets::supports_rule::parse_condition_or_declaration;
use style::stylist::{RuleInclusion, Stylist}; use style::stylist::{add_size_of_ua_cache, RuleInclusion, Stylist};
use style::thread_state; use style::thread_state;
use style::timer::Timer; use style::timer::Timer;
use style::traversal::DomTraversal; use style::traversal::DomTraversal;
@ -3768,6 +3768,19 @@ pub extern "C" fn Servo_StyleSet_AddSizeOfExcludingThis(
data.add_size_of_children(&mut ops, sizes); data.add_size_of_children(&mut ops, sizes);
} }
#[no_mangle]
pub extern "C" fn Servo_UACache_AddSizeOf(
malloc_size_of: GeckoMallocSizeOf,
malloc_enclosing_size_of: GeckoMallocSizeOf,
sizes: *mut ServoStyleSetSizes
) {
let mut ops = MallocSizeOfOps::new(malloc_size_of.unwrap(),
malloc_enclosing_size_of.unwrap(),
None);
let sizes = unsafe { sizes.as_mut() }.unwrap();
add_size_of_ua_cache(&mut ops, sizes);
}
#[no_mangle] #[no_mangle]
pub extern "C" fn Servo_StyleSet_MightHaveAttributeDependency( pub extern "C" fn Servo_StyleSet_MightHaveAttributeDependency(
raw_data: RawServoStyleSetBorrowed, raw_data: RawServoStyleSetBorrowed,