зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1443443 - Extend PContent to retrieve Performance Counters in the parent process - r=baku
Adds the IPDL layer to asynchronously retrieve in the parent process the performance counters. MozReview-Commit-ID: RbKstNx8pi --HG-- extra : rebase_source : d7c00f2ef16623dbbd88ede0f6636ca56501e151
This commit is contained in:
Родитель
3eacaf6b89
Коммит
255bc818dc
|
@ -13,6 +13,7 @@
|
|||
#include "mozilla/BasePrincipal.h"
|
||||
#include "mozilla/CycleCollectedJSRuntime.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/dom/IdleDeadline.h"
|
||||
#include "mozilla/dom/UnionTypes.h"
|
||||
#include "mozilla/dom/WindowBinding.h" // For IdleRequestCallback/Options
|
||||
|
@ -653,6 +654,19 @@ ChromeUtils::ClearRecentJSDevError(GlobalObject&)
|
|||
}
|
||||
#endif // NIGHTLY_BUILD
|
||||
|
||||
#ifndef RELEASE_OR_BETA
|
||||
/* static */ void
|
||||
ChromeUtils::RequestPerformanceMetrics(GlobalObject&)
|
||||
{
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
nsTArray<ContentParent*> children;
|
||||
ContentParent::GetAll(children);
|
||||
for (uint32_t i = 0; i < children.Length(); i++) {
|
||||
mozilla::Unused << children[i]->SendRequestPerformanceMetrics();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
constexpr auto kSkipSelfHosted = JS::SavedFrameSelfHosted::Exclude;
|
||||
|
||||
/* static */ void
|
||||
|
|
|
@ -155,6 +155,10 @@ public:
|
|||
|
||||
static void ClearRecentJSDevError(GlobalObject& aGlobal);
|
||||
|
||||
#ifndef RELEASE_OR_BETA
|
||||
static void RequestPerformanceMetrics(GlobalObject& aGlobal);
|
||||
#endif
|
||||
|
||||
static void Import(const GlobalObject& aGlobal,
|
||||
const nsAString& aResourceURI,
|
||||
const Optional<JS::Handle<JSObject*>>& aTargetObj,
|
||||
|
|
|
@ -5,10 +5,16 @@
|
|||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/dom/DocGroup.h"
|
||||
#include "mozilla/dom/DOMTypes.h"
|
||||
#include "mozilla/dom/TabGroup.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsDOMMutationObserver.h"
|
||||
#if defined(XP_WIN)
|
||||
#include <processthreadsapi.h> // for GetCurrentProcessId()
|
||||
#else
|
||||
#include <unistd.h> // for getpid()
|
||||
#endif // defined(XP_WIN)
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
@ -61,6 +67,68 @@ DocGroup::~DocGroup()
|
|||
mTabGroup->mDocGroups.RemoveEntry(mKey);
|
||||
}
|
||||
|
||||
#ifndef RELEASE_OR_BETA
|
||||
PerformanceInfo
|
||||
DocGroup::ReportPerformanceInfo()
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
#if defined(XP_WIN)
|
||||
uint32_t pid = GetCurrentProcessId();
|
||||
#else
|
||||
uint32_t pid = getpid();
|
||||
#endif
|
||||
uint64_t wid = 0;
|
||||
uint64_t pwid = 0;
|
||||
uint16_t count = 0;
|
||||
uint64_t duration = 0;
|
||||
nsCString host = NS_LITERAL_CSTRING("None");
|
||||
|
||||
for (const auto& document : *this) {
|
||||
// grabbing the host name of the first document
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(document);
|
||||
MOZ_ASSERT(doc);
|
||||
nsCOMPtr<nsIURI> docURI = doc->GetDocumentURI();
|
||||
if (!docURI) {
|
||||
continue;
|
||||
}
|
||||
docURI->GetHost(host);
|
||||
wid = doc->OuterWindowID();
|
||||
|
||||
// getting the top window id - if not possible
|
||||
// pwid gets the same value than wid
|
||||
pwid = wid;
|
||||
nsPIDOMWindowInner* win = doc->GetInnerWindow();
|
||||
if (win) {
|
||||
nsPIDOMWindowOuter* outer = win->GetOuterWindow();
|
||||
if (outer) {
|
||||
nsCOMPtr<nsPIDOMWindowOuter> top = outer->GetTop();
|
||||
if (top) {
|
||||
pwid = top->WindowID();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
duration = mPerformanceCounter->GetExecutionDuration();
|
||||
FallibleTArray<CategoryDispatch> items;
|
||||
|
||||
// now that we have the host and window ids, let's look at the perf counters
|
||||
for (uint32_t index = 0; index < (uint32_t)TaskCategory::Count; index++) {
|
||||
TaskCategory category = static_cast<TaskCategory>(index);
|
||||
count = mPerformanceCounter->GetDispatchCount(DispatchCategory(category));
|
||||
CategoryDispatch item = CategoryDispatch(index, count);
|
||||
if (!items.AppendElement(item, fallible)) {
|
||||
NS_ERROR("Could not complete the operation");
|
||||
return PerformanceInfo(host, pid, wid, pwid, duration, false, items);
|
||||
}
|
||||
}
|
||||
|
||||
// setting back all counters to zero
|
||||
mPerformanceCounter->ResetPerformanceCounters();
|
||||
return PerformanceInfo(host, pid, wid, pwid, duration, false, items);
|
||||
}
|
||||
#endif
|
||||
|
||||
nsresult
|
||||
DocGroup::Dispatch(TaskCategory aCategory,
|
||||
already_AddRefed<nsIRunnable>&& aRunnable)
|
||||
|
|
|
@ -23,6 +23,8 @@ namespace mozilla {
|
|||
class AbstractThread;
|
||||
namespace dom {
|
||||
|
||||
class PerformanceInfo;
|
||||
|
||||
// Two browsing contexts are considered "related" if they are reachable from one
|
||||
// another through window.opener, window.parent, or window.frames. This is the
|
||||
// spec concept of a "unit of related browsing contexts"
|
||||
|
@ -61,6 +63,9 @@ public:
|
|||
{
|
||||
return mPerformanceCounter;
|
||||
}
|
||||
|
||||
PerformanceInfo
|
||||
ReportPerformanceInfo();
|
||||
#endif
|
||||
TabGroup* GetTabGroup()
|
||||
{
|
||||
|
|
|
@ -26,6 +26,7 @@ XPIDL_SOURCES += [
|
|||
'nsIImageLoadingContent.idl',
|
||||
'nsIMessageManager.idl',
|
||||
'nsIObjectLoadingContent.idl',
|
||||
'nsIPerformanceMetrics.idl',
|
||||
'nsIRemoteWindowContext.idl',
|
||||
'nsIScriptChannel.idl',
|
||||
'nsISelection.idl',
|
||||
|
@ -105,6 +106,7 @@ EXPORTS += [
|
|||
'nsNameSpaceManager.h',
|
||||
'nsNodeInfoManager.h',
|
||||
'nsNodeUtils.h',
|
||||
'nsPerformanceMetrics.h',
|
||||
'nsPIDOMWindow.h',
|
||||
'nsPIDOMWindowInlines.h',
|
||||
'nsPIWindowRoot.h',
|
||||
|
@ -313,6 +315,7 @@ UNIFIED_SOURCES += [
|
|||
'nsNodeInfoManager.cpp',
|
||||
'nsNodeUtils.cpp',
|
||||
'nsOpenURIInFrameParams.cpp',
|
||||
'nsPerformanceMetrics.cpp',
|
||||
'nsPlainTextSerializer.cpp',
|
||||
'nsPropertyTable.cpp',
|
||||
'nsQueryContentEventResult.cpp',
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 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 "nsISupports.idl"
|
||||
#include "nsIArray.idl"
|
||||
|
||||
/*
|
||||
* nsIPerformanceMetricsData is used to store performance data collected
|
||||
* in all content processes by nsThread and nsWorkerThread.
|
||||
*
|
||||
* Each (host, category, pid, wid, pwid) is unique to a given DocGroup or
|
||||
* Worker, and we collect the number of dispatches and execution duration.
|
||||
*
|
||||
* This XPCOM interface reflects the data collected in Performance counters.
|
||||
* see xpcom/threads/PerformanceCounter.h
|
||||
*/
|
||||
[scriptable, builtinclass, uuid(1f9a58c9-be37-4463-8996-c7f5b9a5bef8)]
|
||||
interface nsIPerformanceMetricsDispatchCategory : nsISupports
|
||||
{
|
||||
// DispatchCategory value
|
||||
readonly attribute unsigned long category;
|
||||
// Number of dispatch.
|
||||
readonly attribute unsigned long count;
|
||||
};
|
||||
|
||||
|
||||
[scriptable, builtinclass, uuid(02b0cdc6-4be2-4154-a8a9-e8d462073200)]
|
||||
interface nsIPerformanceMetricsData : nsISupports
|
||||
{
|
||||
// Host of the document, if any
|
||||
readonly attribute AUTF8String host;
|
||||
// process id
|
||||
readonly attribute unsigned long pid;
|
||||
// window id
|
||||
readonly attribute unsigned long long wid;
|
||||
// "parent" window id
|
||||
readonly attribute unsigned long long pwid;
|
||||
// Execution time in microseconds
|
||||
readonly attribute unsigned long long duration;
|
||||
// True if the data is collected in a worker
|
||||
readonly attribute bool worker;
|
||||
// Dispatch Category counters
|
||||
readonly attribute nsIArray items;
|
||||
};
|
||||
|
||||
|
|
@ -0,0 +1,124 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- *//* 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 <nsIMutableArray.h>
|
||||
#include <nsArrayUtils.h>
|
||||
#include <nsPerformanceMetrics.h>
|
||||
|
||||
/* ------------------------------------------------------
|
||||
*
|
||||
* class PerformanceMetricsDispatchCategory
|
||||
*
|
||||
*/
|
||||
|
||||
PerformanceMetricsDispatchCategory::PerformanceMetricsDispatchCategory(uint32_t aCategory, uint32_t aCount)
|
||||
: mCategory(aCategory), mCount(aCount)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(PerformanceMetricsDispatchCategory,
|
||||
nsIPerformanceMetricsDispatchCategory);
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
PerformanceMetricsDispatchCategory::GetCategory(uint32_t* aCategory)
|
||||
{
|
||||
*aCategory = mCategory;
|
||||
return NS_OK;
|
||||
};
|
||||
|
||||
NS_IMETHODIMP
|
||||
PerformanceMetricsDispatchCategory::GetCount(uint32_t* aCount)
|
||||
{
|
||||
*aCount = mCount;
|
||||
return NS_OK;
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------
|
||||
*
|
||||
* class PerformanceMetricsData
|
||||
*
|
||||
*/
|
||||
|
||||
PerformanceMetricsData::PerformanceMetricsData(uint32_t aPid, uint64_t aWid,
|
||||
uint64_t aPwid, const nsCString& aHost,
|
||||
uint64_t aDuration, bool aWorker,
|
||||
nsIArray* aItems)
|
||||
: mPid(aPid), mWid(aWid), mPwid(aPwid), mHost(aHost)
|
||||
, mDuration(aDuration), mWorker(aWorker)
|
||||
{
|
||||
uint32_t len;
|
||||
nsresult rv = aItems->GetLength(&len);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_ASSERTION(rv == NS_OK, "Failed to ge the length");
|
||||
}
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
nsCOMPtr<nsIPerformanceMetricsDispatchCategory> item = do_QueryElementAt(aItems, i);
|
||||
mItems.AppendElement(item);
|
||||
}
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(PerformanceMetricsData, nsIPerformanceMetricsData);
|
||||
|
||||
NS_IMETHODIMP
|
||||
PerformanceMetricsData::GetHost(nsACString& aHost)
|
||||
{
|
||||
aHost = mHost;
|
||||
return NS_OK;
|
||||
};
|
||||
|
||||
NS_IMETHODIMP
|
||||
PerformanceMetricsData::GetWorker(bool* aWorker)
|
||||
{
|
||||
*aWorker = mWorker;
|
||||
return NS_OK;
|
||||
};
|
||||
|
||||
NS_IMETHODIMP
|
||||
PerformanceMetricsData::GetPid(uint32_t* aPid)
|
||||
{
|
||||
*aPid = mPid;
|
||||
return NS_OK;
|
||||
};
|
||||
|
||||
NS_IMETHODIMP
|
||||
PerformanceMetricsData::GetWid(uint64_t* aWid)
|
||||
{
|
||||
*aWid = mWid;
|
||||
return NS_OK;
|
||||
};
|
||||
|
||||
NS_IMETHODIMP
|
||||
PerformanceMetricsData::GetDuration(uint64_t* aDuration)
|
||||
{
|
||||
*aDuration = mDuration;
|
||||
return NS_OK;
|
||||
};
|
||||
|
||||
NS_IMETHODIMP
|
||||
PerformanceMetricsData::GetPwid(uint64_t* aPwid)
|
||||
{
|
||||
*aPwid = mPwid;
|
||||
return NS_OK;
|
||||
};
|
||||
|
||||
NS_IMETHODIMP
|
||||
PerformanceMetricsData::GetItems(nsIArray** aItems)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aItems);
|
||||
*aItems = nullptr;
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr<nsIMutableArray> items =
|
||||
do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
uint32_t len = mItems.Length();
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
items->AppendElement(mItems[i]);
|
||||
}
|
||||
|
||||
items.forget(aItems);
|
||||
return NS_OK;
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
#ifndef nsPerformanceMetrics_h___
|
||||
#define nsPerformanceMetrics_h___
|
||||
|
||||
#include "nsIPerformanceMetrics.h"
|
||||
|
||||
|
||||
class PerformanceMetricsDispatchCategory final : public nsIPerformanceMetricsDispatchCategory
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIPERFORMANCEMETRICSDISPATCHCATEGORY
|
||||
PerformanceMetricsDispatchCategory(uint32_t aCategory, uint32_t aCount);
|
||||
private:
|
||||
~PerformanceMetricsDispatchCategory() = default;
|
||||
|
||||
uint32_t mCategory;
|
||||
uint32_t mCount;
|
||||
};
|
||||
|
||||
|
||||
class PerformanceMetricsData final : public nsIPerformanceMetricsData
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIPERFORMANCEMETRICSDATA
|
||||
PerformanceMetricsData(uint32_t aPid, uint64_t aWid, uint64_t aPwid, const nsCString& aHost,
|
||||
uint64_t aDuration, bool aWorker, nsIArray* aItems);
|
||||
private:
|
||||
~PerformanceMetricsData() = default;
|
||||
|
||||
uint32_t mPid;
|
||||
uint64_t mWid;
|
||||
uint64_t mPwid;
|
||||
nsCString mHost;
|
||||
uint64_t mDuration;
|
||||
bool mWorker;
|
||||
nsCOMArray<nsIPerformanceMetricsDispatchCategory> mItems;
|
||||
};
|
||||
|
||||
#endif // end nsPerformanceMetrics_h__
|
|
@ -123,6 +123,10 @@ namespace ChromeUtils {
|
|||
void clearRecentJSDevError();
|
||||
#endif // NIGHTLY_BUILD
|
||||
|
||||
#ifndef RELEASE_OR_BETA
|
||||
void requestPerformanceMetrics();
|
||||
#endif
|
||||
|
||||
/**
|
||||
* IF YOU ADD NEW METHODS HERE, MAKE SURE THEY ARE THREAD-SAFE.
|
||||
*/
|
||||
|
|
|
@ -43,6 +43,8 @@
|
|||
#include "mozilla/dom/TabGroup.h"
|
||||
#include "mozilla/dom/nsIContentChild.h"
|
||||
#include "mozilla/dom/URLClassifierChild.h"
|
||||
#include "mozilla/dom/WorkerDebugger.h"
|
||||
#include "mozilla/dom/WorkerDebuggerManager.h"
|
||||
#include "mozilla/gfx/gfxVars.h"
|
||||
#include "mozilla/gfx/Logging.h"
|
||||
#include "mozilla/psm/PSMContentListener.h"
|
||||
|
@ -78,6 +80,9 @@
|
|||
#include "imgLoader.h"
|
||||
#include "GMPServiceChild.h"
|
||||
#include "NullPrincipal.h"
|
||||
#include "nsIPerformanceMetrics.h"
|
||||
#include "nsISimpleEnumerator.h"
|
||||
#include "nsIWorkerDebuggerManager.h"
|
||||
|
||||
#if !defined(XP_WIN)
|
||||
#include "mozilla/Omnijar.h"
|
||||
|
@ -1371,6 +1376,38 @@ ContentChild::GetResultForRenderingInitFailure(base::ProcessId aOtherPid)
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
ContentChild::RecvRequestPerformanceMetrics()
|
||||
{
|
||||
#ifndef RELEASE_OR_BETA
|
||||
// iterate on all WorkerDebugger
|
||||
RefPtr<WorkerDebuggerManager> wdm = WorkerDebuggerManager::GetOrCreate();
|
||||
if (NS_WARN_IF(!wdm)) {
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
for (uint32_t index = 0; index < wdm->GetDebuggersLength(); index++) {
|
||||
WorkerDebugger* debugger = wdm->GetDebuggerAt(index);
|
||||
MOZ_ASSERT(debugger);
|
||||
SendAddPerformanceMetrics(debugger->ReportPerformanceInfo());
|
||||
}
|
||||
|
||||
// iterate on all DocGroup
|
||||
nsTArray<RefPtr<TabChild>> tabs = TabChild::GetAll();
|
||||
for (const auto& tabChild : tabs) {
|
||||
TabGroup* tabGroup = tabChild->TabGroup();
|
||||
for (auto iter = tabGroup->Iter(); !iter.Done(); iter.Next()) {
|
||||
RefPtr<DocGroup> docGroup = iter.Get()->mDocGroup;
|
||||
SendAddPerformanceMetrics(docGroup->ReportPerformanceInfo());
|
||||
}
|
||||
}
|
||||
return IPC_OK();
|
||||
#endif
|
||||
#ifdef RELEASE_OR_BETA
|
||||
return IPC_OK();
|
||||
#endif
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
ContentChild::RecvInitRendering(Endpoint<PCompositorManagerChild>&& aCompositor,
|
||||
Endpoint<PImageBridgeChild>&& aImageBridge,
|
||||
|
|
|
@ -189,6 +189,9 @@ public:
|
|||
Endpoint<PVideoDecoderManagerChild>&& aVideoManager,
|
||||
nsTArray<uint32_t>&& namespaces) override;
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
RecvRequestPerformanceMetrics() override;
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
RecvReinitRendering(
|
||||
Endpoint<PCompositorManagerChild>&& aCompositor,
|
||||
|
|
|
@ -192,6 +192,7 @@
|
|||
#include "nsHostObjectProtocolHandler.h"
|
||||
#include "nsICaptivePortalService.h"
|
||||
#include "nsIObjectLoadingContent.h"
|
||||
#include "nsPerformanceMetrics.h"
|
||||
|
||||
#include "nsIBidiKeyboard.h"
|
||||
|
||||
|
@ -3329,6 +3330,44 @@ ContentParent::RecvFinishMemoryReport(const uint32_t& aGeneration)
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
ContentParent::RecvAddPerformanceMetrics(const PerformanceInfo& aMetrics)
|
||||
{
|
||||
#ifndef RELEASE_OR_BETA
|
||||
// converting the data we get from a child as a notification
|
||||
if (aMetrics.items().IsEmpty()) {
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIMutableArray> xpItems = do_CreateInstance(NS_ARRAY_CONTRACTID);
|
||||
if (NS_WARN_IF(!xpItems)) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i<aMetrics.items().Length(); i++) {
|
||||
const CategoryDispatch& entry = aMetrics.items()[i];
|
||||
nsCOMPtr<nsIPerformanceMetricsDispatchCategory> item =
|
||||
new PerformanceMetricsDispatchCategory(entry.category(),
|
||||
entry.count());
|
||||
xpItems->AppendElement(item);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPerformanceMetricsData> data =
|
||||
new PerformanceMetricsData(aMetrics.pid(), aMetrics.wid(), aMetrics.pwid(),
|
||||
aMetrics.host(), aMetrics.duration(),
|
||||
aMetrics.worker(), xpItems);
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
if (!obs) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
obs->NotifyObservers(data, "performance-metrics", nullptr);
|
||||
return IPC_OK();
|
||||
#endif
|
||||
#ifdef RELEASE_OR_BETA
|
||||
return IPC_OK();
|
||||
#endif
|
||||
}
|
||||
|
||||
PCycleCollectWithLogsParent*
|
||||
ContentParent::AllocPCycleCollectWithLogsParent(const bool& aDumpAllTraces,
|
||||
const FileDescriptor& aGCLog,
|
||||
|
|
|
@ -848,6 +848,7 @@ private:
|
|||
|
||||
mozilla::ipc::IPCResult RecvAddMemoryReport(const MemoryReport& aReport) override;
|
||||
mozilla::ipc::IPCResult RecvFinishMemoryReport(const uint32_t& aGeneration) override;
|
||||
mozilla::ipc::IPCResult RecvAddPerformanceMetrics(const PerformanceInfo& aMetrics) override;
|
||||
|
||||
virtual bool
|
||||
DeallocPJavaScriptParent(mozilla::jsipc::PJavaScriptParent*) override;
|
||||
|
|
|
@ -124,5 +124,43 @@ struct CreatedWindowInfo
|
|||
DimensionInfo dimensions;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* PerformanceInfo is used to pass performance info stored
|
||||
* in WorkerPrivate & DocGroup instances
|
||||
*
|
||||
* Each (host, pid, wid, pwid) is unique to a given DocGroup or
|
||||
* Worker, and we collect the number of dispatches per Dispatch
|
||||
* category and total execution duration.
|
||||
*
|
||||
* This IPDL struct reflects the data collected in Performance counters.
|
||||
* see xpcom/threads/PerformanceCounter.h
|
||||
*/
|
||||
struct CategoryDispatch
|
||||
{
|
||||
// DispatchCategory value
|
||||
uint16_t category;
|
||||
// Number of dispatch
|
||||
uint16_t count;
|
||||
};
|
||||
|
||||
struct PerformanceInfo
|
||||
{
|
||||
// Host of the document, if any
|
||||
nsCString host;
|
||||
// process id
|
||||
uint16_t pid;
|
||||
// window id
|
||||
uint64_t wid;
|
||||
// "parent" window id
|
||||
uint64_t pwid;
|
||||
// Execution time in microseconds
|
||||
uint64_t duration;
|
||||
// True if the data is collected in a worker
|
||||
bool worker;
|
||||
// Counters per category. For workers, a single entry
|
||||
CategoryDispatch[] items;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -400,6 +400,7 @@ child:
|
|||
bool anonymize,
|
||||
bool minimizeMemoryUsage,
|
||||
MaybeFileDesc DMDFile);
|
||||
async RequestPerformanceMetrics();
|
||||
|
||||
/**
|
||||
* Communication between the PuppetBidiKeyboard and the actual
|
||||
|
@ -1133,6 +1134,8 @@ parent:
|
|||
async MaybeReloadPlugins();
|
||||
|
||||
async BHRThreadHang(HangDetails aHangDetails);
|
||||
|
||||
async AddPerformanceMetrics(PerformanceInfo aMetrics);
|
||||
both:
|
||||
async AsyncMessage(nsString aMessage, CpowEntry[] aCpows,
|
||||
Principal aPrincipal, ClonedMessageData aData);
|
||||
|
|
|
@ -72,3 +72,4 @@ support-files =
|
|||
test_noopener_source.html
|
||||
test_noopener_target.html
|
||||
[browser_noopener_null_uri.js]
|
||||
[browser_test_performance_metrics.js]
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ts=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/. */
|
||||
|
||||
const TEST_URL = "http://example.com/browser/dom/tests/browser/dummy.html";
|
||||
ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
|
||||
|
||||
|
||||
add_task(async function test() {
|
||||
if (!AppConstants.RELEASE_OR_BETA) {
|
||||
SpecialPowers.setBoolPref('dom.performance.enable_scheduler_timing', true);
|
||||
waitForExplicitFinish();
|
||||
|
||||
await BrowserTestUtils.withNewTab({ gBrowser, url: "http://example.com" },
|
||||
async function(browser) {
|
||||
|
||||
// grab events..
|
||||
var events = [];
|
||||
function getInfoFromService(subject, topic, value) {
|
||||
subject = subject.QueryInterface(Ci.nsIPerformanceMetricsData);
|
||||
if (subject.host == "example.com") {
|
||||
events.push(subject);
|
||||
}
|
||||
}
|
||||
Services.obs.addObserver(getInfoFromService, "performance-metrics");
|
||||
|
||||
// trigger an IPDL call
|
||||
ChromeUtils.requestPerformanceMetrics();
|
||||
|
||||
// wait until we get the events back
|
||||
await BrowserTestUtils.waitForCondition(() => {
|
||||
return events.length > 0;
|
||||
}, "wait for events to come in", 100, 20);
|
||||
|
||||
// let's check the last example.com tab event we got
|
||||
let last = events[0];
|
||||
Assert.equal(last.host, "example.com", "host should be example.com");
|
||||
Assert.ok(last.duration > 0, "Duration should be positive");
|
||||
|
||||
// let's look at the XPCOM data we got back
|
||||
let items = last.items.QueryInterface(Ci.nsIMutableArray);
|
||||
let enumerator = items.enumerate();
|
||||
let total = 0;
|
||||
while (enumerator.hasMoreElements()) {
|
||||
let item = enumerator.getNext();
|
||||
item = item.QueryInterface(Ci.nsIPerformanceMetricsDispatchCategory);
|
||||
total += item.count;
|
||||
}
|
||||
Assert.ok(total > 0);
|
||||
});
|
||||
SpecialPowers.clearUserPref('dom.performance.enable_scheduler_timing');
|
||||
}
|
||||
});
|
|
@ -17,6 +17,11 @@
|
|||
#include "WorkerPrivate.h"
|
||||
#include "WorkerRunnable.h"
|
||||
#include "WorkerScope.h"
|
||||
#if defined(XP_WIN)
|
||||
#include <processthreadsapi.h> // for GetCurrentProcessId()
|
||||
#else
|
||||
#include <unistd.h> // for getpid()
|
||||
#endif // defined(XP_WIN)
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
@ -471,6 +476,44 @@ WorkerDebugger::ReportErrorToDebuggerOnMainThread(const nsAString& aFilename,
|
|||
WorkerErrorReport::LogErrorToConsole(report, 0);
|
||||
}
|
||||
|
||||
#ifndef RELEASE_OR_BETA
|
||||
PerformanceInfo
|
||||
WorkerDebugger::ReportPerformanceInfo()
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
#if defined(XP_WIN)
|
||||
uint32_t pid = GetCurrentProcessId();
|
||||
#else
|
||||
uint32_t pid = getpid();
|
||||
#endif
|
||||
uint64_t wid = mWorkerPrivate->WindowID();
|
||||
uint64_t pwid = wid;
|
||||
nsPIDOMWindowInner* win = mWorkerPrivate->GetWindow();
|
||||
if (win) {
|
||||
nsPIDOMWindowOuter* outer = win->GetOuterWindow();
|
||||
if (outer) {
|
||||
nsCOMPtr<nsPIDOMWindowOuter> top = outer->GetTop();
|
||||
if (top) {
|
||||
pwid = top->WindowID();
|
||||
}
|
||||
}
|
||||
}
|
||||
RefPtr<PerformanceCounter> perf = mWorkerPrivate->GetPerformanceCounter();
|
||||
uint16_t count = perf->GetTotalDispatchCount();
|
||||
uint64_t duration = perf->GetExecutionDuration();
|
||||
RefPtr<nsIURI> uri = mWorkerPrivate->GetResolvedScriptURI();
|
||||
CategoryDispatch item = CategoryDispatch(DispatchCategory::Worker.GetValue(), count);
|
||||
FallibleTArray<CategoryDispatch> items;
|
||||
if (!items.AppendElement(item, fallible)) {
|
||||
NS_ERROR("Could not complete the operation");
|
||||
return PerformanceInfo(uri->GetSpecOrDefault(), pid, wid, pwid, duration,
|
||||
true, items);
|
||||
}
|
||||
perf->ResetPerformanceCounters();
|
||||
return PerformanceInfo(uri->GetSpecOrDefault(), pid, wid, pwid, duration,
|
||||
true, items);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // dom namespace
|
||||
} // mozilla namespace
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#ifndef mozilla_dom_workers_WorkerDebugger_h
|
||||
#define mozilla_dom_workers_WorkerDebugger_h
|
||||
|
||||
#include "mozilla/dom/DOMTypes.h"
|
||||
#include "mozilla/dom/WorkerCommon.h"
|
||||
#include "nsIWorkerDebugger.h"
|
||||
|
||||
|
@ -43,6 +44,15 @@ public:
|
|||
ReportErrorToDebugger(const nsAString& aFilename, uint32_t aLineno,
|
||||
const nsAString& aMessage);
|
||||
|
||||
#ifndef RELEASE_OR_BETA
|
||||
/*
|
||||
* Sends back a PerformanceInfo struct from the counters
|
||||
* in mWorkerPrivate. Counters are reset to zero after this call.
|
||||
*/
|
||||
PerformanceInfo
|
||||
ReportPerformanceInfo();
|
||||
#endif
|
||||
|
||||
private:
|
||||
virtual
|
||||
~WorkerDebugger();
|
||||
|
|
|
@ -361,5 +361,17 @@ WorkerDebuggerManager::UnregisterDebuggerMainThread(
|
|||
aWorkerPrivate->SetIsDebuggerRegistered(false);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
WorkerDebuggerManager::GetDebuggersLength() const
|
||||
{
|
||||
return mDebuggers.Length();
|
||||
}
|
||||
|
||||
WorkerDebugger*
|
||||
WorkerDebuggerManager::GetDebuggerAt(uint32_t aIndex) const
|
||||
{
|
||||
return mDebuggers.SafeElementAt(aIndex, nullptr);
|
||||
}
|
||||
|
||||
} // dom namespace
|
||||
} // mozilla namespace
|
||||
|
|
|
@ -74,6 +74,12 @@ public:
|
|||
void
|
||||
UnregisterDebuggerMainThread(WorkerPrivate* aWorkerPrivate);
|
||||
|
||||
uint32_t
|
||||
GetDebuggersLength() const;
|
||||
|
||||
WorkerDebugger*
|
||||
GetDebuggerAt(uint32_t aIndex) const;
|
||||
|
||||
private:
|
||||
virtual ~WorkerDebuggerManager();
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче