зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1553254 - Part 1: Allow low-overhead selective collection of internal performance probes through ChromeUtils. r=brennie,nika
Differential Revision: https://phabricator.services.mozilla.com/D32039 --HG-- extra : rebase_source : 2484b8d3d15495e63b9e02139aafd3e78a710f37
This commit is contained in:
Родитель
c19a162836
Коммит
202c0599be
|
@ -15,6 +15,7 @@
|
|||
#include "mozilla/BasePrincipal.h"
|
||||
#include "mozilla/CycleCollectedJSRuntime.h"
|
||||
#include "mozilla/PerformanceMetricsCollector.h"
|
||||
#include "mozilla/PerfStats.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/ProcInfo.h"
|
||||
#include "mozilla/RDDProcessManager.h"
|
||||
|
@ -865,6 +866,35 @@ already_AddRefed<Promise> ChromeUtils::RequestPerformanceMetrics(
|
|||
return domPromise.forget();
|
||||
}
|
||||
|
||||
void ChromeUtils::SetPerfStatsCollectionMask(GlobalObject& aGlobal,
|
||||
uint64_t aMask) {
|
||||
PerfStats::SetCollectionMask(static_cast<PerfStats::MetricMask>(aMask));
|
||||
}
|
||||
|
||||
already_AddRefed<Promise> ChromeUtils::CollectPerfStats(GlobalObject& aGlobal,
|
||||
ErrorResult& aRv) {
|
||||
// Creating a JS promise
|
||||
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
|
||||
MOZ_ASSERT(global);
|
||||
|
||||
RefPtr<Promise> promise = Promise::Create(global, aRv);
|
||||
if (aRv.Failed()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<PerfStats::PerfStatsPromise> extPromise =
|
||||
PerfStats::CollectPerfStatsJSON();
|
||||
|
||||
extPromise->Then(
|
||||
GetCurrentThreadSerialEventTarget(), __func__,
|
||||
[promise](const nsCString& aResult) {
|
||||
promise->MaybeResolve(NS_ConvertUTF8toUTF16(aResult));
|
||||
},
|
||||
[promise](bool aValue) { promise->MaybeReject(NS_ERROR_FAILURE); });
|
||||
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
constexpr auto kSkipSelfHosted = JS::SavedFrameSelfHosted::Exclude;
|
||||
|
||||
/* static */
|
||||
|
|
|
@ -140,6 +140,11 @@ class ChromeUtils {
|
|||
static already_AddRefed<Promise> RequestPerformanceMetrics(
|
||||
GlobalObject& aGlobal, ErrorResult& aRv);
|
||||
|
||||
static void SetPerfStatsCollectionMask(GlobalObject& aGlobal, uint64_t aMask);
|
||||
|
||||
static already_AddRefed<Promise> CollectPerfStats(GlobalObject& aGlobal,
|
||||
ErrorResult& aRv);
|
||||
|
||||
static already_AddRefed<Promise> RequestProcInfo(GlobalObject& aGlobal,
|
||||
ErrorResult& aRv);
|
||||
|
||||
|
|
|
@ -362,6 +362,23 @@ partial namespace ChromeUtils {
|
|||
[Throws]
|
||||
Promise<sequence<PerformanceInfoDictionary>> requestPerformanceMetrics();
|
||||
|
||||
/**
|
||||
* Set the collection of specific detailed performance timing information.
|
||||
* Selecting 0 for the mask will end existing collection. All metrics that
|
||||
* are chosen will be cleared after updating the mask.
|
||||
*
|
||||
* @param aCollectionMask A bitmask where each bit corresponds to a metric
|
||||
* to be collected as listed in PerfStats::Metric.
|
||||
*/
|
||||
void setPerfStatsCollectionMask(unsigned long long aCollectionMask);
|
||||
|
||||
/**
|
||||
* Collect results of detailed performance timing information.
|
||||
* The output is a JSON string containing performance timings.
|
||||
*/
|
||||
[Throws]
|
||||
Promise<DOMString> collectPerfStats();
|
||||
|
||||
/**
|
||||
* Returns a Promise containing a sequence of I/O activities
|
||||
*/
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "mozilla/LookAndFeel.h"
|
||||
#include "mozilla/MemoryTelemetry.h"
|
||||
#include "mozilla/NullPrincipal.h"
|
||||
#include "mozilla/PerfStats.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/ProcessHangMonitorIPC.h"
|
||||
#include "mozilla/RemoteDecoderManagerChild.h"
|
||||
|
@ -2433,6 +2434,18 @@ mozilla::ipc::IPCResult ContentChild::RecvVarUpdate(const GfxVarUpdate& aVar) {
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult ContentChild::RecvUpdatePerfStatsCollectionMask(
|
||||
const uint64_t& aMask) {
|
||||
PerfStats::SetCollectionMask(static_cast<PerfStats::MetricMask>(aMask));
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult ContentChild::RecvCollectPerfStatsJSON(
|
||||
CollectPerfStatsJSONResolver&& aResolver) {
|
||||
aResolver(PerfStats::CollectLocalPerfStatsJSON());
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult ContentChild::RecvDataStoragePut(
|
||||
const nsString& aFilename, const DataStorageItem& aItem) {
|
||||
RefPtr<DataStorage> storage = DataStorage::GetFromRawFileName(aFilename);
|
||||
|
|
|
@ -349,6 +349,12 @@ class ContentChild final : public PContentChild,
|
|||
mozilla::ipc::IPCResult RecvPreferenceUpdate(const Pref& aPref);
|
||||
mozilla::ipc::IPCResult RecvVarUpdate(const GfxVarUpdate& pref);
|
||||
|
||||
mozilla::ipc::IPCResult RecvUpdatePerfStatsCollectionMask(
|
||||
const uint64_t& aMask);
|
||||
|
||||
mozilla::ipc::IPCResult RecvCollectPerfStatsJSON(
|
||||
CollectPerfStatsJSONResolver&& aResolver);
|
||||
|
||||
mozilla::ipc::IPCResult RecvDataStoragePut(const nsString& aFilename,
|
||||
const DataStorageItem& aItem);
|
||||
|
||||
|
|
|
@ -482,6 +482,9 @@ child:
|
|||
async PreferenceUpdate(Pref pref);
|
||||
async VarUpdate(GfxVarUpdate var);
|
||||
|
||||
async UpdatePerfStatsCollectionMask(uint64_t aMask);
|
||||
async CollectPerfStatsJSON() returns (nsCString aStats);
|
||||
|
||||
async DataStoragePut(nsString aFilename, DataStorageItem aItem);
|
||||
async DataStorageRemove(nsString aFilename, nsCString aKey, DataStorageType aType);
|
||||
async DataStorageClear(nsString aFilename);
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "GPUProcessHost.h"
|
||||
#include "GPUProcessManager.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/PerfStats.h"
|
||||
#include "mozilla/StaticPrefs.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
|
@ -483,6 +484,18 @@ mozilla::ipc::IPCResult GPUParent::RecvShutdownVR() {
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult GPUParent::RecvUpdatePerfStatsCollectionMask(
|
||||
const uint64_t& aMask) {
|
||||
PerfStats::SetCollectionMask(static_cast<PerfStats::MetricMask>(aMask));
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult GPUParent::RecvCollectPerfStatsJSON(
|
||||
CollectPerfStatsJSONResolver&& aResolver) {
|
||||
aResolver(PerfStats::CollectLocalPerfStatsJSON());
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
void GPUParent::ActorDestroy(ActorDestroyReason aWhy) {
|
||||
if (AbnormalShutdown == aWhy) {
|
||||
NS_WARNING("Shutting down GPU process early due to a crash!");
|
||||
|
|
|
@ -77,6 +77,11 @@ class GPUParent final : public PGPUParent {
|
|||
const Maybe<ipc::FileDescriptor>& DMDFile);
|
||||
mozilla::ipc::IPCResult RecvShutdownVR();
|
||||
|
||||
mozilla::ipc::IPCResult RecvUpdatePerfStatsCollectionMask(
|
||||
const uint64_t& aMask);
|
||||
mozilla::ipc::IPCResult RecvCollectPerfStatsJSON(
|
||||
CollectPerfStatsJSONResolver&& aResolver);
|
||||
|
||||
void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
|
||||
private:
|
||||
|
|
|
@ -95,6 +95,10 @@ parent:
|
|||
FileDescriptor? DMDFile);
|
||||
async ShutdownVR();
|
||||
|
||||
// Functions supporting PerfStats data collection.
|
||||
async UpdatePerfStatsCollectionMask(uint64_t aMask);
|
||||
async CollectPerfStatsJSON() returns (nsCString aStats);
|
||||
|
||||
child:
|
||||
// Sent when the GPU process has initialized devices. This occurs once, after
|
||||
// Init().
|
||||
|
|
|
@ -131,6 +131,7 @@ if CONFIG['MOZ_JPROF']:
|
|||
|
||||
DIRS += [
|
||||
'/tools/code-coverage',
|
||||
'/tools/performance',
|
||||
'/tools/power',
|
||||
'/tools/profiler',
|
||||
]
|
||||
|
|
|
@ -29,6 +29,9 @@ with Files("lint/**"):
|
|||
with Files("profiler/**"):
|
||||
BUG_COMPONENT = ("Core", "Gecko Profiler")
|
||||
|
||||
with Files("performance/**"):
|
||||
BUG_COMPONENT = ("Core", "Gecko Profiler")
|
||||
|
||||
with Files("quitter/**"):
|
||||
BUG_COMPONENT = ("Testing", "General")
|
||||
|
||||
|
|
|
@ -0,0 +1,260 @@
|
|||
/* -*- Mode: C++; tab-width: 20; 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 "PerfStats.h"
|
||||
#include "nsAppRunner.h"
|
||||
#include "mozilla/dom/BrowserParent.h"
|
||||
#include "mozilla/dom/CanonicalBrowsingContext.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/dom/ContentProcessManager.h"
|
||||
#include "mozilla/dom/WindowGlobalParent.h"
|
||||
#include "mozilla/gfx/GPUChild.h"
|
||||
#include "mozilla/gfx/GPUProcessManager.h"
|
||||
#include "mozilla/JSONWriter.h"
|
||||
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
static const char* const sMetricNames[] = {"DisplayList Building",
|
||||
"Rasterizing",
|
||||
"LayerBuilding",
|
||||
"Layer Transactions",
|
||||
"Compositing",
|
||||
"Reflowing",
|
||||
"Styling"};
|
||||
|
||||
PerfStats::MetricMask PerfStats::sCollectionMask = 0;
|
||||
StaticMutex PerfStats::sMutex;
|
||||
StaticAutoPtr<PerfStats> PerfStats::sSingleton;
|
||||
|
||||
void PerfStats::SetCollectionMask(MetricMask aMask) {
|
||||
sCollectionMask = aMask;
|
||||
for (uint64_t i = 0; i < static_cast<uint64_t>(Metric::Max); i++) {
|
||||
if (!(sCollectionMask & 1 << i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
GetSingleton()->mRecordedTimes[i] = 0;
|
||||
}
|
||||
|
||||
if (!XRE_IsParentProcess()) {
|
||||
return;
|
||||
}
|
||||
|
||||
GPUProcessManager* gpuManager = GPUProcessManager::Get();
|
||||
GPUChild* gpuChild = nullptr;
|
||||
|
||||
if (gpuManager) {
|
||||
gpuChild = gpuManager->GetGPUChild();
|
||||
if (gpuChild) {
|
||||
gpuChild->SendUpdatePerfStatsCollectionMask(aMask);
|
||||
}
|
||||
}
|
||||
|
||||
nsTArray<ContentParent*> contentParents;
|
||||
ContentParent::GetAll(contentParents);
|
||||
|
||||
for (ContentParent* parent : contentParents) {
|
||||
Unused << parent->SendUpdatePerfStatsCollectionMask(aMask);
|
||||
}
|
||||
}
|
||||
|
||||
PerfStats* PerfStats::GetSingleton() {
|
||||
if (!sSingleton) {
|
||||
sSingleton = new PerfStats;
|
||||
}
|
||||
|
||||
return sSingleton.get();
|
||||
}
|
||||
|
||||
void PerfStats::RecordMeasurementStartInternal(Metric aMetric) {
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
|
||||
GetSingleton()->mRecordedStarts[static_cast<size_t>(aMetric)] =
|
||||
TimeStamp::Now();
|
||||
}
|
||||
|
||||
void PerfStats::RecordMeasurementEndInternal(Metric aMetric) {
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
|
||||
MOZ_ASSERT(sSingleton);
|
||||
|
||||
sSingleton->mRecordedTimes[static_cast<size_t>(aMetric)] +=
|
||||
(TimeStamp::Now() -
|
||||
sSingleton->mRecordedStarts[static_cast<size_t>(aMetric)])
|
||||
.ToMilliseconds();
|
||||
}
|
||||
|
||||
struct StringWriteFunc : public JSONWriteFunc {
|
||||
nsCString& mString;
|
||||
|
||||
explicit StringWriteFunc(nsCString& aString) : mString(aString) {}
|
||||
virtual void Write(const char* aStr) override { mString.Append(aStr); }
|
||||
};
|
||||
|
||||
void AppendJSONStringAsProperty(nsCString& aDest, const char* aPropertyName,
|
||||
const nsCString& aJSON) {
|
||||
// We need to manually append into the string here, since JSONWriter has no
|
||||
// way to allow us to write an existing JSON object into a property.
|
||||
aDest.Append(",\n\"");
|
||||
aDest.Append(aPropertyName);
|
||||
aDest.Append("\": ");
|
||||
aDest.Append(aJSON);
|
||||
}
|
||||
|
||||
struct PerfStatsCollector {
|
||||
PerfStatsCollector() : writer(MakeUnique<StringWriteFunc>(string)) {}
|
||||
|
||||
void AppendPerfStats(const nsCString& aString, ContentParent* aParent) {
|
||||
writer.StartObjectElement();
|
||||
writer.StringProperty("type", "content");
|
||||
writer.IntProperty("id", aParent->ChildID());
|
||||
const ManagedContainer<PBrowserParent>& browsers =
|
||||
aParent->ManagedPBrowserParent();
|
||||
|
||||
writer.StartArrayProperty("urls");
|
||||
for (auto iter = browsers.ConstIter(); !iter.Done(); iter.Next()) {
|
||||
RefPtr<BrowserParent> parent =
|
||||
BrowserParent::GetFrom(iter.Get()->GetKey());
|
||||
|
||||
CanonicalBrowsingContext* ctx = parent->GetBrowsingContext();
|
||||
if (!ctx) {
|
||||
continue;
|
||||
}
|
||||
|
||||
WindowGlobalParent* windowGlobal = ctx->GetCurrentWindowGlobal();
|
||||
if (!windowGlobal) {
|
||||
continue;
|
||||
}
|
||||
|
||||
RefPtr<nsIURI> uri = windowGlobal->GetDocumentURI();
|
||||
if (!uri) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nsAutoCString url;
|
||||
uri->GetSpec(url);
|
||||
|
||||
writer.StringElement(url.BeginReading());
|
||||
}
|
||||
writer.EndArray();
|
||||
AppendJSONStringAsProperty(string, "perfstats", aString);
|
||||
writer.EndObject();
|
||||
}
|
||||
|
||||
void AppendPerfStats(const nsCString& aString, GPUChild* aChild) {
|
||||
writer.StartObjectElement();
|
||||
writer.StringProperty("type", "gpu");
|
||||
writer.IntProperty("id", aChild->Id());
|
||||
AppendJSONStringAsProperty(string, "perfstats", aString);
|
||||
writer.EndObject();
|
||||
}
|
||||
|
||||
~PerfStatsCollector() {
|
||||
writer.EndArray();
|
||||
writer.End();
|
||||
promise.Resolve(string, __func__);
|
||||
}
|
||||
nsCString string;
|
||||
JSONWriter writer;
|
||||
MozPromiseHolder<PerfStats::PerfStatsPromise> promise;
|
||||
};
|
||||
|
||||
auto PerfStats::CollectPerfStatsJSONInternal() -> RefPtr<PerfStatsPromise> {
|
||||
if (!PerfStats::sCollectionMask) {
|
||||
return PerfStatsPromise::CreateAndReject(false, __func__);
|
||||
}
|
||||
|
||||
if (!XRE_IsParentProcess()) {
|
||||
return PerfStatsPromise::CreateAndResolve(
|
||||
CollectLocalPerfStatsJSONInternal(), __func__);
|
||||
}
|
||||
|
||||
std::shared_ptr<PerfStatsCollector> collector =
|
||||
std::make_shared<PerfStatsCollector>();
|
||||
|
||||
JSONWriter& w = collector->writer;
|
||||
|
||||
w.Start();
|
||||
{
|
||||
w.StartArrayProperty("processes");
|
||||
{
|
||||
w.StartObjectElement();
|
||||
{
|
||||
w.StringProperty("type", "parent");
|
||||
AppendJSONStringAsProperty(collector->string, "perfstats",
|
||||
CollectLocalPerfStatsJSONInternal());
|
||||
}
|
||||
w.EndObject();
|
||||
|
||||
GPUProcessManager* gpuManager = GPUProcessManager::Get();
|
||||
GPUChild* gpuChild = nullptr;
|
||||
|
||||
if (gpuManager) {
|
||||
gpuChild = gpuManager->GetGPUChild();
|
||||
}
|
||||
nsTArray<ContentParent*> contentParents;
|
||||
ContentParent::GetAll(contentParents);
|
||||
|
||||
if (gpuChild) {
|
||||
gpuChild->SendCollectPerfStatsJSON(
|
||||
[collector, gpuChild](const nsCString& aString) {
|
||||
collector->AppendPerfStats(aString, gpuChild);
|
||||
},
|
||||
// The only feasible errors here are if something goes wrong in the
|
||||
// the bridge, we choose to ignore those.
|
||||
[](mozilla::ipc::ResponseRejectReason) {});
|
||||
}
|
||||
for (ContentParent* parent : contentParents) {
|
||||
RefPtr<ContentParent> parentRef = parent;
|
||||
parent->SendCollectPerfStatsJSON(
|
||||
[collector, parentRef](const nsCString& aString) {
|
||||
collector->AppendPerfStats(aString, parentRef.get());
|
||||
},
|
||||
// The only feasible errors here are if something goes wrong in the
|
||||
// the bridge, we choose to ignore those.
|
||||
[](mozilla::ipc::ResponseRejectReason) {});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return collector->promise.Ensure(__func__);
|
||||
}
|
||||
|
||||
nsCString PerfStats::CollectLocalPerfStatsJSONInternal() {
|
||||
StaticMutexAutoLock lock(PerfStats::sMutex);
|
||||
|
||||
nsCString jsonString;
|
||||
|
||||
JSONWriter w(MakeUnique<StringWriteFunc>(jsonString));
|
||||
w.Start();
|
||||
{
|
||||
w.StartArrayProperty("metrics");
|
||||
{
|
||||
for (uint64_t i = 0; i < static_cast<uint64_t>(Metric::Max); i++) {
|
||||
if (!(sCollectionMask & (1 << i))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
w.StartObjectElement();
|
||||
{
|
||||
w.IntProperty("id", i);
|
||||
w.StringProperty("metric", sMetricNames[i]);
|
||||
w.DoubleProperty("time", mRecordedTimes[i]);
|
||||
}
|
||||
w.EndObject();
|
||||
}
|
||||
}
|
||||
w.EndArray();
|
||||
}
|
||||
w.End();
|
||||
|
||||
return jsonString;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,91 @@
|
|||
/* -*- 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 PerfStats_h
|
||||
#define PerfStats_h
|
||||
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "mozilla/StaticMutex.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "mozilla/MozPromise.h"
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <limits>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class PerfStats {
|
||||
public:
|
||||
typedef MozPromise<nsCString, bool, true> PerfStatsPromise;
|
||||
|
||||
enum class Metric : uint32_t {
|
||||
DisplayListBuilding = 0,
|
||||
Rasterizing,
|
||||
LayerBuilding,
|
||||
LayerTransactions,
|
||||
Compositing,
|
||||
Reflowing,
|
||||
Styling,
|
||||
Max
|
||||
};
|
||||
|
||||
// MetricMask is a bitmask based on 'Metric', i.e. Metric::LayerBuilding (2)
|
||||
// is synonymous to 1 << 2 in MetricMask.
|
||||
using MetricMask = uint64_t;
|
||||
|
||||
static void RecordMeasurementStart(Metric aMetric) {
|
||||
if (!(sCollectionMask & (1 << static_cast<uint64_t>(aMetric)))) {
|
||||
return;
|
||||
}
|
||||
RecordMeasurementStartInternal(aMetric);
|
||||
}
|
||||
|
||||
static void RecordMeasurementEnd(Metric aMetric) {
|
||||
if (!(sCollectionMask & (1 << static_cast<uint64_t>(aMetric)))) {
|
||||
return;
|
||||
}
|
||||
RecordMeasurementEndInternal(aMetric);
|
||||
}
|
||||
|
||||
template <Metric N>
|
||||
class AutoMetricRecording {
|
||||
public:
|
||||
AutoMetricRecording() { PerfStats::RecordMeasurementStart(N); }
|
||||
~AutoMetricRecording() { PerfStats::RecordMeasurementEnd(N); }
|
||||
};
|
||||
|
||||
static void SetCollectionMask(MetricMask aMask);
|
||||
|
||||
static RefPtr<PerfStatsPromise> CollectPerfStatsJSON() {
|
||||
return GetSingleton()->CollectPerfStatsJSONInternal();
|
||||
}
|
||||
|
||||
static nsCString CollectLocalPerfStatsJSON() {
|
||||
return GetSingleton()->CollectLocalPerfStatsJSONInternal();
|
||||
}
|
||||
|
||||
private:
|
||||
static PerfStats* GetSingleton();
|
||||
static void RecordMeasurementStartInternal(Metric aMetric);
|
||||
static void RecordMeasurementEndInternal(Metric aMetric);
|
||||
|
||||
RefPtr<PerfStatsPromise> CollectPerfStatsJSONInternal();
|
||||
nsCString CollectLocalPerfStatsJSONInternal();
|
||||
|
||||
static MetricMask sCollectionMask;
|
||||
static StaticMutex sMutex;
|
||||
static StaticAutoPtr<PerfStats> sSingleton;
|
||||
TimeStamp mRecordedStarts[static_cast<size_t>(Metric::Max)];
|
||||
double mRecordedTimes[static_cast<size_t>(Metric::Max)];
|
||||
};
|
||||
|
||||
static_assert(1 << (static_cast<uint64_t>(PerfStats::Metric::Max) - 1) <=
|
||||
std::numeric_limits<PerfStats::MetricMask>::max(),
|
||||
"More metrics than can fit into sCollectionMask bitmask");
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // PerfStats_h
|
|
@ -0,0 +1,17 @@
|
|||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'PerfStats.cpp',
|
||||
]
|
||||
|
||||
EXPORTS.mozilla += [
|
||||
'PerfStats.h',
|
||||
]
|
||||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
Загрузка…
Ссылка в новой задаче