Bug 1394729 - Measure memory usage of Stylo's Rule Tree. r=heycam. draft
authorNicholas Nethercote <nnethercote@mozilla.com>
Wed, 30 Aug 2017 18:21:26 +1000
changeset 656419 f2d1441705139e6674d355792255302fcd89f748
parent 656346 04b6be50a2526c7a26a63715f441c47e1aa1f9be
child 729145 95cd65df37613924a11d9232a03fd7d88b0ef218
push id77218
push usernnethercote@mozilla.com
push dateThu, 31 Aug 2017 06:52:51 +0000
reviewersheycam
bugs1394729
milestone57.0a1
Bug 1394729 - Measure memory usage of Stylo's Rule Tree. r=heycam. This patch splits up the existing "layout/style-sets" measurement into "layout/gecko-style-sets", or "layout/servo-style-sets/stylist/rule-tree" and "layout/servo-style-sets/other". (Additional things will be measured under "layout/servo-style-sets/" later, such as cascade data.) This requires introducing a new type, ServoStyleSetSizes, for transferring the multiple measurements from Rust code to C++ code. MozReview-Commit-ID: FbmzpsjBpgI
dom/base/nsWindowMemoryReporter.cpp
dom/base/nsWindowSizes.h
layout/base/PresShell.cpp
layout/style/ServoBindingList.h
layout/style/ServoBindings.toml
layout/style/ServoStyleSet.cpp
layout/style/ServoStyleSet.h
layout/style/ServoTypes.h
layout/style/nsStyleSet.cpp
layout/style/nsStyleSet.h
--- a/dom/base/nsWindowMemoryReporter.cpp
+++ b/dom/base/nsWindowMemoryReporter.cpp
@@ -359,19 +359,33 @@ CollectWindowReports(nsGlobalWindow *aWi
   aWindowTotalSizes->mStyleSheetsSize += windowSizes.mStyleSheetsSize;
 
   REPORT_SIZE("/layout/pres-shell", windowSizes.mLayoutPresShellSize,
               "Memory used by layout's PresShell, along with any structures "
               "allocated in its arena and not measured elsewhere, "
               "within a window.");
   aWindowTotalSizes->mLayoutPresShellSize += windowSizes.mLayoutPresShellSize;
 
-  REPORT_SIZE("/layout/style-sets", windowSizes.mLayoutStyleSetsSize,
-              "Memory used by style sets within a window.");
-  aWindowTotalSizes->mLayoutStyleSetsSize += windowSizes.mLayoutStyleSetsSize;
+  REPORT_SIZE("/layout/gecko-style-sets", windowSizes.mLayoutGeckoStyleSets,
+              "Memory used by Gecko style sets within a window.");
+  aWindowTotalSizes->mLayoutGeckoStyleSets += windowSizes.mLayoutGeckoStyleSets;
+
+  REPORT_SIZE("/layout/servo-style-sets/stylist/rule-tree",
+              windowSizes.mLayoutServoStyleSetsStylistRuleTree,
+              "Memory used by rule trees within Servo style sets within a "
+              "window.");
+  aWindowTotalSizes->mLayoutServoStyleSetsStylistRuleTree +=
+    windowSizes.mLayoutServoStyleSetsStylistRuleTree;
+
+  REPORT_SIZE("/layout/servo-style-sets/other",
+              windowSizes.mLayoutServoStyleSetsOther,
+              "Memory used by other parts of Servo style sets within a "
+              "window.");
+  aWindowTotalSizes->mLayoutServoStyleSetsOther +=
+    windowSizes.mLayoutServoStyleSetsOther;
 
   REPORT_SIZE("/layout/text-runs", windowSizes.mLayoutTextRunsSize,
               "Memory used for text-runs (glyph layout) in the PresShell's "
               "frame tree, within a window.");
   aWindowTotalSizes->mLayoutTextRunsSize += windowSizes.mLayoutTextRunsSize;
 
   REPORT_SIZE("/layout/pres-contexts", windowSizes.mLayoutPresContextSize,
               "Memory used for the PresContext in the PresShell's frame "
@@ -633,19 +647,25 @@ nsWindowMemoryReporter::CollectReports(n
 
   REPORT("window-objects/style-sheets", windowTotalSizes.mStyleSheetsSize,
          "This is the sum of all windows' 'style-sheets' numbers.");
 
   REPORT("window-objects/layout/pres-shell",
          windowTotalSizes.mLayoutPresShellSize,
          "This is the sum of all windows' 'layout/arenas' numbers.");
 
-  REPORT("window-objects/layout/style-sets",
-         windowTotalSizes.mLayoutStyleSetsSize,
-         "This is the sum of all windows' 'layout/style-sets' numbers.");
+  REPORT("window-objects/layout/gecko-style-sets",
+         windowTotalSizes.mLayoutGeckoStyleSets,
+         "This is the sum of all windows' 'layout/gecko-style-sets' numbers.");
+
+  REPORT("window-objects/layout/servo-style-sets",
+         windowTotalSizes.mLayoutServoStyleSetsStylistRuleTree +
+         windowTotalSizes.mLayoutServoStyleSetsOther,
+         "This is the sum of all windows' 'layout/servo-style-sets/' numbers.");
+
 
   REPORT("window-objects/layout/text-runs", windowTotalSizes.mLayoutTextRunsSize,
          "This is the sum of all windows' 'layout/text-runs' numbers.");
 
   REPORT("window-objects/layout/pres-contexts",
          windowTotalSizes.mLayoutPresContextSize,
          "This is the sum of all windows' 'layout/pres-contexts' numbers.");
 
--- a/dom/base/nsWindowSizes.h
+++ b/dom/base/nsWindowSizes.h
@@ -170,17 +170,19 @@ class nsWindowSizes
   macro(DOM,   mDOMCDATANodesSize) \
   macro(DOM,   mDOMCommentNodesSize) \
   macro(DOM,   mDOMEventTargetsSize) \
   macro(DOM,   mDOMPerformanceUserEntries) \
   macro(DOM,   mDOMPerformanceResourceEntries) \
   macro(DOM,   mDOMOtherSize) \
   macro(Style, mStyleSheetsSize) \
   macro(Other, mLayoutPresShellSize) \
-  macro(Style, mLayoutStyleSetsSize) \
+  macro(Style, mLayoutGeckoStyleSets) \
+  macro(Style, mLayoutServoStyleSetsStylistRuleTree) \
+  macro(Style, mLayoutServoStyleSetsOther) \
   macro(Other, mLayoutTextRunsSize) \
   macro(Other, mLayoutPresContextSize) \
   macro(Other, mLayoutFramePropertiesSize) \
   macro(Style, mLayoutComputedValuesDom) \
   macro(Style, mLayoutComputedValuesNonDom) \
   macro(Style, mLayoutComputedValuesVisited) \
   macro(Other, mPropertyTablesSize) \
 
--- a/layout/base/PresShell.cpp
+++ b/layout/base/PresShell.cpp
@@ -11014,19 +11014,19 @@ PresShell::AddSizeOfIncludingThis(nsWind
   if (mCaret) {
     aSizes.mLayoutPresShellSize += mCaret->SizeOfIncludingThis(mallocSizeOf);
   }
   aSizes.mLayoutPresShellSize +=
     mApproximatelyVisibleFrames.ShallowSizeOfExcludingThis(mallocSizeOf) +
     mFramesToDirty.ShallowSizeOfExcludingThis(mallocSizeOf);
 
   if (nsStyleSet* styleSet = StyleSet()->GetAsGecko()) {
-    aSizes.mLayoutStyleSetsSize += styleSet->SizeOfIncludingThis(mallocSizeOf);
+    styleSet->AddSizeOfIncludingThis(aSizes);
   } else if (ServoStyleSet* styleSet = StyleSet()->GetAsServo()) {
-    aSizes.mLayoutStyleSetsSize += styleSet->SizeOfIncludingThis(mallocSizeOf);
+    styleSet->AddSizeOfIncludingThis(aSizes);
   } else {
     MOZ_CRASH();
   }
 
   aSizes.mLayoutTextRunsSize += SizeOfTextRuns(mallocSizeOf);
 
   aSizes.mLayoutPresContextSize +=
     mPresContext->SizeOfIncludingThis(mallocSizeOf);
--- a/layout/style/ServoBindingList.h
+++ b/layout/style/ServoBindingList.h
@@ -107,16 +107,20 @@ SERVO_BINDING_FUNC(Servo_StyleSet_GetCou
 SERVO_BINDING_FUNC(Servo_StyleSet_BuildFontFeatureValueSet, bool,
                    RawServoStyleSetBorrowed set,
                    gfxFontFeatureValueSet* list)
 SERVO_BINDING_FUNC(Servo_StyleSet_ResolveForDeclarations,
                    ServoStyleContextStrong,
                    RawServoStyleSetBorrowed set,
                    ServoStyleContextBorrowedOrNull parent_style,
                    RawServoDeclarationBlockBorrowed declarations)
+SERVO_BINDING_FUNC(Servo_StyleSet_AddSizeOfExcludingThis, void,
+                   mozilla::MallocSizeOf malloc_size_of,
+                   mozilla::ServoStyleSetSizes* sizes,
+                   RawServoStyleSetBorrowed set)
 SERVO_BINDING_FUNC(Servo_StyleContext_AddRef, void, ServoStyleContextBorrowed ctx);
 SERVO_BINDING_FUNC(Servo_StyleContext_Release, void, ServoStyleContextBorrowed ctx);
 
 SERVO_BINDING_FUNC(Servo_StyleSet_MightHaveAttributeDependency, bool,
                    RawServoStyleSetBorrowed set,
                    RawGeckoElementBorrowed element,
                    nsIAtom* local_name)
 SERVO_BINDING_FUNC(Servo_StyleSet_HasStateDependency, bool,
--- a/layout/style/ServoBindings.toml
+++ b/layout/style/ServoBindings.toml
@@ -125,16 +125,17 @@ whitelist-types = [
     "mozilla::AnimationPropertySegment",
     "mozilla::ComputedTiming",
     "mozilla::ComputedTimingFunction",
     "mozilla::ComputedTimingFunction::BeforeFlag",
     "mozilla::SeenPtrs",
     "mozilla::ServoElementSnapshot.*",
     "mozilla::ServoStyleContext",
     "mozilla::ServoStyleSheetInner",
+    "mozilla::ServoStyleSetSizes",
     "mozilla::CSSPseudoClassType",
     "mozilla::css::ErrorReporter",
     "mozilla::css::LoaderReusableStyleSheets",
     "mozilla::css::SheetParsingMode",
     "mozilla::css::URLMatchingFunction",
     "mozilla::dom::IterationCompositeOperation",
     "mozilla::dom::StyleChildrenIterator",
     "mozilla::HalfCorner",
@@ -412,16 +413,17 @@ structs-types = [
     "GeckoFontMetrics",
     "IterationCompositeOperation",
     "Keyframe",
     "PropertyValuePair",
     "SeenPtrs",
     "ServoBundledURI",
     "ServoElementSnapshot",
     "ServoElementSnapshotTable",
+    "ServoStyleSetSizes",
     "SheetParsingMode",
     "StyleBasicShape",
     "StyleBasicShapeType",
     "StyleShapeSource",
     "StyleTransition",
     "gfxFontFeatureValueSet",
     "nsBorderColors",
     "nsCSSCounterStyleRule",
--- a/layout/style/ServoStyleSet.cpp
+++ b/layout/style/ServoStyleSet.cpp
@@ -177,35 +177,49 @@ ServoStyleSet::MediumFeaturesChanged(boo
 
   if (viewportUnitsUsed && aViewportChanged) {
     return eRestyle_ForceDescendants;
   }
 
   return nsRestyleHint(0);
 }
 
-size_t
-ServoStyleSet::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
+MOZ_DEFINE_MALLOC_SIZE_OF(ServoStyleSetMallocSizeOf)
+
+void
+ServoStyleSet::AddSizeOfIncludingThis(nsWindowSizes& aSizes) const
 {
-  size_t n = aMallocSizeOf(this);
+  MallocSizeOf mallocSizeOf = aSizes.mState.mMallocSizeOf;
+
+  aSizes.mLayoutServoStyleSetsOther += mallocSizeOf(this);
+
+  if (mRawSet) {
+    aSizes.mLayoutServoStyleSetsOther += mallocSizeOf(mRawSet.get());
+    ServoStyleSetSizes sizes;
+    // Measure mRawSet. We use ServoStyleSetMallocSizeOf rather than
+    // aMallocSizeOf to distinguish in DMD's output the memory measured within
+    // Servo code.
+    Servo_StyleSet_AddSizeOfExcludingThis(ServoStyleSetMallocSizeOf, &sizes,
+                                          mRawSet.get());
+    aSizes.mLayoutServoStyleSetsStylistRuleTree += sizes.mStylistRuleTree;
+    aSizes.mLayoutServoStyleSetsOther += sizes.mOther;
+  }
 
   if (mStyleRuleMap) {
-    n += mStyleRuleMap->SizeOfIncludingThis(aMallocSizeOf);
+    aSizes.mLayoutServoStyleSetsOther +=
+      mStyleRuleMap->SizeOfIncludingThis(aSizes.mState.mMallocSizeOf);
   }
 
   // Measurement of the following members may be added later if DMD finds it is
   // worthwhile:
-  // - mRawSet
   // - mSheets
   // - mNonInheritingStyleContexts
   //
   // The following members are not measured:
   // - mPresContext, because it a non-owning pointer
-
-  return n;
 }
 
 bool
 ServoStyleSet::GetAuthorStyleDisabled() const
 {
   return mAuthorStyleDisabled;
 }
 
--- a/layout/style/ServoStyleSet.h
+++ b/layout/style/ServoStyleSet.h
@@ -116,17 +116,17 @@ public:
   {
     return StylistNeedsUpdate();
   }
 
   nsRestyleHint MediumFeaturesChanged(bool aViewportChanged);
 
   void InvalidateStyleForCSSRuleChanges();
 
-  size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
+  void AddSizeOfIncludingThis(nsWindowSizes& aSizes) const;
   const RawServoStyleSet* RawSet() const {
     return mRawSet.get();
   }
 
   bool GetAuthorStyleDisabled() const;
   nsresult SetAuthorStyleDisabled(bool aStyleDisabled);
 
   void BeginUpdate();
--- a/layout/style/ServoTypes.h
+++ b/layout/style/ServoTypes.h
@@ -196,16 +196,28 @@ struct ServoComputedValueFlags {
 };
 
 #define STYLE_STRUCT(name_, checkdata_cb_) struct Gecko##name_;
 #define STYLE_STRUCT_LIST_IGNORE_VARIABLES
 #include "nsStyleStructList.h"
 #undef STYLE_STRUCT
 #undef STYLE_STRUCT_LIST_IGNORE_VARIABLES
 
+class ServoStyleSetSizes
+{
+public:
+  size_t mStylistRuleTree;
+  size_t mOther;
+
+  ServoStyleSetSizes()
+    : mStylistRuleTree(0)
+    , mOther(0)
+  {}
+};
+
 } // namespace mozilla
 
 class ServoComputedData;
 
 struct ServoComputedDataForgotten
 {
   // Make sure you manually mem::forget the backing ServoComputedData
   // after calling this
--- a/layout/style/nsStyleSet.cpp
+++ b/layout/style/nsStyleSet.cpp
@@ -245,45 +245,47 @@ nsStyleSet::~nsStyleSet()
   }
   rp = static_cast<nsCSSRuleProcessor*>(mRuleProcessors[SheetType::User].get());
   if (rp) {
     MOZ_ASSERT(rp->IsShared());
     rp->ReleaseStyleSetRef();
   }
 }
 
-size_t
-nsStyleSet::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
+void
+nsStyleSet::AddSizeOfIncludingThis(nsWindowSizes& aSizes) const
 {
-  size_t n = aMallocSizeOf(this);
+  MallocSizeOf mallocSizeOf = aSizes.mState.mMallocSizeOf;
+
+  size_t n = mallocSizeOf(this);
 
   for (SheetType type : MakeEnumeratedRange(SheetType::Count)) {
     if (mRuleProcessors[type]) {
       bool shared = false;
       if (type == SheetType::Agent || type == SheetType::User) {
         // The only two origins we consider caching rule processors for.
         nsCSSRuleProcessor* rp =
           static_cast<nsCSSRuleProcessor*>(mRuleProcessors[type].get());
         shared = rp->IsShared();
       }
       if (!shared) {
-        n += mRuleProcessors[type]->SizeOfIncludingThis(aMallocSizeOf);
+        n += mRuleProcessors[type]->SizeOfIncludingThis(mallocSizeOf);
       }
     }
     // We don't own the sheets (either the nsLayoutStyleSheetCache singleton
     // or our document owns them).
-    n += mSheets[type].ShallowSizeOfExcludingThis(aMallocSizeOf);
+    n += mSheets[type].ShallowSizeOfExcludingThis(mallocSizeOf);
   }
 
   for (uint32_t i = 0; i < mScopedDocSheetRuleProcessors.Length(); i++) {
-    n += mScopedDocSheetRuleProcessors[i]->SizeOfIncludingThis(aMallocSizeOf);
+    n += mScopedDocSheetRuleProcessors[i]->SizeOfIncludingThis(mallocSizeOf);
   }
-  n += mScopedDocSheetRuleProcessors.ShallowSizeOfExcludingThis(aMallocSizeOf);
+  n += mScopedDocSheetRuleProcessors.ShallowSizeOfExcludingThis(mallocSizeOf);
 
-  return n;
+  aSizes.mLayoutGeckoStyleSets += n;
 }
 
 void
 nsStyleSet::Init(nsPresContext* aPresContext, nsBindingManager* aBindingManager)
 {
   mFirstLineRule = new nsEmptyStyleRule;
   mFirstLetterRule = new nsEmptyStyleRule;
   mPlaceholderRule = new nsEmptyStyleRule;
--- a/layout/style/nsStyleSet.h
+++ b/layout/style/nsStyleSet.h
@@ -101,17 +101,17 @@ public:
 // style set.
 
 class nsStyleSet final
 {
  public:
   nsStyleSet();
   ~nsStyleSet();
 
-  size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
+  void AddSizeOfIncludingThis(nsWindowSizes& aSizes) const;
 
   void Init(nsPresContext* aPresContext, nsBindingManager* aBindingManager);
 
   nsRuleNode* GetRuleTree() { return mRuleTree; }
 
   // get a style context for a non-pseudo frame.
   already_AddRefed<mozilla::GeckoStyleContext>
   ResolveStyleFor(mozilla::dom::Element* aElement,