gecko-dev/dom/base/nsWindowMemoryReporter.cpp

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

924 строки
34 KiB
C++
Исходник Обычный вид История

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
2012-05-21 15:12:37 +04:00
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsWindowMemoryReporter.h"
#include "nsWindowSizes.h"
#include "nsGlobalWindow.h"
#include "mozilla/dom/Document.h"
#include "nsDOMWindowList.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/Preferences.h"
#include "mozilla/Services.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/Telemetry.h"
#include "nsNetCID.h"
#include "nsPrintfCString.h"
#include "XPCJSMemoryReporter.h"
#include "js/MemoryMetrics.h"
Bug 1278816 - Move Performance API into dom/performance, r=smaug --HG-- rename : dom/base/PerformanceEntry.cpp => dom/performance/PerformanceEntry.cpp rename : dom/base/PerformanceEntry.h => dom/performance/PerformanceEntry.h rename : dom/base/PerformanceMark.cpp => dom/performance/PerformanceMark.cpp rename : dom/base/PerformanceMark.h => dom/performance/PerformanceMark.h rename : dom/base/PerformanceMeasure.cpp => dom/performance/PerformanceMeasure.cpp rename : dom/base/PerformanceMeasure.h => dom/performance/PerformanceMeasure.h rename : dom/base/PerformanceObserver.cpp => dom/performance/PerformanceObserver.cpp rename : dom/base/PerformanceObserver.h => dom/performance/PerformanceObserver.h rename : dom/base/PerformanceObserverEntryList.cpp => dom/performance/PerformanceObserverEntryList.cpp rename : dom/base/PerformanceObserverEntryList.h => dom/performance/PerformanceObserverEntryList.h rename : dom/base/PerformanceResourceTiming.cpp => dom/performance/PerformanceResourceTiming.cpp rename : dom/base/PerformanceResourceTiming.h => dom/performance/PerformanceResourceTiming.h rename : dom/base/nsPerformance.cpp => dom/performance/nsPerformance.cpp rename : dom/base/nsPerformance.h => dom/performance/nsPerformance.h rename : dom/base/test/performance_observer.html => dom/performance/tests/performance_observer.html rename : dom/base/test/test_performance_observer.html => dom/performance/tests/test_performance_observer.html rename : dom/base/test/test_performance_observer.js => dom/performance/tests/test_performance_observer.js rename : dom/base/test/test_performance_user_timing.html => dom/performance/tests/test_performance_user_timing.html rename : dom/base/test/test_performance_user_timing.js => dom/performance/tests/test_performance_user_timing.js
2016-06-09 13:42:21 +03:00
#include "nsQueryObject.h"
#include "nsServiceManagerUtils.h"
#ifdef MOZ_XUL
# include "nsXULPrototypeCache.h"
#endif
using namespace mozilla;
using namespace mozilla::dom;
StaticRefPtr<nsWindowMemoryReporter> sWindowReporter;
/**
* Don't trigger a ghost window check when a DOM window is detached if we've
* run it this recently.
*/
const int32_t kTimeBetweenChecks = 45; /* seconds */
nsWindowMemoryReporter::nsWindowMemoryReporter()
: mLastCheckForGhostWindows(TimeStamp::NowLoRes()),
mCycleCollectorIsRunning(false),
mCheckTimerWaitingForCCEnd(false),
mGhostWindowCount(0) {}
nsWindowMemoryReporter::~nsWindowMemoryReporter() { KillCheckTimer(); }
NS_IMPL_ISUPPORTS(nsWindowMemoryReporter, nsIMemoryReporter, nsIObserver,
nsISupportsWeakReference)
static nsresult AddNonJSSizeOfWindowAndItsDescendents(
nsGlobalWindowOuter* aWindow, nsTabSizes* aSizes) {
// Measure the window.
SizeOfState state(moz_malloc_size_of);
nsWindowSizes windowSizes(state);
aWindow->AddSizeOfIncludingThis(windowSizes);
// Measure the inner window, if there is one.
nsGlobalWindowInner* inner = aWindow->GetCurrentInnerWindowInternal();
if (inner) {
inner->AddSizeOfIncludingThis(windowSizes);
}
windowSizes.addToTabSizes(aSizes);
nsDOMWindowList* frames = aWindow->GetFrames();
uint32_t length = frames->GetLength();
// Measure this window's descendents.
for (uint32_t i = 0; i < length; i++) {
nsCOMPtr<nsPIDOMWindowOuter> child = frames->IndexedGetter(i);
NS_ENSURE_STATE(child);
nsGlobalWindowOuter* childWin = nsGlobalWindowOuter::Cast(child);
nsresult rv = AddNonJSSizeOfWindowAndItsDescendents(childWin, aSizes);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}
static nsresult NonJSSizeOfTab(nsPIDOMWindowOuter* aWindow, size_t* aDomSize,
size_t* aStyleSize, size_t* aOtherSize) {
nsGlobalWindowOuter* window = nsGlobalWindowOuter::Cast(aWindow);
nsTabSizes sizes;
nsresult rv = AddNonJSSizeOfWindowAndItsDescendents(window, &sizes);
NS_ENSURE_SUCCESS(rv, rv);
*aDomSize = sizes.mDom;
*aStyleSize = sizes.mStyle;
*aOtherSize = sizes.mOther;
return NS_OK;
}
/* static */ void nsWindowMemoryReporter::Init() {
MOZ_ASSERT(!sWindowReporter);
sWindowReporter = new nsWindowMemoryReporter();
ClearOnShutdown(&sWindowReporter);
RegisterStrongMemoryReporter(sWindowReporter);
RegisterNonJSSizeOfTab(NonJSSizeOfTab);
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
if (os) {
os->AddObserver(sWindowReporter, "after-minimize-memory-usage",
/* weakRef = */ true);
os->AddObserver(sWindowReporter, "cycle-collector-begin",
/* weakRef = */ true);
os->AddObserver(sWindowReporter, "cycle-collector-end",
/* weakRef = */ true);
}
RegisterGhostWindowsDistinguishedAmount(GhostWindowsDistinguishedAmount);
}
/* static */ nsWindowMemoryReporter* nsWindowMemoryReporter::Get() {
return sWindowReporter;
}
static already_AddRefed<nsIURI> GetWindowURI(nsGlobalWindowInner* aWindow) {
NS_ENSURE_TRUE(aWindow, nullptr);
nsCOMPtr<Document> doc = aWindow->GetExtantDoc();
nsCOMPtr<nsIURI> uri;
if (doc) {
uri = doc->GetDocumentURI();
}
if (!uri) {
nsCOMPtr<nsIScriptObjectPrincipal> scriptObjPrincipal =
do_QueryObject(aWindow);
NS_ENSURE_TRUE(scriptObjPrincipal, nullptr);
// GetPrincipal() will print a warning if the window does not have an outer
// window, so check here for an outer window first. This code is
// functionally correct if we leave out the GetOuterWindow() check, but we
// end up printing a lot of warnings during debug mochitests.
if (aWindow->GetOuterWindow()) {
nsIPrincipal* principal = scriptObjPrincipal->GetPrincipal();
if (principal) {
principal->GetURI(getter_AddRefs(uri));
}
}
}
return uri.forget();
}
// Forward to the inner window if we need to when getting the window's URI.
static already_AddRefed<nsIURI> GetWindowURI(nsGlobalWindowOuter* aWindow) {
NS_ENSURE_TRUE(aWindow, nullptr);
return GetWindowURI(aWindow->GetCurrentInnerWindowInternal());
}
static void AppendWindowURI(nsGlobalWindowInner* aWindow, nsACString& aStr,
bool aAnonymize) {
nsCOMPtr<nsIURI> uri = GetWindowURI(aWindow);
if (uri) {
if (aAnonymize && !aWindow->IsChromeWindow()) {
aStr.AppendPrintf("<anonymized-%" PRIu64 ">", aWindow->WindowID());
} else {
nsCString spec = uri->GetSpecOrDefault();
// A hack: replace forward slashes with '\\' so they aren't
// treated as path separators. Users of the reporters
// (such as about:memory) have to undo this change.
spec.ReplaceChar('/', '\\');
aStr += spec;
}
} else {
// If we're unable to find a URI, we're dealing with a chrome window with
// no document in it (or somesuch), so we call this a "system window".
aStr += NS_LITERAL_CSTRING("[system]");
}
}
MOZ_DEFINE_MALLOC_SIZE_OF(WindowsMallocSizeOf)
// The key is the window ID.
typedef nsDataHashtable<nsUint64HashKey, nsCString> WindowPaths;
static void ReportAmount(const nsCString& aBasePath, const char* aPathTail,
size_t aAmount, const nsCString& aDescription,
uint32_t aKind, uint32_t aUnits,
nsIHandleReportCallback* aHandleReport,
nsISupports* aData) {
if (aAmount == 0) {
return;
}
nsAutoCString path(aBasePath);
path += aPathTail;
aHandleReport->Callback(EmptyCString(), path, aKind, aUnits, aAmount,
aDescription, aData);
}
static void ReportSize(const nsCString& aBasePath, const char* aPathTail,
size_t aAmount, const nsCString& aDescription,
nsIHandleReportCallback* aHandleReport,
nsISupports* aData) {
ReportAmount(aBasePath, aPathTail, aAmount, aDescription,
nsIMemoryReporter::KIND_HEAP, nsIMemoryReporter::UNITS_BYTES,
aHandleReport, aData);
}
static void ReportCount(const nsCString& aBasePath, const char* aPathTail,
size_t aAmount, const nsCString& aDescription,
nsIHandleReportCallback* aHandleReport,
nsISupports* aData) {
ReportAmount(aBasePath, aPathTail, aAmount, aDescription,
nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_COUNT,
aHandleReport, aData);
}
static void CollectWindowReports(nsGlobalWindowInner* aWindow,
nsWindowSizes* aWindowTotalSizes,
nsTHashtable<nsUint64HashKey>* aGhostWindowIDs,
WindowPaths* aWindowPaths,
WindowPaths* aTopWindowPaths,
nsIHandleReportCallback* aHandleReport,
nsISupports* aData, bool aAnonymize) {
nsAutoCString windowPath("explicit/");
// Avoid calling aWindow->GetTop() if there's no outer window. It will work
// just fine, but will spew a lot of warnings.
nsGlobalWindowOuter* top = nullptr;
nsCOMPtr<nsIURI> location;
if (aWindow->GetOuterWindow()) {
// Our window should have a null top iff it has a null docshell.
MOZ_ASSERT(!!aWindow->GetTopInternal() == !!aWindow->GetDocShell());
top = aWindow->GetTopInternal();
if (top) {
location = GetWindowURI(top);
}
}
if (!location) {
location = GetWindowURI(aWindow);
}
windowPath += NS_LITERAL_CSTRING("window-objects/");
if (top) {
windowPath += NS_LITERAL_CSTRING("top(");
AppendWindowURI(top->GetCurrentInnerWindowInternal(), windowPath,
aAnonymize);
windowPath.AppendPrintf(", id=%" PRIu64 ")", top->WindowID());
aTopWindowPaths->Put(aWindow->WindowID(), windowPath);
windowPath += aWindow->IsFrozen() ? NS_LITERAL_CSTRING("/cached/")
: NS_LITERAL_CSTRING("/active/");
} else {
if (aGhostWindowIDs->Contains(aWindow->WindowID())) {
windowPath += NS_LITERAL_CSTRING("top(none)/ghost/");
} else {
windowPath += NS_LITERAL_CSTRING("top(none)/detached/");
}
}
windowPath += NS_LITERAL_CSTRING("window(");
AppendWindowURI(aWindow, windowPath, aAnonymize);
windowPath += NS_LITERAL_CSTRING(")");
// Use |windowPath|, but replace "explicit/" with "event-counts/".
nsCString censusWindowPath(windowPath);
censusWindowPath.ReplaceLiteral(0, strlen("explicit"), "event-counts");
// Remember the path for later.
aWindowPaths->Put(aWindow->WindowID(), windowPath);
// Report the size from windowSizes and add to the appropriate total in
// aWindowTotalSizes.
#define REPORT_SIZE(_pathTail, _field, _desc) \
ReportSize(windowPath, _pathTail, windowSizes._field, \
NS_LITERAL_CSTRING(_desc), aHandleReport, aData); \
aWindowTotalSizes->_field += windowSizes._field;
// Report the size, which is a sum of other sizes, and so doesn't require
// updating aWindowTotalSizes.
#define REPORT_SUM_SIZE(_pathTail, _amount, _desc) \
ReportSize(windowPath, _pathTail, _amount, NS_LITERAL_CSTRING(_desc), \
aHandleReport, aData);
// Like REPORT_SIZE, but for a count.
#define REPORT_COUNT(_pathTail, _field, _desc) \
ReportCount(censusWindowPath, _pathTail, windowSizes._field, \
NS_LITERAL_CSTRING(_desc), aHandleReport, aData); \
aWindowTotalSizes->_field += windowSizes._field;
// This SizeOfState contains the SeenPtrs used for all memory reporting of
// this window.
SizeOfState state(WindowsMallocSizeOf);
nsWindowSizes windowSizes(state);
aWindow->AddSizeOfIncludingThis(windowSizes);
REPORT_SIZE("/dom/element-nodes", mDOMElementNodesSize,
"Memory used by the element nodes in a window's DOM.");
REPORT_SIZE("/dom/text-nodes", mDOMTextNodesSize,
"Memory used by the text nodes in a window's DOM.");
REPORT_SIZE("/dom/cdata-nodes", mDOMCDATANodesSize,
"Memory used by the CDATA nodes in a window's DOM.");
REPORT_SIZE("/dom/comment-nodes", mDOMCommentNodesSize,
"Memory used by the comment nodes in a window's DOM.");
REPORT_SIZE("/dom/event-targets", mDOMEventTargetsSize,
"Memory used by the event targets table in a window's DOM, and "
"the objects it points to, which include XHRs.");
REPORT_SIZE("/dom/performance/user-entries", mDOMPerformanceUserEntries,
"Memory used for performance user entries.");
REPORT_SIZE("/dom/performance/resource-entries",
mDOMPerformanceResourceEntries,
"Memory used for performance resource entries.");
REPORT_SIZE("/dom/media-query-lists", mDOMMediaQueryLists,
"Memory used by MediaQueryList objects for the window's "
"document.");
REPORT_SIZE("/dom/other", mDOMOtherSize,
"Memory used by a window's DOM that isn't measured by the "
"other 'dom/' numbers.");
REPORT_SIZE("/layout/style-sheets", mLayoutStyleSheetsSize,
"Memory used by document style sheets within a window.");
REPORT_SIZE("/layout/shadow-dom/style-sheets",
mLayoutShadowDomStyleSheetsSize,
"Memory used by Shadow DOM style sheets within a window.");
// TODO(emilio): We might want to split this up between invalidation map /
// element-and-pseudos / revalidation too just like the style set.
REPORT_SIZE("/layout/shadow-dom/author-styles", mLayoutShadowDomAuthorStyles,
"Memory used by Shadow DOM computed rule data within a window.");
REPORT_SIZE("/layout/pres-shell", mLayoutPresShellSize,
"Memory used by layout's PresShell, along with any structures "
"allocated in its arena and not measured elsewhere, "
"within a window.");
REPORT_SIZE("/layout/style-sets/stylist/rule-tree",
mLayoutStyleSetsStylistRuleTree,
"Memory used by rule trees within style sets within a window.");
REPORT_SIZE("/layout/style-sets/stylist/element-and-pseudos-maps",
mLayoutStyleSetsStylistElementAndPseudosMaps,
"Memory used by element and pseudos maps within style "
"sets within a window.");
REPORT_SIZE("/layout/style-sets/stylist/invalidation-map",
mLayoutStyleSetsStylistInvalidationMap,
"Memory used by invalidation maps within style sets "
"within a window.");
REPORT_SIZE("/layout/style-sets/stylist/revalidation-selectors",
mLayoutStyleSetsStylistRevalidationSelectors,
"Memory used by selectors for cache revalidation within "
"style sets within a window.");
REPORT_SIZE("/layout/style-sets/stylist/other", mLayoutStyleSetsStylistOther,
"Memory used by other Stylist data within style sets "
"within a window.");
REPORT_SIZE("/layout/style-sets/other", mLayoutStyleSetsOther,
"Memory used by other parts of style sets within a window.");
REPORT_SIZE("/layout/element-data-objects", mLayoutElementDataObjects,
"Memory used for ElementData objects, but not the things "
"hanging off them.");
REPORT_SIZE("/layout/text-runs", mLayoutTextRunsSize,
"Memory used for text-runs (glyph layout) in the PresShell's "
"frame tree, within a window.");
REPORT_SIZE("/layout/pres-contexts", mLayoutPresContextSize,
"Memory used for the PresContext in the PresShell's frame "
"within a window.");
REPORT_SIZE("/layout/frame-properties", mLayoutFramePropertiesSize,
"Memory used for frame properties attached to frames "
"within a window.");
REPORT_SIZE("/layout/computed-values/dom", mLayoutComputedValuesDom,
"Memory used by ComputedValues objects accessible from DOM "
"elements.");
REPORT_SIZE("/layout/computed-values/non-dom", mLayoutComputedValuesNonDom,
"Memory used by ComputedValues objects not accessible from DOM "
"elements.");
REPORT_SIZE("/layout/computed-values/visited", mLayoutComputedValuesVisited,
"Memory used by ComputedValues objects used for visited styles.");
REPORT_SIZE("/property-tables", mPropertyTablesSize,
"Memory used for the property tables within a window.");
REPORT_SIZE("/bindings", mBindingsSize,
"Memory used by bindings within a window.");
REPORT_COUNT("/dom/event-targets", mDOMEventTargetsCount,
"Number of non-node event targets in the event targets table "
"in a window's DOM, such as XHRs.");
REPORT_COUNT("/dom/event-listeners", mDOMEventListenersCount,
"Number of event listeners in a window, including event "
"listeners on nodes and other event targets.");
REPORT_SIZE("/layout/line-boxes", mArenaSizes.mLineBoxes,
"Memory used by line boxes within a window.");
REPORT_SIZE("/layout/rule-nodes", mArenaSizes.mRuleNodes,
"Memory used by CSS rule nodes within a window.");
REPORT_SIZE("/layout/style-contexts", mArenaSizes.mComputedStyles,
"Memory used by ComputedStyles within a window.");
// There are many different kinds of style structs, but it is likely that
// only a few matter. Implement a cutoff so we don't bloat about:memory with
// many uninteresting entries.
const size_t STYLE_SUNDRIES_THRESHOLD =
js::MemoryReportingSundriesThreshold();
// There are many different kinds of frames, but it is very likely
// that only a few matter. Implement a cutoff so we don't bloat
// about:memory with many uninteresting entries.
const size_t FRAME_SUNDRIES_THRESHOLD =
js::MemoryReportingSundriesThreshold();
size_t frameSundriesSize = 0;
Bug 1387956 - Overhaul ComputedValues measurement, and add style structs measurement. r=bholley. This patch moves measurement of ComputedValues objects from Rust to C++. Measurement now happens (a) via DOM elements and (b) remaining elements via the frame tree. Likewise for the style structs hanging off ComputedValues objects. Here is an example of the output. > ├──27,600,448 B (26.49%) -- active/window(https://en.wikipedia.org/wiki/Barack_Obama) > │ ├──12,772,544 B (12.26%) -- layout > │ │ ├───4,483,744 B (04.30%) -- frames > │ │ │ ├──1,653,552 B (01.59%) ── nsInlineFrame > │ │ │ ├──1,415,760 B (01.36%) ── nsTextFrame > │ │ │ ├────431,376 B (00.41%) ── nsBlockFrame > │ │ │ ├────340,560 B (00.33%) ── nsHTMLScrollFrame > │ │ │ ├────302,544 B (00.29%) ── nsContinuingTextFrame > │ │ │ ├────156,408 B (00.15%) ── nsBulletFrame > │ │ │ ├─────73,024 B (00.07%) ── nsPlaceholderFrame > │ │ │ ├─────27,656 B (00.03%) ── sundries > │ │ │ ├─────23,520 B (00.02%) ── nsTableCellFrame > │ │ │ ├─────16,704 B (00.02%) ── nsImageFrame > │ │ │ ├─────15,488 B (00.01%) ── nsTableRowFrame > │ │ │ ├─────13,776 B (00.01%) ── nsTableColFrame > │ │ │ └─────13,376 B (00.01%) ── nsTableFrame > │ │ ├───3,412,192 B (03.28%) -- servo-style-structs > │ │ │ ├──1,288,224 B (01.24%) ── Display > │ │ │ ├────742,400 B (00.71%) ── Position > │ │ │ ├────308,736 B (00.30%) ── Font > │ │ │ ├────226,512 B (00.22%) ── Background > │ │ │ ├────218,304 B (00.21%) ── TextReset > │ │ │ ├────214,896 B (00.21%) ── Text > │ │ │ ├────130,560 B (00.13%) ── Border > │ │ │ ├─────81,408 B (00.08%) ── UIReset > │ │ │ ├─────61,440 B (00.06%) ── Padding > │ │ │ ├─────38,176 B (00.04%) ── UserInterface > │ │ │ ├─────29,232 B (00.03%) ── Margin > │ │ │ ├─────21,824 B (00.02%) ── sundries > │ │ │ ├─────20,080 B (00.02%) ── Color > │ │ │ ├─────20,080 B (00.02%) ── Column > │ │ │ └─────10,320 B (00.01%) ── Effects > │ │ ├───2,227,680 B (02.14%) -- computed-values > │ │ │ ├──1,182,928 B (01.14%) ── non-dom > │ │ │ └──1,044,752 B (01.00%) ── dom > │ │ ├───1,500,016 B (01.44%) ── text-runs > │ │ ├─────492,640 B (00.47%) ── line-boxes > │ │ ├─────326,688 B (00.31%) ── frame-properties > │ │ ├─────301,760 B (00.29%) ── pres-shell > │ │ ├──────27,648 B (00.03%) ── pres-contexts > │ │ └─────────176 B (00.00%) ── style-sets The 'servo-style-structs' and 'computed-values' sub-trees are new. (Prior to this patch, ComputedValues under DOM elements were tallied under the the 'dom/element-nodes' sub-tree, and ComputedValues not under DOM element were ignored.) 'servo-style-structs/sundries' aggregates all the style structs that are smaller than 8 KiB. Other notable things done by the patch are as follows. - It significantly changes the signatures of the methods measuring nsINode and its subclasses, in order to handle the tallying of style structs separately from element-nodes. Likewise for nsIFrame. - It renames the 'layout/style-structs' sub-tree as 'layout/gecko-style-structs', to clearly distinguish it from the new 'layout/servo-style-structs' sub-tree. - It adds some FFI functions to access various Rust-side data structures from C++ code. - There is a nasty hack used twice to measure Arcs, by stepping backwards from an interior pointer to a base pointer. It works, but I want to replace it with something better eventually. The "XXX WARNING" comments have details. - It makes DMD print a line to the console if it sees a pointer it doesn't recognise. This is useful for detecting when we are measuring an interior pointer instead of a base pointer, which is bad but easy to do when Arcs are involved. - It removes the Rust code for measuring CVs, because it's now all done on the C++ side. MozReview-Commit-ID: BKebACLKtCi --HG-- extra : rebase_source : 4d9a8c6b198a0ff025b811759a6bfa9f33a260ba
2017-08-11 09:37:33 +03:00
#define FRAME_ID(classname, ...) \
{ \
size_t size = windowSizes.mArenaSizes.NS_ARENA_SIZES_FIELD(classname); \
if (size < FRAME_SUNDRIES_THRESHOLD) { \
frameSundriesSize += size; \
} else { \
REPORT_SUM_SIZE("/layout/frames/" #classname, size, \
"Memory used by frames of type " #classname \
" within a window."); \
Bug 1387956 - Overhaul ComputedValues measurement, and add style structs measurement. r=bholley. This patch moves measurement of ComputedValues objects from Rust to C++. Measurement now happens (a) via DOM elements and (b) remaining elements via the frame tree. Likewise for the style structs hanging off ComputedValues objects. Here is an example of the output. > ├──27,600,448 B (26.49%) -- active/window(https://en.wikipedia.org/wiki/Barack_Obama) > │ ├──12,772,544 B (12.26%) -- layout > │ │ ├───4,483,744 B (04.30%) -- frames > │ │ │ ├──1,653,552 B (01.59%) ── nsInlineFrame > │ │ │ ├──1,415,760 B (01.36%) ── nsTextFrame > │ │ │ ├────431,376 B (00.41%) ── nsBlockFrame > │ │ │ ├────340,560 B (00.33%) ── nsHTMLScrollFrame > │ │ │ ├────302,544 B (00.29%) ── nsContinuingTextFrame > │ │ │ ├────156,408 B (00.15%) ── nsBulletFrame > │ │ │ ├─────73,024 B (00.07%) ── nsPlaceholderFrame > │ │ │ ├─────27,656 B (00.03%) ── sundries > │ │ │ ├─────23,520 B (00.02%) ── nsTableCellFrame > │ │ │ ├─────16,704 B (00.02%) ── nsImageFrame > │ │ │ ├─────15,488 B (00.01%) ── nsTableRowFrame > │ │ │ ├─────13,776 B (00.01%) ── nsTableColFrame > │ │ │ └─────13,376 B (00.01%) ── nsTableFrame > │ │ ├───3,412,192 B (03.28%) -- servo-style-structs > │ │ │ ├──1,288,224 B (01.24%) ── Display > │ │ │ ├────742,400 B (00.71%) ── Position > │ │ │ ├────308,736 B (00.30%) ── Font > │ │ │ ├────226,512 B (00.22%) ── Background > │ │ │ ├────218,304 B (00.21%) ── TextReset > │ │ │ ├────214,896 B (00.21%) ── Text > │ │ │ ├────130,560 B (00.13%) ── Border > │ │ │ ├─────81,408 B (00.08%) ── UIReset > │ │ │ ├─────61,440 B (00.06%) ── Padding > │ │ │ ├─────38,176 B (00.04%) ── UserInterface > │ │ │ ├─────29,232 B (00.03%) ── Margin > │ │ │ ├─────21,824 B (00.02%) ── sundries > │ │ │ ├─────20,080 B (00.02%) ── Color > │ │ │ ├─────20,080 B (00.02%) ── Column > │ │ │ └─────10,320 B (00.01%) ── Effects > │ │ ├───2,227,680 B (02.14%) -- computed-values > │ │ │ ├──1,182,928 B (01.14%) ── non-dom > │ │ │ └──1,044,752 B (01.00%) ── dom > │ │ ├───1,500,016 B (01.44%) ── text-runs > │ │ ├─────492,640 B (00.47%) ── line-boxes > │ │ ├─────326,688 B (00.31%) ── frame-properties > │ │ ├─────301,760 B (00.29%) ── pres-shell > │ │ ├──────27,648 B (00.03%) ── pres-contexts > │ │ └─────────176 B (00.00%) ── style-sets The 'servo-style-structs' and 'computed-values' sub-trees are new. (Prior to this patch, ComputedValues under DOM elements were tallied under the the 'dom/element-nodes' sub-tree, and ComputedValues not under DOM element were ignored.) 'servo-style-structs/sundries' aggregates all the style structs that are smaller than 8 KiB. Other notable things done by the patch are as follows. - It significantly changes the signatures of the methods measuring nsINode and its subclasses, in order to handle the tallying of style structs separately from element-nodes. Likewise for nsIFrame. - It renames the 'layout/style-structs' sub-tree as 'layout/gecko-style-structs', to clearly distinguish it from the new 'layout/servo-style-structs' sub-tree. - It adds some FFI functions to access various Rust-side data structures from C++ code. - There is a nasty hack used twice to measure Arcs, by stepping backwards from an interior pointer to a base pointer. It works, but I want to replace it with something better eventually. The "XXX WARNING" comments have details. - It makes DMD print a line to the console if it sees a pointer it doesn't recognise. This is useful for detecting when we are measuring an interior pointer instead of a base pointer, which is bad but easy to do when Arcs are involved. - It removes the Rust code for measuring CVs, because it's now all done on the C++ side. MozReview-Commit-ID: BKebACLKtCi --HG-- extra : rebase_source : 4d9a8c6b198a0ff025b811759a6bfa9f33a260ba
2017-08-11 09:37:33 +03:00
} \
aWindowTotalSizes->mArenaSizes.NS_ARENA_SIZES_FIELD(classname) += size; \
}
#define ABSTRACT_FRAME_ID(...)
#include "nsFrameIdList.h"
#undef FRAME_ID
#undef ABSTRACT_FRAME_ID
if (frameSundriesSize > 0) {
REPORT_SUM_SIZE(
"/layout/frames/sundries", frameSundriesSize,
"The sum of all memory used by frames which were too small to be shown "
"individually.");
}
// This is the style structs.
size_t styleSundriesSize = 0;
#define STYLE_STRUCT(name_) \
Bug 1387956 - Overhaul ComputedValues measurement, and add style structs measurement. r=bholley. This patch moves measurement of ComputedValues objects from Rust to C++. Measurement now happens (a) via DOM elements and (b) remaining elements via the frame tree. Likewise for the style structs hanging off ComputedValues objects. Here is an example of the output. > ├──27,600,448 B (26.49%) -- active/window(https://en.wikipedia.org/wiki/Barack_Obama) > │ ├──12,772,544 B (12.26%) -- layout > │ │ ├───4,483,744 B (04.30%) -- frames > │ │ │ ├──1,653,552 B (01.59%) ── nsInlineFrame > │ │ │ ├──1,415,760 B (01.36%) ── nsTextFrame > │ │ │ ├────431,376 B (00.41%) ── nsBlockFrame > │ │ │ ├────340,560 B (00.33%) ── nsHTMLScrollFrame > │ │ │ ├────302,544 B (00.29%) ── nsContinuingTextFrame > │ │ │ ├────156,408 B (00.15%) ── nsBulletFrame > │ │ │ ├─────73,024 B (00.07%) ── nsPlaceholderFrame > │ │ │ ├─────27,656 B (00.03%) ── sundries > │ │ │ ├─────23,520 B (00.02%) ── nsTableCellFrame > │ │ │ ├─────16,704 B (00.02%) ── nsImageFrame > │ │ │ ├─────15,488 B (00.01%) ── nsTableRowFrame > │ │ │ ├─────13,776 B (00.01%) ── nsTableColFrame > │ │ │ └─────13,376 B (00.01%) ── nsTableFrame > │ │ ├───3,412,192 B (03.28%) -- servo-style-structs > │ │ │ ├──1,288,224 B (01.24%) ── Display > │ │ │ ├────742,400 B (00.71%) ── Position > │ │ │ ├────308,736 B (00.30%) ── Font > │ │ │ ├────226,512 B (00.22%) ── Background > │ │ │ ├────218,304 B (00.21%) ── TextReset > │ │ │ ├────214,896 B (00.21%) ── Text > │ │ │ ├────130,560 B (00.13%) ── Border > │ │ │ ├─────81,408 B (00.08%) ── UIReset > │ │ │ ├─────61,440 B (00.06%) ── Padding > │ │ │ ├─────38,176 B (00.04%) ── UserInterface > │ │ │ ├─────29,232 B (00.03%) ── Margin > │ │ │ ├─────21,824 B (00.02%) ── sundries > │ │ │ ├─────20,080 B (00.02%) ── Color > │ │ │ ├─────20,080 B (00.02%) ── Column > │ │ │ └─────10,320 B (00.01%) ── Effects > │ │ ├───2,227,680 B (02.14%) -- computed-values > │ │ │ ├──1,182,928 B (01.14%) ── non-dom > │ │ │ └──1,044,752 B (01.00%) ── dom > │ │ ├───1,500,016 B (01.44%) ── text-runs > │ │ ├─────492,640 B (00.47%) ── line-boxes > │ │ ├─────326,688 B (00.31%) ── frame-properties > │ │ ├─────301,760 B (00.29%) ── pres-shell > │ │ ├──────27,648 B (00.03%) ── pres-contexts > │ │ └─────────176 B (00.00%) ── style-sets The 'servo-style-structs' and 'computed-values' sub-trees are new. (Prior to this patch, ComputedValues under DOM elements were tallied under the the 'dom/element-nodes' sub-tree, and ComputedValues not under DOM element were ignored.) 'servo-style-structs/sundries' aggregates all the style structs that are smaller than 8 KiB. Other notable things done by the patch are as follows. - It significantly changes the signatures of the methods measuring nsINode and its subclasses, in order to handle the tallying of style structs separately from element-nodes. Likewise for nsIFrame. - It renames the 'layout/style-structs' sub-tree as 'layout/gecko-style-structs', to clearly distinguish it from the new 'layout/servo-style-structs' sub-tree. - It adds some FFI functions to access various Rust-side data structures from C++ code. - There is a nasty hack used twice to measure Arcs, by stepping backwards from an interior pointer to a base pointer. It works, but I want to replace it with something better eventually. The "XXX WARNING" comments have details. - It makes DMD print a line to the console if it sees a pointer it doesn't recognise. This is useful for detecting when we are measuring an interior pointer instead of a base pointer, which is bad but easy to do when Arcs are involved. - It removes the Rust code for measuring CVs, because it's now all done on the C++ side. MozReview-Commit-ID: BKebACLKtCi --HG-- extra : rebase_source : 4d9a8c6b198a0ff025b811759a6bfa9f33a260ba
2017-08-11 09:37:33 +03:00
{ \
size_t size = windowSizes.mStyleSizes.NS_STYLE_SIZES_FIELD(name_); \
Bug 1387956 - Overhaul ComputedValues measurement, and add style structs measurement. r=bholley. This patch moves measurement of ComputedValues objects from Rust to C++. Measurement now happens (a) via DOM elements and (b) remaining elements via the frame tree. Likewise for the style structs hanging off ComputedValues objects. Here is an example of the output. > ├──27,600,448 B (26.49%) -- active/window(https://en.wikipedia.org/wiki/Barack_Obama) > │ ├──12,772,544 B (12.26%) -- layout > │ │ ├───4,483,744 B (04.30%) -- frames > │ │ │ ├──1,653,552 B (01.59%) ── nsInlineFrame > │ │ │ ├──1,415,760 B (01.36%) ── nsTextFrame > │ │ │ ├────431,376 B (00.41%) ── nsBlockFrame > │ │ │ ├────340,560 B (00.33%) ── nsHTMLScrollFrame > │ │ │ ├────302,544 B (00.29%) ── nsContinuingTextFrame > │ │ │ ├────156,408 B (00.15%) ── nsBulletFrame > │ │ │ ├─────73,024 B (00.07%) ── nsPlaceholderFrame > │ │ │ ├─────27,656 B (00.03%) ── sundries > │ │ │ ├─────23,520 B (00.02%) ── nsTableCellFrame > │ │ │ ├─────16,704 B (00.02%) ── nsImageFrame > │ │ │ ├─────15,488 B (00.01%) ── nsTableRowFrame > │ │ │ ├─────13,776 B (00.01%) ── nsTableColFrame > │ │ │ └─────13,376 B (00.01%) ── nsTableFrame > │ │ ├───3,412,192 B (03.28%) -- servo-style-structs > │ │ │ ├──1,288,224 B (01.24%) ── Display > │ │ │ ├────742,400 B (00.71%) ── Position > │ │ │ ├────308,736 B (00.30%) ── Font > │ │ │ ├────226,512 B (00.22%) ── Background > │ │ │ ├────218,304 B (00.21%) ── TextReset > │ │ │ ├────214,896 B (00.21%) ── Text > │ │ │ ├────130,560 B (00.13%) ── Border > │ │ │ ├─────81,408 B (00.08%) ── UIReset > │ │ │ ├─────61,440 B (00.06%) ── Padding > │ │ │ ├─────38,176 B (00.04%) ── UserInterface > │ │ │ ├─────29,232 B (00.03%) ── Margin > │ │ │ ├─────21,824 B (00.02%) ── sundries > │ │ │ ├─────20,080 B (00.02%) ── Color > │ │ │ ├─────20,080 B (00.02%) ── Column > │ │ │ └─────10,320 B (00.01%) ── Effects > │ │ ├───2,227,680 B (02.14%) -- computed-values > │ │ │ ├──1,182,928 B (01.14%) ── non-dom > │ │ │ └──1,044,752 B (01.00%) ── dom > │ │ ├───1,500,016 B (01.44%) ── text-runs > │ │ ├─────492,640 B (00.47%) ── line-boxes > │ │ ├─────326,688 B (00.31%) ── frame-properties > │ │ ├─────301,760 B (00.29%) ── pres-shell > │ │ ├──────27,648 B (00.03%) ── pres-contexts > │ │ └─────────176 B (00.00%) ── style-sets The 'servo-style-structs' and 'computed-values' sub-trees are new. (Prior to this patch, ComputedValues under DOM elements were tallied under the the 'dom/element-nodes' sub-tree, and ComputedValues not under DOM element were ignored.) 'servo-style-structs/sundries' aggregates all the style structs that are smaller than 8 KiB. Other notable things done by the patch are as follows. - It significantly changes the signatures of the methods measuring nsINode and its subclasses, in order to handle the tallying of style structs separately from element-nodes. Likewise for nsIFrame. - It renames the 'layout/style-structs' sub-tree as 'layout/gecko-style-structs', to clearly distinguish it from the new 'layout/servo-style-structs' sub-tree. - It adds some FFI functions to access various Rust-side data structures from C++ code. - There is a nasty hack used twice to measure Arcs, by stepping backwards from an interior pointer to a base pointer. It works, but I want to replace it with something better eventually. The "XXX WARNING" comments have details. - It makes DMD print a line to the console if it sees a pointer it doesn't recognise. This is useful for detecting when we are measuring an interior pointer instead of a base pointer, which is bad but easy to do when Arcs are involved. - It removes the Rust code for measuring CVs, because it's now all done on the C++ side. MozReview-Commit-ID: BKebACLKtCi --HG-- extra : rebase_source : 4d9a8c6b198a0ff025b811759a6bfa9f33a260ba
2017-08-11 09:37:33 +03:00
if (size < STYLE_SUNDRIES_THRESHOLD) { \
styleSundriesSize += size; \
Bug 1387956 - Overhaul ComputedValues measurement, and add style structs measurement. r=bholley. This patch moves measurement of ComputedValues objects from Rust to C++. Measurement now happens (a) via DOM elements and (b) remaining elements via the frame tree. Likewise for the style structs hanging off ComputedValues objects. Here is an example of the output. > ├──27,600,448 B (26.49%) -- active/window(https://en.wikipedia.org/wiki/Barack_Obama) > │ ├──12,772,544 B (12.26%) -- layout > │ │ ├───4,483,744 B (04.30%) -- frames > │ │ │ ├──1,653,552 B (01.59%) ── nsInlineFrame > │ │ │ ├──1,415,760 B (01.36%) ── nsTextFrame > │ │ │ ├────431,376 B (00.41%) ── nsBlockFrame > │ │ │ ├────340,560 B (00.33%) ── nsHTMLScrollFrame > │ │ │ ├────302,544 B (00.29%) ── nsContinuingTextFrame > │ │ │ ├────156,408 B (00.15%) ── nsBulletFrame > │ │ │ ├─────73,024 B (00.07%) ── nsPlaceholderFrame > │ │ │ ├─────27,656 B (00.03%) ── sundries > │ │ │ ├─────23,520 B (00.02%) ── nsTableCellFrame > │ │ │ ├─────16,704 B (00.02%) ── nsImageFrame > │ │ │ ├─────15,488 B (00.01%) ── nsTableRowFrame > │ │ │ ├─────13,776 B (00.01%) ── nsTableColFrame > │ │ │ └─────13,376 B (00.01%) ── nsTableFrame > │ │ ├───3,412,192 B (03.28%) -- servo-style-structs > │ │ │ ├──1,288,224 B (01.24%) ── Display > │ │ │ ├────742,400 B (00.71%) ── Position > │ │ │ ├────308,736 B (00.30%) ── Font > │ │ │ ├────226,512 B (00.22%) ── Background > │ │ │ ├────218,304 B (00.21%) ── TextReset > │ │ │ ├────214,896 B (00.21%) ── Text > │ │ │ ├────130,560 B (00.13%) ── Border > │ │ │ ├─────81,408 B (00.08%) ── UIReset > │ │ │ ├─────61,440 B (00.06%) ── Padding > │ │ │ ├─────38,176 B (00.04%) ── UserInterface > │ │ │ ├─────29,232 B (00.03%) ── Margin > │ │ │ ├─────21,824 B (00.02%) ── sundries > │ │ │ ├─────20,080 B (00.02%) ── Color > │ │ │ ├─────20,080 B (00.02%) ── Column > │ │ │ └─────10,320 B (00.01%) ── Effects > │ │ ├───2,227,680 B (02.14%) -- computed-values > │ │ │ ├──1,182,928 B (01.14%) ── non-dom > │ │ │ └──1,044,752 B (01.00%) ── dom > │ │ ├───1,500,016 B (01.44%) ── text-runs > │ │ ├─────492,640 B (00.47%) ── line-boxes > │ │ ├─────326,688 B (00.31%) ── frame-properties > │ │ ├─────301,760 B (00.29%) ── pres-shell > │ │ ├──────27,648 B (00.03%) ── pres-contexts > │ │ └─────────176 B (00.00%) ── style-sets The 'servo-style-structs' and 'computed-values' sub-trees are new. (Prior to this patch, ComputedValues under DOM elements were tallied under the the 'dom/element-nodes' sub-tree, and ComputedValues not under DOM element were ignored.) 'servo-style-structs/sundries' aggregates all the style structs that are smaller than 8 KiB. Other notable things done by the patch are as follows. - It significantly changes the signatures of the methods measuring nsINode and its subclasses, in order to handle the tallying of style structs separately from element-nodes. Likewise for nsIFrame. - It renames the 'layout/style-structs' sub-tree as 'layout/gecko-style-structs', to clearly distinguish it from the new 'layout/servo-style-structs' sub-tree. - It adds some FFI functions to access various Rust-side data structures from C++ code. - There is a nasty hack used twice to measure Arcs, by stepping backwards from an interior pointer to a base pointer. It works, but I want to replace it with something better eventually. The "XXX WARNING" comments have details. - It makes DMD print a line to the console if it sees a pointer it doesn't recognise. This is useful for detecting when we are measuring an interior pointer instead of a base pointer, which is bad but easy to do when Arcs are involved. - It removes the Rust code for measuring CVs, because it's now all done on the C++ side. MozReview-Commit-ID: BKebACLKtCi --HG-- extra : rebase_source : 4d9a8c6b198a0ff025b811759a6bfa9f33a260ba
2017-08-11 09:37:33 +03:00
} else { \
REPORT_SUM_SIZE("/layout/style-structs/" #name_, size, \
"Memory used by the " #name_ \
" style structs within a window."); \
Bug 1387956 - Overhaul ComputedValues measurement, and add style structs measurement. r=bholley. This patch moves measurement of ComputedValues objects from Rust to C++. Measurement now happens (a) via DOM elements and (b) remaining elements via the frame tree. Likewise for the style structs hanging off ComputedValues objects. Here is an example of the output. > ├──27,600,448 B (26.49%) -- active/window(https://en.wikipedia.org/wiki/Barack_Obama) > │ ├──12,772,544 B (12.26%) -- layout > │ │ ├───4,483,744 B (04.30%) -- frames > │ │ │ ├──1,653,552 B (01.59%) ── nsInlineFrame > │ │ │ ├──1,415,760 B (01.36%) ── nsTextFrame > │ │ │ ├────431,376 B (00.41%) ── nsBlockFrame > │ │ │ ├────340,560 B (00.33%) ── nsHTMLScrollFrame > │ │ │ ├────302,544 B (00.29%) ── nsContinuingTextFrame > │ │ │ ├────156,408 B (00.15%) ── nsBulletFrame > │ │ │ ├─────73,024 B (00.07%) ── nsPlaceholderFrame > │ │ │ ├─────27,656 B (00.03%) ── sundries > │ │ │ ├─────23,520 B (00.02%) ── nsTableCellFrame > │ │ │ ├─────16,704 B (00.02%) ── nsImageFrame > │ │ │ ├─────15,488 B (00.01%) ── nsTableRowFrame > │ │ │ ├─────13,776 B (00.01%) ── nsTableColFrame > │ │ │ └─────13,376 B (00.01%) ── nsTableFrame > │ │ ├───3,412,192 B (03.28%) -- servo-style-structs > │ │ │ ├──1,288,224 B (01.24%) ── Display > │ │ │ ├────742,400 B (00.71%) ── Position > │ │ │ ├────308,736 B (00.30%) ── Font > │ │ │ ├────226,512 B (00.22%) ── Background > │ │ │ ├────218,304 B (00.21%) ── TextReset > │ │ │ ├────214,896 B (00.21%) ── Text > │ │ │ ├────130,560 B (00.13%) ── Border > │ │ │ ├─────81,408 B (00.08%) ── UIReset > │ │ │ ├─────61,440 B (00.06%) ── Padding > │ │ │ ├─────38,176 B (00.04%) ── UserInterface > │ │ │ ├─────29,232 B (00.03%) ── Margin > │ │ │ ├─────21,824 B (00.02%) ── sundries > │ │ │ ├─────20,080 B (00.02%) ── Color > │ │ │ ├─────20,080 B (00.02%) ── Column > │ │ │ └─────10,320 B (00.01%) ── Effects > │ │ ├───2,227,680 B (02.14%) -- computed-values > │ │ │ ├──1,182,928 B (01.14%) ── non-dom > │ │ │ └──1,044,752 B (01.00%) ── dom > │ │ ├───1,500,016 B (01.44%) ── text-runs > │ │ ├─────492,640 B (00.47%) ── line-boxes > │ │ ├─────326,688 B (00.31%) ── frame-properties > │ │ ├─────301,760 B (00.29%) ── pres-shell > │ │ ├──────27,648 B (00.03%) ── pres-contexts > │ │ └─────────176 B (00.00%) ── style-sets The 'servo-style-structs' and 'computed-values' sub-trees are new. (Prior to this patch, ComputedValues under DOM elements were tallied under the the 'dom/element-nodes' sub-tree, and ComputedValues not under DOM element were ignored.) 'servo-style-structs/sundries' aggregates all the style structs that are smaller than 8 KiB. Other notable things done by the patch are as follows. - It significantly changes the signatures of the methods measuring nsINode and its subclasses, in order to handle the tallying of style structs separately from element-nodes. Likewise for nsIFrame. - It renames the 'layout/style-structs' sub-tree as 'layout/gecko-style-structs', to clearly distinguish it from the new 'layout/servo-style-structs' sub-tree. - It adds some FFI functions to access various Rust-side data structures from C++ code. - There is a nasty hack used twice to measure Arcs, by stepping backwards from an interior pointer to a base pointer. It works, but I want to replace it with something better eventually. The "XXX WARNING" comments have details. - It makes DMD print a line to the console if it sees a pointer it doesn't recognise. This is useful for detecting when we are measuring an interior pointer instead of a base pointer, which is bad but easy to do when Arcs are involved. - It removes the Rust code for measuring CVs, because it's now all done on the C++ side. MozReview-Commit-ID: BKebACLKtCi --HG-- extra : rebase_source : 4d9a8c6b198a0ff025b811759a6bfa9f33a260ba
2017-08-11 09:37:33 +03:00
} \
aWindowTotalSizes->mStyleSizes.NS_STYLE_SIZES_FIELD(name_) += size; \
Bug 1387956 - Overhaul ComputedValues measurement, and add style structs measurement. r=bholley. This patch moves measurement of ComputedValues objects from Rust to C++. Measurement now happens (a) via DOM elements and (b) remaining elements via the frame tree. Likewise for the style structs hanging off ComputedValues objects. Here is an example of the output. > ├──27,600,448 B (26.49%) -- active/window(https://en.wikipedia.org/wiki/Barack_Obama) > │ ├──12,772,544 B (12.26%) -- layout > │ │ ├───4,483,744 B (04.30%) -- frames > │ │ │ ├──1,653,552 B (01.59%) ── nsInlineFrame > │ │ │ ├──1,415,760 B (01.36%) ── nsTextFrame > │ │ │ ├────431,376 B (00.41%) ── nsBlockFrame > │ │ │ ├────340,560 B (00.33%) ── nsHTMLScrollFrame > │ │ │ ├────302,544 B (00.29%) ── nsContinuingTextFrame > │ │ │ ├────156,408 B (00.15%) ── nsBulletFrame > │ │ │ ├─────73,024 B (00.07%) ── nsPlaceholderFrame > │ │ │ ├─────27,656 B (00.03%) ── sundries > │ │ │ ├─────23,520 B (00.02%) ── nsTableCellFrame > │ │ │ ├─────16,704 B (00.02%) ── nsImageFrame > │ │ │ ├─────15,488 B (00.01%) ── nsTableRowFrame > │ │ │ ├─────13,776 B (00.01%) ── nsTableColFrame > │ │ │ └─────13,376 B (00.01%) ── nsTableFrame > │ │ ├───3,412,192 B (03.28%) -- servo-style-structs > │ │ │ ├──1,288,224 B (01.24%) ── Display > │ │ │ ├────742,400 B (00.71%) ── Position > │ │ │ ├────308,736 B (00.30%) ── Font > │ │ │ ├────226,512 B (00.22%) ── Background > │ │ │ ├────218,304 B (00.21%) ── TextReset > │ │ │ ├────214,896 B (00.21%) ── Text > │ │ │ ├────130,560 B (00.13%) ── Border > │ │ │ ├─────81,408 B (00.08%) ── UIReset > │ │ │ ├─────61,440 B (00.06%) ── Padding > │ │ │ ├─────38,176 B (00.04%) ── UserInterface > │ │ │ ├─────29,232 B (00.03%) ── Margin > │ │ │ ├─────21,824 B (00.02%) ── sundries > │ │ │ ├─────20,080 B (00.02%) ── Color > │ │ │ ├─────20,080 B (00.02%) ── Column > │ │ │ └─────10,320 B (00.01%) ── Effects > │ │ ├───2,227,680 B (02.14%) -- computed-values > │ │ │ ├──1,182,928 B (01.14%) ── non-dom > │ │ │ └──1,044,752 B (01.00%) ── dom > │ │ ├───1,500,016 B (01.44%) ── text-runs > │ │ ├─────492,640 B (00.47%) ── line-boxes > │ │ ├─────326,688 B (00.31%) ── frame-properties > │ │ ├─────301,760 B (00.29%) ── pres-shell > │ │ ├──────27,648 B (00.03%) ── pres-contexts > │ │ └─────────176 B (00.00%) ── style-sets The 'servo-style-structs' and 'computed-values' sub-trees are new. (Prior to this patch, ComputedValues under DOM elements were tallied under the the 'dom/element-nodes' sub-tree, and ComputedValues not under DOM element were ignored.) 'servo-style-structs/sundries' aggregates all the style structs that are smaller than 8 KiB. Other notable things done by the patch are as follows. - It significantly changes the signatures of the methods measuring nsINode and its subclasses, in order to handle the tallying of style structs separately from element-nodes. Likewise for nsIFrame. - It renames the 'layout/style-structs' sub-tree as 'layout/gecko-style-structs', to clearly distinguish it from the new 'layout/servo-style-structs' sub-tree. - It adds some FFI functions to access various Rust-side data structures from C++ code. - There is a nasty hack used twice to measure Arcs, by stepping backwards from an interior pointer to a base pointer. It works, but I want to replace it with something better eventually. The "XXX WARNING" comments have details. - It makes DMD print a line to the console if it sees a pointer it doesn't recognise. This is useful for detecting when we are measuring an interior pointer instead of a base pointer, which is bad but easy to do when Arcs are involved. - It removes the Rust code for measuring CVs, because it's now all done on the C++ side. MozReview-Commit-ID: BKebACLKtCi --HG-- extra : rebase_source : 4d9a8c6b198a0ff025b811759a6bfa9f33a260ba
2017-08-11 09:37:33 +03:00
}
#include "nsStyleStructList.h"
#undef STYLE_STRUCT
if (styleSundriesSize > 0) {
REPORT_SUM_SIZE(
"/layout/style-structs/sundries", styleSundriesSize,
"The sum of all memory used by style structs which were too "
"small to be shown individually.");
Bug 1387956 - Overhaul ComputedValues measurement, and add style structs measurement. r=bholley. This patch moves measurement of ComputedValues objects from Rust to C++. Measurement now happens (a) via DOM elements and (b) remaining elements via the frame tree. Likewise for the style structs hanging off ComputedValues objects. Here is an example of the output. > ├──27,600,448 B (26.49%) -- active/window(https://en.wikipedia.org/wiki/Barack_Obama) > │ ├──12,772,544 B (12.26%) -- layout > │ │ ├───4,483,744 B (04.30%) -- frames > │ │ │ ├──1,653,552 B (01.59%) ── nsInlineFrame > │ │ │ ├──1,415,760 B (01.36%) ── nsTextFrame > │ │ │ ├────431,376 B (00.41%) ── nsBlockFrame > │ │ │ ├────340,560 B (00.33%) ── nsHTMLScrollFrame > │ │ │ ├────302,544 B (00.29%) ── nsContinuingTextFrame > │ │ │ ├────156,408 B (00.15%) ── nsBulletFrame > │ │ │ ├─────73,024 B (00.07%) ── nsPlaceholderFrame > │ │ │ ├─────27,656 B (00.03%) ── sundries > │ │ │ ├─────23,520 B (00.02%) ── nsTableCellFrame > │ │ │ ├─────16,704 B (00.02%) ── nsImageFrame > │ │ │ ├─────15,488 B (00.01%) ── nsTableRowFrame > │ │ │ ├─────13,776 B (00.01%) ── nsTableColFrame > │ │ │ └─────13,376 B (00.01%) ── nsTableFrame > │ │ ├───3,412,192 B (03.28%) -- servo-style-structs > │ │ │ ├──1,288,224 B (01.24%) ── Display > │ │ │ ├────742,400 B (00.71%) ── Position > │ │ │ ├────308,736 B (00.30%) ── Font > │ │ │ ├────226,512 B (00.22%) ── Background > │ │ │ ├────218,304 B (00.21%) ── TextReset > │ │ │ ├────214,896 B (00.21%) ── Text > │ │ │ ├────130,560 B (00.13%) ── Border > │ │ │ ├─────81,408 B (00.08%) ── UIReset > │ │ │ ├─────61,440 B (00.06%) ── Padding > │ │ │ ├─────38,176 B (00.04%) ── UserInterface > │ │ │ ├─────29,232 B (00.03%) ── Margin > │ │ │ ├─────21,824 B (00.02%) ── sundries > │ │ │ ├─────20,080 B (00.02%) ── Color > │ │ │ ├─────20,080 B (00.02%) ── Column > │ │ │ └─────10,320 B (00.01%) ── Effects > │ │ ├───2,227,680 B (02.14%) -- computed-values > │ │ │ ├──1,182,928 B (01.14%) ── non-dom > │ │ │ └──1,044,752 B (01.00%) ── dom > │ │ ├───1,500,016 B (01.44%) ── text-runs > │ │ ├─────492,640 B (00.47%) ── line-boxes > │ │ ├─────326,688 B (00.31%) ── frame-properties > │ │ ├─────301,760 B (00.29%) ── pres-shell > │ │ ├──────27,648 B (00.03%) ── pres-contexts > │ │ └─────────176 B (00.00%) ── style-sets The 'servo-style-structs' and 'computed-values' sub-trees are new. (Prior to this patch, ComputedValues under DOM elements were tallied under the the 'dom/element-nodes' sub-tree, and ComputedValues not under DOM element were ignored.) 'servo-style-structs/sundries' aggregates all the style structs that are smaller than 8 KiB. Other notable things done by the patch are as follows. - It significantly changes the signatures of the methods measuring nsINode and its subclasses, in order to handle the tallying of style structs separately from element-nodes. Likewise for nsIFrame. - It renames the 'layout/style-structs' sub-tree as 'layout/gecko-style-structs', to clearly distinguish it from the new 'layout/servo-style-structs' sub-tree. - It adds some FFI functions to access various Rust-side data structures from C++ code. - There is a nasty hack used twice to measure Arcs, by stepping backwards from an interior pointer to a base pointer. It works, but I want to replace it with something better eventually. The "XXX WARNING" comments have details. - It makes DMD print a line to the console if it sees a pointer it doesn't recognise. This is useful for detecting when we are measuring an interior pointer instead of a base pointer, which is bad but easy to do when Arcs are involved. - It removes the Rust code for measuring CVs, because it's now all done on the C++ side. MozReview-Commit-ID: BKebACLKtCi --HG-- extra : rebase_source : 4d9a8c6b198a0ff025b811759a6bfa9f33a260ba
2017-08-11 09:37:33 +03:00
}
#undef REPORT_SIZE
#undef REPORT_SUM_SIZE
#undef REPORT_COUNT
2011-06-29 16:29:29 +04:00
}
typedef nsTArray<RefPtr<nsGlobalWindowInner>> WindowArray;
NS_IMETHODIMP
nsWindowMemoryReporter::CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData, bool aAnonymize) {
nsGlobalWindowInner::InnerWindowByIdTable* windowsById =
nsGlobalWindowInner::GetWindowsTable();
NS_ENSURE_TRUE(windowsById, NS_OK);
// Hold on to every window in memory so that window objects can't be
// destroyed while we're calling the memory reporter callback.
WindowArray windows;
for (auto iter = windowsById->Iter(); !iter.Done(); iter.Next()) {
windows.AppendElement(iter.Data());
}
// Get the IDs of all the "ghost" windows, and call aHandleReport->Callback()
// for each one.
nsTHashtable<nsUint64HashKey> ghostWindows;
CheckForGhostWindows(&ghostWindows);
for (auto iter = ghostWindows.ConstIter(); !iter.Done(); iter.Next()) {
nsGlobalWindowInner::InnerWindowByIdTable* windowsById =
nsGlobalWindowInner::GetWindowsTable();
if (!windowsById) {
NS_WARNING("Couldn't get window-by-id hashtable?");
continue;
}
nsGlobalWindowInner* window = windowsById->Get(iter.Get()->GetKey());
if (!window) {
NS_WARNING("Could not look up window?");
continue;
}
nsAutoCString path;
path.AppendLiteral("ghost-windows/");
AppendWindowURI(window, path, aAnonymize);
aHandleReport->Callback(
/* process = */ EmptyCString(), path, nsIMemoryReporter::KIND_OTHER,
nsIMemoryReporter::UNITS_COUNT,
/* amount = */ 1,
/* description = */ NS_LITERAL_CSTRING("A ghost window."), aData);
}
// clang-format off
MOZ_COLLECT_REPORT(
"ghost-windows", KIND_OTHER, UNITS_COUNT, ghostWindows.Count(),
"The number of ghost windows present (the number of nodes underneath "
"explicit/window-objects/top(none)/ghost, modulo race conditions). A ghost "
"window is not shown in any tab, is not in a tab group with any "
"non-detached windows, and has met these criteria for at least "
"memory.ghost_window_timeout_seconds, or has survived a round of "
"about:memory's minimize memory usage button.\n\n"
"Ghost windows can happen legitimately, but they are often indicative of "
"leaks in the browser or add-ons.");
// clang-format on
WindowPaths windowPaths;
WindowPaths topWindowPaths;
// Collect window memory usage.
SizeOfState fakeState(nullptr); // this won't be used
nsWindowSizes windowTotalSizes(fakeState);
for (uint32_t i = 0; i < windows.Length(); i++) {
CollectWindowReports(windows[i], &windowTotalSizes, &ghostWindows,
&windowPaths, &topWindowPaths, aHandleReport, aData,
aAnonymize);
}
// Report JS memory usage. We do this from here because the JS memory
// reporter needs to be passed |windowPaths|.
xpc::JSReporter::CollectReports(&windowPaths, &topWindowPaths, aHandleReport,
aData, aAnonymize);
#ifdef MOZ_XUL
nsXULPrototypeCache::CollectMemoryReports(aHandleReport, aData);
#endif
#define REPORT(_path, _amount, _desc) \
aHandleReport->Callback(EmptyCString(), NS_LITERAL_CSTRING(_path), \
KIND_OTHER, UNITS_BYTES, _amount, \
NS_LITERAL_CSTRING(_desc), aData);
REPORT("window-objects/dom/element-nodes",
windowTotalSizes.mDOMElementNodesSize,
"This is the sum of all windows' 'dom/element-nodes' numbers.");
REPORT("window-objects/dom/text-nodes", windowTotalSizes.mDOMTextNodesSize,
"This is the sum of all windows' 'dom/text-nodes' numbers.");
REPORT("window-objects/dom/cdata-nodes", windowTotalSizes.mDOMCDATANodesSize,
"This is the sum of all windows' 'dom/cdata-nodes' numbers.");
REPORT("window-objects/dom/comment-nodes",
windowTotalSizes.mDOMCommentNodesSize,
"This is the sum of all windows' 'dom/comment-nodes' numbers.");
REPORT("window-objects/dom/event-targets",
windowTotalSizes.mDOMEventTargetsSize,
"This is the sum of all windows' 'dom/event-targets' numbers.");
REPORT("window-objects/dom/performance",
windowTotalSizes.mDOMPerformanceUserEntries +
windowTotalSizes.mDOMPerformanceResourceEntries,
"This is the sum of all windows' 'dom/performance/' numbers.");
REPORT("window-objects/dom/other", windowTotalSizes.mDOMOtherSize,
"This is the sum of all windows' 'dom/other' numbers.");
REPORT("window-objects/layout/style-sheets",
windowTotalSizes.mLayoutStyleSheetsSize,
"This is the sum of all windows' 'layout/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.mLayoutStyleSetsStylistRuleTree +
windowTotalSizes.mLayoutStyleSetsStylistElementAndPseudosMaps +
windowTotalSizes.mLayoutStyleSetsStylistInvalidationMap +
windowTotalSizes.mLayoutStyleSetsStylistRevalidationSelectors +
windowTotalSizes.mLayoutStyleSetsStylistOther +
windowTotalSizes.mLayoutStyleSetsOther,
"This is the sum of all windows' 'layout/style-sets/' numbers.");
REPORT("window-objects/layout/element-data-objects",
windowTotalSizes.mLayoutElementDataObjects,
"This is the sum of all windows' 'layout/element-data-objects' "
"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.");
REPORT("window-objects/layout/frame-properties",
windowTotalSizes.mLayoutFramePropertiesSize,
"This is the sum of all windows' 'layout/frame-properties' numbers.");
REPORT("window-objects/layout/computed-values",
windowTotalSizes.mLayoutComputedValuesDom +
windowTotalSizes.mLayoutComputedValuesNonDom +
windowTotalSizes.mLayoutComputedValuesVisited,
"This is the sum of all windows' 'layout/computed-values/' numbers.");
REPORT("window-objects/property-tables", windowTotalSizes.mPropertyTablesSize,
"This is the sum of all windows' 'property-tables' numbers.");
REPORT("window-objects/layout/line-boxes",
windowTotalSizes.mArenaSizes.mLineBoxes,
"This is the sum of all windows' 'layout/line-boxes' numbers.");
REPORT("window-objects/layout/rule-nodes",
windowTotalSizes.mArenaSizes.mRuleNodes,
"This is the sum of all windows' 'layout/rule-nodes' numbers.");
REPORT("window-objects/layout/style-contexts",
windowTotalSizes.mArenaSizes.mComputedStyles,
"This is the sum of all windows' 'layout/style-contexts' numbers.");
size_t frameTotal = 0;
#define FRAME_ID(classname, ...) \
frameTotal += windowTotalSizes.mArenaSizes.NS_ARENA_SIZES_FIELD(classname);
#define ABSTRACT_FRAME_ID(...)
#include "nsFrameIdList.h"
#undef FRAME_ID
#undef ABSTRACT_FRAME_ID
REPORT("window-objects/layout/frames", frameTotal,
"Memory used for layout frames within windows. "
"This is the sum of all windows' 'layout/frames/' numbers.");
size_t styleTotal = 0;
#define STYLE_STRUCT(name_) \
styleTotal += windowTotalSizes.mStyleSizes.NS_STYLE_SIZES_FIELD(name_);
Bug 1387956 - Overhaul ComputedValues measurement, and add style structs measurement. r=bholley. This patch moves measurement of ComputedValues objects from Rust to C++. Measurement now happens (a) via DOM elements and (b) remaining elements via the frame tree. Likewise for the style structs hanging off ComputedValues objects. Here is an example of the output. > ├──27,600,448 B (26.49%) -- active/window(https://en.wikipedia.org/wiki/Barack_Obama) > │ ├──12,772,544 B (12.26%) -- layout > │ │ ├───4,483,744 B (04.30%) -- frames > │ │ │ ├──1,653,552 B (01.59%) ── nsInlineFrame > │ │ │ ├──1,415,760 B (01.36%) ── nsTextFrame > │ │ │ ├────431,376 B (00.41%) ── nsBlockFrame > │ │ │ ├────340,560 B (00.33%) ── nsHTMLScrollFrame > │ │ │ ├────302,544 B (00.29%) ── nsContinuingTextFrame > │ │ │ ├────156,408 B (00.15%) ── nsBulletFrame > │ │ │ ├─────73,024 B (00.07%) ── nsPlaceholderFrame > │ │ │ ├─────27,656 B (00.03%) ── sundries > │ │ │ ├─────23,520 B (00.02%) ── nsTableCellFrame > │ │ │ ├─────16,704 B (00.02%) ── nsImageFrame > │ │ │ ├─────15,488 B (00.01%) ── nsTableRowFrame > │ │ │ ├─────13,776 B (00.01%) ── nsTableColFrame > │ │ │ └─────13,376 B (00.01%) ── nsTableFrame > │ │ ├───3,412,192 B (03.28%) -- servo-style-structs > │ │ │ ├──1,288,224 B (01.24%) ── Display > │ │ │ ├────742,400 B (00.71%) ── Position > │ │ │ ├────308,736 B (00.30%) ── Font > │ │ │ ├────226,512 B (00.22%) ── Background > │ │ │ ├────218,304 B (00.21%) ── TextReset > │ │ │ ├────214,896 B (00.21%) ── Text > │ │ │ ├────130,560 B (00.13%) ── Border > │ │ │ ├─────81,408 B (00.08%) ── UIReset > │ │ │ ├─────61,440 B (00.06%) ── Padding > │ │ │ ├─────38,176 B (00.04%) ── UserInterface > │ │ │ ├─────29,232 B (00.03%) ── Margin > │ │ │ ├─────21,824 B (00.02%) ── sundries > │ │ │ ├─────20,080 B (00.02%) ── Color > │ │ │ ├─────20,080 B (00.02%) ── Column > │ │ │ └─────10,320 B (00.01%) ── Effects > │ │ ├───2,227,680 B (02.14%) -- computed-values > │ │ │ ├──1,182,928 B (01.14%) ── non-dom > │ │ │ └──1,044,752 B (01.00%) ── dom > │ │ ├───1,500,016 B (01.44%) ── text-runs > │ │ ├─────492,640 B (00.47%) ── line-boxes > │ │ ├─────326,688 B (00.31%) ── frame-properties > │ │ ├─────301,760 B (00.29%) ── pres-shell > │ │ ├──────27,648 B (00.03%) ── pres-contexts > │ │ └─────────176 B (00.00%) ── style-sets The 'servo-style-structs' and 'computed-values' sub-trees are new. (Prior to this patch, ComputedValues under DOM elements were tallied under the the 'dom/element-nodes' sub-tree, and ComputedValues not under DOM element were ignored.) 'servo-style-structs/sundries' aggregates all the style structs that are smaller than 8 KiB. Other notable things done by the patch are as follows. - It significantly changes the signatures of the methods measuring nsINode and its subclasses, in order to handle the tallying of style structs separately from element-nodes. Likewise for nsIFrame. - It renames the 'layout/style-structs' sub-tree as 'layout/gecko-style-structs', to clearly distinguish it from the new 'layout/servo-style-structs' sub-tree. - It adds some FFI functions to access various Rust-side data structures from C++ code. - There is a nasty hack used twice to measure Arcs, by stepping backwards from an interior pointer to a base pointer. It works, but I want to replace it with something better eventually. The "XXX WARNING" comments have details. - It makes DMD print a line to the console if it sees a pointer it doesn't recognise. This is useful for detecting when we are measuring an interior pointer instead of a base pointer, which is bad but easy to do when Arcs are involved. - It removes the Rust code for measuring CVs, because it's now all done on the C++ side. MozReview-Commit-ID: BKebACLKtCi --HG-- extra : rebase_source : 4d9a8c6b198a0ff025b811759a6bfa9f33a260ba
2017-08-11 09:37:33 +03:00
#include "nsStyleStructList.h"
#undef STYLE_STRUCT
REPORT("window-objects/layout/style-structs", styleTotal,
Bug 1387956 - Overhaul ComputedValues measurement, and add style structs measurement. r=bholley. This patch moves measurement of ComputedValues objects from Rust to C++. Measurement now happens (a) via DOM elements and (b) remaining elements via the frame tree. Likewise for the style structs hanging off ComputedValues objects. Here is an example of the output. > ├──27,600,448 B (26.49%) -- active/window(https://en.wikipedia.org/wiki/Barack_Obama) > │ ├──12,772,544 B (12.26%) -- layout > │ │ ├───4,483,744 B (04.30%) -- frames > │ │ │ ├──1,653,552 B (01.59%) ── nsInlineFrame > │ │ │ ├──1,415,760 B (01.36%) ── nsTextFrame > │ │ │ ├────431,376 B (00.41%) ── nsBlockFrame > │ │ │ ├────340,560 B (00.33%) ── nsHTMLScrollFrame > │ │ │ ├────302,544 B (00.29%) ── nsContinuingTextFrame > │ │ │ ├────156,408 B (00.15%) ── nsBulletFrame > │ │ │ ├─────73,024 B (00.07%) ── nsPlaceholderFrame > │ │ │ ├─────27,656 B (00.03%) ── sundries > │ │ │ ├─────23,520 B (00.02%) ── nsTableCellFrame > │ │ │ ├─────16,704 B (00.02%) ── nsImageFrame > │ │ │ ├─────15,488 B (00.01%) ── nsTableRowFrame > │ │ │ ├─────13,776 B (00.01%) ── nsTableColFrame > │ │ │ └─────13,376 B (00.01%) ── nsTableFrame > │ │ ├───3,412,192 B (03.28%) -- servo-style-structs > │ │ │ ├──1,288,224 B (01.24%) ── Display > │ │ │ ├────742,400 B (00.71%) ── Position > │ │ │ ├────308,736 B (00.30%) ── Font > │ │ │ ├────226,512 B (00.22%) ── Background > │ │ │ ├────218,304 B (00.21%) ── TextReset > │ │ │ ├────214,896 B (00.21%) ── Text > │ │ │ ├────130,560 B (00.13%) ── Border > │ │ │ ├─────81,408 B (00.08%) ── UIReset > │ │ │ ├─────61,440 B (00.06%) ── Padding > │ │ │ ├─────38,176 B (00.04%) ── UserInterface > │ │ │ ├─────29,232 B (00.03%) ── Margin > │ │ │ ├─────21,824 B (00.02%) ── sundries > │ │ │ ├─────20,080 B (00.02%) ── Color > │ │ │ ├─────20,080 B (00.02%) ── Column > │ │ │ └─────10,320 B (00.01%) ── Effects > │ │ ├───2,227,680 B (02.14%) -- computed-values > │ │ │ ├──1,182,928 B (01.14%) ── non-dom > │ │ │ └──1,044,752 B (01.00%) ── dom > │ │ ├───1,500,016 B (01.44%) ── text-runs > │ │ ├─────492,640 B (00.47%) ── line-boxes > │ │ ├─────326,688 B (00.31%) ── frame-properties > │ │ ├─────301,760 B (00.29%) ── pres-shell > │ │ ├──────27,648 B (00.03%) ── pres-contexts > │ │ └─────────176 B (00.00%) ── style-sets The 'servo-style-structs' and 'computed-values' sub-trees are new. (Prior to this patch, ComputedValues under DOM elements were tallied under the the 'dom/element-nodes' sub-tree, and ComputedValues not under DOM element were ignored.) 'servo-style-structs/sundries' aggregates all the style structs that are smaller than 8 KiB. Other notable things done by the patch are as follows. - It significantly changes the signatures of the methods measuring nsINode and its subclasses, in order to handle the tallying of style structs separately from element-nodes. Likewise for nsIFrame. - It renames the 'layout/style-structs' sub-tree as 'layout/gecko-style-structs', to clearly distinguish it from the new 'layout/servo-style-structs' sub-tree. - It adds some FFI functions to access various Rust-side data structures from C++ code. - There is a nasty hack used twice to measure Arcs, by stepping backwards from an interior pointer to a base pointer. It works, but I want to replace it with something better eventually. The "XXX WARNING" comments have details. - It makes DMD print a line to the console if it sees a pointer it doesn't recognise. This is useful for detecting when we are measuring an interior pointer instead of a base pointer, which is bad but easy to do when Arcs are involved. - It removes the Rust code for measuring CVs, because it's now all done on the C++ side. MozReview-Commit-ID: BKebACLKtCi --HG-- extra : rebase_source : 4d9a8c6b198a0ff025b811759a6bfa9f33a260ba
2017-08-11 09:37:33 +03:00
"Memory used for style structs within windows. This is the sum of "
"all windows' 'layout/style-structs/' numbers.");
Bug 1387956 - Overhaul ComputedValues measurement, and add style structs measurement. r=bholley. This patch moves measurement of ComputedValues objects from Rust to C++. Measurement now happens (a) via DOM elements and (b) remaining elements via the frame tree. Likewise for the style structs hanging off ComputedValues objects. Here is an example of the output. > ├──27,600,448 B (26.49%) -- active/window(https://en.wikipedia.org/wiki/Barack_Obama) > │ ├──12,772,544 B (12.26%) -- layout > │ │ ├───4,483,744 B (04.30%) -- frames > │ │ │ ├──1,653,552 B (01.59%) ── nsInlineFrame > │ │ │ ├──1,415,760 B (01.36%) ── nsTextFrame > │ │ │ ├────431,376 B (00.41%) ── nsBlockFrame > │ │ │ ├────340,560 B (00.33%) ── nsHTMLScrollFrame > │ │ │ ├────302,544 B (00.29%) ── nsContinuingTextFrame > │ │ │ ├────156,408 B (00.15%) ── nsBulletFrame > │ │ │ ├─────73,024 B (00.07%) ── nsPlaceholderFrame > │ │ │ ├─────27,656 B (00.03%) ── sundries > │ │ │ ├─────23,520 B (00.02%) ── nsTableCellFrame > │ │ │ ├─────16,704 B (00.02%) ── nsImageFrame > │ │ │ ├─────15,488 B (00.01%) ── nsTableRowFrame > │ │ │ ├─────13,776 B (00.01%) ── nsTableColFrame > │ │ │ └─────13,376 B (00.01%) ── nsTableFrame > │ │ ├───3,412,192 B (03.28%) -- servo-style-structs > │ │ │ ├──1,288,224 B (01.24%) ── Display > │ │ │ ├────742,400 B (00.71%) ── Position > │ │ │ ├────308,736 B (00.30%) ── Font > │ │ │ ├────226,512 B (00.22%) ── Background > │ │ │ ├────218,304 B (00.21%) ── TextReset > │ │ │ ├────214,896 B (00.21%) ── Text > │ │ │ ├────130,560 B (00.13%) ── Border > │ │ │ ├─────81,408 B (00.08%) ── UIReset > │ │ │ ├─────61,440 B (00.06%) ── Padding > │ │ │ ├─────38,176 B (00.04%) ── UserInterface > │ │ │ ├─────29,232 B (00.03%) ── Margin > │ │ │ ├─────21,824 B (00.02%) ── sundries > │ │ │ ├─────20,080 B (00.02%) ── Color > │ │ │ ├─────20,080 B (00.02%) ── Column > │ │ │ └─────10,320 B (00.01%) ── Effects > │ │ ├───2,227,680 B (02.14%) -- computed-values > │ │ │ ├──1,182,928 B (01.14%) ── non-dom > │ │ │ └──1,044,752 B (01.00%) ── dom > │ │ ├───1,500,016 B (01.44%) ── text-runs > │ │ ├─────492,640 B (00.47%) ── line-boxes > │ │ ├─────326,688 B (00.31%) ── frame-properties > │ │ ├─────301,760 B (00.29%) ── pres-shell > │ │ ├──────27,648 B (00.03%) ── pres-contexts > │ │ └─────────176 B (00.00%) ── style-sets The 'servo-style-structs' and 'computed-values' sub-trees are new. (Prior to this patch, ComputedValues under DOM elements were tallied under the the 'dom/element-nodes' sub-tree, and ComputedValues not under DOM element were ignored.) 'servo-style-structs/sundries' aggregates all the style structs that are smaller than 8 KiB. Other notable things done by the patch are as follows. - It significantly changes the signatures of the methods measuring nsINode and its subclasses, in order to handle the tallying of style structs separately from element-nodes. Likewise for nsIFrame. - It renames the 'layout/style-structs' sub-tree as 'layout/gecko-style-structs', to clearly distinguish it from the new 'layout/servo-style-structs' sub-tree. - It adds some FFI functions to access various Rust-side data structures from C++ code. - There is a nasty hack used twice to measure Arcs, by stepping backwards from an interior pointer to a base pointer. It works, but I want to replace it with something better eventually. The "XXX WARNING" comments have details. - It makes DMD print a line to the console if it sees a pointer it doesn't recognise. This is useful for detecting when we are measuring an interior pointer instead of a base pointer, which is bad but easy to do when Arcs are involved. - It removes the Rust code for measuring CVs, because it's now all done on the C++ side. MozReview-Commit-ID: BKebACLKtCi --HG-- extra : rebase_source : 4d9a8c6b198a0ff025b811759a6bfa9f33a260ba
2017-08-11 09:37:33 +03:00
#undef REPORT
return NS_OK;
}
uint32_t nsWindowMemoryReporter::GetGhostTimeout() {
return Preferences::GetUint("memory.ghost_window_timeout_seconds", 60);
}
NS_IMETHODIMP
nsWindowMemoryReporter::Observe(nsISupports* aSubject, const char* aTopic,
const char16_t* aData) {
if (!strcmp(aTopic, "after-minimize-memory-usage")) {
ObserveAfterMinimizeMemoryUsage();
} else if (!strcmp(aTopic, "cycle-collector-begin")) {
if (mCheckTimer) {
mCheckTimerWaitingForCCEnd = true;
KillCheckTimer();
}
mCycleCollectorIsRunning = true;
} else if (!strcmp(aTopic, "cycle-collector-end")) {
mCycleCollectorIsRunning = false;
if (mCheckTimerWaitingForCCEnd) {
mCheckTimerWaitingForCCEnd = false;
AsyncCheckForGhostWindows();
}
} else {
MOZ_ASSERT(false);
}
return NS_OK;
}
void nsWindowMemoryReporter::ObserveDOMWindowDetached(
nsGlobalWindowInner* aWindow) {
nsWeakPtr weakWindow = do_GetWeakReference(aWindow);
if (!weakWindow) {
NS_WARNING("Couldn't take weak reference to a window?");
return;
}
mDetachedWindows.Put(weakWindow, TimeStamp());
AsyncCheckForGhostWindows();
}
// static
void nsWindowMemoryReporter::CheckTimerFired(nsITimer* aTimer, void* aData) {
if (sWindowReporter) {
MOZ_ASSERT(!sWindowReporter->mCycleCollectorIsRunning);
sWindowReporter->CheckForGhostWindows();
}
}
void nsWindowMemoryReporter::AsyncCheckForGhostWindows() {
if (mCheckTimer) {
return;
}
if (mCycleCollectorIsRunning) {
mCheckTimerWaitingForCCEnd = true;
return;
}
// If more than kTimeBetweenChecks seconds have elapsed since the last check,
// timerDelay is 0. Otherwise, it is kTimeBetweenChecks, reduced by the time
// since the last check. Reducing the delay by the time since the last check
// prevents the timer from being completely starved if it is repeatedly killed
// and restarted.
int32_t timeSinceLastCheck =
(TimeStamp::NowLoRes() - mLastCheckForGhostWindows).ToSeconds();
int32_t timerDelay =
(kTimeBetweenChecks - std::min(timeSinceLastCheck, kTimeBetweenChecks)) *
PR_MSEC_PER_SEC;
NS_NewTimerWithFuncCallback(
getter_AddRefs(mCheckTimer), CheckTimerFired, nullptr, timerDelay,
nsITimer::TYPE_ONE_SHOT,
"nsWindowMemoryReporter::AsyncCheckForGhostWindows_timer");
}
void nsWindowMemoryReporter::ObserveAfterMinimizeMemoryUsage() {
// Someone claims they've done enough GC/CCs so that all eligible windows
// have been free'd. So we deem that any windows which satisfy ghost
// criteria (1) and (2) now satisfy criterion (3) as well.
//
// To effect this change, we'll backdate some of our timestamps.
TimeStamp minTimeStamp =
TimeStamp::Now() - TimeDuration::FromSeconds(GetGhostTimeout());
for (auto iter = mDetachedWindows.Iter(); !iter.Done(); iter.Next()) {
TimeStamp& timeStamp = iter.Data();
if (!timeStamp.IsNull() && timeStamp > minTimeStamp) {
timeStamp = minTimeStamp;
}
}
}
/**
* Iterate over mDetachedWindows and update it to reflect the current state of
* the world. In particular:
*
* - Remove weak refs to windows which no longer exist.
*
* - Remove references to windows which are no longer detached.
*
* - Reset the timestamp on detached windows which share a domain with a
* non-detached window (they no longer meet ghost criterion (2)).
*
* - If a window now meets ghost criterion (2) but didn't before, set its
* timestamp to now.
*
* Additionally, if aOutGhostIDs is not null, fill it with the window IDs of
* all ghost windows we found.
*/
void nsWindowMemoryReporter::CheckForGhostWindows(
nsTHashtable<nsUint64HashKey>* aOutGhostIDs /* = nullptr */) {
nsGlobalWindowInner::InnerWindowByIdTable* windowsById =
nsGlobalWindowInner::GetWindowsTable();
if (!windowsById) {
NS_WARNING("GetWindowsTable returned null");
return;
}
mLastCheckForGhostWindows = TimeStamp::NowLoRes();
KillCheckTimer();
nsTHashtable<nsPtrHashKey<TabGroup>> nonDetachedTabGroups;
// Populate nonDetachedTabGroups.
for (auto iter = windowsById->Iter(); !iter.Done(); iter.Next()) {
// Null outer window implies null top, but calling GetTop() when there's no
// outer window causes us to spew debug warnings.
nsGlobalWindowInner* window = iter.UserData();
if (!window->GetOuterWindow() || !window->GetTopInternal()) {
// This window is detached, so we don't care about its tab group.
continue;
}
nonDetachedTabGroups.PutEntry(window->TabGroup());
}
// Update mDetachedWindows and write the ghost window IDs into aOutGhostIDs,
// if it's not null.
uint32_t ghostTimeout = GetGhostTimeout();
TimeStamp now = mLastCheckForGhostWindows;
mGhostWindowCount = 0;
for (auto iter = mDetachedWindows.Iter(); !iter.Done(); iter.Next()) {
nsWeakPtr weakKey = do_QueryInterface(iter.Key());
nsCOMPtr<mozIDOMWindow> iwindow = do_QueryReferent(weakKey);
if (!iwindow) {
// The window object has been destroyed. Stop tracking its weak ref in
// our hashtable.
iter.Remove();
continue;
}
nsPIDOMWindowInner* window = nsPIDOMWindowInner::From(iwindow);
// Avoid calling GetTop() if we have no outer window. Nothing will break if
// we do, but it will spew debug output, which can cause our test logs to
// overflow.
nsCOMPtr<nsPIDOMWindowOuter> top;
if (window->GetOuterWindow()) {
top = window->GetOuterWindow()->GetTop();
}
if (top) {
// The window is no longer detached, so we no longer want to track it.
iter.Remove();
continue;
}
TimeStamp& timeStamp = iter.Data();
if (nonDetachedTabGroups.GetEntry(window->TabGroup())) {
// This window is in the same tab group as a non-detached
// window, so reset its clock.
timeStamp = TimeStamp();
} else {
// This window is not in the same tab group as a non-detached
// window, so it meets ghost criterion (2).
if (timeStamp.IsNull()) {
// This may become a ghost window later; start its clock.
timeStamp = now;
} else if ((now - timeStamp).ToSeconds() > ghostTimeout) {
// This definitely is a ghost window, so add it to aOutGhostIDs, if
// that is not null.
mGhostWindowCount++;
if (aOutGhostIDs && window) {
aOutGhostIDs->PutEntry(window->WindowID());
}
}
}
}
Telemetry::ScalarSetMaximum(
Telemetry::ScalarID::MEMORYREPORTER_MAX_GHOST_WINDOWS, mGhostWindowCount);
}
/* static */ int64_t nsWindowMemoryReporter::GhostWindowsDistinguishedAmount() {
return sWindowReporter->mGhostWindowCount;
}
void nsWindowMemoryReporter::KillCheckTimer() {
if (mCheckTimer) {
mCheckTimer->Cancel();
mCheckTimer = nullptr;
}
}
#ifdef DEBUG
/* static */ void nsWindowMemoryReporter::UnlinkGhostWindows() {
if (!sWindowReporter) {
return;
}
nsGlobalWindowInner::InnerWindowByIdTable* windowsById =
nsGlobalWindowInner::GetWindowsTable();
if (!windowsById) {
return;
}
// Hold on to every window in memory so that window objects can't be
// destroyed while we're calling the UnlinkGhostWindows callback.
WindowArray windows;
for (auto iter = windowsById->Iter(); !iter.Done(); iter.Next()) {
windows.AppendElement(iter.Data());
}
// Get the IDs of all the "ghost" windows, and unlink them all.
nsTHashtable<nsUint64HashKey> ghostWindows;
sWindowReporter->CheckForGhostWindows(&ghostWindows);
for (auto iter = ghostWindows.ConstIter(); !iter.Done(); iter.Next()) {
nsGlobalWindowInner::InnerWindowByIdTable* windowsById =
nsGlobalWindowInner::GetWindowsTable();
if (!windowsById) {
continue;
}
RefPtr<nsGlobalWindowInner> window = windowsById->Get(iter.Get()->GetKey());
if (window) {
window->RiskyUnlink();
}
}
}
#endif