Bug 1400078 - Measure the UA cache. r=emilio. draft
authorNicholas Nethercote <nnethercote@mozilla.com>
Tue, 19 Sep 2017 09:25:00 +1000
changeset 667359 0a6ba538c92d0be55481cdbbe026f080a25489db
parent 667303 a0eb21bf55e1c1ae0ba311e6f2273da05c712799
child 732360 8145d5d5d1e7dca2105e96c71d7f1347adb4ee21
push id80685
push usernnethercote@mozilla.com
push dateWed, 20 Sep 2017 01:02:56 +0000
reviewersemilio
bugs1400078
milestone57.0a1
Bug 1400078 - Measure the UA cache. r=emilio. 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 MozReview-Commit-ID: 8oxuJO0ojp
dom/base/nsWindowMemoryReporter.cpp
dom/base/nsWindowSizes.h
layout/style/ServoBindingList.h
layout/style/ServoBindings.cpp
layout/style/ServoStyleSet.cpp
layout/style/ServoStyleSet.h
layout/style/ServoTypes.h
--- a/dom/base/nsWindowMemoryReporter.cpp
+++ b/dom/base/nsWindowMemoryReporter.cpp
@@ -371,23 +371,16 @@ CollectWindowReports(nsGlobalWindow *aWi
 
   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/stylist/precomputed-pseudos",
-              windowSizes.mLayoutServoStyleSetsStylistPrecomputedPseudos,
-              "Memory used by precomputed pseudo-element declarations within "
-              "Servo style sets within a window.");
-  aWindowTotalSizes->mLayoutServoStyleSetsStylistPrecomputedPseudos +=
-    windowSizes.mLayoutServoStyleSetsStylistPrecomputedPseudos;
-
   REPORT_SIZE("/layout/servo-style-sets/stylist/element-and-pseudos-maps",
               windowSizes.mLayoutServoStyleSetsStylistElementAndPseudosMaps,
               "Memory used by element and pseudos maps within Servo style "
               "sets within a window.");
   aWindowTotalSizes->mLayoutServoStyleSetsStylistElementAndPseudosMaps +=
     windowSizes.mLayoutServoStyleSetsStylistElementAndPseudosMaps;
 
   REPORT_SIZE("/layout/servo-style-sets/stylist/invalidation-map",
@@ -708,17 +701,16 @@ nsWindowMemoryReporter::CollectReports(n
          "This is the sum of all windows' 'layout/arenas' 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.mLayoutServoStyleSetsStylistPrecomputedPseudos +
          windowTotalSizes.mLayoutServoStyleSetsStylistElementAndPseudosMaps +
          windowTotalSizes.mLayoutServoStyleSetsStylistInvalidationMap +
          windowTotalSizes.mLayoutServoStyleSetsStylistRevalidationSelectors +
          windowTotalSizes.mLayoutServoStyleSetsStylistOther +
          windowTotalSizes.mLayoutServoStyleSetsOther,
          "This is the sum of all windows' 'layout/servo-style-sets/' numbers.");
 
   REPORT("window-objects/layout/servo-element-data-objects",
--- a/dom/base/nsWindowSizes.h
+++ b/dom/base/nsWindowSizes.h
@@ -172,17 +172,16 @@ class nsWindowSizes
   macro(DOM,   mDOMEventTargetsSize) \
   macro(DOM,   mDOMPerformanceUserEntries) \
   macro(DOM,   mDOMPerformanceResourceEntries) \
   macro(DOM,   mDOMOtherSize) \
   macro(Style, mLayoutStyleSheetsSize) \
   macro(Other, mLayoutPresShellSize) \
   macro(Style, mLayoutGeckoStyleSets) \
   macro(Style, mLayoutServoStyleSetsStylistRuleTree) \
-  macro(Style, mLayoutServoStyleSetsStylistPrecomputedPseudos) \
   macro(Style, mLayoutServoStyleSetsStylistElementAndPseudosMaps) \
   macro(Style, mLayoutServoStyleSetsStylistInvalidationMap) \
   macro(Style, mLayoutServoStyleSetsStylistRevalidationSelectors) \
   macro(Style, mLayoutServoStyleSetsStylistOther) \
   macro(Style, mLayoutServoStyleSetsOther) \
   macro(Style, mLayoutServoElementDataObjects) \
   macro(Other, mLayoutTextRunsSize) \
   macro(Other, mLayoutPresContextSize) \
--- a/layout/style/ServoBindingList.h
+++ b/layout/style/ServoBindingList.h
@@ -124,16 +124,20 @@ SERVO_BINDING_FUNC(Servo_StyleSet_Resolv
                    RawServoStyleSetBorrowed set,
                    ServoStyleContextBorrowedOrNull parent_style,
                    RawServoDeclarationBlockBorrowed declarations)
 SERVO_BINDING_FUNC(Servo_StyleSet_AddSizeOfExcludingThis, void,
                    mozilla::MallocSizeOf malloc_size_of,
                    mozilla::MallocSizeOf malloc_enclosing_size_of,
                    mozilla::ServoStyleSetSizes* sizes,
                    RawServoStyleSetBorrowed set)
+SERVO_BINDING_FUNC(Servo_UACache_AddSizeOf, void,
+                   mozilla::MallocSizeOf malloc_size_of,
+                   mozilla::MallocSizeOf malloc_enclosing_size_of,
+                   mozilla::ServoStyleSetSizes* sizes)
 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.cpp
+++ b/layout/style/ServoBindings.cpp
@@ -2437,34 +2437,41 @@ Gecko_XBLBinding_GetRawServoStyleSet(Raw
 }
 
 bool
 Gecko_XBLBinding_InheritsStyle(RawGeckoXBLBindingBorrowed aXBLBinding)
 {
   return aXBLBinding->InheritsStyle();
 }
 
+static StaticRefPtr<UACacheReporter> gUACacheReporter;
+
 void
 InitializeServo()
 {
   URLExtraData::InitDummy();
   Servo_Initialize(URLExtraData::Dummy());
 
+  gUACacheReporter = new UACacheReporter();
+  RegisterWeakMemoryReporter(gUACacheReporter);
+
   sServoFontMetricsLock = new Mutex("Gecko_GetFontMetrics");
   sServoWidgetLock = new Mutex("Servo::WidgetLock");
   sServoLangFontPrefsLock = new RWLock("nsPresContext::GetDefaultFont");
 }
 
 void
 ShutdownServo()
 {
   MOZ_ASSERT(sServoFontMetricsLock);
   MOZ_ASSERT(sServoWidgetLock);
   MOZ_ASSERT(sServoLangFontPrefsLock);
 
+  UnregisterWeakMemoryReporter(gUACacheReporter);
+
   delete sServoFontMetricsLock;
   delete sServoWidgetLock;
   delete sServoLangFontPrefsLock;
   Servo_Shutdown();
 }
 
 namespace mozilla {
 
--- a/layout/style/ServoStyleSet.cpp
+++ b/layout/style/ServoStyleSet.cpp
@@ -5,26 +5,27 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/ServoStyleSet.h"
 
 #include "gfxPlatformFontList.h"
 #include "mozilla/AutoRestyleTimelineMarker.h"
 #include "mozilla/DocumentStyleRootIterator.h"
 #include "mozilla/LookAndFeel.h"
+#include "mozilla/RestyleManagerInlines.h"
 #include "mozilla/ServoBindings.h"
 #include "mozilla/ServoRestyleManager.h"
 #include "mozilla/ServoStyleRuleMap.h"
+#include "mozilla/ServoTypes.h"
 #include "mozilla/css/Loader.h"
 #include "mozilla/dom/AnonymousContent.h"
 #include "mozilla/dom/ChildIterator.h"
 #include "mozilla/dom/FontFaceSet.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/ElementInlines.h"
-#include "mozilla/RestyleManagerInlines.h"
 #include "nsCSSAnonBoxes.h"
 #include "nsCSSFrameConstructor.h"
 #include "nsCSSPseudoElements.h"
 #include "nsCSSRuleProcessor.h"
 #include "nsDeviceContext.h"
 #include "nsHTMLStyleSheet.h"
 #include "nsIAnonymousContentCreator.h"
 #include "nsIDocumentInlines.h"
@@ -262,30 +263,29 @@ ServoStyleSet::AddSizeOfIncludingThis(ns
     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,
                                           ServoStyleSetMallocEnclosingSizeOf,
                                           &sizes, mRawSet.get());
-    aSizes.mLayoutServoStyleSetsStylistRuleTree +=
-      sizes.mStylistRuleTree;
-    aSizes.mLayoutServoStyleSetsStylistPrecomputedPseudos +=
-      sizes.mStylistPrecomputedPseudos;
+
+    // The StyleSet does not contain precomputed pseudos; they are in the UA
+    // cache.
+    MOZ_RELEASE_ASSERT(sizes.mPrecomputedPseudos == 0);
+
+    aSizes.mLayoutServoStyleSetsStylistRuleTree += sizes.mRuleTree;
     aSizes.mLayoutServoStyleSetsStylistElementAndPseudosMaps +=
-      sizes.mStylistElementAndPseudosMaps;
+      sizes.mElementAndPseudosMaps;
     aSizes.mLayoutServoStyleSetsStylistInvalidationMap +=
-      sizes.mStylistInvalidationMap;
+      sizes.mInvalidationMap;
     aSizes.mLayoutServoStyleSetsStylistRevalidationSelectors +=
-      sizes.mStylistRevalidationSelectors;
-    aSizes.mLayoutServoStyleSetsStylistOther +=
-      sizes.mStylistOther;
-    aSizes.mLayoutServoStyleSetsOther +=
-      sizes.mOther;
+      sizes.mRevalidationSelectors;
+    aSizes.mLayoutServoStyleSetsStylistOther += sizes.mOther;
   }
 
   if (mStyleRuleMap) {
     aSizes.mLayoutServoStyleSetsOther +=
       mStyleRuleMap->SizeOfIncludingThis(aSizes.mState.mMallocSizeOf);
   }
 
   // Measurement of the following members may be added later if DMD finds it is
@@ -1528,8 +1528,57 @@ ServoStyleSet::ReparentStyleContext(Serv
                                     ServoStyleContext* aNewParentIgnoringFirstLine,
                                     ServoStyleContext* aNewLayoutParent,
                                     Element* aElement)
 {
   return Servo_ReparentStyle(aStyleContext, aNewParent,
                              aNewParentIgnoringFirstLine, aNewLayoutParent,
                              aElement, mRawSet.get()).Consume();
 }
+
+NS_IMPL_ISUPPORTS(UACacheReporter, nsIMemoryReporter)
+
+MOZ_DEFINE_MALLOC_SIZE_OF(ServoUACacheMallocSizeOf)
+MOZ_DEFINE_MALLOC_ENCLOSING_SIZE_OF(ServoUACacheMallocEnclosingSizeOf)
+
+NS_IMETHODIMP
+UACacheReporter::CollectReports(nsIHandleReportCallback* aHandleReport,
+                                nsISupports* aData, bool aAnonymize)
+{
+  ServoStyleSetSizes sizes;
+  Servo_UACache_AddSizeOf(ServoUACacheMallocSizeOf,
+                          ServoUACacheMallocEnclosingSizeOf, &sizes);
+
+#define REPORT(_path, _amount, _desc) \
+  do { \
+    size_t __amount = _amount;  /* evaluate _amount only once */ \
+    if (__amount > 0) { \
+      MOZ_COLLECT_REPORT(_path, KIND_HEAP, UNITS_BYTES, __amount, _desc); \
+    } \
+  } while (0)
+
+  // The UA cache does not contain the rule tree; that's in the StyleSet.
+  MOZ_RELEASE_ASSERT(sizes.mRuleTree == 0);
+
+  REPORT("explicit/layout/servo-ua-cache/precomputed-pseudos",
+         sizes.mPrecomputedPseudos,
+         "Memory used by precomputed pseudo-element declarations within the "
+         "UA cache.");
+
+  REPORT("explicit/layout/servo-ua-cache/element-and-pseudos-maps",
+         sizes.mElementAndPseudosMaps,
+         "Memory used by element and pseudos maps within the UA cache.");
+
+  REPORT("explicit/layout/servo-ua-cache/invalidation-map",
+         sizes.mInvalidationMap,
+         "Memory used by invalidation maps within the UA cache.");
+
+  REPORT("explicit/layout/servo-ua-cache/revalidation-selectors",
+         sizes.mRevalidationSelectors,
+         "Memory used by selectors for cache revalidation within the UA "
+         "cache.");
+
+  REPORT("explicit/layout/servo-ua-cache/other",
+         sizes.mOther,
+         "Memory used by other data within the UA cache");
+
+  return NS_OK;
+}
--- a/layout/style/ServoStyleSet.h
+++ b/layout/style/ServoStyleSet.h
@@ -17,16 +17,17 @@
 #include "mozilla/StyleSheetInlines.h"
 #include "mozilla/SheetType.h"
 #include "mozilla/UniquePtr.h"
 #include "MainThreadUtils.h"
 #include "nsCSSPseudoElements.h"
 #include "nsCSSAnonBoxes.h"
 #include "nsChangeHint.h"
 #include "nsIAtom.h"
+#include "nsIMemoryReporter.h"
 #include "nsTArray.h"
 
 namespace mozilla {
 namespace dom {
 class Element;
 } // namespace dom
 class CSSStyleSheet;
 class ServoRestyleManager;
@@ -609,11 +610,20 @@ private:
   RefPtr<ServoStyleRuleMap> mStyleRuleMap;
 
   // This can be null if we are used to hold XBL style sheets.
   RefPtr<nsBindingManager> mBindingManager;
 
   static ServoStyleSet* sInServoTraversal;
 };
 
+class UACacheReporter final : public nsIMemoryReporter
+{
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIMEMORYREPORTER
+
+private:
+  ~UACacheReporter() {}
+};
+
 } // namespace mozilla
 
 #endif // mozilla_ServoStyleSet_h
--- a/layout/style/ServoTypes.h
+++ b/layout/style/ServoTypes.h
@@ -194,34 +194,34 @@ 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
 
+// These measurements are obtained for both the UA cache and the Stylist, but
+// not all the fields are used in both cases.
 class ServoStyleSetSizes
 {
 public:
-  size_t mStylistRuleTree;
-  size_t mStylistPrecomputedPseudos;
-  size_t mStylistElementAndPseudosMaps;
-  size_t mStylistInvalidationMap;
-  size_t mStylistRevalidationSelectors;
-  size_t mStylistOther;
-  size_t mOther;
+  size_t mRuleTree;                // Stylist-only
+  size_t mPrecomputedPseudos;      // UA cache-only
+  size_t mElementAndPseudosMaps;   // Used for both
+  size_t mInvalidationMap;         // Used for both
+  size_t mRevalidationSelectors;   // Used for both
+  size_t mOther;                   // Used for both
 
   ServoStyleSetSizes()
-    : mStylistRuleTree(0)
-    , mStylistPrecomputedPseudos(0)
-    , mStylistElementAndPseudosMaps(0)
-    , mStylistInvalidationMap(0)
-    , mStylistRevalidationSelectors(0)
-    , mStylistOther(0)
+    : mRuleTree(0)
+    , mPrecomputedPseudos(0)
+    , mElementAndPseudosMaps(0)
+    , mInvalidationMap(0)
+    , mRevalidationSelectors(0)
     , mOther(0)
   {}
 };
 
 } // namespace mozilla
 
 class ServoComputedData;