mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
Measure the stylist during memory reporting.
This commit is contained in:
parent
f648e12935
commit
d880efcab3
14 changed files with 356 additions and 28 deletions
|
@ -16,7 +16,8 @@ use media_queries::{Device, MediaList};
|
|||
use properties::ComputedValues;
|
||||
use servo_arc::Arc;
|
||||
use shared_lock::{Locked, StylesheetGuards, SharedRwLockReadGuard};
|
||||
use stylesheets::{MallocSizeOfFn, PerOrigin, StylesheetContents, StylesheetInDocument};
|
||||
use stylesheets::{MallocEnclosingSizeOfFn, MallocSizeOfFn, PerOrigin, StylesheetContents};
|
||||
use stylesheets::StylesheetInDocument;
|
||||
use stylist::{ExtraStyleData, Stylist};
|
||||
|
||||
/// Little wrapper to a Gecko style sheet.
|
||||
|
@ -187,10 +188,17 @@ impl PerDocumentStyleDataImpl {
|
|||
|
||||
/// Measures heap usage.
|
||||
pub fn malloc_add_size_of_children(&self, malloc_size_of: MallocSizeOfFn,
|
||||
malloc_enclosing_size_of: MallocEnclosingSizeOfFn,
|
||||
sizes: &mut ServoStyleSetSizes) {
|
||||
self.stylist.malloc_add_size_of_children(malloc_size_of, sizes);
|
||||
self.stylist.malloc_add_size_of_children(malloc_size_of, malloc_enclosing_size_of, sizes);
|
||||
|
||||
// We may measure more fields in the future if DMD says it's worth it.
|
||||
let data = &self.extra_style_data;
|
||||
sizes.mStylistOther +=
|
||||
data.user_agent.malloc_size_of_children(malloc_size_of, malloc_enclosing_size_of);
|
||||
sizes.mStylistOther +=
|
||||
data.user.malloc_size_of_children(malloc_size_of, malloc_enclosing_size_of);
|
||||
sizes.mStylistOther +=
|
||||
data.author.malloc_size_of_children(malloc_size_of, malloc_enclosing_size_of);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2063,6 +2063,8 @@ extern "C" {
|
|||
}
|
||||
extern "C" {
|
||||
pub fn Servo_StyleSet_AddSizeOfExcludingThis(malloc_size_of: MallocSizeOf,
|
||||
malloc_enclosing_size_of:
|
||||
MallocSizeOf,
|
||||
sizes:
|
||||
*mut ServoStyleSetSizes,
|
||||
set:
|
||||
|
|
|
@ -5565,11 +5565,16 @@ pub mod root {
|
|||
#[derive(Debug, Copy)]
|
||||
pub struct ServoStyleSetSizes {
|
||||
pub mStylistRuleTree: usize,
|
||||
pub mStylistPrecomputedPseudos: usize,
|
||||
pub mStylistElementAndPseudosMaps: usize,
|
||||
pub mStylistInvalidationMap: usize,
|
||||
pub mStylistRevalidationSelectors: usize,
|
||||
pub mStylistOther: usize,
|
||||
pub mOther: usize,
|
||||
}
|
||||
#[test]
|
||||
fn bindgen_test_layout_ServoStyleSetSizes() {
|
||||
assert_eq!(::std::mem::size_of::<ServoStyleSetSizes>() , 16usize ,
|
||||
assert_eq!(::std::mem::size_of::<ServoStyleSetSizes>() , 56usize ,
|
||||
concat ! (
|
||||
"Size of: " , stringify ! ( ServoStyleSetSizes ) ));
|
||||
assert_eq! (::std::mem::align_of::<ServoStyleSetSizes>() , 8usize
|
||||
|
@ -5583,9 +5588,44 @@ pub mod root {
|
|||
"Alignment of field: " , stringify ! (
|
||||
ServoStyleSetSizes ) , "::" , stringify ! (
|
||||
mStylistRuleTree ) ));
|
||||
assert_eq! (unsafe {
|
||||
& ( * ( 0 as * const ServoStyleSetSizes ) ) .
|
||||
mStylistPrecomputedPseudos as * const _ as usize } ,
|
||||
8usize , concat ! (
|
||||
"Alignment of field: " , stringify ! (
|
||||
ServoStyleSetSizes ) , "::" , stringify ! (
|
||||
mStylistPrecomputedPseudos ) ));
|
||||
assert_eq! (unsafe {
|
||||
& ( * ( 0 as * const ServoStyleSetSizes ) ) .
|
||||
mStylistElementAndPseudosMaps as * const _ as usize }
|
||||
, 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 ! (
|
||||
"Alignment of field: " , stringify ! (
|
||||
ServoStyleSetSizes ) , "::" , stringify ! (
|
||||
mStylistOther ) ));
|
||||
assert_eq! (unsafe {
|
||||
& ( * ( 0 as * const ServoStyleSetSizes ) ) . mOther
|
||||
as * const _ as usize } , 8usize , concat ! (
|
||||
as * const _ as usize } , 48usize , concat ! (
|
||||
"Alignment of field: " , stringify ! (
|
||||
ServoStyleSetSizes ) , "::" , stringify ! ( mOther )
|
||||
));
|
||||
|
|
|
@ -5453,11 +5453,16 @@ pub mod root {
|
|||
#[derive(Debug, Copy)]
|
||||
pub struct ServoStyleSetSizes {
|
||||
pub mStylistRuleTree: usize,
|
||||
pub mStylistPrecomputedPseudos: usize,
|
||||
pub mStylistElementAndPseudosMaps: usize,
|
||||
pub mStylistInvalidationMap: usize,
|
||||
pub mStylistRevalidationSelectors: usize,
|
||||
pub mStylistOther: usize,
|
||||
pub mOther: usize,
|
||||
}
|
||||
#[test]
|
||||
fn bindgen_test_layout_ServoStyleSetSizes() {
|
||||
assert_eq!(::std::mem::size_of::<ServoStyleSetSizes>() , 16usize ,
|
||||
assert_eq!(::std::mem::size_of::<ServoStyleSetSizes>() , 56usize ,
|
||||
concat ! (
|
||||
"Size of: " , stringify ! ( ServoStyleSetSizes ) ));
|
||||
assert_eq! (::std::mem::align_of::<ServoStyleSetSizes>() , 8usize
|
||||
|
@ -5471,9 +5476,44 @@ pub mod root {
|
|||
"Alignment of field: " , stringify ! (
|
||||
ServoStyleSetSizes ) , "::" , stringify ! (
|
||||
mStylistRuleTree ) ));
|
||||
assert_eq! (unsafe {
|
||||
& ( * ( 0 as * const ServoStyleSetSizes ) ) .
|
||||
mStylistPrecomputedPseudos as * const _ as usize } ,
|
||||
8usize , concat ! (
|
||||
"Alignment of field: " , stringify ! (
|
||||
ServoStyleSetSizes ) , "::" , stringify ! (
|
||||
mStylistPrecomputedPseudos ) ));
|
||||
assert_eq! (unsafe {
|
||||
& ( * ( 0 as * const ServoStyleSetSizes ) ) .
|
||||
mStylistElementAndPseudosMaps as * const _ as usize }
|
||||
, 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 ! (
|
||||
"Alignment of field: " , stringify ! (
|
||||
ServoStyleSetSizes ) , "::" , stringify ! (
|
||||
mStylistOther ) ));
|
||||
assert_eq! (unsafe {
|
||||
& ( * ( 0 as * const ServoStyleSetSizes ) ) . mOther
|
||||
as * const _ as usize } , 8usize , concat ! (
|
||||
as * const _ as usize } , 48usize , concat ! (
|
||||
"Alignment of field: " , stringify ! (
|
||||
ServoStyleSetSizes ) , "::" , stringify ! ( mOther )
|
||||
));
|
||||
|
|
|
@ -14,6 +14,8 @@ use selectors::parser::{Combinator, Component};
|
|||
use selectors::parser::{Selector, SelectorIter, SelectorMethods};
|
||||
use selectors::visitor::SelectorVisitor;
|
||||
use smallvec::SmallVec;
|
||||
#[cfg(feature = "gecko")]
|
||||
use stylesheets::{MallocEnclosingSizeOfFn, MallocSizeOfHash};
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
/// Gets the element state relevant to the given `:dir` pseudo-class selector.
|
||||
|
@ -287,6 +289,31 @@ impl InvalidationMap {
|
|||
index += 1; // Account for the combinator.
|
||||
}
|
||||
}
|
||||
|
||||
/// Measures heap usage.
|
||||
#[cfg(feature = "gecko")]
|
||||
pub fn malloc_size_of_children(&self, malloc_enclosing_size_of: MallocEnclosingSizeOfFn)
|
||||
-> usize {
|
||||
// Currently we measure the HashMap storage, but not things pointed to
|
||||
// by keys and values.
|
||||
let mut n = 0;
|
||||
|
||||
n += self.class_to_selector.malloc_shallow_size_of_hash(malloc_enclosing_size_of);
|
||||
for (_, val) in self.class_to_selector.iter() {
|
||||
n += val.malloc_size_of_children(malloc_enclosing_size_of);
|
||||
}
|
||||
|
||||
n += self.id_to_selector.malloc_shallow_size_of_hash(malloc_enclosing_size_of);
|
||||
for (_, val) in self.id_to_selector.iter() {
|
||||
n += val.malloc_size_of_children(malloc_enclosing_size_of);
|
||||
}
|
||||
|
||||
n += self.state_affecting_selectors.malloc_size_of_children(malloc_enclosing_size_of);
|
||||
|
||||
n += self.other_attribute_affecting_selectors.malloc_size_of_children(
|
||||
malloc_enclosing_size_of);
|
||||
n
|
||||
}
|
||||
}
|
||||
|
||||
/// A struct that collects invalidations for a given compound selector.
|
||||
|
|
|
@ -8,8 +8,8 @@ use context::QuirksMode;
|
|||
use fnv::FnvHashSet;
|
||||
use media_queries::Device;
|
||||
use shared_lock::SharedRwLockReadGuard;
|
||||
use stylesheets::{DocumentRule, ImportRule, MediaRule, SupportsRule};
|
||||
use stylesheets::{NestedRuleIterationCondition, Stylesheet};
|
||||
use stylesheets::{DocumentRule, ImportRule, MallocEnclosingSizeOfFn, MallocSizeOfHash, MediaRule};
|
||||
use stylesheets::{NestedRuleIterationCondition, Stylesheet, SupportsRule};
|
||||
|
||||
/// A key for a given media query result.
|
||||
///
|
||||
|
@ -88,6 +88,12 @@ impl EffectiveMediaQueryResults {
|
|||
// because of stylesheet reusing... shrug.
|
||||
self.set.insert(item.to_media_list_key());
|
||||
}
|
||||
|
||||
/// Measure heap usage.
|
||||
pub fn malloc_size_of_children(&self, malloc_enclosing_size_of: MallocEnclosingSizeOfFn)
|
||||
-> usize {
|
||||
self.set.malloc_shallow_size_of_hash(malloc_enclosing_size_of)
|
||||
}
|
||||
}
|
||||
|
||||
/// A filter that filters over effective rules, but allowing all potentially
|
||||
|
|
|
@ -796,7 +796,7 @@ impl RuleNode {
|
|||
}
|
||||
|
||||
fn malloc_size_of_including_self(&self, malloc_size_of: MallocSizeOfFn) -> usize {
|
||||
let mut n = unsafe { malloc_size_of(self as *const _ as *const _) };
|
||||
let mut n = unsafe { (malloc_size_of.0)(self as *const _ as *const _) };
|
||||
for child in self.iter_children() {
|
||||
n += unsafe { (*child.ptr()).malloc_size_of_including_self(malloc_size_of) };
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@ use selectors::matching::{matches_selector, MatchingContext, ElementSelectorFlag
|
|||
use selectors::parser::{Component, Combinator, SelectorIter};
|
||||
use smallvec::{SmallVec, VecLike};
|
||||
use std::hash::{BuildHasherDefault, Hash, Hasher};
|
||||
#[cfg(feature = "gecko")]
|
||||
use stylesheets::{MallocEnclosingSizeOfFn, MallocSizeOfHash};
|
||||
use stylist::Rule;
|
||||
|
||||
/// A hasher implementation that doesn't hash anything, because it expects its
|
||||
|
@ -144,6 +146,22 @@ impl<T: 'static> SelectorMap<T> {
|
|||
pub fn len(&self) -> usize {
|
||||
self.count
|
||||
}
|
||||
|
||||
/// Measures heap usage.
|
||||
#[cfg(feature = "gecko")]
|
||||
pub fn malloc_size_of_children(&self, malloc_enclosing_size_of: MallocEnclosingSizeOfFn)
|
||||
-> usize {
|
||||
// Currently we measure the HashMap storage, but not things pointed to
|
||||
// by keys and values.
|
||||
let mut n = 0;
|
||||
n += self.id_hash.malloc_shallow_size_of_hash(malloc_enclosing_size_of);
|
||||
n += self.class_hash.malloc_shallow_size_of_hash(malloc_enclosing_size_of);
|
||||
n += self.local_name_hash.malloc_shallow_size_of_hash(malloc_enclosing_size_of);
|
||||
|
||||
// We may measure other fields in the future if DMD says it's worth it.
|
||||
|
||||
n
|
||||
}
|
||||
}
|
||||
|
||||
impl SelectorMap<Rule> {
|
||||
|
@ -502,3 +520,14 @@ impl<V: 'static> MaybeCaseInsensitiveHashMap<Atom, V> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
impl<K, V> MallocSizeOfHash for MaybeCaseInsensitiveHashMap<K, V>
|
||||
where K: PrecomputedHash + Eq + Hash
|
||||
{
|
||||
fn malloc_shallow_size_of_hash(&self, malloc_enclosing_size_of: MallocEnclosingSizeOfFn)
|
||||
-> usize {
|
||||
self.0.malloc_shallow_size_of_hash(malloc_enclosing_size_of)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -188,4 +188,9 @@ impl<T> PerPseudoElementMap<T> {
|
|||
}
|
||||
Ok(self.entries[index].as_mut().unwrap())
|
||||
}
|
||||
|
||||
/// Get an iterator for the entries.
|
||||
pub fn iter(&self) -> ::std::slice::Iter<Option<T>> {
|
||||
self.entries.iter()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ use shared_lock::{DeepCloneParams, DeepCloneWithLock, SharedRwLock, SharedRwLock
|
|||
use std::fmt;
|
||||
use style_traits::{PARSING_MODE_DEFAULT, ToCss, ParseError, StyleParseError};
|
||||
use style_traits::PropertyDeclarationParseError;
|
||||
use stylesheets::{CssRuleType, StylesheetContents};
|
||||
use stylesheets::{CssRuleType, MallocSizeOfFn, MallocSizeOfVec, StylesheetContents};
|
||||
use stylesheets::rule_parser::{VendorPrefix, get_location_with_offset};
|
||||
use values::{KeyframesName, serialize_percentage};
|
||||
|
||||
|
@ -442,6 +442,14 @@ impl KeyframesAnimation {
|
|||
|
||||
result
|
||||
}
|
||||
|
||||
/// Measure heap usage.
|
||||
pub fn malloc_size_of_children(&self, malloc_size_of: MallocSizeOfFn) -> usize {
|
||||
let mut n = 0;
|
||||
n += self.steps.malloc_shallow_size_of_vec(malloc_size_of);
|
||||
n += self.properties_changed.malloc_shallow_size_of_vec(malloc_size_of);
|
||||
n
|
||||
}
|
||||
}
|
||||
|
||||
/// Parses a keyframes list, like:
|
||||
|
|
|
@ -9,16 +9,25 @@ use gecko_bindings::bindings::Gecko_HaveSeenPtr;
|
|||
#[cfg(feature = "gecko")]
|
||||
use gecko_bindings::structs::SeenPtrs;
|
||||
#[cfg(feature = "gecko")]
|
||||
use hash::HashMap;
|
||||
#[cfg(feature = "gecko")]
|
||||
use servo_arc::Arc;
|
||||
use shared_lock::SharedRwLockReadGuard;
|
||||
use std::collections::HashSet;
|
||||
use std::hash::{BuildHasher, Hash};
|
||||
use std::os::raw::c_void;
|
||||
|
||||
/// Like gecko_bindings::structs::MallocSizeOf, but without the Option<>
|
||||
/// wrapper.
|
||||
///
|
||||
/// Note that functions of this type should not be called via
|
||||
/// do_malloc_size_of(), rather than directly.
|
||||
pub type MallocSizeOfFn = unsafe extern "C" fn(ptr: *const c_void) -> usize;
|
||||
/// Note that functions of this type should be called via do_malloc_size_of(),
|
||||
/// rather than directly.
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct MallocSizeOfFn(pub unsafe extern "C" fn(ptr: *const c_void) -> usize);
|
||||
|
||||
/// Like MallocSizeOfFn, but can take an interior pointer.
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct MallocEnclosingSizeOfFn(pub unsafe extern "C" fn(ptr: *const c_void) -> usize);
|
||||
|
||||
/// Servo-side counterpart to mozilla::SizeOfState. The only difference is that
|
||||
/// this struct doesn't contain the SeenPtrs table, just a pointer to it.
|
||||
|
@ -30,7 +39,7 @@ pub struct SizeOfState {
|
|||
pub seen_ptrs: *mut SeenPtrs,
|
||||
}
|
||||
|
||||
/// Call malloc_size_of on ptr, first checking that the allocation isn't empty.
|
||||
/// Check if an allocation is empty.
|
||||
pub unsafe fn is_empty<T>(ptr: *const T) -> bool {
|
||||
return ptr as usize <= ::std::mem::align_of::<T>();
|
||||
}
|
||||
|
@ -40,10 +49,18 @@ pub unsafe fn do_malloc_size_of<T>(malloc_size_of: MallocSizeOfFn, ptr: *const T
|
|||
if is_empty(ptr) {
|
||||
0
|
||||
} else {
|
||||
malloc_size_of(ptr as *const c_void)
|
||||
(malloc_size_of.0)(ptr as *const c_void)
|
||||
}
|
||||
}
|
||||
|
||||
/// Call malloc_enclosing_size_of on ptr, which must not be empty.
|
||||
pub unsafe fn do_malloc_enclosing_size_of<T>(
|
||||
malloc_enclosing_size_of: MallocEnclosingSizeOfFn, ptr: *const T) -> usize
|
||||
{
|
||||
assert!(!is_empty(ptr));
|
||||
(malloc_enclosing_size_of.0)(ptr as *const c_void)
|
||||
}
|
||||
|
||||
/// Trait for measuring the size of heap data structures.
|
||||
pub trait MallocSizeOf {
|
||||
/// Measure the size of any heap-allocated structures that hang off this
|
||||
|
@ -92,7 +109,7 @@ impl<T: MallocSizeOfWithRepeats> MallocSizeOfWithRepeats for Arc<T> {
|
|||
let mut n = 0;
|
||||
let heap_ptr = self.heap_ptr();
|
||||
if unsafe { !is_empty(heap_ptr) && !Gecko_HaveSeenPtr(state.seen_ptrs, heap_ptr) } {
|
||||
n += unsafe { (state.malloc_size_of)(heap_ptr) };
|
||||
n += unsafe { (state.malloc_size_of.0)(heap_ptr) };
|
||||
n += (**self).malloc_size_of_children(state);
|
||||
}
|
||||
n
|
||||
|
@ -110,3 +127,78 @@ impl<T: MallocSizeOfWithGuard> MallocSizeOfWithGuard for Vec<T> {
|
|||
|n, elem| n + elem.malloc_size_of_children(guard, malloc_size_of))
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait for measuring the heap usage of a Box<T>.
|
||||
pub trait MallocSizeOfBox {
|
||||
/// Measure shallowly the size of the memory used by the T -- anything
|
||||
/// pointed to by the T must be measured separately.
|
||||
fn malloc_shallow_size_of_box(&self, malloc_size_of: MallocSizeOfFn) -> usize;
|
||||
}
|
||||
|
||||
impl<T> MallocSizeOfBox for Box<T> {
|
||||
fn malloc_shallow_size_of_box(&self, malloc_size_of: MallocSizeOfFn) -> usize {
|
||||
unsafe { do_malloc_size_of(malloc_size_of, &**self as *const T) }
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait for measuring the heap usage of a vector.
|
||||
pub trait MallocSizeOfVec {
|
||||
/// Measure shallowly the size of the memory used by the Vec's elements --
|
||||
/// anything pointed to by the elements must be measured separately, using
|
||||
/// iteration.
|
||||
fn malloc_shallow_size_of_vec(&self, malloc_size_of: MallocSizeOfFn) -> usize;
|
||||
}
|
||||
|
||||
impl<T> MallocSizeOfVec for Vec<T> {
|
||||
fn malloc_shallow_size_of_vec(&self, malloc_size_of: MallocSizeOfFn) -> usize {
|
||||
unsafe { do_malloc_size_of(malloc_size_of, self.as_ptr()) }
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait for measuring the heap usage of a hash table.
|
||||
pub trait MallocSizeOfHash {
|
||||
/// Measure shallowly the size of the memory used within a hash table --
|
||||
/// anything pointer to by the keys and values must be measured separately,
|
||||
/// using iteration.
|
||||
fn malloc_shallow_size_of_hash(&self, malloc_enclosing_size_of: MallocEnclosingSizeOfFn)
|
||||
-> usize;
|
||||
}
|
||||
|
||||
impl<T, S> MallocSizeOfHash for HashSet<T, S>
|
||||
where T: Eq + Hash,
|
||||
S: BuildHasher
|
||||
{
|
||||
fn malloc_shallow_size_of_hash(&self, malloc_enclosing_size_of: MallocEnclosingSizeOfFn)
|
||||
-> usize {
|
||||
// The first value from the iterator gives us an interior pointer.
|
||||
// malloc_enclosing_size_of() then gives us the storage size. This
|
||||
// assumes that the HashSet's contents (values and hashes) are all
|
||||
// stored in a single contiguous heap allocation.
|
||||
let mut n = 0;
|
||||
for v in self.iter() {
|
||||
n += unsafe { do_malloc_enclosing_size_of(malloc_enclosing_size_of, v as *const T) };
|
||||
break;
|
||||
}
|
||||
n
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
impl<K, V, S> MallocSizeOfHash for HashMap<K, V, S>
|
||||
where K: Eq + Hash,
|
||||
S: BuildHasher
|
||||
{
|
||||
fn malloc_shallow_size_of_hash(&self, malloc_enclosing_size_of: MallocEnclosingSizeOfFn)
|
||||
-> usize {
|
||||
// The first value from the iterator gives us an interior pointer.
|
||||
// malloc_enclosing_size_of() then gives us the storage size. This
|
||||
// assumes that the HashMap's contents (keys, values, and hashes) are
|
||||
// all stored in a single contiguous heap allocation.
|
||||
let mut n = 0;
|
||||
for v in self.values() {
|
||||
n += unsafe { do_malloc_enclosing_size_of(malloc_enclosing_size_of, v as *const V) };
|
||||
break;
|
||||
}
|
||||
n
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,7 +40,8 @@ pub use self::import_rule::ImportRule;
|
|||
pub use self::keyframes_rule::KeyframesRule;
|
||||
pub use self::loader::StylesheetLoader;
|
||||
pub use self::media_rule::MediaRule;
|
||||
pub use self::memory::{MallocSizeOf, MallocSizeOfFn, MallocSizeOfWithGuard};
|
||||
pub use self::memory::{MallocEnclosingSizeOfFn, MallocSizeOf, MallocSizeOfBox, MallocSizeOfFn};
|
||||
pub use self::memory::{MallocSizeOfHash, MallocSizeOfVec, MallocSizeOfWithGuard};
|
||||
#[cfg(feature = "gecko")]
|
||||
pub use self::memory::{MallocSizeOfWithRepeats, SizeOfState};
|
||||
pub use self::namespace_rule::NamespaceRule;
|
||||
|
|
|
@ -43,7 +43,9 @@ use stylesheet_set::{OriginValidity, SheetRebuildKind, StylesheetSet, Stylesheet
|
|||
use stylesheets::{CounterStyleRule, FontFaceRule, FontFeatureValuesRule};
|
||||
use stylesheets::{CssRule, Origin, OriginSet, PerOrigin, PerOriginIter};
|
||||
#[cfg(feature = "gecko")]
|
||||
use stylesheets::{MallocSizeOf, MallocSizeOfFn};
|
||||
use stylesheets::{MallocEnclosingSizeOfFn, MallocSizeOf, MallocSizeOfBox, MallocSizeOfFn};
|
||||
#[cfg(feature = "gecko")]
|
||||
use stylesheets::{MallocSizeOfHash, MallocSizeOfVec};
|
||||
use stylesheets::StyleRule;
|
||||
use stylesheets::StylesheetInDocument;
|
||||
use stylesheets::UserAgentStylesheets;
|
||||
|
@ -360,6 +362,25 @@ impl DocumentCascadeData {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Measures heap usage.
|
||||
#[cfg(feature = "gecko")]
|
||||
pub fn malloc_add_size_of_children(&self, malloc_size_of: MallocSizeOfFn,
|
||||
malloc_enclosing_size_of: MallocEnclosingSizeOfFn,
|
||||
sizes: &mut ServoStyleSetSizes) {
|
||||
self.per_origin.user_agent.malloc_add_size_of_children(malloc_size_of,
|
||||
malloc_enclosing_size_of, sizes);
|
||||
self.per_origin.user.malloc_add_size_of_children(malloc_size_of,
|
||||
malloc_enclosing_size_of, sizes);
|
||||
self.per_origin.author.malloc_add_size_of_children(malloc_size_of,
|
||||
malloc_enclosing_size_of, sizes);
|
||||
|
||||
for elem in self.precomputed_pseudo_element_decls.iter() {
|
||||
if let Some(ref elem) = *elem {
|
||||
sizes.mStylistPrecomputedPseudos += elem.malloc_shallow_size_of_vec(malloc_size_of);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A wrapper over a StylesheetSet that can be `Sync`, since it's only used and
|
||||
|
@ -1565,9 +1586,13 @@ impl Stylist {
|
|||
/// Measures heap usage.
|
||||
#[cfg(feature = "gecko")]
|
||||
pub fn malloc_add_size_of_children(&self, malloc_size_of: MallocSizeOfFn,
|
||||
malloc_enclosing_size_of: MallocEnclosingSizeOfFn,
|
||||
sizes: &mut ServoStyleSetSizes) {
|
||||
// XXX: need to measure other fields
|
||||
self.cascade_data.malloc_add_size_of_children(malloc_size_of, malloc_enclosing_size_of,
|
||||
sizes);
|
||||
sizes.mStylistRuleTree += self.rule_tree.malloc_size_of_children(malloc_size_of);
|
||||
|
||||
// We may measure other fields in the future if DMD says it's worth it.
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1620,6 +1645,17 @@ impl ExtraStyleData {
|
|||
self.counter_styles.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/// Measure heap usage.
|
||||
#[cfg(feature = "gecko")]
|
||||
pub fn malloc_size_of_children(&self, malloc_size_of: MallocSizeOfFn,
|
||||
malloc_enclosing_size_of: MallocEnclosingSizeOfFn) -> usize {
|
||||
let mut n = 0;
|
||||
n += self.font_faces.malloc_shallow_size_of_vec(malloc_size_of);
|
||||
n += self.font_feature_values.malloc_shallow_size_of_vec(malloc_size_of);
|
||||
n += self.counter_styles.malloc_shallow_size_of_hash(malloc_enclosing_size_of);
|
||||
n
|
||||
}
|
||||
}
|
||||
|
||||
/// SelectorMapEntry implementation for use in our revalidation selector map.
|
||||
|
@ -1913,6 +1949,38 @@ impl CascadeData {
|
|||
self.mapped_ids.clear();
|
||||
self.selectors_for_cache_revalidation.clear();
|
||||
}
|
||||
|
||||
/// Measures heap usage.
|
||||
#[cfg(feature = "gecko")]
|
||||
pub fn malloc_add_size_of_children(&self, malloc_size_of: MallocSizeOfFn,
|
||||
malloc_enclosing_size_of: MallocEnclosingSizeOfFn,
|
||||
sizes: &mut ServoStyleSetSizes) {
|
||||
sizes.mStylistElementAndPseudosMaps +=
|
||||
self.element_map.malloc_size_of_children(malloc_enclosing_size_of);
|
||||
|
||||
for elem in self.pseudos_map.iter() {
|
||||
if let Some(ref elem) = *elem {
|
||||
sizes.mStylistElementAndPseudosMaps +=
|
||||
elem.malloc_shallow_size_of_box(malloc_size_of) +
|
||||
elem.malloc_size_of_children(malloc_enclosing_size_of)
|
||||
}
|
||||
}
|
||||
|
||||
sizes.mStylistOther +=
|
||||
self.animations.malloc_shallow_size_of_hash(malloc_enclosing_size_of);
|
||||
for val in self.animations.values() {
|
||||
sizes.mStylistOther += val.malloc_size_of_children(malloc_size_of);
|
||||
}
|
||||
|
||||
sizes.mStylistInvalidationMap +=
|
||||
self.invalidation_map.malloc_size_of_children(malloc_enclosing_size_of);
|
||||
|
||||
sizes.mStylistRevalidationSelectors +=
|
||||
self.selectors_for_cache_revalidation.malloc_size_of_children(malloc_enclosing_size_of);
|
||||
|
||||
sizes.mStylistOther +=
|
||||
self.effective_media_query_results.malloc_size_of_children(malloc_enclosing_size_of);
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for CascadeData {
|
||||
|
|
|
@ -118,8 +118,9 @@ use style::shared_lock::{SharedRwLockReadGuard, StylesheetGuards, ToCssWithGuard
|
|||
use style::string_cache::Atom;
|
||||
use style::style_adjuster::StyleAdjuster;
|
||||
use style::stylesheets::{CssRule, CssRules, CssRuleType, CssRulesHelpers, DocumentRule};
|
||||
use style::stylesheets::{FontFeatureValuesRule, ImportRule, KeyframesRule, MallocSizeOfWithGuard};
|
||||
use style::stylesheets::{MediaRule, NamespaceRule, Origin, OriginSet, PageRule, SizeOfState, StyleRule};
|
||||
use style::stylesheets::{FontFeatureValuesRule, ImportRule, KeyframesRule, MallocEnclosingSizeOfFn};
|
||||
use style::stylesheets::{MallocSizeOfFn, MallocSizeOfWithGuard, MediaRule};
|
||||
use style::stylesheets::{NamespaceRule, Origin, OriginSet, PageRule, SizeOfState, StyleRule};
|
||||
use style::stylesheets::{StylesheetContents, SupportsRule};
|
||||
use style::stylesheets::StylesheetLoader as StyleStylesheetLoader;
|
||||
use style::stylesheets::keyframes_rule::{Keyframe, KeyframeSelector, KeyframesStepValue};
|
||||
|
@ -775,7 +776,7 @@ pub extern "C" fn Servo_Element_ClearData(element: RawGeckoElementBorrowed) {
|
|||
pub extern "C" fn Servo_Element_SizeOfExcludingThisAndCVs(malloc_size_of: GeckoMallocSizeOf,
|
||||
seen_ptrs: *mut SeenPtrs,
|
||||
element: RawGeckoElementBorrowed) -> usize {
|
||||
let malloc_size_of = malloc_size_of.unwrap();
|
||||
let malloc_size_of = MallocSizeOfFn(malloc_size_of.unwrap());
|
||||
let element = GeckoElement(element);
|
||||
let borrow = element.borrow_data();
|
||||
if let Some(data) = borrow {
|
||||
|
@ -1083,9 +1084,8 @@ pub extern "C" fn Servo_StyleSheet_SizeOfIncludingThis(
|
|||
) -> usize {
|
||||
let global_style_data = &*GLOBAL_STYLE_DATA;
|
||||
let guard = global_style_data.shared_lock.read();
|
||||
let malloc_size_of = malloc_size_of.unwrap();
|
||||
StylesheetContents::as_arc(&sheet)
|
||||
.malloc_size_of_children(&guard, malloc_size_of)
|
||||
let malloc_size_of = MallocSizeOfFn(malloc_size_of.unwrap());
|
||||
StylesheetContents::as_arc(&sheet).malloc_size_of_children(&guard, malloc_size_of)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
@ -3610,13 +3610,15 @@ pub extern "C" fn Servo_StyleSet_ResolveForDeclarations(
|
|||
#[no_mangle]
|
||||
pub extern "C" fn Servo_StyleSet_AddSizeOfExcludingThis(
|
||||
malloc_size_of: GeckoMallocSizeOf,
|
||||
malloc_enclosing_size_of: GeckoMallocSizeOf,
|
||||
sizes: *mut ServoStyleSetSizes,
|
||||
raw_data: RawServoStyleSetBorrowed
|
||||
) {
|
||||
let data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
|
||||
let malloc_size_of = malloc_size_of.unwrap();
|
||||
let malloc_size_of = MallocSizeOfFn(malloc_size_of.unwrap());
|
||||
let malloc_enclosing_size_of = MallocEnclosingSizeOfFn(malloc_enclosing_size_of.unwrap());
|
||||
let sizes = unsafe { sizes.as_mut() }.unwrap();
|
||||
data.malloc_add_size_of_children(malloc_size_of, sizes);
|
||||
data.malloc_add_size_of_children(malloc_size_of, malloc_enclosing_size_of, sizes);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue