Bug 1473634: Part 3 - Update nsDOMComputedStyle to use RegisterCallbacks. r?bz
nsComputedDOMStyle is currently one of the biggest sources of pref callback
memory overhead. It currently registers about 5KB of callbacks per process. A
lot of that has to do with it registering multiple callbacks for the same
preference. But even with that problem fixed, we can do better by registering
a single callback for all observed preferences.
This patch does that, but also adds the optimization of deduplicating the list
of observed preferences to avoid wasted cycles needlessly matching against
many identical strings.
MozReview-Commit-ID: LZNgd7cAwo2
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -7,16 +7,17 @@
/* DOM object returned from element.getComputedStyle() */
#include "nsComputedDOMStyle.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/FloatingPoint.h"
#include "mozilla/FontPropertyTypes.h"
#include "mozilla/Preferences.h"
+#include "mozilla/StaticPtr.h"
#include "nsError.h"
#include "nsIFrame.h"
#include "nsIFrameInlines.h"
#include "mozilla/ComputedStyle.h"
#include "nsIScrollableFrame.h"
#include "nsContentUtils.h"
#include "nsIContent.h"
@@ -5487,34 +5488,47 @@ nsComputedDOMStyle::ParentChainChanged(n
/* static */ ComputedStyleMap*
nsComputedDOMStyle::GetComputedStyleMap()
{
static ComputedStyleMap map{};
return ↦
}
+static StaticAutoPtr<nsTArray<const char*>> gCallbackPrefs;
+
/* static */ void
nsComputedDOMStyle::RegisterPrefChangeCallbacks()
{
// Note that this will register callbacks for all properties with prefs, not
// just those that are implemented on computed style objects, as it's not
// easy to grab specific property data from ServoCSSPropList.h based on the
// entries iterated in nsComputedDOMStylePropertyList.h.
- ComputedStyleMap* data = GetComputedStyleMap();
+
+ AutoTArray<const char*, 64> prefs;
for (const auto* p = nsCSSProps::kPropertyPrefTable;
p->mPropID != eCSSProperty_UNKNOWN; p++) {
- nsCString name;
- name.AssignLiteral(p->mPref, strlen(p->mPref));
- Preferences::RegisterCallback(MarkComputedStyleMapDirty, name, data);
- }
+ // Many properties are controlled by the same preference, so de-duplicate
+ // them before adding observers.
+ if (!prefs.ContainsSorted(p->mPref)) {
+ prefs.InsertElementSorted(p->mPref);
+ }
+ }
+ prefs.AppendElement(nullptr);
+
+ MOZ_ASSERT(!gCallbackPrefs);
+ gCallbackPrefs = new nsTArray<const char*>(std::move(prefs));
+
+ Preferences::RegisterCallbacks(MarkComputedStyleMapDirty,
+ gCallbackPrefs->Elements(),
+ GetComputedStyleMap());
}
/* static */ void
nsComputedDOMStyle::UnregisterPrefChangeCallbacks()
{
- ComputedStyleMap* data = GetComputedStyleMap();
- for (const auto* p = nsCSSProps::kPropertyPrefTable;
- p->mPropID != eCSSProperty_UNKNOWN; p++) {
- Preferences::UnregisterCallback(MarkComputedStyleMapDirty,
- nsDependentCString(p->mPref), data);
- }
-}
+ MOZ_ASSERT(gCallbackPrefs);
+
+ Preferences::UnregisterCallbacks(MarkComputedStyleMapDirty,
+ gCallbackPrefs->Elements(),
+ GetComputedStyleMap());
+ gCallbackPrefs = nullptr;
+}