mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 05:11:16 +00:00
Bug 1471517 - Converts ChromeUtils.requestPerformanceMetrics as Promise - r=baku
This ChromeUtils API now returns a promise that gets resolved once all the data has been collected via IPDL and the main process. The existing notification design and its related XPCOM classes are removed. MozReview-Commit-ID: CYKukBOC8yh --HG-- extra : rebase_source : 1e27524726ace0bfed5297d48af8be268c5b4945
This commit is contained in:
parent
cb45bdaf67
commit
80d44a0d4e
@ -12,7 +12,7 @@
|
|||||||
#include "mozilla/Base64.h"
|
#include "mozilla/Base64.h"
|
||||||
#include "mozilla/BasePrincipal.h"
|
#include "mozilla/BasePrincipal.h"
|
||||||
#include "mozilla/CycleCollectedJSRuntime.h"
|
#include "mozilla/CycleCollectedJSRuntime.h"
|
||||||
#include "mozilla/PerformanceUtils.h"
|
#include "mozilla/PerformanceMetricsCollector.h"
|
||||||
#include "mozilla/Preferences.h"
|
#include "mozilla/Preferences.h"
|
||||||
#include "mozilla/TimeStamp.h"
|
#include "mozilla/TimeStamp.h"
|
||||||
#include "mozilla/dom/ContentParent.h"
|
#include "mozilla/dom/ContentParent.h"
|
||||||
@ -655,29 +655,27 @@ ChromeUtils::ClearRecentJSDevError(GlobalObject&)
|
|||||||
}
|
}
|
||||||
#endif // NIGHTLY_BUILD
|
#endif // NIGHTLY_BUILD
|
||||||
|
|
||||||
/* static */ void
|
/* static */
|
||||||
ChromeUtils::RequestPerformanceMetrics(GlobalObject&)
|
already_AddRefed<Promise>
|
||||||
|
ChromeUtils::RequestPerformanceMetrics(GlobalObject& aGlobal,
|
||||||
|
ErrorResult& aRv)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(XRE_IsParentProcess());
|
MOZ_ASSERT(XRE_IsParentProcess());
|
||||||
|
|
||||||
// calling all content processes via IPDL (async)
|
// Creating a promise
|
||||||
nsTArray<ContentParent*> children;
|
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
|
||||||
ContentParent::GetAll(children);
|
MOZ_ASSERT(global);
|
||||||
for (uint32_t i = 0; i < children.Length(); i++) {
|
RefPtr<Promise> domPromise = Promise::Create(global, aRv);
|
||||||
mozilla::Unused << children[i]->SendRequestPerformanceMetrics();
|
if (NS_WARN_IF(aRv.Failed())) {
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
MOZ_ASSERT(domPromise);
|
||||||
|
|
||||||
|
// requesting metrics, that will be returned into the promise
|
||||||
|
PerformanceMetricsCollector::RequestMetrics(domPromise);
|
||||||
|
|
||||||
// collecting the current process counters and notifying them
|
// sending back the promise instance
|
||||||
nsTArray<PerformanceInfo> info;
|
return domPromise.forget();
|
||||||
CollectPerformanceInfo(info);
|
|
||||||
SystemGroup::Dispatch(TaskCategory::Performance,
|
|
||||||
NS_NewRunnableFunction(
|
|
||||||
"RequestPerformanceMetrics",
|
|
||||||
[info]() { mozilla::Unused << NS_WARN_IF(NS_FAILED(NotifyPerformanceInfo(info))); }
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr auto kSkipSelfHosted = JS::SavedFrameSelfHosted::Exclude;
|
constexpr auto kSkipSelfHosted = JS::SavedFrameSelfHosted::Exclude;
|
||||||
|
@ -160,7 +160,9 @@ public:
|
|||||||
|
|
||||||
static void ClearRecentJSDevError(GlobalObject& aGlobal);
|
static void ClearRecentJSDevError(GlobalObject& aGlobal);
|
||||||
|
|
||||||
static void RequestPerformanceMetrics(GlobalObject& aGlobal);
|
static already_AddRefed<Promise>
|
||||||
|
RequestPerformanceMetrics(GlobalObject& aGlobal,
|
||||||
|
ErrorResult& aRv);
|
||||||
|
|
||||||
static void Import(const GlobalObject& aGlobal,
|
static void Import(const GlobalObject& aGlobal,
|
||||||
const nsAString& aResourceURI,
|
const nsAString& aResourceURI,
|
||||||
|
@ -22,7 +22,6 @@ XPIDL_SOURCES += [
|
|||||||
'nsIImageLoadingContent.idl',
|
'nsIImageLoadingContent.idl',
|
||||||
'nsIMessageManager.idl',
|
'nsIMessageManager.idl',
|
||||||
'nsIObjectLoadingContent.idl',
|
'nsIObjectLoadingContent.idl',
|
||||||
'nsIPerformanceMetrics.idl',
|
|
||||||
'nsIRemoteWindowContext.idl',
|
'nsIRemoteWindowContext.idl',
|
||||||
'nsIScriptChannel.idl',
|
'nsIScriptChannel.idl',
|
||||||
'nsISelectionController.idl',
|
'nsISelectionController.idl',
|
||||||
@ -98,7 +97,6 @@ EXPORTS += [
|
|||||||
'nsNameSpaceManager.h',
|
'nsNameSpaceManager.h',
|
||||||
'nsNodeInfoManager.h',
|
'nsNodeInfoManager.h',
|
||||||
'nsNodeUtils.h',
|
'nsNodeUtils.h',
|
||||||
'nsPerformanceMetrics.h',
|
|
||||||
'nsPIDOMWindow.h',
|
'nsPIDOMWindow.h',
|
||||||
'nsPIDOMWindowInlines.h',
|
'nsPIDOMWindowInlines.h',
|
||||||
'nsPIWindowRoot.h',
|
'nsPIWindowRoot.h',
|
||||||
@ -329,7 +327,6 @@ UNIFIED_SOURCES += [
|
|||||||
'nsNodeInfoManager.cpp',
|
'nsNodeInfoManager.cpp',
|
||||||
'nsNodeUtils.cpp',
|
'nsNodeUtils.cpp',
|
||||||
'nsOpenURIInFrameParams.cpp',
|
'nsOpenURIInFrameParams.cpp',
|
||||||
'nsPerformanceMetrics.cpp',
|
|
||||||
'nsPlainTextSerializer.cpp',
|
'nsPlainTextSerializer.cpp',
|
||||||
'nsPropertyTable.cpp',
|
'nsPropertyTable.cpp',
|
||||||
'nsQueryContentEventResult.cpp',
|
'nsQueryContentEventResult.cpp',
|
||||||
|
@ -1,49 +0,0 @@
|
|||||||
/* -*- 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;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
@ -1,125 +0,0 @@
|
|||||||
/* -*- 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>
|
|
||||||
#include "nsComponentManagerUtils.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;
|
|
||||||
}
|
|
@ -1,48 +0,0 @@
|
|||||||
/* -*- 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 "nsCOMArray.h"
|
|
||||||
#include "nsIPerformanceMetrics.h"
|
|
||||||
#include "nsString.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__
|
|
@ -345,9 +345,10 @@ partial namespace ChromeUtils {
|
|||||||
object createError(DOMString message, optional object? stack = null);
|
object createError(DOMString message, optional object? stack = null);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request performance metrics to the current process & all ontent processes.
|
* Request performance metrics to the current process & all content processes.
|
||||||
*/
|
*/
|
||||||
void requestPerformanceMetrics();
|
[Throws]
|
||||||
|
Promise<sequence<PerformanceInfoDictionary>> requestPerformanceMetrics();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a Promise containing a sequence of I/O activities
|
* Returns a Promise containing a sequence of I/O activities
|
||||||
@ -356,6 +357,25 @@ partial namespace ChromeUtils {
|
|||||||
Promise<sequence<IOActivityDataDictionary>> requestIOActivity();
|
Promise<sequence<IOActivityDataDictionary>> requestIOActivity();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dictionaries duplicating IPDL types in dom/ipc/DOMTypes.ipdlh
|
||||||
|
* Used by requestPerformanceMetrics
|
||||||
|
*/
|
||||||
|
dictionary CategoryDispatchDictionary
|
||||||
|
{
|
||||||
|
unsigned short category = 0;
|
||||||
|
unsigned short count = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary PerformanceInfoDictionary {
|
||||||
|
DOMString host = "";
|
||||||
|
unsigned long pid = 0;
|
||||||
|
unsigned long long wid = 0;
|
||||||
|
unsigned long long pwid = 0;
|
||||||
|
unsigned long long duration = 0;
|
||||||
|
boolean worker = false;
|
||||||
|
sequence<CategoryDispatchDictionary> items = [];
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used by requestIOActivity() to return the number of bytes
|
* Used by requestIOActivity() to return the number of bytes
|
||||||
|
@ -71,6 +71,7 @@
|
|||||||
#include "mozilla/net/NeckoChild.h"
|
#include "mozilla/net/NeckoChild.h"
|
||||||
#include "mozilla/net/CookieServiceChild.h"
|
#include "mozilla/net/CookieServiceChild.h"
|
||||||
#include "mozilla/net/CaptivePortalService.h"
|
#include "mozilla/net/CaptivePortalService.h"
|
||||||
|
#include "mozilla/PerformanceMetricsCollector.h"
|
||||||
#include "mozilla/PerformanceUtils.h"
|
#include "mozilla/PerformanceUtils.h"
|
||||||
#include "mozilla/plugins/PluginInstanceParent.h"
|
#include "mozilla/plugins/PluginInstanceParent.h"
|
||||||
#include "mozilla/plugins/PluginModuleParent.h"
|
#include "mozilla/plugins/PluginModuleParent.h"
|
||||||
@ -1392,12 +1393,12 @@ ContentChild::GetResultForRenderingInitFailure(base::ProcessId aOtherPid)
|
|||||||
}
|
}
|
||||||
|
|
||||||
mozilla::ipc::IPCResult
|
mozilla::ipc::IPCResult
|
||||||
ContentChild::RecvRequestPerformanceMetrics()
|
ContentChild::RecvRequestPerformanceMetrics(const nsID& aID)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(mozilla::StaticPrefs::dom_performance_enable_scheduler_timing());
|
MOZ_ASSERT(mozilla::StaticPrefs::dom_performance_enable_scheduler_timing());
|
||||||
nsTArray<PerformanceInfo> info;
|
nsTArray<PerformanceInfo> info;
|
||||||
CollectPerformanceInfo(info);
|
CollectPerformanceInfo(info);
|
||||||
SendAddPerformanceMetrics(info);
|
SendAddPerformanceMetrics(aID, info);
|
||||||
return IPC_OK();
|
return IPC_OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,7 +192,7 @@ public:
|
|||||||
nsTArray<uint32_t>&& namespaces) override;
|
nsTArray<uint32_t>&& namespaces) override;
|
||||||
|
|
||||||
mozilla::ipc::IPCResult
|
mozilla::ipc::IPCResult
|
||||||
RecvRequestPerformanceMetrics() override;
|
RecvRequestPerformanceMetrics(const nsID& aID) override;
|
||||||
|
|
||||||
mozilla::ipc::IPCResult
|
mozilla::ipc::IPCResult
|
||||||
RecvReinitRendering(
|
RecvReinitRendering(
|
||||||
|
@ -188,7 +188,7 @@
|
|||||||
#include "ContentProcessManager.h"
|
#include "ContentProcessManager.h"
|
||||||
#include "mozilla/dom/BlobURLProtocolHandler.h"
|
#include "mozilla/dom/BlobURLProtocolHandler.h"
|
||||||
#include "mozilla/dom/ipc/StructuredCloneData.h"
|
#include "mozilla/dom/ipc/StructuredCloneData.h"
|
||||||
#include "mozilla/PerformanceUtils.h"
|
#include "mozilla/PerformanceMetricsCollector.h"
|
||||||
#include "mozilla/psm/PSMContentListener.h"
|
#include "mozilla/psm/PSMContentListener.h"
|
||||||
#include "nsPluginHost.h"
|
#include "nsPluginHost.h"
|
||||||
#include "nsPluginTags.h"
|
#include "nsPluginTags.h"
|
||||||
@ -3339,14 +3339,16 @@ ContentParent::RecvFinishMemoryReport(const uint32_t& aGeneration)
|
|||||||
}
|
}
|
||||||
|
|
||||||
mozilla::ipc::IPCResult
|
mozilla::ipc::IPCResult
|
||||||
ContentParent::RecvAddPerformanceMetrics(nsTArray<PerformanceInfo>&& aMetrics)
|
ContentParent::RecvAddPerformanceMetrics(const nsID& aID,
|
||||||
|
nsTArray<PerformanceInfo>&& aMetrics)
|
||||||
{
|
{
|
||||||
if (!mozilla::StaticPrefs::dom_performance_enable_scheduler_timing()) {
|
if (!mozilla::StaticPrefs::dom_performance_enable_scheduler_timing()) {
|
||||||
// The pref is off, we should not get a performance metrics from the content
|
// The pref is off, we should not get a performance metrics from the content
|
||||||
// child
|
// child
|
||||||
return IPC_OK();
|
return IPC_OK();
|
||||||
}
|
}
|
||||||
Unused << NS_WARN_IF(NS_FAILED(mozilla::NotifyPerformanceInfo(aMetrics)));
|
nsresult rv = PerformanceMetricsCollector::DataReceived(aID, aMetrics);
|
||||||
|
Unused << NS_WARN_IF(NS_FAILED(rv));
|
||||||
return IPC_OK();
|
return IPC_OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -856,7 +856,7 @@ private:
|
|||||||
|
|
||||||
mozilla::ipc::IPCResult RecvAddMemoryReport(const MemoryReport& aReport) override;
|
mozilla::ipc::IPCResult RecvAddMemoryReport(const MemoryReport& aReport) override;
|
||||||
mozilla::ipc::IPCResult RecvFinishMemoryReport(const uint32_t& aGeneration) override;
|
mozilla::ipc::IPCResult RecvFinishMemoryReport(const uint32_t& aGeneration) override;
|
||||||
mozilla::ipc::IPCResult RecvAddPerformanceMetrics(nsTArray<PerformanceInfo>&& aMetrics) override;
|
mozilla::ipc::IPCResult RecvAddPerformanceMetrics(const nsID& aID, nsTArray<PerformanceInfo>&& aMetrics) override;
|
||||||
|
|
||||||
virtual bool
|
virtual bool
|
||||||
DeallocPJavaScriptParent(mozilla::jsipc::PJavaScriptParent*) override;
|
DeallocPJavaScriptParent(mozilla::jsipc::PJavaScriptParent*) override;
|
||||||
|
@ -408,7 +408,7 @@ child:
|
|||||||
bool anonymize,
|
bool anonymize,
|
||||||
bool minimizeMemoryUsage,
|
bool minimizeMemoryUsage,
|
||||||
MaybeFileDesc DMDFile);
|
MaybeFileDesc DMDFile);
|
||||||
async RequestPerformanceMetrics();
|
async RequestPerformanceMetrics(nsID aID);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Communication between the PuppetBidiKeyboard and the actual
|
* Communication between the PuppetBidiKeyboard and the actual
|
||||||
@ -1150,7 +1150,7 @@ parent:
|
|||||||
|
|
||||||
async BHRThreadHang(HangDetails aHangDetails);
|
async BHRThreadHang(HangDetails aHangDetails);
|
||||||
|
|
||||||
async AddPerformanceMetrics(PerformanceInfo[] aMetrics);
|
async AddPerformanceMetrics(nsID aID, PerformanceInfo[] aMetrics);
|
||||||
both:
|
both:
|
||||||
async AsyncMessage(nsString aMessage, CpowEntry[] aCpows,
|
async AsyncMessage(nsString aMessage, CpowEntry[] aCpows,
|
||||||
Principal aPrincipal, ClonedMessageData aData);
|
Principal aPrincipal, ClonedMessageData aData);
|
||||||
|
@ -68,12 +68,8 @@ add_task(async function test() {
|
|||||||
let duration = 0;
|
let duration = 0;
|
||||||
let total = 0;
|
let total = 0;
|
||||||
|
|
||||||
function getInfoFromService(subject, topic, value) {
|
function exploreResults(data) {
|
||||||
subject = subject.QueryInterface(Ci.nsIMutableArray);
|
for (let entry of data) {
|
||||||
let enumerator = subject.enumerate();
|
|
||||||
while (enumerator.hasMoreElements()) {
|
|
||||||
let entry = enumerator.getNext();
|
|
||||||
entry = entry.QueryInterface(Ci.nsIPerformanceMetricsData);
|
|
||||||
if (entry.pid == Services.appinfo.processID) {
|
if (entry.pid == Services.appinfo.processID) {
|
||||||
parent_process_event = true;
|
parent_process_event = true;
|
||||||
}
|
}
|
||||||
@ -83,12 +79,8 @@ add_task(async function test() {
|
|||||||
} else {
|
} else {
|
||||||
duration += entry.duration;
|
duration += entry.duration;
|
||||||
}
|
}
|
||||||
// let's look at the XPCOM data we got back
|
// let's look at the data we got back
|
||||||
let items = entry.items.QueryInterface(Ci.nsIMutableArray);
|
for (let item of entry.items) {
|
||||||
let enumerator2 = items.enumerate();
|
|
||||||
while (enumerator2.hasMoreElements()) {
|
|
||||||
let item = enumerator2.getNext();
|
|
||||||
item = item.QueryInterface(Ci.nsIPerformanceMetricsDispatchCategory);
|
|
||||||
if (entry.worker) {
|
if (entry.worker) {
|
||||||
worker_total += item.count;
|
worker_total += item.count;
|
||||||
} else {
|
} else {
|
||||||
@ -98,17 +90,9 @@ add_task(async function test() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Services.obs.addObserver(getInfoFromService, "performance-metrics");
|
// get all metrics via the promise
|
||||||
|
let results = await ChromeUtils.requestPerformanceMetrics();
|
||||||
// wait until we get some events back by triggering requestPerformanceMetrics
|
exploreResults(results);
|
||||||
await BrowserTestUtils.waitForCondition(() => {
|
|
||||||
ChromeUtils.requestPerformanceMetrics();
|
|
||||||
return worker_duration > 0 && duration > 0 && parent_process_event;
|
|
||||||
}, "wait for events to come in", 250, 20);
|
|
||||||
|
|
||||||
BrowserTestUtils.removeTab(page1);
|
|
||||||
BrowserTestUtils.removeTab(page2);
|
|
||||||
BrowserTestUtils.removeTab(page3);
|
|
||||||
|
|
||||||
Assert.ok(worker_duration > 0, "Worker duration should be positive");
|
Assert.ok(worker_duration > 0, "Worker duration should be positive");
|
||||||
Assert.ok(worker_total > 0, "Worker count should be positive");
|
Assert.ok(worker_total > 0, "Worker count should be positive");
|
||||||
@ -117,5 +101,8 @@ add_task(async function test() {
|
|||||||
Assert.ok(parent_process_event, "parent process sent back some events");
|
Assert.ok(parent_process_event, "parent process sent back some events");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
BrowserTestUtils.removeTab(page1);
|
||||||
|
BrowserTestUtils.removeTab(page2);
|
||||||
|
BrowserTestUtils.removeTab(page3);
|
||||||
SpecialPowers.clearUserPref('dom.performance.enable_scheduler_timing');
|
SpecialPowers.clearUserPref('dom.performance.enable_scheduler_timing');
|
||||||
});
|
});
|
||||||
|
@ -478,6 +478,7 @@ PerformanceInfo
|
|||||||
WorkerDebugger::ReportPerformanceInfo()
|
WorkerDebugger::ReportPerformanceInfo()
|
||||||
{
|
{
|
||||||
AssertIsOnMainThread();
|
AssertIsOnMainThread();
|
||||||
|
|
||||||
#if defined(XP_WIN)
|
#if defined(XP_WIN)
|
||||||
uint32_t pid = GetCurrentProcessId();
|
uint32_t pid = GetCurrentProcessId();
|
||||||
#else
|
#else
|
||||||
@ -495,22 +496,29 @@ WorkerDebugger::ReportPerformanceInfo()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RefPtr<PerformanceCounter> perf = mWorkerPrivate->GetPerformanceCounter();
|
|
||||||
uint16_t count = perf->GetTotalDispatchCount();
|
|
||||||
uint64_t duration = perf->GetExecutionDuration();
|
|
||||||
RefPtr<nsIURI> uri = mWorkerPrivate->GetResolvedScriptURI();
|
|
||||||
|
|
||||||
// Workers only produce metrics for a single category - DispatchCategory::Worker.
|
// Workers only produce metrics for a single category - DispatchCategory::Worker.
|
||||||
// We still return an array of CategoryDispatch so the PerformanceInfo
|
// We still return an array of CategoryDispatch so the PerformanceInfo
|
||||||
// struct is common to all performance counters throughout Firefox.
|
// struct is common to all performance counters throughout Firefox.
|
||||||
FallibleTArray<CategoryDispatch> items;
|
FallibleTArray<CategoryDispatch> items;
|
||||||
CategoryDispatch item = CategoryDispatch(DispatchCategory::Worker.GetValue(), count);
|
uint64_t duration = 0;
|
||||||
if (!items.AppendElement(item, fallible)) {
|
uint16_t count = 0;
|
||||||
NS_ERROR("Could not complete the operation");
|
RefPtr<nsIURI> uri = mWorkerPrivate->GetResolvedScriptURI();
|
||||||
return PerformanceInfo(uri->GetSpecOrDefault(), pid, wid, pwid, duration,
|
|
||||||
|
RefPtr<PerformanceCounter> perf = mWorkerPrivate->GetPerformanceCounter();
|
||||||
|
if (perf) {
|
||||||
|
count = perf->GetTotalDispatchCount();
|
||||||
|
duration = perf->GetExecutionDuration();
|
||||||
|
CategoryDispatch item = CategoryDispatch(DispatchCategory::Worker.GetValue(), count);
|
||||||
|
if (!items.AppendElement(item, fallible)) {
|
||||||
|
NS_ERROR("Could not complete the operation");
|
||||||
|
return PerformanceInfo(uri->GetSpecOrDefault(), pid, wid, pwid, duration,
|
||||||
true, items);
|
true, items);
|
||||||
|
}
|
||||||
|
perf->ResetPerformanceCounters();
|
||||||
}
|
}
|
||||||
perf->ResetPerformanceCounters();
|
|
||||||
return PerformanceInfo(uri->GetSpecOrDefault(), pid, wid, pwid, duration,
|
return PerformanceInfo(uri->GetSpecOrDefault(), pid, wid, pwid, duration,
|
||||||
true, items);
|
true, items);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,220 @@
|
|||||||
|
/* -*- 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/Logging.h"
|
||||||
|
#include "mozilla/PerformanceUtils.h"
|
||||||
|
#include "mozilla/PerformanceMetricsCollector.h"
|
||||||
|
#include "mozilla/dom/ContentParent.h"
|
||||||
|
#include "mozilla/dom/Promise.h"
|
||||||
|
#include "mozilla/dom/WorkerDebugger.h"
|
||||||
|
#include "mozilla/dom/WorkerDebuggerManager.h"
|
||||||
|
|
||||||
|
using namespace mozilla;
|
||||||
|
using namespace mozilla::dom;
|
||||||
|
|
||||||
|
static mozilla::LazyLogModule sPerfLog("PerformanceMetricsCollector");
|
||||||
|
#ifdef LOG
|
||||||
|
#undef LOG
|
||||||
|
#endif
|
||||||
|
#define LOG(args) MOZ_LOG(sPerfLog, mozilla::LogLevel::Debug, args)
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
//
|
||||||
|
// class AggregatedResults
|
||||||
|
//
|
||||||
|
AggregatedResults::AggregatedResults(nsID aUUID,
|
||||||
|
PerformanceMetricsCollector* aCollector,
|
||||||
|
dom::Promise* aPromise)
|
||||||
|
: mPromise(aPromise)
|
||||||
|
, mPendingResults(0)
|
||||||
|
, mCollector(aCollector)
|
||||||
|
, mUUID(aUUID)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aCollector);
|
||||||
|
MOZ_ASSERT(aPromise);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AggregatedResults::Abort(nsresult aReason)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(mPromise);
|
||||||
|
MOZ_ASSERT(NS_FAILED(aReason));
|
||||||
|
mPromise->MaybeReject(aReason);
|
||||||
|
mPromise = nullptr;
|
||||||
|
mPendingResults = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AggregatedResults::AppendResult(const nsTArray<dom::PerformanceInfo>& aMetrics)
|
||||||
|
{
|
||||||
|
if (!mPromise) {
|
||||||
|
// A previous call failed and the promise was already rejected
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
MOZ_ASSERT(mPendingResults > 0);
|
||||||
|
|
||||||
|
// Each PerformanceInfo is converted into a PerformanceInfoDictionary
|
||||||
|
for (const PerformanceInfo& result : aMetrics) {
|
||||||
|
mozilla::dom::Sequence<mozilla::dom::CategoryDispatchDictionary> items;
|
||||||
|
|
||||||
|
for (const CategoryDispatch& entry : result.items()) {
|
||||||
|
CategoryDispatchDictionary* item = items.AppendElement(fallible);
|
||||||
|
if (NS_WARN_IF(!item)) {
|
||||||
|
Abort(NS_ERROR_OUT_OF_MEMORY);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
item->mCategory = entry.category();
|
||||||
|
item->mCount = entry.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
PerformanceInfoDictionary* data = mData.AppendElement(fallible);
|
||||||
|
if (NS_WARN_IF(!data)) {
|
||||||
|
Abort(NS_ERROR_OUT_OF_MEMORY);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
data->mPid = result.pid();
|
||||||
|
data->mWid = result.wid();
|
||||||
|
data->mPwid = result.pwid();
|
||||||
|
data->mHost = *result.host().get();
|
||||||
|
data->mDuration = result.pid();
|
||||||
|
data->mWorker = result.worker();
|
||||||
|
data->mItems = items;
|
||||||
|
}
|
||||||
|
|
||||||
|
mPendingResults--;
|
||||||
|
if (mPendingResults) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG(("[%s] All data collected, resolving promise", nsIDToCString(mUUID).get()));
|
||||||
|
mPromise->MaybeResolve(mData);
|
||||||
|
mCollector->ForgetAggregatedResults(mUUID);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AggregatedResults::SetNumResultsRequired(uint32_t aNumResultsRequired)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(!mPendingResults && aNumResultsRequired);
|
||||||
|
mPendingResults = aNumResultsRequired;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// class PerformanceMetricsCollector (singleton)
|
||||||
|
//
|
||||||
|
|
||||||
|
// raw pointer for the singleton
|
||||||
|
PerformanceMetricsCollector* gInstance = nullptr;
|
||||||
|
|
||||||
|
PerformanceMetricsCollector::~PerformanceMetricsCollector()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(gInstance == this);
|
||||||
|
gInstance = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PerformanceMetricsCollector::ForgetAggregatedResults(const nsID& aUUID)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(gInstance);
|
||||||
|
MOZ_ASSERT(XRE_IsParentProcess());
|
||||||
|
// This Remove() call will trigger AggregatedResults DTOR and if its
|
||||||
|
// the last in the table, the DTOR of PerformanceMetricsCollector.
|
||||||
|
// That's why we need to make sure we hold a reference here before the call
|
||||||
|
RefPtr<PerformanceMetricsCollector> kungFuDeathGrip = this;
|
||||||
|
LOG(("[%s] Removing from the table", nsIDToCString(aUUID).get()));
|
||||||
|
mAggregatedResults.Remove(aUUID);
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
void
|
||||||
|
PerformanceMetricsCollector::RequestMetrics(dom::Promise* aPromise)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aPromise);
|
||||||
|
MOZ_ASSERT(XRE_IsParentProcess());
|
||||||
|
RefPtr<PerformanceMetricsCollector> pmc = gInstance;
|
||||||
|
if (!pmc) {
|
||||||
|
pmc = new PerformanceMetricsCollector();
|
||||||
|
gInstance = pmc;
|
||||||
|
}
|
||||||
|
pmc->RequestMetricsInternal(aPromise);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PerformanceMetricsCollector::RequestMetricsInternal(dom::Promise* aPromise)
|
||||||
|
{
|
||||||
|
// each request has its own UUID
|
||||||
|
nsID uuid;
|
||||||
|
nsresult rv = nsContentUtils::GenerateUUIDInPlace(uuid);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
aPromise->MaybeReject(rv);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG(("[%s] Requesting Performance Metrics", nsIDToCString(uuid).get()));
|
||||||
|
|
||||||
|
// Getting all content processes
|
||||||
|
nsTArray<ContentParent*> children;
|
||||||
|
ContentParent::GetAll(children);
|
||||||
|
|
||||||
|
uint32_t numChildren = children.Length();
|
||||||
|
LOG(("[%s] Expecting %d results back", nsIDToCString(uuid).get(), numChildren + 1));
|
||||||
|
|
||||||
|
// keep track of all results in an AggregatedResults instance
|
||||||
|
UniquePtr<AggregatedResults> results = MakeUnique<AggregatedResults>(uuid, this, aPromise);
|
||||||
|
|
||||||
|
// We want to get back as many results as children, plus the result
|
||||||
|
// from the content parent itself
|
||||||
|
results->SetNumResultsRequired(numChildren + 1);
|
||||||
|
mAggregatedResults.Put(uuid, std::move(results));
|
||||||
|
|
||||||
|
// calling all content processes via IPDL (async)
|
||||||
|
for (uint32_t i = 0; i < numChildren; i++) {
|
||||||
|
if (NS_WARN_IF(!children[i]->SendRequestPerformanceMetrics(uuid))) {
|
||||||
|
LOG(("[%s] Failed to send request to child %d", nsIDToCString(uuid).get(), i));
|
||||||
|
mAggregatedResults.GetValue(uuid)->get()->Abort(NS_ERROR_FAILURE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// collecting the current process PerformanceInfo
|
||||||
|
nsTArray<PerformanceInfo> info;
|
||||||
|
CollectPerformanceInfo(info);
|
||||||
|
DataReceived(uuid, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// static
|
||||||
|
nsresult
|
||||||
|
PerformanceMetricsCollector::DataReceived(const nsID& aUUID,
|
||||||
|
const nsTArray<PerformanceInfo>& aMetrics)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(gInstance);
|
||||||
|
MOZ_ASSERT(XRE_IsParentProcess());
|
||||||
|
return gInstance->DataReceivedInternal(aUUID, aMetrics);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
PerformanceMetricsCollector::DataReceivedInternal(const nsID& aUUID,
|
||||||
|
const nsTArray<PerformanceInfo>& aMetrics)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(gInstance == this);
|
||||||
|
UniquePtr<AggregatedResults>* results = mAggregatedResults.GetValue(aUUID);
|
||||||
|
if (!results) {
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG(("[%s] Received one PerformanceInfo array", nsIDToCString(aUUID).get()));
|
||||||
|
AggregatedResults* aggregatedResults = results->get();
|
||||||
|
MOZ_ASSERT(aggregatedResults);
|
||||||
|
|
||||||
|
// If this is the last result, APpendResult() will trigger the deletion
|
||||||
|
// of this collector, nothing should be done after this line.
|
||||||
|
aggregatedResults->AppendResult(aMetrics);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
@ -0,0 +1,87 @@
|
|||||||
|
/* -*- 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/. */
|
||||||
|
|
||||||
|
#ifndef PerformanceMetricsCollector_h
|
||||||
|
#define PerformanceMetricsCollector_h
|
||||||
|
|
||||||
|
#include "nsID.h"
|
||||||
|
#include "mozilla/dom/ChromeUtilsBinding.h" // defines PerformanceInfoDictionary
|
||||||
|
#include "mozilla/dom/DOMTypes.h" // defines PerformanceInfo
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
namespace dom {
|
||||||
|
class Promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
class PerformanceMetricsCollector;
|
||||||
|
|
||||||
|
// AggregatedResults receives PerformanceInfo results that are collected
|
||||||
|
// via IPDL from all content processes and the main process. They
|
||||||
|
// are converted into an array of PerformanceInfoDictionary dictionaries (webidl)
|
||||||
|
//
|
||||||
|
// The class is instanciated with a Promise and a number of processes
|
||||||
|
// that are supposed to send back results.
|
||||||
|
//
|
||||||
|
// Once every process have sent back its results, AggregatedResults will
|
||||||
|
// resolve the promise with all the collected data and send back the
|
||||||
|
// dictionnary.
|
||||||
|
//
|
||||||
|
class AggregatedResults final
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AggregatedResults(nsID aUUID, PerformanceMetricsCollector* aCollector,
|
||||||
|
dom::Promise* aPromise);
|
||||||
|
~AggregatedResults() = default;
|
||||||
|
void AppendResult(const nsTArray<dom::PerformanceInfo>& aMetrics);
|
||||||
|
void SetNumResultsRequired(uint32_t aNumResultsRequired);
|
||||||
|
void Abort(nsresult aReason);
|
||||||
|
|
||||||
|
private:
|
||||||
|
RefPtr<dom::Promise> mPromise;
|
||||||
|
uint32_t mPendingResults;
|
||||||
|
FallibleTArray<dom::PerformanceInfoDictionary> mData;
|
||||||
|
|
||||||
|
// AggregatedResults keeps a reference on the collector
|
||||||
|
// so it gets destructed when all pending AggregatedResults
|
||||||
|
// are themselves destructed when removed from
|
||||||
|
// PerformanceMetricsCollector::mAggregatedResults.
|
||||||
|
//
|
||||||
|
// This lifecycle ensures that everything is released once
|
||||||
|
// all pending results are sent.
|
||||||
|
RefPtr<PerformanceMetricsCollector> mCollector;
|
||||||
|
nsID mUUID;
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// PerformanceMetricsCollector is instanciated as a singleton, and creates
|
||||||
|
// one AggregatedResults instance everytime metrics are requested.
|
||||||
|
//
|
||||||
|
// Each AggregatedResults has a unique identifier (UUID) that is used
|
||||||
|
// to send metrics requests via IPDL. When metrics are back in an
|
||||||
|
// asynchronous fashion, the UUID is used to append the data to the
|
||||||
|
// right AggregatedResults instance and eventually let it resolve the
|
||||||
|
// linked promise.
|
||||||
|
//
|
||||||
|
class PerformanceMetricsCollector final
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NS_INLINE_DECL_REFCOUNTING(PerformanceMetricsCollector)
|
||||||
|
|
||||||
|
static void RequestMetrics(dom::Promise* aPromise);
|
||||||
|
static nsresult DataReceived(const nsID& aUUID,
|
||||||
|
const nsTArray<dom::PerformanceInfo>& aMetrics);
|
||||||
|
void ForgetAggregatedResults(const nsID& aUUID);
|
||||||
|
|
||||||
|
private:
|
||||||
|
~PerformanceMetricsCollector();
|
||||||
|
void RequestMetricsInternal(dom::Promise* aPromise);
|
||||||
|
nsresult DataReceivedInternal(const nsID& aUUID,
|
||||||
|
const nsTArray<dom::PerformanceInfo>& aMetrics);
|
||||||
|
nsDataHashtable<nsIDHashKey, UniquePtr<AggregatedResults>> mAggregatedResults;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace mozilla
|
||||||
|
#endif // PerformanceMetricsCollector_h
|
@ -4,8 +4,6 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include "nsIMutableArray.h"
|
|
||||||
#include "nsPerformanceMetrics.h"
|
|
||||||
#include "nsThreadUtils.h"
|
#include "nsThreadUtils.h"
|
||||||
#include "mozilla/PerformanceUtils.h"
|
#include "mozilla/PerformanceUtils.h"
|
||||||
#include "mozilla/dom/DocGroup.h"
|
#include "mozilla/dom/DocGroup.h"
|
||||||
@ -41,50 +39,4 @@ CollectPerformanceInfo(nsTArray<PerformanceInfo>& aMetrics)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
|
||||||
NotifyPerformanceInfo(const nsTArray<PerformanceInfo>& aMetrics)
|
|
||||||
{
|
|
||||||
nsresult rv;
|
|
||||||
|
|
||||||
nsCOMPtr<nsIMutableArray> array = do_CreateInstance(NS_ARRAY_CONTRACTID);
|
|
||||||
if (NS_WARN_IF(!array)) {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Each PerformanceInfo is converted into a nsIPerformanceMetricsData
|
|
||||||
for (const PerformanceInfo& info : aMetrics) {
|
|
||||||
nsCOMPtr<nsIMutableArray> items = do_CreateInstance(NS_ARRAY_CONTRACTID);
|
|
||||||
if (NS_WARN_IF(!items)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
for (const CategoryDispatch& entry : info.items()) {
|
|
||||||
nsCOMPtr<nsIPerformanceMetricsDispatchCategory> item =
|
|
||||||
new PerformanceMetricsDispatchCategory(entry.category(),
|
|
||||||
entry.count());
|
|
||||||
rv = items->AppendElement(item);
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nsCOMPtr<nsIPerformanceMetricsData> data;
|
|
||||||
data = new PerformanceMetricsData(info.pid(), info.wid(), info.pwid(),
|
|
||||||
info.host(), info.duration(),
|
|
||||||
info.worker(), items);
|
|
||||||
rv = array->AppendElement(data);
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
|
||||||
if (NS_WARN_IF(!obs)) {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
rv = obs->NotifyObservers(array, "performance-metrics", nullptr);
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#ifndef PerformanceCollector_h
|
#ifndef PerformanceUtils_h
|
||||||
#define PerformanceCollector_h
|
#define PerformanceUtils_h
|
||||||
|
|
||||||
#include "mozilla/dom/DOMTypes.h" // defines PerformanceInfo
|
#include "mozilla/dom/DOMTypes.h" // defines PerformanceInfo
|
||||||
|
|
||||||
@ -12,15 +12,9 @@ namespace mozilla {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Collects all performance info in the current process
|
* Collects all performance info in the current process
|
||||||
* and adds then in the aMetrics arrey
|
* and adds then in the aMetrics array
|
||||||
*/
|
*/
|
||||||
void CollectPerformanceInfo(nsTArray<dom::PerformanceInfo>& aMetrics);
|
void CollectPerformanceInfo(nsTArray<dom::PerformanceInfo>& aMetrics);
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts a PerformanceInfo array into a nsIPerformanceMetricsData and
|
|
||||||
* sends a performance-metrics notification with it
|
|
||||||
*/
|
|
||||||
nsresult NotifyPerformanceInfo(const nsTArray<dom::PerformanceInfo>& aMetrics);
|
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
#endif // PerformanceCollector_h
|
#endif // PerformanceUtils_h
|
||||||
|
@ -27,10 +27,12 @@ UNIFIED_SOURCES += [
|
|||||||
]
|
]
|
||||||
|
|
||||||
UNIFIED_SOURCES += [
|
UNIFIED_SOURCES += [
|
||||||
|
'PerformanceMetricsCollector.cpp',
|
||||||
'PerformanceUtils.cpp'
|
'PerformanceUtils.cpp'
|
||||||
]
|
]
|
||||||
|
|
||||||
EXPORTS.mozilla += [
|
EXPORTS.mozilla += [
|
||||||
|
'PerformanceMetricsCollector.h',
|
||||||
'PerformanceUtils.h'
|
'PerformanceUtils.h'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user