1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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 "nsThreadUtils.h"
#include "mozilla/PerformanceUtils.h"
#include "mozilla/dom/DocGroup.h"
#include "mozilla/dom/BrowserChild.h"
#include "mozilla/dom/WorkerDebugger.h"
#include "mozilla/dom/WorkerDebuggerManager.h"
#include "MediaDecoder.h"
#include "XPCJSMemoryReporter.h"
#include "jsfriendapi.h"
#include "js/MemoryMetrics.h"
#include "nsWindowMemoryReporter.h"
#include "nsDOMWindowList.h"
using namespace mozilla;
using namespace mozilla::dom;
namespace mozilla {
nsTArray<RefPtr<PerformanceInfoPromise>> CollectPerformanceInfo() {
nsTArray<RefPtr<PerformanceInfoPromise>> promises;
// collecting ReportPerformanceInfo from all WorkerDebugger instances
RefPtr<mozilla::dom::WorkerDebuggerManager> wdm =
WorkerDebuggerManager::GetOrCreate();
if (NS_WARN_IF(!wdm)) {
return promises;
}
for (uint32_t i = 0; i < wdm->GetDebuggersLength(); i++) {
const RefPtr<WorkerDebugger> debugger = wdm->GetDebuggerAt(i);
promises.AppendElement(debugger->ReportPerformanceInfo());
}
// collecting ReportPerformanceInfo from all DocGroup instances
LinkedList<TabGroup>* tabGroups = TabGroup::GetTabGroupList();
// if GetTabGroupList() returns null, we don't have any tab group
if (tabGroups) {
// Per Bug 1519038, we want to collect DocGroup objects
// and use them outside the iterator, to avoid a read-write conflict.
nsTArray<RefPtr<DocGroup>> docGroups;
for (TabGroup* tabGroup = tabGroups->getFirst(); tabGroup;
tabGroup =
static_cast<LinkedListElement<TabGroup>*>(tabGroup)->getNext()) {
for (auto iter = tabGroup->Iter(); !iter.Done(); iter.Next()) {
docGroups.AppendElement(iter.Get()->mDocGroup);
}
}
for (DocGroup* docGroup : docGroups) {
promises.AppendElement(docGroup->ReportPerformanceInfo());
}
}
return promises;
}
void AddWindowTabSizes(nsGlobalWindowOuter* aWindow, nsTabSizes* aSizes) {
Document* document = aWindow->GetDocument();
if (document && document->GetCachedSizes(aSizes)) {
// We got a cached version
return;
}
// We measure the sizes on a fresh nsTabSizes instance
// because we want to cache the value and aSizes might
// already have some values from other windows.
nsTabSizes sizes;
// 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 != nullptr) {
inner->AddSizeOfIncludingThis(windowSizes);
}
windowSizes.addToTabSizes(&sizes);
if (document) {
document->SetCachedSizes(&sizes);
}
aSizes->mDom += sizes.mDom;
aSizes->mStyle += sizes.mStyle;
aSizes->mOther += sizes.mOther;
}
nsresult GetTabSizes(nsGlobalWindowOuter* aWindow, nsTabSizes* aSizes) {
// Add the window (and inner window) sizes. Might be cached.
AddWindowTabSizes(aWindow, 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 = GetTabSizes(childWin, aSizes);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}
RefPtr<MemoryPromise> CollectMemoryInfo(
const nsCOMPtr<nsPIDOMWindowOuter>& aWindow,
const RefPtr<AbstractThread>& aEventTarget) {
// Getting Dom sizes. -- XXX should we reimplement GetTabSizes to async here ?
nsGlobalWindowOuter* window = nsGlobalWindowOuter::Cast(aWindow);
nsTabSizes sizes;
nsresult rv = GetTabSizes(window, &sizes);
if (NS_FAILED(rv)) {
return MemoryPromise::CreateAndReject(rv, __func__);
}
// Getting GC Heap Usage
JSObject* obj = window->GetGlobalJSObject();
uint64_t GCHeapUsage = 0;
if (obj != nullptr) {
GCHeapUsage = js::GetGCHeapUsageForObjectZone(obj);
}
// Getting Media sizes.
return GetMediaMemorySizes()->Then(
aEventTarget, __func__,
[GCHeapUsage, sizes](const MediaMemoryInfo& media) {
return MemoryPromise::CreateAndResolve(
PerformanceMemoryInfo(media, sizes.mDom, sizes.mStyle, sizes.mOther,
GCHeapUsage),
__func__);
},
[](const nsresult rv) {
return MemoryPromise::CreateAndReject(rv, __func__);
});
}
} // namespace mozilla
|