From 61877b7316dd6ebaaf08a54f791ec8c56c2b1b83 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 7 Sep 2017 13:24:40 +1000 Subject: [PATCH] Measure selectors. This patch adds measurement of Selectors within StyleRule. This requires exposing the pointer within ThinArc. The patch also adds measurement of the several CssRule variants, in order to measure nested CssRules (and PropertyDeclarationBlocks) within them: DocumentRule, MediaRule, PageRule, SupportsRule. --- components/selectors/parser.rs | 6 +++- components/servo_arc/lib.rs | 6 ++++ components/style/stylesheets/document_rule.rs | 11 +++++- components/style/stylesheets/media_rule.rs | 11 +++++- components/style/stylesheets/mod.rs | 35 ++++++++++++++----- components/style/stylesheets/page_rule.rs | 10 ++++++ components/style/stylesheets/style_rule.rs | 20 +++++++++-- components/style/stylesheets/supports_rule.rs | 11 +++++- 8 files changed, 95 insertions(+), 15 deletions(-) diff --git a/components/selectors/parser.rs b/components/selectors/parser.rs index 45ff70df416..c17e8af1a71 100644 --- a/components/selectors/parser.rs +++ b/components/selectors/parser.rs @@ -423,7 +423,6 @@ impl Selector { )) } - /// Returns an iterator over this selector in matching order (right-to-left). /// When a combinator is reached, the iterator will return None, and /// next_sequence() may be called to continue to the next sequence. @@ -494,6 +493,11 @@ impl Selector { pub fn len(&self) -> usize { self.0.slice.len() } + + /// Returns the address on the heap of the ThinArc for memory reporting. + pub fn thin_arc_heap_ptr(&self) -> *const ::std::os::raw::c_void { + self.0.heap_ptr() + } } #[derive(Clone)] diff --git a/components/servo_arc/lib.rs b/components/servo_arc/lib.rs index 2d0dbd8236c..5cac8c9b9bb 100644 --- a/components/servo_arc/lib.rs +++ b/components/servo_arc/lib.rs @@ -676,6 +676,12 @@ impl ThinArc { // Forward the result. result } + + /// Returns the address on the heap of the ThinArc itself -- not the T + /// within it -- for memory reporting. + pub fn heap_ptr(&self) -> *const c_void { + self.ptr as *const ArcInner as *const c_void + } } impl Deref for ThinArc { diff --git a/components/style/stylesheets/document_rule.rs b/components/style/stylesheets/document_rule.rs index 5465a4b9759..327994ad3ae 100644 --- a/components/style/stylesheets/document_rule.rs +++ b/components/style/stylesheets/document_rule.rs @@ -13,7 +13,7 @@ use servo_arc::Arc; use shared_lock::{DeepCloneParams, DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard}; use std::fmt; use style_traits::{ToCss, ParseError, StyleParseError}; -use stylesheets::CssRules; +use stylesheets::{CssRules, MallocSizeOfFn, MallocSizeOfWithGuard}; use values::specified::url::SpecifiedUrl; #[derive(Debug)] @@ -27,6 +27,15 @@ pub struct DocumentRule { pub source_location: SourceLocation, } +impl DocumentRule { + /// Measure heap usage. + pub fn malloc_size_of_children(&self, guard: &SharedRwLockReadGuard, + malloc_size_of: MallocSizeOfFn) -> usize { + // Measurement of other fields may be added later. + self.rules.read_with(guard).malloc_size_of_children(guard, malloc_size_of) + } +} + impl ToCssWithGuard for DocumentRule { fn to_css(&self, guard: &SharedRwLockReadGuard, dest: &mut W) -> fmt::Result where W: fmt::Write { diff --git a/components/style/stylesheets/media_rule.rs b/components/style/stylesheets/media_rule.rs index 4eb68999113..f336dc12d89 100644 --- a/components/style/stylesheets/media_rule.rs +++ b/components/style/stylesheets/media_rule.rs @@ -12,7 +12,7 @@ use servo_arc::Arc; use shared_lock::{DeepCloneParams, DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard}; use std::fmt; use style_traits::ToCss; -use stylesheets::CssRules; +use stylesheets::{CssRules, MallocSizeOfFn, MallocSizeOfWithGuard}; /// An [`@media`][media] urle. /// @@ -27,6 +27,15 @@ pub struct MediaRule { pub source_location: SourceLocation, } +impl MediaRule { + /// Measure heap usage. + pub fn malloc_size_of_children(&self, guard: &SharedRwLockReadGuard, + malloc_size_of: MallocSizeOfFn) -> usize { + // Measurement of other fields may be added later. + self.rules.read_with(guard).malloc_size_of_children(guard, malloc_size_of) + } +} + impl ToCssWithGuard for MediaRule { // Serialization of MediaRule is not specced. // https://drafts.csswg.org/cssom/#serialize-a-css-rule CSSMediaRule diff --git a/components/style/stylesheets/mod.rs b/components/style/stylesheets/mod.rs index 78c4e6d2dfb..87ee2b413c0 100644 --- a/components/style/stylesheets/mod.rs +++ b/components/style/stylesheets/mod.rs @@ -116,21 +116,40 @@ impl MallocSizeOfWithGuard for CssRule { malloc_size_of: MallocSizeOfFn ) -> usize { match *self { + // Not all fields are currently fully measured. Extra measurement + // may be added later. + + CssRule::Namespace(_) => 0, + + // We don't need to measure ImportRule::stylesheet because we measure + // it on the C++ side in the child list of the ServoStyleSheet. + CssRule::Import(_) => 0, + CssRule::Style(ref lock) => { lock.read_with(guard).malloc_size_of_children(guard, malloc_size_of) }, - // Measurement of these fields may be added later. - CssRule::Import(_) => 0, - CssRule::Media(_) => 0, + + CssRule::Media(ref lock) => { + lock.read_with(guard).malloc_size_of_children(guard, malloc_size_of) + }, + CssRule::FontFace(_) => 0, CssRule::FontFeatureValues(_) => 0, CssRule::CounterStyle(_) => 0, - CssRule::Keyframes(_) => 0, - CssRule::Namespace(_) => 0, CssRule::Viewport(_) => 0, - CssRule::Supports(_) => 0, - CssRule::Page(_) => 0, - CssRule::Document(_) => 0, + CssRule::Keyframes(_) => 0, + + CssRule::Supports(ref lock) => { + lock.read_with(guard).malloc_size_of_children(guard, malloc_size_of) + }, + + CssRule::Page(ref lock) => { + lock.read_with(guard).malloc_size_of_children(guard, malloc_size_of) + }, + + CssRule::Document(ref lock) => { + lock.read_with(guard).malloc_size_of_children(guard, malloc_size_of) + }, } } } diff --git a/components/style/stylesheets/page_rule.rs b/components/style/stylesheets/page_rule.rs index f47c1316a50..c334df44042 100644 --- a/components/style/stylesheets/page_rule.rs +++ b/components/style/stylesheets/page_rule.rs @@ -12,6 +12,7 @@ use servo_arc::Arc; use shared_lock::{DeepCloneParams, DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard}; use std::fmt; use style_traits::ToCss; +use stylesheets::{MallocSizeOf, MallocSizeOfFn}; /// A [`@page`][page] rule. /// @@ -30,6 +31,15 @@ pub struct PageRule { pub source_location: SourceLocation, } +impl PageRule { + /// Measure heap usage. + pub fn malloc_size_of_children(&self, guard: &SharedRwLockReadGuard, + malloc_size_of: MallocSizeOfFn) -> usize { + // Measurement of other fields may be added later. + self.block.read_with(guard).malloc_size_of_children(malloc_size_of) + } +} + impl ToCssWithGuard for PageRule { /// Serialization of PageRule is not specced, adapted from steps for /// StyleRule. diff --git a/components/style/stylesheets/style_rule.rs b/components/style/stylesheets/style_rule.rs index a66ad7eb5e8..72dbbed0548 100644 --- a/components/style/stylesheets/style_rule.rs +++ b/components/style/stylesheets/style_rule.rs @@ -12,7 +12,7 @@ use servo_arc::Arc; use shared_lock::{DeepCloneParams, DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard}; use std::fmt; use style_traits::ToCss; -use stylesheets::{MallocSizeOf, MallocSizeOfFn, MallocSizeOfWithGuard}; +use stylesheets::{MallocSizeOf, MallocSizeOfFn, MallocSizeOfVec, MallocSizeOfWithGuard}; /// A style rule, with selectors and declarations. #[derive(Debug)] @@ -47,8 +47,22 @@ impl MallocSizeOfWithGuard for StyleRule { guard: &SharedRwLockReadGuard, malloc_size_of: MallocSizeOfFn ) -> usize { - // Measurement of other fields may be added later. - self.block.read_with(guard).malloc_size_of_children(malloc_size_of) + let mut n = 0; + + // We may add measurement of things hanging off the embedded Components + // later. + n += self.selectors.0.malloc_shallow_size_of_vec(malloc_size_of); + for selector in self.selectors.0.iter() { + // It's safe to measure this ThinArc directly because it's the + // "primary" reference. (The secondary references are on the + // Stylist.) + let ptr = selector.thin_arc_heap_ptr(); + n += unsafe { (malloc_size_of.0)(ptr) }; + } + + n += self.block.read_with(guard).malloc_size_of_children(malloc_size_of); + + n } } diff --git a/components/style/stylesheets/supports_rule.rs b/components/style/stylesheets/supports_rule.rs index 96c7e7b6cc3..ee5e7516642 100644 --- a/components/style/stylesheets/supports_rule.rs +++ b/components/style/stylesheets/supports_rule.rs @@ -13,7 +13,7 @@ use servo_arc::Arc; use shared_lock::{DeepCloneParams, DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard}; use std::fmt; use style_traits::{ToCss, ParseError, StyleParseError}; -use stylesheets::{CssRuleType, CssRules}; +use stylesheets::{CssRuleType, CssRules, MallocSizeOfFn, MallocSizeOfWithGuard}; /// An [`@supports`][supports] rule. /// @@ -30,6 +30,15 @@ pub struct SupportsRule { pub source_location: SourceLocation, } +impl SupportsRule { + /// Measure heap usage. + pub fn malloc_size_of_children(&self, guard: &SharedRwLockReadGuard, + malloc_size_of: MallocSizeOfFn) -> usize { + // Measurement of other fields may be added later. + self.rules.read_with(guard).malloc_size_of_children(guard, malloc_size_of) + } +} + impl ToCssWithGuard for SupportsRule { fn to_css(&self, guard: &SharedRwLockReadGuard, dest: &mut W) -> fmt::Result where W: fmt::Write {