зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 24 changesets (bug 1666566, bug 1675409) for causing hazard failures in profiler/core/platform.cpp
CLOSED TREE Backed out changeset 4d8af8533fd4 (bug 1666566) Backed out changeset f031a3a8a20f (bug 1675409) Backed out changeset 2b7e1a031921 (bug 1675409) Backed out changeset bda5a24b2d0a (bug 1675409) Backed out changeset 4282e2284314 (bug 1675409) Backed out changeset 0637f1b26e9f (bug 1675409) Backed out changeset 67ae04c8f607 (bug 1675409) Backed out changeset 6c7b3f3618ef (bug 1675409) Backed out changeset 2f325c22d169 (bug 1675409) Backed out changeset 1e48ff70ad8f (bug 1675409) Backed out changeset 1dfc32d6871d (bug 1675409) Backed out changeset 4f1f218a777b (bug 1675409) Backed out changeset e6ac8722b38e (bug 1675409) Backed out changeset cf132e15fb57 (bug 1675409) Backed out changeset a126e6b00ba9 (bug 1675409) Backed out changeset fbc7fbb04f33 (bug 1675409) Backed out changeset 554c69681474 (bug 1675409) Backed out changeset 44d0521c701f (bug 1675409) Backed out changeset 04653dfe4720 (bug 1675409) Backed out changeset 41ca2c043a00 (bug 1675409) Backed out changeset 264ae4c805d4 (bug 1675409) Backed out changeset 5f3bbdac0d52 (bug 1675409) Backed out changeset 11311c11a6e8 (bug 1675409) Backed out changeset 0355fbc44baf (bug 1675409)
This commit is contained in:
Родитель
d06ca5f7d1
Коммит
c0d25b01b2
|
@ -244,6 +244,10 @@
|
||||||
# include "nsIWebBrowserPrint.h"
|
# include "nsIWebBrowserPrint.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
|
# include "ProfilerMarkerPayload.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
using namespace mozilla::dom;
|
using namespace mozilla::dom;
|
||||||
using namespace mozilla::net;
|
using namespace mozilla::net;
|
||||||
|
|
|
@ -51,6 +51,9 @@
|
||||||
#include "nsThreadUtils.h"
|
#include "nsThreadUtils.h"
|
||||||
#include "mozJSComponentLoader.h"
|
#include "mozJSComponentLoader.h"
|
||||||
#include "GeckoProfiler.h"
|
#include "GeckoProfiler.h"
|
||||||
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
|
# include "ProfilerMarkerPayload.h"
|
||||||
|
#endif
|
||||||
#include "nsIException.h"
|
#include "nsIException.h"
|
||||||
|
|
||||||
namespace mozilla::dom {
|
namespace mozilla::dom {
|
||||||
|
|
|
@ -22,6 +22,9 @@
|
||||||
#include "TimeoutBudgetManager.h"
|
#include "TimeoutBudgetManager.h"
|
||||||
#include "mozilla/net/WebSocketEventService.h"
|
#include "mozilla/net/WebSocketEventService.h"
|
||||||
#include "mozilla/MediaManager.h"
|
#include "mozilla/MediaManager.h"
|
||||||
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
|
# include "ProfilerMarkerPayload.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
using namespace mozilla::dom;
|
using namespace mozilla::dom;
|
||||||
|
@ -151,13 +154,10 @@ void TimeoutManager::MoveIdleToActive() {
|
||||||
int(elapsed.ToMilliseconds()), int(target.ToMilliseconds()),
|
int(elapsed.ToMilliseconds()), int(target.ToMilliseconds()),
|
||||||
int(delta.ToMilliseconds()));
|
int(delta.ToMilliseconds()));
|
||||||
// don't have end before start...
|
// don't have end before start...
|
||||||
PROFILER_MARKER_TEXT(
|
PROFILER_ADD_MARKER_WITH_PAYLOAD(
|
||||||
"setTimeout deferred release", DOM,
|
"setTimeout deferred release", DOM, TextMarkerPayload,
|
||||||
MarkerOptions(
|
(marker, delta.ToMilliseconds() >= 0 ? timeout->When() : now, now,
|
||||||
MarkerTiming::Interval(
|
Some(mWindow.WindowID())));
|
||||||
delta.ToMilliseconds() >= 0 ? timeout->When() : now, now),
|
|
||||||
MarkerInnerWindowId(mWindow.WindowID())),
|
|
||||||
marker);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
num++;
|
num++;
|
||||||
|
@ -905,13 +905,10 @@ void TimeoutManager::RunTimeout(const TimeStamp& aNow,
|
||||||
int(elapsed.ToMilliseconds()), int(target.ToMilliseconds()),
|
int(elapsed.ToMilliseconds()), int(target.ToMilliseconds()),
|
||||||
int(delta.ToMilliseconds()), int(runtime.ToMilliseconds()));
|
int(delta.ToMilliseconds()), int(runtime.ToMilliseconds()));
|
||||||
// don't have end before start...
|
// don't have end before start...
|
||||||
PROFILER_MARKER_TEXT(
|
PROFILER_ADD_MARKER_WITH_PAYLOAD(
|
||||||
"setTimeout", DOM,
|
"setTimeout", DOM, TextMarkerPayload,
|
||||||
MarkerOptions(
|
(marker, delta.ToMilliseconds() >= 0 ? timeout->When() : now, now,
|
||||||
MarkerTiming::Interval(
|
Some(mWindow.WindowID())));
|
||||||
delta.ToMilliseconds() >= 0 ? timeout->When() : now, now),
|
|
||||||
MarkerInnerWindowId(mWindow.WindowID())),
|
|
||||||
marker);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
#include "nsPrintfCString.h"
|
#include "nsPrintfCString.h"
|
||||||
#include "prtime.h"
|
#include "prtime.h"
|
||||||
#ifdef MOZ_GECKO_PROFILER
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
# include "mozilla/ProfilerMarkerTypes.h"
|
# include "ProfilerMarkerPayload.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
|
@ -116,18 +116,14 @@ void nsDOMNavigationTiming::NotifyUnloadAccepted(nsIURI* aOldURI) {
|
||||||
|
|
||||||
void nsDOMNavigationTiming::NotifyUnloadEventStart() {
|
void nsDOMNavigationTiming::NotifyUnloadEventStart() {
|
||||||
mUnloadStart = TimeStamp::Now();
|
mUnloadStart = TimeStamp::Now();
|
||||||
PROFILER_MARKER("Unload", NETWORK,
|
PROFILER_TRACING_MARKER_DOCSHELL("Navigation", "Unload", NETWORK,
|
||||||
MarkerOptions(MarkerTiming::IntervalStart(),
|
TRACING_INTERVAL_START, mDocShell);
|
||||||
MarkerInnerWindowIdFromDocShell(mDocShell)),
|
|
||||||
Tracing, "Navigation");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsDOMNavigationTiming::NotifyUnloadEventEnd() {
|
void nsDOMNavigationTiming::NotifyUnloadEventEnd() {
|
||||||
mUnloadEnd = TimeStamp::Now();
|
mUnloadEnd = TimeStamp::Now();
|
||||||
PROFILER_MARKER("Unload", NETWORK,
|
PROFILER_TRACING_MARKER_DOCSHELL("Navigation", "Unload", NETWORK,
|
||||||
MarkerOptions(MarkerTiming::IntervalEnd(),
|
TRACING_INTERVAL_END, mDocShell);
|
||||||
MarkerInnerWindowIdFromDocShell(mDocShell)),
|
|
||||||
Tracing, "Navigation");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsDOMNavigationTiming::NotifyLoadEventStart() {
|
void nsDOMNavigationTiming::NotifyLoadEventStart() {
|
||||||
|
@ -136,10 +132,8 @@ void nsDOMNavigationTiming::NotifyLoadEventStart() {
|
||||||
}
|
}
|
||||||
mLoadEventStart = TimeStamp::Now();
|
mLoadEventStart = TimeStamp::Now();
|
||||||
|
|
||||||
PROFILER_MARKER("Load", NETWORK,
|
PROFILER_TRACING_MARKER_DOCSHELL("Navigation", "Load", NETWORK,
|
||||||
MarkerOptions(MarkerTiming::IntervalStart(),
|
TRACING_INTERVAL_START, mDocShell);
|
||||||
MarkerInnerWindowIdFromDocShell(mDocShell)),
|
|
||||||
Tracing, "Navigation");
|
|
||||||
|
|
||||||
if (IsTopLevelContentDocumentInContentProcess()) {
|
if (IsTopLevelContentDocumentInContentProcess()) {
|
||||||
mLoadEventStartForTelemetry = TimeStamp::Now();
|
mLoadEventStartForTelemetry = TimeStamp::Now();
|
||||||
|
@ -169,10 +163,8 @@ void nsDOMNavigationTiming::NotifyLoadEventEnd() {
|
||||||
}
|
}
|
||||||
mLoadEventEnd = TimeStamp::Now();
|
mLoadEventEnd = TimeStamp::Now();
|
||||||
|
|
||||||
PROFILER_MARKER("Load", NETWORK,
|
PROFILER_TRACING_MARKER_DOCSHELL("Navigation", "Load", NETWORK,
|
||||||
MarkerOptions(MarkerTiming::IntervalEnd(),
|
TRACING_INTERVAL_END, mDocShell);
|
||||||
MarkerInnerWindowIdFromDocShell(mDocShell)),
|
|
||||||
Tracing, "Navigation");
|
|
||||||
|
|
||||||
if (IsTopLevelContentDocumentInContentProcess()) {
|
if (IsTopLevelContentDocumentInContentProcess()) {
|
||||||
#ifdef MOZ_GECKO_PROFILER
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
|
@ -187,13 +179,10 @@ void nsDOMNavigationTiming::NotifyLoadEventEnd() {
|
||||||
"Document %s loaded after %dms, load event duration %dms", spec.get(),
|
"Document %s loaded after %dms, load event duration %dms", spec.get(),
|
||||||
int(elapsed.ToMilliseconds()), int(duration.ToMilliseconds()));
|
int(elapsed.ToMilliseconds()), int(duration.ToMilliseconds()));
|
||||||
PAGELOAD_LOG(("%s", marker.get()));
|
PAGELOAD_LOG(("%s", marker.get()));
|
||||||
PROFILER_MARKER_TEXT(
|
PROFILER_ADD_MARKER_WITH_PAYLOAD(
|
||||||
"DocumentLoad", DOM,
|
"DocumentLoad", DOM, TextMarkerPayload,
|
||||||
MarkerOptions(
|
(marker, mNavigationStart, mLoadEventEnd,
|
||||||
MarkerTiming::Interval(mNavigationStart, mLoadEventEnd),
|
profiler_get_inner_window_id_from_docshell(mDocShell)));
|
||||||
MarkerInnerWindowId(
|
|
||||||
profiler_get_inner_window_id_from_docshell(mDocShell))),
|
|
||||||
marker);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
TimeStamp loadEventEnd = TimeStamp::Now();
|
TimeStamp loadEventEnd = TimeStamp::Now();
|
||||||
|
@ -252,10 +241,8 @@ void nsDOMNavigationTiming::NotifyDOMContentLoadedStart(nsIURI* aURI) {
|
||||||
mLoadedURI = aURI;
|
mLoadedURI = aURI;
|
||||||
mDOMContentLoadedEventStart = TimeStamp::Now();
|
mDOMContentLoadedEventStart = TimeStamp::Now();
|
||||||
|
|
||||||
PROFILER_MARKER("DOMContentLoaded", NETWORK,
|
PROFILER_TRACING_MARKER_DOCSHELL("Navigation", "DOMContentLoaded", NETWORK,
|
||||||
MarkerOptions(MarkerTiming::IntervalStart(),
|
TRACING_INTERVAL_START, mDocShell);
|
||||||
MarkerInnerWindowIdFromDocShell(mDocShell)),
|
|
||||||
Tracing, "Navigation");
|
|
||||||
|
|
||||||
if (IsTopLevelContentDocumentInContentProcess()) {
|
if (IsTopLevelContentDocumentInContentProcess()) {
|
||||||
TimeStamp now = TimeStamp::Now();
|
TimeStamp now = TimeStamp::Now();
|
||||||
|
@ -286,10 +273,8 @@ void nsDOMNavigationTiming::NotifyDOMContentLoadedEnd(nsIURI* aURI) {
|
||||||
mLoadedURI = aURI;
|
mLoadedURI = aURI;
|
||||||
mDOMContentLoadedEventEnd = TimeStamp::Now();
|
mDOMContentLoadedEventEnd = TimeStamp::Now();
|
||||||
|
|
||||||
PROFILER_MARKER("DOMContentLoaded", NETWORK,
|
PROFILER_TRACING_MARKER_DOCSHELL("Navigation", "DOMContentLoaded", NETWORK,
|
||||||
MarkerOptions(MarkerTiming::IntervalEnd(),
|
TRACING_INTERVAL_END, mDocShell);
|
||||||
MarkerInnerWindowIdFromDocShell(mDocShell)),
|
|
||||||
Tracing, "Navigation");
|
|
||||||
|
|
||||||
if (IsTopLevelContentDocumentInContentProcess()) {
|
if (IsTopLevelContentDocumentInContentProcess()) {
|
||||||
Telemetry::AccumulateTimeDelta(Telemetry::TIME_TO_DOM_CONTENT_LOADED_END_MS,
|
Telemetry::AccumulateTimeDelta(Telemetry::TIME_TO_DOM_CONTENT_LOADED_END_MS,
|
||||||
|
@ -392,13 +377,10 @@ void nsDOMNavigationTiming::TTITimeout(nsITimer* aTimer) {
|
||||||
int(elapsed.ToMilliseconds()),
|
int(elapsed.ToMilliseconds()),
|
||||||
int(elapsedLongTask.ToMilliseconds()), spec.get());
|
int(elapsedLongTask.ToMilliseconds()), spec.get());
|
||||||
|
|
||||||
PROFILER_MARKER_TEXT(
|
PROFILER_ADD_MARKER_WITH_PAYLOAD(
|
||||||
"TimeToFirstInteractive (TTFI)", DOM,
|
"TimeToFirstInteractive (TTFI)", DOM, TextMarkerPayload,
|
||||||
MarkerOptions(
|
(marker, mNavigationStart, mTTFI,
|
||||||
MarkerTiming::Interval(mNavigationStart, mTTFI),
|
profiler_get_inner_window_id_from_docshell(mDocShell)));
|
||||||
MarkerInnerWindowId(
|
|
||||||
profiler_get_inner_window_id_from_docshell(mDocShell))),
|
|
||||||
marker);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -428,13 +410,10 @@ void nsDOMNavigationTiming::NotifyNonBlankPaintForRootContentDocument() {
|
||||||
: "this tab was inactive some of the time between navigation start "
|
: "this tab was inactive some of the time between navigation start "
|
||||||
"and first non-blank paint");
|
"and first non-blank paint");
|
||||||
PAGELOAD_LOG(("%s", marker.get()));
|
PAGELOAD_LOG(("%s", marker.get()));
|
||||||
PROFILER_MARKER_TEXT(
|
PROFILER_ADD_MARKER_WITH_PAYLOAD(
|
||||||
"FirstNonBlankPaint", DOM,
|
"FirstNonBlankPaint", DOM, TextMarkerPayload,
|
||||||
MarkerOptions(
|
(marker, mNavigationStart, mNonBlankPaint,
|
||||||
MarkerTiming::Interval(mNavigationStart, mNonBlankPaint),
|
profiler_get_inner_window_id_from_docshell(mDocShell)));
|
||||||
MarkerInnerWindowId(
|
|
||||||
profiler_get_inner_window_id_from_docshell(mDocShell))),
|
|
||||||
marker);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -480,13 +459,10 @@ void nsDOMNavigationTiming::NotifyContentfulPaintForRootContentDocument(
|
||||||
: "this tab was inactive some of the time between navigation start "
|
: "this tab was inactive some of the time between navigation start "
|
||||||
"and first non-blank paint");
|
"and first non-blank paint");
|
||||||
PAGELOAD_LOG(("%s", marker.get()));
|
PAGELOAD_LOG(("%s", marker.get()));
|
||||||
PROFILER_MARKER_TEXT(
|
PROFILER_ADD_MARKER_WITH_PAYLOAD(
|
||||||
"FirstContentfulPaint", DOM,
|
"FirstContentfulPaint", DOM, TextMarkerPayload,
|
||||||
MarkerOptions(
|
(marker, mNavigationStart, mContentfulPaint,
|
||||||
MarkerTiming::Interval(mNavigationStart, mContentfulPaint),
|
profiler_get_inner_window_id_from_docshell(mDocShell)));
|
||||||
MarkerInnerWindowId(
|
|
||||||
profiler_get_inner_window_id_from_docshell(mDocShell))),
|
|
||||||
marker);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -532,13 +508,10 @@ void nsDOMNavigationTiming::NotifyDOMContentFlushedForRootContentDocument() {
|
||||||
: "this tab was inactive some of the time between navigation start "
|
: "this tab was inactive some of the time between navigation start "
|
||||||
"and DOMContentFlushed");
|
"and DOMContentFlushed");
|
||||||
PAGELOAD_LOG(("%s", marker.get()));
|
PAGELOAD_LOG(("%s", marker.get()));
|
||||||
PROFILER_MARKER_TEXT(
|
PROFILER_ADD_MARKER_WITH_PAYLOAD(
|
||||||
"DOMContentFlushed", DOM,
|
"DOMContentFlushed", DOM, TextMarkerPayload,
|
||||||
MarkerOptions(
|
(marker, mNavigationStart, mDOMContentFlushed,
|
||||||
MarkerTiming::Interval(mNavigationStart, mDOMContentFlushed),
|
profiler_get_inner_window_id_from_docshell(mDocShell)));
|
||||||
MarkerInnerWindowId(
|
|
||||||
profiler_get_inner_window_id_from_docshell(mDocShell))),
|
|
||||||
marker);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -1039,6 +1039,10 @@ nsresult EventDispatcher::Dispatch(nsISupports* aTarget,
|
||||||
|
|
||||||
struct DOMEventMarker {
|
struct DOMEventMarker {
|
||||||
static constexpr Span<const char> MarkerTypeName() {
|
static constexpr Span<const char> MarkerTypeName() {
|
||||||
|
// Note: DOMEventMarkerPayload was originally a sub-class of
|
||||||
|
// TracingMarkerPayload, so it uses the same payload type.
|
||||||
|
// TODO: Change to its own distinct type, but this will require
|
||||||
|
// front-end changes.
|
||||||
return MakeStringSpan("DOMEvent");
|
return MakeStringSpan("DOMEvent");
|
||||||
}
|
}
|
||||||
static void StreamJSONMarkerData(
|
static void StreamJSONMarkerData(
|
||||||
|
|
|
@ -21,6 +21,9 @@
|
||||||
# include "mozilla/a11y/PDocAccessible.h"
|
# include "mozilla/a11y/PDocAccessible.h"
|
||||||
#endif
|
#endif
|
||||||
#include "GeckoProfiler.h"
|
#include "GeckoProfiler.h"
|
||||||
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
|
# include "ProfilerMarkerPayload.h"
|
||||||
|
#endif
|
||||||
#include "GMPServiceParent.h"
|
#include "GMPServiceParent.h"
|
||||||
#include "HandlerServiceParent.h"
|
#include "HandlerServiceParent.h"
|
||||||
#include "IHistory.h"
|
#include "IHistory.h"
|
||||||
|
@ -915,7 +918,9 @@ already_AddRefed<ContentParent> ContentParent::GetUsedBrowserProcess(
|
||||||
if (profiler_thread_is_being_profiled()) {
|
if (profiler_thread_is_being_profiled()) {
|
||||||
nsPrintfCString marker("Reused process %u",
|
nsPrintfCString marker("Reused process %u",
|
||||||
(unsigned int)retval->ChildID());
|
(unsigned int)retval->ChildID());
|
||||||
PROFILER_MARKER_TEXT("Process", DOM, {}, marker);
|
TimeStamp now = TimeStamp::Now();
|
||||||
|
PROFILER_ADD_MARKER_WITH_PAYLOAD("Process", DOM, TextMarkerPayload,
|
||||||
|
(marker, now, now));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
|
MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
|
||||||
|
@ -954,7 +959,9 @@ already_AddRefed<ContentParent> ContentParent::GetUsedBrowserProcess(
|
||||||
if (profiler_thread_is_being_profiled()) {
|
if (profiler_thread_is_being_profiled()) {
|
||||||
nsPrintfCString marker("Recycled process %u (%p)",
|
nsPrintfCString marker("Recycled process %u (%p)",
|
||||||
(unsigned int)recycled->ChildID(), recycled.get());
|
(unsigned int)recycled->ChildID(), recycled.get());
|
||||||
PROFILER_MARKER_TEXT("Process", DOM, {}, marker);
|
TimeStamp now = TimeStamp::Now();
|
||||||
|
PROFILER_ADD_MARKER_WITH_PAYLOAD("Process", DOM, TextMarkerPayload,
|
||||||
|
(marker, now, now));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
|
MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
|
||||||
|
@ -977,7 +984,9 @@ already_AddRefed<ContentParent> ContentParent::GetUsedBrowserProcess(
|
||||||
if (profiler_thread_is_being_profiled()) {
|
if (profiler_thread_is_being_profiled()) {
|
||||||
nsPrintfCString marker("Assigned preallocated process %u",
|
nsPrintfCString marker("Assigned preallocated process %u",
|
||||||
(unsigned int)preallocated->ChildID());
|
(unsigned int)preallocated->ChildID());
|
||||||
PROFILER_MARKER_TEXT("Process", DOM, {}, marker);
|
TimeStamp now = TimeStamp::Now();
|
||||||
|
PROFILER_ADD_MARKER_WITH_PAYLOAD("Process", DOM, TextMarkerPayload,
|
||||||
|
(marker, now, now));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
|
MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
|
||||||
|
@ -2414,10 +2423,9 @@ bool ContentParent::LaunchSubprocessResolve(bool aIsSync,
|
||||||
nsPrintfCString marker("Process start%s for %u",
|
nsPrintfCString marker("Process start%s for %u",
|
||||||
mIsAPreallocBlocker ? " (immediate)" : "",
|
mIsAPreallocBlocker ? " (immediate)" : "",
|
||||||
(unsigned int)ChildID());
|
(unsigned int)ChildID());
|
||||||
PROFILER_MARKER_TEXT(
|
PROFILER_ADD_MARKER_WITH_PAYLOAD(
|
||||||
mIsAPreallocBlocker ? ProfilerString8View("Process Immediate Launch")
|
mIsAPreallocBlocker ? "Process Immediate Launch" : "Process Launch",
|
||||||
: ProfilerString8View("Process Launch"),
|
DOM, TextMarkerPayload, (marker, mLaunchTS, launchResumeTS));
|
||||||
DOM, MarkerTiming::Interval(mLaunchTS, launchResumeTS), marker);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,9 @@
|
||||||
#include "mozilla/MathAlgorithms.h"
|
#include "mozilla/MathAlgorithms.h"
|
||||||
#include "mozilla/Sprintf.h"
|
#include "mozilla/Sprintf.h"
|
||||||
#include "GeckoProfiler.h"
|
#include "GeckoProfiler.h"
|
||||||
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
|
# include "ProfilerMarkerPayload.h"
|
||||||
|
#endif
|
||||||
#include "MPSCQueue.h"
|
#include "MPSCQueue.h"
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
@ -196,41 +199,24 @@ class AsyncLogger {
|
||||||
}
|
}
|
||||||
#ifdef MOZ_GECKO_PROFILER
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
{
|
{
|
||||||
struct Budget {
|
|
||||||
static constexpr Span<const char> MarkerTypeName() {
|
|
||||||
return MakeStringSpan("Budget");
|
|
||||||
}
|
|
||||||
static void StreamJSONMarkerData(
|
|
||||||
baseprofiler::SpliceableJSONWriter& aWriter) {}
|
|
||||||
static MarkerSchema MarkerTypeDisplay() {
|
|
||||||
using MS = MarkerSchema;
|
|
||||||
MS schema{MS::Location::markerChart, MS::Location::markerTable};
|
|
||||||
// Nothing outside the defaults.
|
|
||||||
return schema;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
TracePayload message;
|
TracePayload message;
|
||||||
while (mMessageQueueProfiler.Pop(&message) && mRunning) {
|
while (mMessageQueueProfiler.Pop(&message) && mRunning) {
|
||||||
if (message.mPhase != TracingPhase::COMPLETE) {
|
if (message.mPhase != TracingPhase::COMPLETE) {
|
||||||
profiler_add_marker(
|
TracingKind kind = message.mPhase == TracingPhase::BEGIN
|
||||||
ProfilerString8View::WrapNullTerminatedString(message.mName),
|
? TracingKind::TRACING_INTERVAL_START
|
||||||
geckoprofiler::category::MEDIA_RT,
|
: TracingKind::TRACING_INTERVAL_END;
|
||||||
{MarkerThreadId(message.mTID),
|
TracingMarkerPayload payload("media", kind, message.mTimestamp);
|
||||||
(message.mPhase == TracingPhase::BEGIN)
|
profiler_add_marker_for_thread(
|
||||||
? MarkerTiming::IntervalStart(message.mTimestamp)
|
message.mTID, JS::ProfilingCategoryPair::MEDIA_RT,
|
||||||
: MarkerTiming::IntervalEnd(message.mTimestamp)},
|
message.mName, payload);
|
||||||
Budget{});
|
|
||||||
} else {
|
} else {
|
||||||
profiler_add_marker(
|
mozilla::TimeStamp end =
|
||||||
ProfilerString8View::WrapNullTerminatedString(message.mName),
|
message.mTimestamp +
|
||||||
geckoprofiler::category::MEDIA_RT,
|
TimeDuration::FromMicroseconds(message.mDurationUs);
|
||||||
{MarkerThreadId(message.mTID),
|
BudgetMarkerPayload payload(message.mTimestamp, end);
|
||||||
MarkerTiming::Interval(
|
profiler_add_marker_for_thread(
|
||||||
message.mTimestamp,
|
message.mTID, JS::ProfilingCategoryPair::MEDIA_RT,
|
||||||
message.mTimestamp + TimeDuration::FromMicroseconds(
|
message.mName, payload);
|
||||||
message.mDurationUs))},
|
|
||||||
Budget{});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,6 @@
|
||||||
#include "AudioSegment.h"
|
#include "AudioSegment.h"
|
||||||
#include "DOMMediaStream.h"
|
#include "DOMMediaStream.h"
|
||||||
#include "ImageContainer.h"
|
#include "ImageContainer.h"
|
||||||
#include "GeckoProfiler.h"
|
|
||||||
#include "MediaDecoder.h"
|
#include "MediaDecoder.h"
|
||||||
#include "MediaDecoderStateMachine.h"
|
#include "MediaDecoderStateMachine.h"
|
||||||
#include "MediaShutdownManager.h"
|
#include "MediaShutdownManager.h"
|
||||||
|
@ -39,8 +38,17 @@
|
||||||
#include "VideoUtils.h"
|
#include "VideoUtils.h"
|
||||||
|
|
||||||
#ifdef MOZ_GECKO_PROFILER
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
# include "mozilla/ProfilerMarkerTypes.h"
|
# include "ProfilerMarkerPayload.h"
|
||||||
#endif // MOZ_GECKO_PROFILER
|
# define MDSM_ERROR_MARKER(tag, error, markerTime) \
|
||||||
|
PROFILER_ADD_MARKER_WITH_PAYLOAD(tag, MEDIA_PLAYBACK, TextMarkerPayload, \
|
||||||
|
(error, markerTime))
|
||||||
|
# define MDSM_SAMPLE_MARKER(tag, startTime, endTime) \
|
||||||
|
PROFILER_ADD_MARKER_WITH_PAYLOAD( \
|
||||||
|
tag, MEDIA_PLAYBACK, MediaSampleMarkerPayload, (startTime, endTime))
|
||||||
|
#else
|
||||||
|
# define MDSM_ERROR_MARKER(tag, error, markerTime)
|
||||||
|
# define MDSM_SAMPLE_MARKER(tag, startTime, endTime)
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
|
@ -2851,9 +2859,8 @@ void MediaDecoderStateMachine::PushAudio(AudioData* aSample) {
|
||||||
MOZ_ASSERT(OnTaskQueue());
|
MOZ_ASSERT(OnTaskQueue());
|
||||||
MOZ_ASSERT(aSample);
|
MOZ_ASSERT(aSample);
|
||||||
AudioQueue().Push(aSample);
|
AudioQueue().Push(aSample);
|
||||||
PROFILER_MARKER("MDSM::PushAudio", MEDIA_PLAYBACK, {}, MediaSampleMarker,
|
MDSM_SAMPLE_MARKER("MDSM::PushAudio", aSample->mTime.ToMicroseconds(),
|
||||||
aSample->mTime.ToMicroseconds(),
|
aSample->GetEndTime().ToMicroseconds());
|
||||||
aSample->GetEndTime().ToMicroseconds());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MediaDecoderStateMachine::PushVideo(VideoData* aSample) {
|
void MediaDecoderStateMachine::PushVideo(VideoData* aSample) {
|
||||||
|
@ -2861,9 +2868,8 @@ void MediaDecoderStateMachine::PushVideo(VideoData* aSample) {
|
||||||
MOZ_ASSERT(aSample);
|
MOZ_ASSERT(aSample);
|
||||||
aSample->mFrameID = ++mCurrentFrameID;
|
aSample->mFrameID = ++mCurrentFrameID;
|
||||||
VideoQueue().Push(aSample);
|
VideoQueue().Push(aSample);
|
||||||
PROFILER_MARKER("MDSM::PushVideo", MEDIA_PLAYBACK, {}, MediaSampleMarker,
|
MDSM_SAMPLE_MARKER("MDSM::PushVideo", aSample->mTime.ToMicroseconds(),
|
||||||
aSample->mTime.ToMicroseconds(),
|
aSample->GetEndTime().ToMicroseconds());
|
||||||
aSample->GetEndTime().ToMicroseconds());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MediaDecoderStateMachine::OnAudioPopped(const RefPtr<AudioData>& aSample) {
|
void MediaDecoderStateMachine::OnAudioPopped(const RefPtr<AudioData>& aSample) {
|
||||||
|
@ -3463,8 +3469,8 @@ bool MediaDecoderStateMachine::HasLowBufferedData(const TimeUnit& aThreshold) {
|
||||||
void MediaDecoderStateMachine::DecodeError(const MediaResult& aError) {
|
void MediaDecoderStateMachine::DecodeError(const MediaResult& aError) {
|
||||||
MOZ_ASSERT(OnTaskQueue());
|
MOZ_ASSERT(OnTaskQueue());
|
||||||
LOGE("Decode error: %s", aError.Description().get());
|
LOGE("Decode error: %s", aError.Description().get());
|
||||||
PROFILER_MARKER_TEXT("MDSM::DecodeError", MEDIA_PLAYBACK, {},
|
MDSM_ERROR_MARKER("MDSM::DecodeError", aError.Description(),
|
||||||
aError.Description());
|
TimeStamp::NowUnfuzzed());
|
||||||
// Notify the decode error and MediaDecoder will shut down MDSM.
|
// Notify the decode error and MediaDecoder will shut down MDSM.
|
||||||
mOnPlaybackErrorEvent.Notify(aError);
|
mOnPlaybackErrorEvent.Notify(aError);
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,15 @@ mozilla::LazyLogModule gMediaDemuxerLog("MediaDemuxer");
|
||||||
DDMOZ_LOG(sFormatDecoderLog, mozilla::LogLevel::Verbose, "::%s: " arg, \
|
DDMOZ_LOG(sFormatDecoderLog, mozilla::LogLevel::Verbose, "::%s: " arg, \
|
||||||
__func__, ##__VA_ARGS__)
|
__func__, ##__VA_ARGS__)
|
||||||
|
|
||||||
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
|
# include "ProfilerMarkerPayload.h"
|
||||||
|
# define MEDIA_FORMAT_READER_STATUS_MARKER(tag, text, markerTime) \
|
||||||
|
PROFILER_ADD_MARKER_WITH_PAYLOAD(tag, MEDIA_PLAYBACK, TextMarkerPayload, \
|
||||||
|
(text, markerTime))
|
||||||
|
#else
|
||||||
|
# define MEDIA_FORMAT_READER_STATUS_MARKER(tag, text, markerTime)
|
||||||
|
#endif
|
||||||
|
|
||||||
#define NS_DispatchToMainThread(...) CompileError_UseAbstractMainThreadInstead
|
#define NS_DispatchToMainThread(...) CompileError_UseAbstractMainThreadInstead
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
@ -1924,7 +1933,8 @@ void MediaFormatReader::HandleDemuxedSamples(
|
||||||
nsPrintfCString markerString(
|
nsPrintfCString markerString(
|
||||||
"%s stream id changed from:%" PRIu32 " to:%" PRIu32,
|
"%s stream id changed from:%" PRIu32 " to:%" PRIu32,
|
||||||
TrackTypeToStr(aTrack), decoder.mLastStreamSourceID, info->GetID());
|
TrackTypeToStr(aTrack), decoder.mLastStreamSourceID, info->GetID());
|
||||||
PROFILER_MARKER_TEXT("StreamID Change", MEDIA_PLAYBACK, {}, markerString);
|
MEDIA_FORMAT_READER_STATUS_MARKER("StreamID Change", markerString,
|
||||||
|
TimeStamp::NowUnfuzzed());
|
||||||
LOG("%s", markerString.get());
|
LOG("%s", markerString.get());
|
||||||
|
|
||||||
if (aTrack == TrackInfo::kVideoTrack) {
|
if (aTrack == TrackInfo::kVideoTrack) {
|
||||||
|
@ -3142,5 +3152,6 @@ void MediaFormatReader::OnFirstDemuxFailed(TrackInfo::TrackType aType,
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
||||||
#undef NS_DispatchToMainThread
|
#undef NS_DispatchToMainThread
|
||||||
|
#undef MEDIA_FORMAT_READER_STATUS_MARKER
|
||||||
#undef LOGV
|
#undef LOGV
|
||||||
#undef LOG
|
#undef LOG
|
||||||
|
|
|
@ -12,11 +12,28 @@
|
||||||
#include "mozilla/CheckedInt.h"
|
#include "mozilla/CheckedInt.h"
|
||||||
#include "mozilla/DebugOnly.h"
|
#include "mozilla/DebugOnly.h"
|
||||||
#include "mozilla/IntegerPrintfMacros.h"
|
#include "mozilla/IntegerPrintfMacros.h"
|
||||||
#include "mozilla/ProfilerMarkerTypes.h"
|
|
||||||
#include "mozilla/StaticPrefs_media.h"
|
#include "mozilla/StaticPrefs_media.h"
|
||||||
#include "mozilla/StaticPrefs_dom.h"
|
#include "mozilla/StaticPrefs_dom.h"
|
||||||
#include "nsPrintfCString.h"
|
#include "nsPrintfCString.h"
|
||||||
|
|
||||||
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
|
# include "ProfilerMarkerPayload.h"
|
||||||
|
# define PROFILER_AUDIO_MARKER(tag, sample) \
|
||||||
|
do { \
|
||||||
|
uint64_t startTime = (sample)->mTime.ToMicroseconds(); \
|
||||||
|
uint64_t endTime = (sample)->GetEndTime().ToMicroseconds(); \
|
||||||
|
auto profilerTag = (tag); \
|
||||||
|
mOwnerThread->Dispatch(NS_NewRunnableFunction( \
|
||||||
|
"AudioSink:AddMarker", [profilerTag, startTime, endTime] { \
|
||||||
|
PROFILER_ADD_MARKER_WITH_PAYLOAD(profilerTag, MEDIA_PLAYBACK, \
|
||||||
|
MediaSampleMarkerPayload, \
|
||||||
|
(startTime, endTime)); \
|
||||||
|
})); \
|
||||||
|
} while (0)
|
||||||
|
#else
|
||||||
|
# define PROFILER_AUDIO_MARKER(tag, sample)
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
extern LazyLogModule gMediaDecoderLog;
|
extern LazyLogModule gMediaDecoderLog;
|
||||||
|
@ -254,16 +271,7 @@ UniquePtr<AudioStream::Chunk> AudioSink::PopFrames(uint32_t aFrames) {
|
||||||
SINK_LOG_V("playing audio at time=%" PRId64 " offset=%u length=%u",
|
SINK_LOG_V("playing audio at time=%" PRId64 " offset=%u length=%u",
|
||||||
mCurrentData->mTime.ToMicroseconds(),
|
mCurrentData->mTime.ToMicroseconds(),
|
||||||
mCurrentData->Frames() - mCursor->Available(), framesToPop);
|
mCurrentData->Frames() - mCursor->Available(), framesToPop);
|
||||||
|
PROFILER_AUDIO_MARKER("PlayAudio", mCurrentData);
|
||||||
#ifdef MOZ_GECKO_PROFILER
|
|
||||||
mOwnerThread->Dispatch(NS_NewRunnableFunction(
|
|
||||||
"AudioSink:AddMarker",
|
|
||||||
[startTime = mCurrentData->mTime.ToMicroseconds(),
|
|
||||||
endTime = mCurrentData->GetEndTime().ToMicroseconds()] {
|
|
||||||
PROFILER_MARKER("PlayAudio", MEDIA_PLAYBACK, {}, MediaSampleMarker,
|
|
||||||
startTime, endTime);
|
|
||||||
}));
|
|
||||||
#endif // MOZ_GECKO_PROFILER
|
|
||||||
|
|
||||||
UniquePtr<AudioStream::Chunk> chunk =
|
UniquePtr<AudioStream::Chunk> chunk =
|
||||||
MakeUnique<Chunk>(mCurrentData, framesToPop, mCursor->Ptr());
|
MakeUnique<Chunk>(mCurrentData, framesToPop, mCursor->Ptr());
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
#include "VideoUtils.h"
|
#include "VideoUtils.h"
|
||||||
|
|
||||||
#include "mozilla/IntegerPrintfMacros.h"
|
#include "mozilla/IntegerPrintfMacros.h"
|
||||||
#include "mozilla/ProfilerMarkerTypes.h"
|
|
||||||
#include "mozilla/StaticPrefs_browser.h"
|
#include "mozilla/StaticPrefs_browser.h"
|
||||||
#include "mozilla/StaticPrefs_media.h"
|
#include "mozilla/StaticPrefs_media.h"
|
||||||
|
|
||||||
|
@ -30,6 +29,15 @@ extern mozilla::LazyLogModule gMediaDecoderLog;
|
||||||
#define VSINK_LOG_V(x, ...) \
|
#define VSINK_LOG_V(x, ...) \
|
||||||
MOZ_LOG(gMediaDecoderLog, LogLevel::Verbose, (FMT(x, ##__VA_ARGS__)))
|
MOZ_LOG(gMediaDecoderLog, LogLevel::Verbose, (FMT(x, ##__VA_ARGS__)))
|
||||||
|
|
||||||
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
|
# include "ProfilerMarkerPayload.h"
|
||||||
|
# define VSINK_ADD_PROFILER_MARKER(tag, startTime, endTime) \
|
||||||
|
PROFILER_ADD_MARKER_WITH_PAYLOAD( \
|
||||||
|
tag, MEDIA_PLAYBACK, MediaSampleMarkerPayload, (startTime, endTime))
|
||||||
|
#else
|
||||||
|
# define VSINK_ADD_PROFILER_MARKER(tag, startTime, endTime)
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
using namespace mozilla::layers;
|
using namespace mozilla::layers;
|
||||||
|
@ -455,9 +463,8 @@ void VideoSink::RenderVideoFrames(int32_t aMaxFrames, int64_t aClockTime,
|
||||||
frame->mTime.ToMicroseconds(), frame->mFrameID,
|
frame->mTime.ToMicroseconds(), frame->mFrameID,
|
||||||
VideoQueue().GetSize());
|
VideoQueue().GetSize());
|
||||||
if (!wasSent) {
|
if (!wasSent) {
|
||||||
PROFILER_MARKER("PlayVideo", MEDIA_PLAYBACK, {}, MediaSampleMarker,
|
VSINK_ADD_PROFILER_MARKER("PlayVideo", frame->mTime.ToMicroseconds(),
|
||||||
frame->mTime.ToMicroseconds(),
|
frame->GetEndTime().ToMicroseconds());
|
||||||
frame->GetEndTime().ToMicroseconds());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -496,9 +503,8 @@ void VideoSink::UpdateRenderedVideoFrames() {
|
||||||
VSINK_LOG_V("discarding video frame mTime=%" PRId64
|
VSINK_LOG_V("discarding video frame mTime=%" PRId64
|
||||||
" clock_time=%" PRId64,
|
" clock_time=%" PRId64,
|
||||||
frame->mTime.ToMicroseconds(), clockTime.ToMicroseconds());
|
frame->mTime.ToMicroseconds(), clockTime.ToMicroseconds());
|
||||||
PROFILER_MARKER("DiscardVideo", MEDIA_PLAYBACK, {}, MediaSampleMarker,
|
VSINK_ADD_PROFILER_MARKER("DiscardVideo", frame->mTime.ToMicroseconds(),
|
||||||
frame->mTime.ToMicroseconds(),
|
frame->GetEndTime().ToMicroseconds());
|
||||||
frame->GetEndTime().ToMicroseconds());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,6 @@
|
||||||
#include "mozilla/WindowsVersion.h"
|
#include "mozilla/WindowsVersion.h"
|
||||||
#include "mozilla/gfx/gfxVars.h"
|
#include "mozilla/gfx/gfxVars.h"
|
||||||
#include "mozilla/mscom/EnsureMTA.h"
|
#include "mozilla/mscom/EnsureMTA.h"
|
||||||
#include "mozilla/ProfilerMarkers.h"
|
|
||||||
#include "nsComponentManagerUtils.h"
|
#include "nsComponentManagerUtils.h"
|
||||||
#include "nsIXULRuntime.h"
|
#include "nsIXULRuntime.h"
|
||||||
#include "nsIXULRuntime.h" // for BrowserTabsRemoteAutostart
|
#include "nsIXULRuntime.h" // for BrowserTabsRemoteAutostart
|
||||||
|
@ -37,19 +36,28 @@
|
||||||
|
|
||||||
#define LOG(...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
|
#define LOG(...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
|
||||||
|
|
||||||
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
|
# include "ProfilerMarkerPayload.h"
|
||||||
|
# define WFM_DECODER_MODULE_STATUS_MARKER(tag, text, markerTime) \
|
||||||
|
PROFILER_ADD_MARKER_WITH_PAYLOAD(tag, MEDIA_PLAYBACK, TextMarkerPayload, \
|
||||||
|
(text, markerTime))
|
||||||
|
#else
|
||||||
|
# define WFM_DECODER_MODULE_STATUS_MARKER(tag, text, markerTime)
|
||||||
|
#endif
|
||||||
|
|
||||||
extern const GUID CLSID_WebmMfVpxDec;
|
extern const GUID CLSID_WebmMfVpxDec;
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
// Helper function to add a profile marker and log at the same time.
|
// Helper function to add a profile marker and log at the same time.
|
||||||
static void MOZ_FORMAT_PRINTF(2, 3)
|
static void MOZ_FORMAT_PRINTF(2, 3)
|
||||||
WmfDeocderModuleMarkerAndLog(const ProfilerString8View& aMarkerTag,
|
WmfDeocderModuleMarkerAndLog(const char* aTag, const char* aFormat, ...) {
|
||||||
const char* aFormat, ...) {
|
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, aFormat);
|
va_start(ap, aFormat);
|
||||||
const nsVprintfCString markerString(aFormat, ap);
|
const nsVprintfCString markerString(aFormat, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
PROFILER_MARKER_TEXT(aMarkerTag, MEDIA_PLAYBACK, {}, markerString);
|
WFM_DECODER_MODULE_STATUS_MARKER(aTag, markerString,
|
||||||
|
TimeStamp::NowUnfuzzed());
|
||||||
LOG("%s", markerString.get());
|
LOG("%s", markerString.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
#include "VideoUtils.h"
|
#include "VideoUtils.h"
|
||||||
#include "WMFUtils.h"
|
#include "WMFUtils.h"
|
||||||
#include "mozilla/Logging.h"
|
#include "mozilla/Logging.h"
|
||||||
#include "mozilla/ProfilerMarkers.h"
|
|
||||||
#include "mozilla/SyncRunnable.h"
|
#include "mozilla/SyncRunnable.h"
|
||||||
#include "mozilla/TaskQueue.h"
|
#include "mozilla/TaskQueue.h"
|
||||||
#include "mozilla/Telemetry.h"
|
#include "mozilla/Telemetry.h"
|
||||||
|
@ -17,6 +16,15 @@
|
||||||
|
|
||||||
#define LOG(...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
|
#define LOG(...) MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
|
||||||
|
|
||||||
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
|
# include "ProfilerMarkerPayload.h"
|
||||||
|
# define WFM_MEDIA_DATA_DECODER_STATUS_MARKER(tag, text, markerTime) \
|
||||||
|
PROFILER_ADD_MARKER_WITH_PAYLOAD(tag, MEDIA_PLAYBACK, TextMarkerPayload, \
|
||||||
|
(text, markerTime))
|
||||||
|
#else
|
||||||
|
# define WFM_MEDIA_DATA_DECODER_STATUS_MARKER(tag, text, markerTime)
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
WMFMediaDataDecoder::WMFMediaDataDecoder(MFTManager* aMFTManager)
|
WMFMediaDataDecoder::WMFMediaDataDecoder(MFTManager* aMFTManager)
|
||||||
|
@ -94,7 +102,8 @@ RefPtr<MediaDataDecoder::DecodePromise> WMFMediaDataDecoder::ProcessError(
|
||||||
"reason: %s",
|
"reason: %s",
|
||||||
GetDescriptionName().get(), aReason);
|
GetDescriptionName().get(), aReason);
|
||||||
LOG(markerString.get());
|
LOG(markerString.get());
|
||||||
PROFILER_MARKER_TEXT("WMFDecoder Error", MEDIA_PLAYBACK, {}, markerString);
|
WFM_MEDIA_DATA_DECODER_STATUS_MARKER("WMFDecoder Error", markerString,
|
||||||
|
TimeStamp::NowUnfuzzed());
|
||||||
|
|
||||||
// TODO: For the error DXGI_ERROR_DEVICE_RESET, we could return
|
// TODO: For the error DXGI_ERROR_DEVICE_RESET, we could return
|
||||||
// NS_ERROR_DOM_MEDIA_NEED_NEW_DECODER to get the latest device. Maybe retry
|
// NS_ERROR_DOM_MEDIA_NEED_NEW_DECODER to get the latest device. Maybe retry
|
||||||
|
|
|
@ -13,10 +13,18 @@
|
||||||
#include "MediaInfo.h"
|
#include "MediaInfo.h"
|
||||||
#include "PDMFactory.h"
|
#include "PDMFactory.h"
|
||||||
#include "VPXDecoder.h"
|
#include "VPXDecoder.h"
|
||||||
#include "mozilla/ProfilerMarkers.h"
|
|
||||||
#include "mozilla/StaticPrefs_media.h"
|
#include "mozilla/StaticPrefs_media.h"
|
||||||
#include "mozilla/TaskQueue.h"
|
#include "mozilla/TaskQueue.h"
|
||||||
|
|
||||||
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
|
# include "ProfilerMarkerPayload.h"
|
||||||
|
# define MEDIA_CHANGE_MONITOR_STATUS_MARKER(tag, text, markerTime) \
|
||||||
|
PROFILER_ADD_MARKER_WITH_PAYLOAD(tag, MEDIA_PLAYBACK, TextMarkerPayload, \
|
||||||
|
(text, markerTime))
|
||||||
|
#else
|
||||||
|
# define MEDIA_CHANGE_MONITOR_STATUS_MARKER(tag, text, markerTime)
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
// H264ChangeMonitor is used to ensure that only AVCC or AnnexB is fed to the
|
// H264ChangeMonitor is used to ensure that only AVCC or AnnexB is fed to the
|
||||||
|
@ -90,9 +98,11 @@ class H264ChangeMonitor : public MediaChangeMonitor::CodecChangeMonitor {
|
||||||
mPreviousExtraData = aSample->mExtraData;
|
mPreviousExtraData = aSample->mExtraData;
|
||||||
UpdateConfigFromExtraData(extra_data);
|
UpdateConfigFromExtraData(extra_data);
|
||||||
|
|
||||||
PROFILER_MARKER_TEXT("H264 Stream Change", MEDIA_PLAYBACK, {},
|
MEDIA_CHANGE_MONITOR_STATUS_MARKER(
|
||||||
"H264ChangeMonitor::CheckForChange has detected a "
|
"H264 Stream Change",
|
||||||
"change in the stream and will request a new decoder");
|
"H264ChangeMonitor::CheckForChange has detected a change in the "
|
||||||
|
"stream and will request a new decoder"_ns,
|
||||||
|
TimeStamp::NowUnfuzzed());
|
||||||
return NS_ERROR_DOM_MEDIA_NEED_NEW_DECODER;
|
return NS_ERROR_DOM_MEDIA_NEED_NEW_DECODER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,10 +204,11 @@ class VPXChangeMonitor : public MediaChangeMonitor::CodecChangeMonitor {
|
||||||
mCurrentConfig.SetImageRect(
|
mCurrentConfig.SetImageRect(
|
||||||
gfx::IntRect(0, 0, info.mImage.width, info.mImage.height));
|
gfx::IntRect(0, 0, info.mImage.width, info.mImage.height));
|
||||||
|
|
||||||
PROFILER_MARKER_TEXT(
|
MEDIA_CHANGE_MONITOR_STATUS_MARKER(
|
||||||
"VPX Stream Change", MEDIA_PLAYBACK, {},
|
"VPX Stream Change",
|
||||||
"VPXChangeMonitor::CheckForChange has detected a change in the "
|
"VPXChangeMonitor::CheckForChange has detected a change in the "
|
||||||
"stream and will request a new decoder");
|
"stream and will request a new decoder"_ns,
|
||||||
|
TimeStamp::NowUnfuzzed());
|
||||||
rv = NS_ERROR_DOM_MEDIA_NEED_NEW_DECODER;
|
rv = NS_ERROR_DOM_MEDIA_NEED_NEW_DECODER;
|
||||||
}
|
}
|
||||||
mInfo = Some(info);
|
mInfo = Some(info);
|
||||||
|
@ -744,3 +755,5 @@ void MediaChangeMonitor::FlushThenShutdownDecoder(
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#undef MEDIA_CHANGE_MONITOR_STATUS_MARKER
|
||||||
|
|
|
@ -28,6 +28,10 @@
|
||||||
#include "mozilla/dom/WorkerPrivate.h"
|
#include "mozilla/dom/WorkerPrivate.h"
|
||||||
#include "mozilla/dom/WorkerRunnable.h"
|
#include "mozilla/dom/WorkerRunnable.h"
|
||||||
|
|
||||||
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
|
# include "ProfilerMarkerPayload.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define PERFLOG(msg, ...) printf_stderr(msg, ##__VA_ARGS__)
|
#define PERFLOG(msg, ...) printf_stderr(msg, ##__VA_ARGS__)
|
||||||
|
|
||||||
namespace mozilla::dom {
|
namespace mozilla::dom {
|
||||||
|
@ -212,53 +216,6 @@ void Performance::ClearUserEntries(const Optional<nsAString>& aEntryName,
|
||||||
|
|
||||||
void Performance::ClearResourceTimings() { mResourceEntries.Clear(); }
|
void Performance::ClearResourceTimings() { mResourceEntries.Clear(); }
|
||||||
|
|
||||||
#ifdef MOZ_GECKO_PROFILER
|
|
||||||
struct UserTimingMarker {
|
|
||||||
static constexpr Span<const char> MarkerTypeName() {
|
|
||||||
return MakeStringSpan("UserTiming");
|
|
||||||
}
|
|
||||||
static void StreamJSONMarkerData(
|
|
||||||
baseprofiler::SpliceableJSONWriter& aWriter,
|
|
||||||
const ProfilerString16View& aName, bool aIsMeasure,
|
|
||||||
const Maybe<ProfilerString16View>& aStartMark,
|
|
||||||
const Maybe<ProfilerString16View>& aEndMark) {
|
|
||||||
aWriter.StringProperty("name", NS_ConvertUTF16toUTF8(aName.Data()));
|
|
||||||
if (aIsMeasure) {
|
|
||||||
aWriter.StringProperty("entryType", "measure");
|
|
||||||
} else {
|
|
||||||
aWriter.StringProperty("entryType", "mark");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aStartMark.isSome()) {
|
|
||||||
aWriter.StringProperty("startMark",
|
|
||||||
NS_ConvertUTF16toUTF8(aStartMark->Data()));
|
|
||||||
} else {
|
|
||||||
aWriter.NullProperty("startMark");
|
|
||||||
}
|
|
||||||
if (aEndMark.isSome()) {
|
|
||||||
aWriter.StringProperty("endMark",
|
|
||||||
NS_ConvertUTF16toUTF8(aEndMark->Data()));
|
|
||||||
} else {
|
|
||||||
aWriter.NullProperty("endMark");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static MarkerSchema MarkerTypeDisplay() {
|
|
||||||
using MS = MarkerSchema;
|
|
||||||
MS schema{MS::Location::markerChart, MS::Location::markerTable};
|
|
||||||
schema.SetAllLabels("{marker.data.name}");
|
|
||||||
schema.AddStaticLabelValue("Marker", "UserTiming");
|
|
||||||
schema.AddKeyLabelFormat("entryType", "Entry Type", MS::Format::string);
|
|
||||||
schema.AddKeyLabelFormat("name", "Name", MS::Format::string);
|
|
||||||
schema.AddKeyLabelFormat("startMark", "Start Mark", MS::Format::string);
|
|
||||||
schema.AddKeyLabelFormat("endMark", "End Mark", MS::Format::string);
|
|
||||||
schema.AddStaticLabelValue("Description",
|
|
||||||
"UserTimingMeasure is created using the DOM API "
|
|
||||||
"performance.measure().");
|
|
||||||
return schema;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void Performance::Mark(const nsAString& aName, ErrorResult& aRv) {
|
void Performance::Mark(const nsAString& aName, ErrorResult& aRv) {
|
||||||
// We add nothing when 'privacy.resistFingerprinting' is on.
|
// We add nothing when 'privacy.resistFingerprinting' is on.
|
||||||
if (nsContentUtils::ShouldResistFingerprinting()) {
|
if (nsContentUtils::ShouldResistFingerprinting()) {
|
||||||
|
@ -280,9 +237,8 @@ void Performance::Mark(const nsAString& aName, ErrorResult& aRv) {
|
||||||
if (GetOwner()) {
|
if (GetOwner()) {
|
||||||
innerWindowId = Some(GetOwner()->WindowID());
|
innerWindowId = Some(GetOwner()->WindowID());
|
||||||
}
|
}
|
||||||
profiler_add_marker("UserTiming", geckoprofiler::category::DOM,
|
PROFILER_ADD_MARKER_WITH_PAYLOAD("UserTiming", DOM, UserTimingMarkerPayload,
|
||||||
MarkerInnerWindowId(innerWindowId), UserTimingMarker{},
|
(aName, TimeStamp::Now(), innerWindowId));
|
||||||
aName, /* aIsMeasure */ false, Nothing{}, Nothing{});
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -376,11 +332,9 @@ void Performance::Measure(const nsAString& aName,
|
||||||
if (GetOwner()) {
|
if (GetOwner()) {
|
||||||
innerWindowId = Some(GetOwner()->WindowID());
|
innerWindowId = Some(GetOwner()->WindowID());
|
||||||
}
|
}
|
||||||
profiler_add_marker("UserTiming", geckoprofiler::category::DOM,
|
PROFILER_ADD_MARKER_WITH_PAYLOAD("UserTiming", DOM, UserTimingMarkerPayload,
|
||||||
{MarkerTiming::Interval(startTimeStamp, endTimeStamp),
|
(aName, startMark, endMark, startTimeStamp,
|
||||||
MarkerInnerWindowId(innerWindowId)},
|
endTimeStamp, innerWindowId));
|
||||||
UserTimingMarker{}, aName, /* aIsMeasure */ true,
|
|
||||||
startMark, endMark);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
#include "js/SourceText.h"
|
#include "js/SourceText.h"
|
||||||
#include "js/Utility.h"
|
#include "js/Utility.h"
|
||||||
#include "xpcpublic.h"
|
#include "xpcpublic.h"
|
||||||
#include "GeckoProfiler.h"
|
|
||||||
#include "nsCycleCollectionParticipant.h"
|
#include "nsCycleCollectionParticipant.h"
|
||||||
#include "nsIContent.h"
|
#include "nsIContent.h"
|
||||||
#include "nsJSUtils.h"
|
#include "nsJSUtils.h"
|
||||||
|
@ -84,6 +83,10 @@
|
||||||
#include "nsIScriptError.h"
|
#include "nsIScriptError.h"
|
||||||
#include "nsIAsyncOutputStream.h"
|
#include "nsIAsyncOutputStream.h"
|
||||||
|
|
||||||
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
|
# include "ProfilerMarkerPayload.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
using JS::SourceText;
|
using JS::SourceText;
|
||||||
|
|
||||||
using mozilla::Telemetry::LABELS_DOM_SCRIPT_PRELOAD_RESULT;
|
using mozilla::Telemetry::LABELS_DOM_SCRIPT_PRELOAD_RESULT;
|
||||||
|
@ -2177,7 +2180,7 @@ NotifyOffThreadScriptLoadCompletedRunnable::Run() {
|
||||||
|
|
||||||
#ifdef MOZ_GECKO_PROFILER
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
if (profiler_is_active()) {
|
if (profiler_is_active()) {
|
||||||
ProfilerString8View scriptSourceString;
|
const char* scriptSourceString;
|
||||||
if (request->IsTextSource()) {
|
if (request->IsTextSource()) {
|
||||||
scriptSourceString = "ScriptCompileOffThread";
|
scriptSourceString = "ScriptCompileOffThread";
|
||||||
} else if (request->IsBinASTSource()) {
|
} else if (request->IsBinASTSource()) {
|
||||||
|
@ -2189,11 +2192,10 @@ NotifyOffThreadScriptLoadCompletedRunnable::Run() {
|
||||||
|
|
||||||
nsAutoCString profilerLabelString;
|
nsAutoCString profilerLabelString;
|
||||||
GetProfilerLabelForRequest(request, profilerLabelString);
|
GetProfilerLabelForRequest(request, profilerLabelString);
|
||||||
PROFILER_MARKER_TEXT(
|
PROFILER_ADD_MARKER_WITH_PAYLOAD(
|
||||||
scriptSourceString, JS,
|
scriptSourceString, JS, TextMarkerPayload,
|
||||||
MarkerTiming::Interval(request->mOffThreadParseStartTime,
|
(profilerLabelString, request->mOffThreadParseStartTime,
|
||||||
request->mOffThreadParseStopTime),
|
request->mOffThreadParseStopTime));
|
||||||
profilerLabelString);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -2458,7 +2458,7 @@ nsresult XMLHttpRequestMainThread::CreateChannel() {
|
||||||
rv = httpChannel->SetRequestMethod(mRequestMethod);
|
rv = httpChannel->SetRequestMethod(mRequestMethod);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
httpChannel->SetSource(profiler_capture_backtrace());
|
httpChannel->SetSource(profiler_get_backtrace());
|
||||||
|
|
||||||
// Set the initiator type
|
// Set the initiator type
|
||||||
nsCOMPtr<nsITimedChannel> timedChannel(do_QueryInterface(httpChannel));
|
nsCOMPtr<nsITimedChannel> timedChannel(do_QueryInterface(httpChannel));
|
||||||
|
@ -3240,8 +3240,7 @@ void XMLHttpRequestMainThread::SetOriginStack(
|
||||||
mOriginStack = std::move(aOriginStack);
|
mOriginStack = std::move(aOriginStack);
|
||||||
}
|
}
|
||||||
|
|
||||||
void XMLHttpRequestMainThread::SetSource(
|
void XMLHttpRequestMainThread::SetSource(UniqueProfilerBacktrace aSource) {
|
||||||
UniquePtr<ProfileChunkedBuffer> aSource) {
|
|
||||||
if (!mChannel) {
|
if (!mChannel) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -396,7 +396,7 @@ class XMLHttpRequestMainThread final : public XMLHttpRequest,
|
||||||
|
|
||||||
void SetOriginStack(UniquePtr<SerializedStackHolder> aOriginStack);
|
void SetOriginStack(UniquePtr<SerializedStackHolder> aOriginStack);
|
||||||
|
|
||||||
void SetSource(UniquePtr<ProfileChunkedBuffer> aSource);
|
void SetSource(UniqueProfilerBacktrace aSource);
|
||||||
|
|
||||||
virtual uint16_t ErrorCode() const override {
|
virtual uint16_t ErrorCode() const override {
|
||||||
return static_cast<uint16_t>(mErrorLoad);
|
return static_cast<uint16_t>(mErrorLoad);
|
||||||
|
|
|
@ -653,7 +653,7 @@ class OpenRunnable final : public WorkerThreadProxySyncRunnable {
|
||||||
|
|
||||||
// Remember the worker thread's stack when the XHR was opened for profiling
|
// Remember the worker thread's stack when the XHR was opened for profiling
|
||||||
// purposes.
|
// purposes.
|
||||||
UniquePtr<ProfileChunkedBuffer> mSource;
|
UniqueProfilerBacktrace mSource;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
OpenRunnable(WorkerPrivate* aWorkerPrivate, Proxy* aProxy,
|
OpenRunnable(WorkerPrivate* aWorkerPrivate, Proxy* aProxy,
|
||||||
|
@ -664,7 +664,7 @@ class OpenRunnable final : public WorkerThreadProxySyncRunnable {
|
||||||
XMLHttpRequestResponseType aResponseType,
|
XMLHttpRequestResponseType aResponseType,
|
||||||
const nsString& aMimeTypeOverride,
|
const nsString& aMimeTypeOverride,
|
||||||
UniquePtr<SerializedStackHolder> aOriginStack,
|
UniquePtr<SerializedStackHolder> aOriginStack,
|
||||||
UniquePtr<ProfileChunkedBuffer> aSource = nullptr)
|
UniqueProfilerBacktrace aSource = nullptr)
|
||||||
: WorkerThreadProxySyncRunnable(aWorkerPrivate, aProxy),
|
: WorkerThreadProxySyncRunnable(aWorkerPrivate, aProxy),
|
||||||
mMethod(aMethod),
|
mMethod(aMethod),
|
||||||
mURL(aURL),
|
mURL(aURL),
|
||||||
|
@ -1741,7 +1741,7 @@ void XMLHttpRequestWorker::Open(const nsACString& aMethod,
|
||||||
mWorkerPrivate, mProxy, aMethod, aUrl, aUser, aPassword,
|
mWorkerPrivate, mProxy, aMethod, aUrl, aUser, aPassword,
|
||||||
mBackgroundRequest, mWithCredentials, mTimeout, mResponseType,
|
mBackgroundRequest, mWithCredentials, mTimeout, mResponseType,
|
||||||
alsoOverrideMimeType ? mMimeTypeOverride : VoidString(), std::move(stack),
|
alsoOverrideMimeType ? mMimeTypeOverride : VoidString(), std::move(stack),
|
||||||
profiler_capture_backtrace());
|
profiler_get_backtrace());
|
||||||
|
|
||||||
++mProxy->mOpenCount;
|
++mProxy->mOpenCount;
|
||||||
runnable->Dispatch(Canceling, aRv);
|
runnable->Dispatch(Canceling, aRv);
|
||||||
|
|
|
@ -11,6 +11,9 @@
|
||||||
#include "GeckoProfiler.h"
|
#include "GeckoProfiler.h"
|
||||||
#include "gfxUtils.h"
|
#include "gfxUtils.h"
|
||||||
#include "nsThreadUtils.h"
|
#include "nsThreadUtils.h"
|
||||||
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
|
# include "ProfilerMarkerPayload.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
using namespace mozilla::gfx;
|
using namespace mozilla::gfx;
|
||||||
|
@ -81,32 +84,12 @@ void ProfilerScreenshots::SubmitScreenshot(
|
||||||
nullptr, &dataURL);
|
nullptr, &dataURL);
|
||||||
if (NS_SUCCEEDED(rv)) {
|
if (NS_SUCCEEDED(rv)) {
|
||||||
// Add a marker with the data URL.
|
// Add a marker with the data URL.
|
||||||
struct ScreenshotMarker {
|
AUTO_PROFILER_STATS(add_marker_with_ScreenshotPayload);
|
||||||
static constexpr mozilla::Span<const char> MarkerTypeName() {
|
profiler_add_marker_for_thread(
|
||||||
return mozilla::MakeStringSpan("CompositorScreenshot");
|
sourceThread, JS::ProfilingCategoryPair::GRAPHICS,
|
||||||
}
|
"CompositorScreenshot",
|
||||||
static void StreamJSONMarkerData(
|
ScreenshotPayload(timeStamp, std::move(dataURL), originalSize,
|
||||||
mozilla::baseprofiler::SpliceableJSONWriter& aWriter,
|
windowIdentifier));
|
||||||
const mozilla::ProfilerString8View& aScreenshotDataURL,
|
|
||||||
const mozilla::gfx::IntSize& aWindowSize,
|
|
||||||
uintptr_t aWindowIdentifier) {
|
|
||||||
aWriter.UniqueStringProperty("url", aScreenshotDataURL);
|
|
||||||
|
|
||||||
char hexWindowID[32];
|
|
||||||
SprintfLiteral(hexWindowID, "0x%" PRIXPTR, aWindowIdentifier);
|
|
||||||
aWriter.StringProperty("windowID", hexWindowID);
|
|
||||||
aWriter.DoubleProperty("windowWidth", aWindowSize.width);
|
|
||||||
aWriter.DoubleProperty("windowHeight", aWindowSize.height);
|
|
||||||
}
|
|
||||||
static mozilla::MarkerSchema MarkerTypeDisplay() {
|
|
||||||
return mozilla::MarkerSchema::SpecialFrontendLocation{};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
profiler_add_marker(
|
|
||||||
"CompositorScreenshot", geckoprofiler::category::GRAPHICS,
|
|
||||||
{MarkerThreadId(sourceThread),
|
|
||||||
MarkerTiming::InstantAt(timeStamp)},
|
|
||||||
ScreenshotMarker{}, dataURL, originalSize, windowIdentifier);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,10 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "GeckoProfiler.h" // for GeckoProfiler
|
#include "GeckoProfiler.h" // for GeckoProfiler
|
||||||
|
|
||||||
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
|
# include "ProfilerMarkerPayload.h" // for LayerTranslationMarkerPayload
|
||||||
|
#endif
|
||||||
|
|
||||||
static mozilla::LazyLogModule sGfxCullLog("gfx.culling");
|
static mozilla::LazyLogModule sGfxCullLog("gfx.culling");
|
||||||
#define CULLING_LOG(...) MOZ_LOG(sGfxCullLog, LogLevel::Debug, (__VA_ARGS__))
|
#define CULLING_LOG(...) MOZ_LOG(sGfxCullLog, LogLevel::Debug, (__VA_ARGS__))
|
||||||
|
|
||||||
|
@ -99,37 +103,9 @@ static void PrintUniformityInfo(Layer* aLayer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Point translation = transform.As2D().GetTranslation();
|
Point translation = transform.As2D().GetTranslation();
|
||||||
|
PROFILER_ADD_MARKER_WITH_PAYLOAD("LayerTranslation", GRAPHICS,
|
||||||
// Contains the translation applied to a 2d layer so we can track the layer
|
LayerTranslationMarkerPayload,
|
||||||
// position at each frame.
|
(aLayer, translation, TimeStamp::Now()));
|
||||||
struct LayerTranslationMarker {
|
|
||||||
static constexpr Span<const char> MarkerTypeName() {
|
|
||||||
return MakeStringSpan("LayerTranslation");
|
|
||||||
}
|
|
||||||
static void StreamJSONMarkerData(
|
|
||||||
baseprofiler::SpliceableJSONWriter& aWriter,
|
|
||||||
ProfileBufferRawPointer<layers::Layer> aLayer, gfx::Point aPoint) {
|
|
||||||
const size_t bufferSize = 32;
|
|
||||||
char buffer[bufferSize];
|
|
||||||
SprintfLiteral(buffer, "%p", aLayer.mRawPointer);
|
|
||||||
|
|
||||||
aWriter.StringProperty("layer", buffer);
|
|
||||||
aWriter.IntProperty("x", aPoint.x);
|
|
||||||
aWriter.IntProperty("y", aPoint.y);
|
|
||||||
}
|
|
||||||
static MarkerSchema MarkerTypeDisplay() {
|
|
||||||
using MS = MarkerSchema;
|
|
||||||
MS schema{MS::Location::markerChart, MS::Location::markerTable};
|
|
||||||
schema.AddKeyLabelFormat("layer", "Layer", MS::Format::string);
|
|
||||||
schema.AddKeyLabelFormat("x", "X", MS::Format::integer);
|
|
||||||
schema.AddKeyLabelFormat("y", "Y", MS::Format::integer);
|
|
||||||
return schema;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
profiler_add_marker("LayerTranslation", geckoprofiler::category::GRAPHICS, {},
|
|
||||||
LayerTranslationMarker{},
|
|
||||||
WrapProfileBufferRawPointer(aLayer), translation);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -90,6 +90,9 @@
|
||||||
#include "mozilla/HalTypes.h"
|
#include "mozilla/HalTypes.h"
|
||||||
#include "mozilla/StaticPtr.h"
|
#include "mozilla/StaticPtr.h"
|
||||||
#include "mozilla/Telemetry.h"
|
#include "mozilla/Telemetry.h"
|
||||||
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
|
# include "ProfilerMarkerPayload.h"
|
||||||
|
#endif
|
||||||
#include "mozilla/VsyncDispatcher.h"
|
#include "mozilla/VsyncDispatcher.h"
|
||||||
#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
|
#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
|
||||||
# include "VsyncSource.h"
|
# include "VsyncSource.h"
|
||||||
|
@ -2173,23 +2176,8 @@ already_AddRefed<IAPZCTreeManager> CompositorBridgeParent::GetAPZCTreeManager(
|
||||||
static void InsertVsyncProfilerMarker(TimeStamp aVsyncTimestamp) {
|
static void InsertVsyncProfilerMarker(TimeStamp aVsyncTimestamp) {
|
||||||
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
|
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
|
||||||
if (profiler_thread_is_being_profiled()) {
|
if (profiler_thread_is_being_profiled()) {
|
||||||
// Tracks when a vsync occurs according to the HardwareComposer.
|
PROFILER_ADD_MARKER_WITH_PAYLOAD("VsyncTimestamp", GRAPHICS,
|
||||||
struct VsyncMarker {
|
VsyncMarkerPayload, (aVsyncTimestamp));
|
||||||
static constexpr mozilla::Span<const char> MarkerTypeName() {
|
|
||||||
return mozilla::MakeStringSpan("VsyncTimestamp");
|
|
||||||
}
|
|
||||||
static void StreamJSONMarkerData(
|
|
||||||
baseprofiler::SpliceableJSONWriter& aWriter) {}
|
|
||||||
static MarkerSchema MarkerTypeDisplay() {
|
|
||||||
using MS = MarkerSchema;
|
|
||||||
MS schema{MS::Location::markerChart, MS::Location::markerTable};
|
|
||||||
// Nothing outside the defaults.
|
|
||||||
return schema;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
profiler_add_marker("VsyncTimestamp", geckoprofiler::category::GRAPHICS,
|
|
||||||
MarkerTiming::InstantAt(aVsyncTimestamp),
|
|
||||||
VsyncMarker{});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -2754,23 +2742,42 @@ int32_t RecordContentFrameTime(
|
||||||
|
|
||||||
#ifdef MOZ_GECKO_PROFILER
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
if (profiler_can_accept_markers()) {
|
if (profiler_can_accept_markers()) {
|
||||||
struct ContentFrameMarker {
|
class ContentFramePayload : public ProfilerMarkerPayload {
|
||||||
static constexpr Span<const char> MarkerTypeName() {
|
public:
|
||||||
return MakeStringSpan("CONTENT_FRAME_TIME");
|
ContentFramePayload(const mozilla::TimeStamp& aStartTime,
|
||||||
|
const mozilla::TimeStamp& aEndTime)
|
||||||
|
: ProfilerMarkerPayload(aStartTime, aEndTime) {}
|
||||||
|
mozilla::ProfileBufferEntryWriter::Length TagAndSerializationBytes()
|
||||||
|
const override {
|
||||||
|
return CommonPropsTagAndSerializationBytes();
|
||||||
}
|
}
|
||||||
static void StreamJSONMarkerData(
|
void SerializeTagAndPayload(
|
||||||
baseprofiler::SpliceableJSONWriter& aWriter) {}
|
mozilla::ProfileBufferEntryWriter& aEntryWriter) const override {
|
||||||
static MarkerSchema MarkerTypeDisplay() {
|
static const DeserializerTag tag = TagForDeserializer(Deserialize);
|
||||||
using MS = MarkerSchema;
|
SerializeTagAndCommonProps(tag, aEntryWriter);
|
||||||
MS schema{MS::Location::markerChart, MS::Location::markerTable};
|
}
|
||||||
// Nothing outside the defaults.
|
void StreamPayload(mozilla::baseprofiler::SpliceableJSONWriter& aWriter,
|
||||||
return schema;
|
const TimeStamp& aProcessStartTime,
|
||||||
|
UniqueStacks& aUniqueStacks) const override {
|
||||||
|
StreamCommonProps("CONTENT_FRAME_TIME", aWriter, aProcessStartTime,
|
||||||
|
aUniqueStacks);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
explicit ContentFramePayload(CommonProps&& aCommonProps)
|
||||||
|
: ProfilerMarkerPayload(std::move(aCommonProps)) {}
|
||||||
|
static mozilla::UniquePtr<ProfilerMarkerPayload> Deserialize(
|
||||||
|
mozilla::ProfileBufferEntryReader& aEntryReader) {
|
||||||
|
ProfilerMarkerPayload::CommonProps props =
|
||||||
|
DeserializeCommonProps(aEntryReader);
|
||||||
|
return UniquePtr<ProfilerMarkerPayload>(
|
||||||
|
new ContentFramePayload(std::move(props)));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
AUTO_PROFILER_STATS(add_marker_with_ContentFramePayload);
|
||||||
profiler_add_marker("CONTENT_FRAME_TIME", geckoprofiler::category::GRAPHICS,
|
profiler_add_marker_for_thread(
|
||||||
MarkerTiming::Interval(aTxnStart, aCompositeEnd),
|
profiler_current_thread_id(), JS::ProfilingCategoryPair::GRAPHICS,
|
||||||
ContentFrameMarker{});
|
"CONTENT_FRAME_TIME", ContentFramePayload(aTxnStart, aCompositeEnd));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@
|
||||||
#include "mozilla/StaticPtr.h"
|
#include "mozilla/StaticPtr.h"
|
||||||
#include "mozilla/Telemetry.h"
|
#include "mozilla/Telemetry.h"
|
||||||
#ifdef MOZ_GECKO_PROFILER
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
# include "mozilla/BaseProfilerMarkerTypes.h"
|
# include "ProfilerMarkerPayload.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
@ -372,10 +372,43 @@ void ContentCompositorBridgeParent::ShadowLayersUpdated(
|
||||||
auto endTime = TimeStamp::Now();
|
auto endTime = TimeStamp::Now();
|
||||||
#ifdef MOZ_GECKO_PROFILER
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
if (profiler_can_accept_markers()) {
|
if (profiler_can_accept_markers()) {
|
||||||
profiler_add_marker(
|
class ContentBuildPayload : public ProfilerMarkerPayload {
|
||||||
"CONTENT_FULL_PAINT_TIME", geckoprofiler::category::GRAPHICS,
|
public:
|
||||||
MarkerTiming::Interval(aInfo.transactionStart(), endTime),
|
ContentBuildPayload(const mozilla::TimeStamp& aStartTime,
|
||||||
baseprofiler::markers::ContentBuildMarker{});
|
const mozilla::TimeStamp& aEndTime)
|
||||||
|
: ProfilerMarkerPayload(aStartTime, aEndTime) {}
|
||||||
|
mozilla::ProfileBufferEntryWriter::Length TagAndSerializationBytes()
|
||||||
|
const override {
|
||||||
|
return CommonPropsTagAndSerializationBytes();
|
||||||
|
}
|
||||||
|
void SerializeTagAndPayload(
|
||||||
|
mozilla::ProfileBufferEntryWriter& aEntryWriter) const override {
|
||||||
|
static const DeserializerTag tag = TagForDeserializer(Deserialize);
|
||||||
|
SerializeTagAndCommonProps(tag, aEntryWriter);
|
||||||
|
}
|
||||||
|
void StreamPayload(mozilla::baseprofiler::SpliceableJSONWriter& aWriter,
|
||||||
|
const TimeStamp& aProcessStartTime,
|
||||||
|
UniqueStacks& aUniqueStacks) const override {
|
||||||
|
StreamCommonProps("CONTENT_FULL_PAINT_TIME", aWriter, aProcessStartTime,
|
||||||
|
aUniqueStacks);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
explicit ContentBuildPayload(CommonProps&& aCommonProps)
|
||||||
|
: ProfilerMarkerPayload(std::move(aCommonProps)) {}
|
||||||
|
static mozilla::UniquePtr<ProfilerMarkerPayload> Deserialize(
|
||||||
|
mozilla::ProfileBufferEntryReader& aEntryReader) {
|
||||||
|
ProfilerMarkerPayload::CommonProps props =
|
||||||
|
DeserializeCommonProps(aEntryReader);
|
||||||
|
return UniquePtr<ProfilerMarkerPayload>(
|
||||||
|
new ContentBuildPayload(std::move(props)));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
AUTO_PROFILER_STATS(add_marker_with_ContentBuildPayload);
|
||||||
|
profiler_add_marker_for_thread(
|
||||||
|
profiler_current_thread_id(), JS::ProfilingCategoryPair::GRAPHICS,
|
||||||
|
"CONTENT_FULL_PAINT_TIME",
|
||||||
|
ContentBuildPayload(aInfo.transactionStart(), endTime));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
Telemetry::Accumulate(
|
Telemetry::Accumulate(
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MOZ_GECKO_PROFILER
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
# include "mozilla/ProfilerMarkerTypes.h"
|
# include "ProfilerMarkerPayload.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool is_in_main_thread() { return NS_IsMainThread(); }
|
bool is_in_main_thread() { return NS_IsMainThread(); }
|
||||||
|
@ -59,20 +59,26 @@ bool is_in_render_thread() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void gecko_profiler_start_marker(const char* name) {
|
void gecko_profiler_start_marker(const char* name) {
|
||||||
PROFILER_MARKER(mozilla::ProfilerString8View::WrapNullTerminatedString(name),
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
GRAPHICS, mozilla::MarkerTiming::IntervalStart(), Tracing,
|
profiler_tracing_marker("WebRender", name,
|
||||||
"WebRender");
|
JS::ProfilingCategoryPair::GRAPHICS,
|
||||||
|
TRACING_INTERVAL_START);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void gecko_profiler_end_marker(const char* name) {
|
void gecko_profiler_end_marker(const char* name) {
|
||||||
PROFILER_MARKER(mozilla::ProfilerString8View::WrapNullTerminatedString(name),
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
GRAPHICS, mozilla::MarkerTiming::IntervalEnd(), Tracing,
|
profiler_tracing_marker("WebRender", name,
|
||||||
"WebRender");
|
JS::ProfilingCategoryPair::GRAPHICS,
|
||||||
|
TRACING_INTERVAL_END);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void gecko_profiler_event_marker(const char* name) {
|
void gecko_profiler_event_marker(const char* name) {
|
||||||
PROFILER_MARKER(mozilla::ProfilerString8View::WrapNullTerminatedString(name),
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
GRAPHICS, {}, Tracing, "WebRender");
|
profiler_tracing_marker("WebRender", name,
|
||||||
|
JS::ProfilingCategoryPair::GRAPHICS, TRACING_EVENT);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void gecko_profiler_add_text_marker(const char* name, const char* text_bytes,
|
void gecko_profiler_add_text_marker(const char* name, const char* text_bytes,
|
||||||
|
@ -220,10 +226,46 @@ class SceneBuiltNotification : public wr::NotificationHandler {
|
||||||
auto endTime = TimeStamp::Now();
|
auto endTime = TimeStamp::Now();
|
||||||
#ifdef MOZ_GECKO_PROFILER
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
if (profiler_can_accept_markers()) {
|
if (profiler_can_accept_markers()) {
|
||||||
profiler_add_marker("CONTENT_FULL_PAINT_TIME",
|
class ContentFullPaintPayload : public ProfilerMarkerPayload {
|
||||||
geckoprofiler::category::GRAPHICS,
|
public:
|
||||||
MarkerTiming::Interval(startTime, endTime),
|
ContentFullPaintPayload(const mozilla::TimeStamp& aStartTime,
|
||||||
baseprofiler::markers::ContentBuildMarker{});
|
const mozilla::TimeStamp& aEndTime)
|
||||||
|
: ProfilerMarkerPayload(aStartTime, aEndTime) {}
|
||||||
|
mozilla::ProfileBufferEntryWriter::Length
|
||||||
|
TagAndSerializationBytes() const override {
|
||||||
|
return CommonPropsTagAndSerializationBytes();
|
||||||
|
}
|
||||||
|
void SerializeTagAndPayload(mozilla::ProfileBufferEntryWriter&
|
||||||
|
aEntryWriter) const override {
|
||||||
|
static const DeserializerTag tag =
|
||||||
|
TagForDeserializer(Deserialize);
|
||||||
|
SerializeTagAndCommonProps(tag, aEntryWriter);
|
||||||
|
}
|
||||||
|
void StreamPayload(
|
||||||
|
mozilla::baseprofiler::SpliceableJSONWriter& aWriter,
|
||||||
|
const TimeStamp& aProcessStartTime,
|
||||||
|
UniqueStacks& aUniqueStacks) const override {
|
||||||
|
StreamCommonProps("CONTENT_FULL_PAINT_TIME", aWriter,
|
||||||
|
aProcessStartTime, aUniqueStacks);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
explicit ContentFullPaintPayload(CommonProps&& aCommonProps)
|
||||||
|
: ProfilerMarkerPayload(std::move(aCommonProps)) {}
|
||||||
|
static mozilla::UniquePtr<ProfilerMarkerPayload> Deserialize(
|
||||||
|
mozilla::ProfileBufferEntryReader& aEntryReader) {
|
||||||
|
ProfilerMarkerPayload::CommonProps props =
|
||||||
|
DeserializeCommonProps(aEntryReader);
|
||||||
|
return UniquePtr<ProfilerMarkerPayload>(
|
||||||
|
new ContentFullPaintPayload(std::move(props)));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
AUTO_PROFILER_STATS(add_marker_with_ContentFullPaintPayload);
|
||||||
|
profiler_add_marker_for_thread(
|
||||||
|
profiler_current_thread_id(),
|
||||||
|
JS::ProfilingCategoryPair::GRAPHICS, "CONTENT_FULL_PAINT_TIME",
|
||||||
|
ContentFullPaintPayload(startTime, endTime));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
Telemetry::Accumulate(
|
Telemetry::Accumulate(
|
||||||
|
|
|
@ -17,6 +17,10 @@
|
||||||
#include "mozilla/webrender/RenderThread.h"
|
#include "mozilla/webrender/RenderThread.h"
|
||||||
#include "mozilla/widget/CompositorWidget.h"
|
#include "mozilla/widget/CompositorWidget.h"
|
||||||
|
|
||||||
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
|
# include "ProfilerMarkerPayload.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace wr {
|
namespace wr {
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,10 @@
|
||||||
|
|
||||||
#include "chrome/common/ipc_message.h"
|
#include "chrome/common/ipc_message.h"
|
||||||
|
|
||||||
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
|
# include "ProfilerMarkerPayload.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace IPC {
|
namespace IPC {
|
||||||
|
|
||||||
void AddIPCProfilerMarker(const Message& aMessage, int32_t aOtherPid,
|
void AddIPCProfilerMarker(const Message& aMessage, int32_t aOtherPid,
|
||||||
|
@ -21,12 +25,11 @@ void AddIPCProfilerMarker(const Message& aMessage, int32_t aOtherPid,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The current timestamp must be given to the `IPCMarker` payload.
|
PROFILER_ADD_MARKER_WITH_PAYLOAD(
|
||||||
const mozilla::TimeStamp now = mozilla::TimeStamp::NowUnfuzzed();
|
"IPC", IPC, IPCMarkerPayload,
|
||||||
PROFILER_MARKER("IPC", IPC, mozilla::MarkerTiming::InstantAt(now),
|
(aOtherPid, aMessage.seqno(), aMessage.type(),
|
||||||
IPCMarker, now, now, aOtherPid, aMessage.seqno(),
|
mozilla::ipc::UnknownSide, aDirection, aPhase, aMessage.is_sync(),
|
||||||
aMessage.type(), mozilla::ipc::UnknownSide, aDirection,
|
mozilla::TimeStamp::NowUnfuzzed()));
|
||||||
aPhase, aMessage.is_sync());
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,10 @@
|
||||||
using namespace mozilla::tasktracer;
|
using namespace mozilla::tasktracer;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
|
# include "ProfilerMarkerPayload.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
// Undo the damage done by mozzconf.h
|
// Undo the damage done by mozzconf.h
|
||||||
#undef compress
|
#undef compress
|
||||||
|
|
||||||
|
@ -2785,11 +2789,11 @@ void MessageChannel::AddProfilerMarker(const IPC::Message& aMessage,
|
||||||
if (profiler_feature_active(ProfilerFeature::IPCMessages)) {
|
if (profiler_feature_active(ProfilerFeature::IPCMessages)) {
|
||||||
int32_t pid = mListener->OtherPidMaybeInvalid();
|
int32_t pid = mListener->OtherPidMaybeInvalid();
|
||||||
if (pid != kInvalidProcessId) {
|
if (pid != kInvalidProcessId) {
|
||||||
// The current timestamp must be given to the `IPCMarker` payload.
|
PROFILER_ADD_MARKER_WITH_PAYLOAD(
|
||||||
const TimeStamp now = TimeStamp::NowUnfuzzed();
|
"IPC", IPC, IPCMarkerPayload,
|
||||||
PROFILER_MARKER("IPC", IPC, MarkerTiming::InstantAt(now), IPCMarker, now,
|
(pid, aMessage.seqno(), aMessage.type(), mSide, aDirection,
|
||||||
now, pid, aMessage.seqno(), aMessage.type(), mSide,
|
MessagePhase::Endpoint, aMessage.is_sync(),
|
||||||
aDirection, MessagePhase::Endpoint, aMessage.is_sync());
|
TimeStamp::NowUnfuzzed()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -29,10 +29,6 @@
|
||||||
#include "MessageLink.h"
|
#include "MessageLink.h"
|
||||||
#include "mozilla/ipc/Transport.h"
|
#include "mozilla/ipc/Transport.h"
|
||||||
|
|
||||||
#ifdef MOZ_GECKO_PROFILER
|
|
||||||
# include "mozilla/ProfilerMarkersPrerequisites.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class nsIEventTarget;
|
class nsIEventTarget;
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
@ -883,74 +879,4 @@ struct ParamTraits<mozilla::ipc::ResponseRejectReason>
|
||||||
mozilla::ipc::ResponseRejectReason::EndGuard_> {};
|
mozilla::ipc::ResponseRejectReason::EndGuard_> {};
|
||||||
} // namespace IPC
|
} // namespace IPC
|
||||||
|
|
||||||
#ifdef MOZ_GECKO_PROFILER
|
|
||||||
namespace geckoprofiler::markers {
|
|
||||||
|
|
||||||
struct IPCMarker {
|
|
||||||
static constexpr mozilla::Span<const char> MarkerTypeName() {
|
|
||||||
return mozilla::MakeStringSpan("IPC");
|
|
||||||
}
|
|
||||||
static void StreamJSONMarkerData(
|
|
||||||
mozilla::baseprofiler::SpliceableJSONWriter& aWriter,
|
|
||||||
mozilla::TimeStamp aStart, mozilla::TimeStamp aEnd, int32_t aOtherPid,
|
|
||||||
int32_t aMessageSeqno, IPC::Message::msgid_t aMessageType,
|
|
||||||
mozilla::ipc::Side aSide, mozilla::ipc::MessageDirection aDirection,
|
|
||||||
mozilla::ipc::MessagePhase aPhase, bool aSync) {
|
|
||||||
using namespace mozilla::ipc;
|
|
||||||
// This payload still streams a startTime and endTime property because it
|
|
||||||
// made the migration to MarkerTiming on the front-end easier.
|
|
||||||
mozilla::baseprofiler::WritePropertyTime(aWriter, "startTime", aStart);
|
|
||||||
mozilla::baseprofiler::WritePropertyTime(aWriter, "endTime", aEnd);
|
|
||||||
|
|
||||||
aWriter.IntProperty("otherPid", aOtherPid);
|
|
||||||
aWriter.IntProperty("messageSeqno", aMessageSeqno);
|
|
||||||
aWriter.StringProperty(
|
|
||||||
"messageType",
|
|
||||||
mozilla::MakeStringSpan(IPC::StringFromIPCMessageType(aMessageType)));
|
|
||||||
aWriter.StringProperty("side", IPCSideToString(aSide));
|
|
||||||
aWriter.StringProperty("direction",
|
|
||||||
aDirection == MessageDirection::eSending
|
|
||||||
? mozilla::MakeStringSpan("sending")
|
|
||||||
: mozilla::MakeStringSpan("receiving"));
|
|
||||||
aWriter.StringProperty("phase", IPCPhaseToString(aPhase));
|
|
||||||
aWriter.BoolProperty("sync", aSync);
|
|
||||||
}
|
|
||||||
static mozilla::MarkerSchema MarkerTypeDisplay() {
|
|
||||||
return mozilla::MarkerSchema::SpecialFrontendLocation{};
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
static mozilla::Span<const char> IPCSideToString(mozilla::ipc::Side aSide) {
|
|
||||||
switch (aSide) {
|
|
||||||
case mozilla::ipc::ParentSide:
|
|
||||||
return mozilla::MakeStringSpan("parent");
|
|
||||||
case mozilla::ipc::ChildSide:
|
|
||||||
return mozilla::MakeStringSpan("child");
|
|
||||||
case mozilla::ipc::UnknownSide:
|
|
||||||
return mozilla::MakeStringSpan("unknown");
|
|
||||||
default:
|
|
||||||
MOZ_ASSERT_UNREACHABLE("Invalid IPC side");
|
|
||||||
return mozilla::MakeStringSpan("<invalid IPC side>");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static mozilla::Span<const char> IPCPhaseToString(
|
|
||||||
mozilla::ipc::MessagePhase aPhase) {
|
|
||||||
switch (aPhase) {
|
|
||||||
case mozilla::ipc::MessagePhase::Endpoint:
|
|
||||||
return mozilla::MakeStringSpan("endpoint");
|
|
||||||
case mozilla::ipc::MessagePhase::TransferStart:
|
|
||||||
return mozilla::MakeStringSpan("transferStart");
|
|
||||||
case mozilla::ipc::MessagePhase::TransferEnd:
|
|
||||||
return mozilla::MakeStringSpan("transferEnd");
|
|
||||||
default:
|
|
||||||
MOZ_ASSERT_UNREACHABLE("Invalid IPC phase");
|
|
||||||
return mozilla::MakeStringSpan("<invalid IPC phase>");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace geckoprofiler::markers
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // ifndef ipc_glue_MessageChannel_h
|
#endif // ifndef ipc_glue_MessageChannel_h
|
||||||
|
|
|
@ -23,10 +23,6 @@
|
||||||
#include <objbase.h>
|
#include <objbase.h>
|
||||||
#include <objidlbase.h>
|
#include <objidlbase.h>
|
||||||
|
|
||||||
#ifdef MOZ_GECKO_PROFILER
|
|
||||||
# include "mozilla/ProfilerMarkerTypes.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// {9DBE6B28-E5E7-4FDE-AF00-9404604E74DC}
|
// {9DBE6B28-E5E7-4FDE-AF00-9404604E74DC}
|
||||||
static const GUID GUID_MozProfilerMarkerExtension = {
|
static const GUID GUID_MozProfilerMarkerExtension = {
|
||||||
0x9dbe6b28, 0xe5e7, 0x4fde, {0xaf, 0x0, 0x94, 0x4, 0x60, 0x4e, 0x74, 0xdc}};
|
0x9dbe6b28, 0xe5e7, 0x4fde, {0xaf, 0x0, 0x94, 0x4, 0x60, 0x4e, 0x74, 0xdc}};
|
||||||
|
@ -137,8 +133,8 @@ void ProfilerMarkerChannelHook::ClientGetSize(REFGUID aExtensionId, REFIID aIid,
|
||||||
if (NS_IsMainThread()) {
|
if (NS_IsMainThread()) {
|
||||||
nsAutoCString markerName;
|
nsAutoCString markerName;
|
||||||
BuildMarkerName(aIid, markerName);
|
BuildMarkerName(aIid, markerName);
|
||||||
PROFILER_MARKER(markerName, IPC, mozilla::MarkerTiming::IntervalStart(),
|
PROFILER_TRACING_MARKER("MSCOM", markerName.get(), IPC,
|
||||||
Tracing, "MSCOM");
|
TRACING_INTERVAL_START);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aOutDataSize) {
|
if (aOutDataSize) {
|
||||||
|
@ -154,8 +150,8 @@ void ProfilerMarkerChannelHook::ClientNotify(REFGUID aExtensionId, REFIID aIid,
|
||||||
if (NS_IsMainThread() && aExtensionId == GUID_MozProfilerMarkerExtension) {
|
if (NS_IsMainThread() && aExtensionId == GUID_MozProfilerMarkerExtension) {
|
||||||
nsAutoCString markerName;
|
nsAutoCString markerName;
|
||||||
BuildMarkerName(aIid, markerName);
|
BuildMarkerName(aIid, markerName);
|
||||||
PROFILER_MARKER(markerName, IPC, mozilla::MarkerTiming::IntervalEnd(),
|
PROFILER_TRACING_MARKER("MSCOM", markerName.get(), IPC,
|
||||||
Tracing, "MSCOM");
|
TRACING_INTERVAL_END);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,6 +63,9 @@
|
||||||
#include "nsIXULRuntime.h"
|
#include "nsIXULRuntime.h"
|
||||||
#include "nsJSPrincipals.h"
|
#include "nsJSPrincipals.h"
|
||||||
#include "ExpandedPrincipal.h"
|
#include "ExpandedPrincipal.h"
|
||||||
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
|
# include "ProfilerMarkerPayload.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(XP_LINUX) && !defined(ANDROID)
|
#if defined(XP_LINUX) && !defined(ANDROID)
|
||||||
// For getrlimit and min/max.
|
// For getrlimit and min/max.
|
||||||
|
@ -588,7 +591,9 @@ bool XPCJSContext::InterruptCallback(JSContext* cx) {
|
||||||
if (const char* file = scriptFilename.get()) {
|
if (const char* file = scriptFilename.get()) {
|
||||||
filename.Assign(file, strlen(file));
|
filename.Assign(file, strlen(file));
|
||||||
}
|
}
|
||||||
PROFILER_MARKER_TEXT("JS::InterruptCallback", JS, {}, filename);
|
PROFILER_ADD_MARKER_WITH_PAYLOAD("JS::InterruptCallback", JS,
|
||||||
|
TextMarkerPayload,
|
||||||
|
(filename, TimeStamp::Now()));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -8,15 +8,16 @@
|
||||||
#define mozilla_AutoProfilerStyleMarker_h
|
#define mozilla_AutoProfilerStyleMarker_h
|
||||||
|
|
||||||
#include "mozilla/Attributes.h"
|
#include "mozilla/Attributes.h"
|
||||||
#include "mozilla/ProfilerMarkers.h"
|
|
||||||
#include "mozilla/ServoTraversalStatistics.h"
|
#include "mozilla/ServoTraversalStatistics.h"
|
||||||
#include "mozilla/TimeStamp.h"
|
#include "mozilla/TimeStamp.h"
|
||||||
|
#include "GeckoProfiler.h"
|
||||||
|
#include "ProfilerMarkerPayload.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
class MOZ_RAII AutoProfilerStyleMarker {
|
class MOZ_RAII AutoProfilerStyleMarker {
|
||||||
public:
|
public:
|
||||||
explicit AutoProfilerStyleMarker(UniquePtr<ProfileChunkedBuffer> aCause,
|
explicit AutoProfilerStyleMarker(UniqueProfilerBacktrace aCause,
|
||||||
const Maybe<uint64_t>& aInnerWindowID)
|
const Maybe<uint64_t>& aInnerWindowID)
|
||||||
: mActive(profiler_can_accept_markers()),
|
: mActive(profiler_can_accept_markers()),
|
||||||
mStartTime(TimeStamp::Now()),
|
mStartTime(TimeStamp::Now()),
|
||||||
|
@ -35,57 +36,17 @@ class MOZ_RAII AutoProfilerStyleMarker {
|
||||||
if (!mActive) {
|
if (!mActive) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct StyleMarker {
|
|
||||||
static constexpr mozilla::Span<const char> MarkerTypeName() {
|
|
||||||
return mozilla::MakeStringSpan("Styles");
|
|
||||||
}
|
|
||||||
static void StreamJSONMarkerData(
|
|
||||||
baseprofiler::SpliceableJSONWriter& aWriter,
|
|
||||||
uint32_t aElementsTraversed, uint32_t aElementsStyled,
|
|
||||||
uint32_t aElementsMatched, uint32_t aStylesShared,
|
|
||||||
uint32_t aStylesReused) {
|
|
||||||
aWriter.IntProperty("elementsTraversed", aElementsTraversed);
|
|
||||||
aWriter.IntProperty("elementsStyled", aElementsStyled);
|
|
||||||
aWriter.IntProperty("elementsMatched", aElementsMatched);
|
|
||||||
aWriter.IntProperty("stylesShared", aStylesShared);
|
|
||||||
aWriter.IntProperty("stylesReused", aStylesReused);
|
|
||||||
}
|
|
||||||
static MarkerSchema MarkerTypeDisplay() {
|
|
||||||
using MS = MarkerSchema;
|
|
||||||
MS schema{MS::Location::markerChart, MS::Location::markerTable,
|
|
||||||
MS::Location::timelineOverview};
|
|
||||||
schema.AddKeyLabelFormat("elementsTraversed", "Elements traversed",
|
|
||||||
MS::Format::integer);
|
|
||||||
schema.AddKeyLabelFormat("elementsStyled", "Elements styled",
|
|
||||||
MS::Format::integer);
|
|
||||||
schema.AddKeyLabelFormat("elementsMatched", "Elements matched",
|
|
||||||
MS::Format::integer);
|
|
||||||
schema.AddKeyLabelFormat("stylesShared", "Styles shared",
|
|
||||||
MS::Format::integer);
|
|
||||||
schema.AddKeyLabelFormat("stylesReused", "Styles reused",
|
|
||||||
MS::Format::integer);
|
|
||||||
return schema;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
ServoTraversalStatistics::sActive = false;
|
ServoTraversalStatistics::sActive = false;
|
||||||
profiler_add_marker("Styles", geckoprofiler::category::LAYOUT,
|
PROFILER_ADD_MARKER_WITH_PAYLOAD(
|
||||||
{MarkerTiming::IntervalUntilNowFrom(mStartTime),
|
"Styles", LAYOUT, StyleMarkerPayload,
|
||||||
MarkerStack::TakeBacktrace(std::move(mCause)),
|
(mStartTime, TimeStamp::Now(), std::move(mCause),
|
||||||
MarkerInnerWindowId(mInnerWindowID)},
|
ServoTraversalStatistics::sSingleton, mInnerWindowID));
|
||||||
StyleMarker{},
|
|
||||||
ServoTraversalStatistics::sSingleton.mElementsTraversed,
|
|
||||||
ServoTraversalStatistics::sSingleton.mElementsStyled,
|
|
||||||
ServoTraversalStatistics::sSingleton.mElementsMatched,
|
|
||||||
ServoTraversalStatistics::sSingleton.mStylesShared,
|
|
||||||
ServoTraversalStatistics::sSingleton.mStylesReused);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool mActive;
|
bool mActive;
|
||||||
TimeStamp mStartTime;
|
TimeStamp mStartTime;
|
||||||
UniquePtr<ProfileChunkedBuffer> mCause;
|
UniqueProfilerBacktrace mCause;
|
||||||
Maybe<uint64_t> mInnerWindowID;
|
Maybe<uint64_t> mInnerWindowID;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -9565,7 +9565,7 @@ bool PresShell::DoReflow(nsIFrame* target, bool aInterruptible,
|
||||||
innerWindowID = Some(window->WindowID());
|
innerWindowID = Some(window->WindowID());
|
||||||
}
|
}
|
||||||
AutoProfilerTracing tracingLayoutFlush(
|
AutoProfilerTracing tracingLayoutFlush(
|
||||||
"Paint", "Reflow", geckoprofiler::category::LAYOUT,
|
"Paint", "Reflow", JS::ProfilingCategoryPair::LAYOUT,
|
||||||
std::move(mReflowCause), innerWindowID);
|
std::move(mReflowCause), innerWindowID);
|
||||||
mReflowCause = nullptr;
|
mReflowCause = nullptr;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -2861,8 +2861,8 @@ class PresShell final : public nsStubDocumentObserver,
|
||||||
// These two fields capture call stacks of any changes that require a restyle
|
// These two fields capture call stacks of any changes that require a restyle
|
||||||
// or a reflow. Only the first change per restyle / reflow is recorded (the
|
// or a reflow. Only the first change per restyle / reflow is recorded (the
|
||||||
// one that caused a call to SetNeedStyleFlush() / SetNeedLayoutFlush()).
|
// one that caused a call to SetNeedStyleFlush() / SetNeedLayoutFlush()).
|
||||||
UniquePtr<ProfileChunkedBuffer> mStyleCause;
|
UniqueProfilerBacktrace mStyleCause;
|
||||||
UniquePtr<ProfileChunkedBuffer> mReflowCause;
|
UniqueProfilerBacktrace mReflowCause;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
nsTArray<UniquePtr<DelayedEvent>> mDelayedEvents;
|
nsTArray<UniquePtr<DelayedEvent>> mDelayedEvents;
|
||||||
|
|
|
@ -23,7 +23,7 @@ void PresShell::SetNeedLayoutFlush() {
|
||||||
|
|
||||||
#ifdef MOZ_GECKO_PROFILER
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
if (!mReflowCause) {
|
if (!mReflowCause) {
|
||||||
mReflowCause = profiler_capture_backtrace();
|
mReflowCause = profiler_get_backtrace();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ void PresShell::SetNeedStyleFlush() {
|
||||||
|
|
||||||
#ifdef MOZ_GECKO_PROFILER
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
if (!mStyleCause) {
|
if (!mStyleCause) {
|
||||||
mStyleCause = profiler_capture_backtrace();
|
mStyleCause = profiler_get_backtrace();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -129,10 +129,6 @@
|
||||||
#include "nsTextNode.h"
|
#include "nsTextNode.h"
|
||||||
#include "ActiveLayerTracker.h"
|
#include "ActiveLayerTracker.h"
|
||||||
|
|
||||||
#ifdef MOZ_GECKO_PROFILER
|
|
||||||
# include "mozilla/ProfilerMarkerTypes.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
using namespace mozilla::dom;
|
using namespace mozilla::dom;
|
||||||
|
|
||||||
|
@ -8198,8 +8194,9 @@ static nsIFrame* FindPreviousNonWhitespaceSibling(nsIFrame* aFrame) {
|
||||||
bool nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval(
|
bool nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval(
|
||||||
nsIFrame* aFrame) {
|
nsIFrame* aFrame) {
|
||||||
#define TRACE(reason) \
|
#define TRACE(reason) \
|
||||||
PROFILER_MARKER("MaybeRecreateContainerForFrameRemoval: " reason, LAYOUT, \
|
PROFILER_TRACING_MARKER("Layout", \
|
||||||
{}, Tracing, "Layout")
|
"MaybeRecreateContainerForFrameRemoval: " reason, \
|
||||||
|
LAYOUT, TRACING_EVENT)
|
||||||
MOZ_ASSERT(aFrame, "Must have a frame");
|
MOZ_ASSERT(aFrame, "Must have a frame");
|
||||||
MOZ_ASSERT(aFrame->GetParent(), "Frame shouldn't be root");
|
MOZ_ASSERT(aFrame->GetParent(), "Frame shouldn't be root");
|
||||||
MOZ_ASSERT(aFrame == aFrame->FirstContinuation(),
|
MOZ_ASSERT(aFrame == aFrame->FirstContinuation(),
|
||||||
|
@ -10722,8 +10719,9 @@ bool nsCSSFrameConstructor::MaybeRecreateForColumnSpan(
|
||||||
// some of them have column-span:all descendants. Sadly, there's no way to
|
// some of them have column-span:all descendants. Sadly, there's no way to
|
||||||
// detect this by checking FrameConstructionItems in WipeContainingBlock().
|
// detect this by checking FrameConstructionItems in WipeContainingBlock().
|
||||||
// Otherwise, we would have already wiped the multi-column containing block.
|
// Otherwise, we would have already wiped the multi-column containing block.
|
||||||
PROFILER_MARKER("Reframe multi-column after constructing frame list",
|
PROFILER_TRACING_MARKER(
|
||||||
LAYOUT, {}, Tracing, "Layout");
|
"Layout", "Reframe multi-column after constructing frame list", LAYOUT,
|
||||||
|
TRACING_EVENT);
|
||||||
|
|
||||||
// aFrameList can contain placeholder frames. In order to destroy their
|
// aFrameList can contain placeholder frames. In order to destroy their
|
||||||
// associated out-of-flow frames properly, we need to manually flush all the
|
// associated out-of-flow frames properly, we need to manually flush all the
|
||||||
|
@ -11048,9 +11046,9 @@ static bool IsSafeToAppendToIBSplitInline(nsIFrame* aParentFrame,
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nsCSSFrameConstructor::WipeInsertionParent(nsContainerFrame* aFrame) {
|
bool nsCSSFrameConstructor::WipeInsertionParent(nsContainerFrame* aFrame) {
|
||||||
#define TRACE(reason) \
|
#define TRACE(reason) \
|
||||||
PROFILER_MARKER("WipeInsertionParent: " reason, LAYOUT, {}, Tracing, \
|
PROFILER_TRACING_MARKER("Layout", "WipeInsertionParent: " reason, LAYOUT, \
|
||||||
"Layout");
|
TRACING_EVENT)
|
||||||
|
|
||||||
const LayoutFrameType frameType = aFrame->Type();
|
const LayoutFrameType frameType = aFrame->Type();
|
||||||
|
|
||||||
|
@ -11110,9 +11108,9 @@ bool nsCSSFrameConstructor::WipeContainingBlock(
|
||||||
nsFrameConstructorState& aState, nsIFrame* aContainingBlock,
|
nsFrameConstructorState& aState, nsIFrame* aContainingBlock,
|
||||||
nsIFrame* aFrame, FrameConstructionItemList& aItems, bool aIsAppend,
|
nsIFrame* aFrame, FrameConstructionItemList& aItems, bool aIsAppend,
|
||||||
nsIFrame* aPrevSibling) {
|
nsIFrame* aPrevSibling) {
|
||||||
#define TRACE(reason) \
|
#define TRACE(reason) \
|
||||||
PROFILER_MARKER("WipeContainingBlock: " reason, LAYOUT, {}, Tracing, \
|
PROFILER_TRACING_MARKER("Layout", "WipeContainingBlock: " reason, LAYOUT, \
|
||||||
"Layout");
|
TRACING_EVENT)
|
||||||
|
|
||||||
if (aItems.IsEmpty()) {
|
if (aItems.IsEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -2066,8 +2066,9 @@ void nsRefreshDriver::Tick(VsyncId aId, TimeStamp aNowTime) {
|
||||||
// On top level content pages keep the timer running initially so that we
|
// On top level content pages keep the timer running initially so that we
|
||||||
// paint the page soon enough.
|
// paint the page soon enough.
|
||||||
if (ShouldKeepTimerRunningWhileWaitingForFirstContentfulPaint()) {
|
if (ShouldKeepTimerRunningWhileWaitingForFirstContentfulPaint()) {
|
||||||
PROFILER_MARKER("RefreshDriver waiting for first contentful paint",
|
PROFILER_TRACING_MARKER(
|
||||||
GRAPHICS, {}, Tracing, "Paint");
|
"Paint", "RefreshDriver waiting for first contentful paint", GRAPHICS,
|
||||||
|
TRACING_EVENT);
|
||||||
} else {
|
} else {
|
||||||
StopTimer();
|
StopTimer();
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,9 @@
|
||||||
|
|
||||||
#include "base/basictypes.h"
|
#include "base/basictypes.h"
|
||||||
#include "GeckoProfiler.h"
|
#include "GeckoProfiler.h"
|
||||||
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
|
# include "ProfilerMarkerPayload.h"
|
||||||
|
#endif
|
||||||
#include "MainThreadUtils.h"
|
#include "MainThreadUtils.h"
|
||||||
#include "mozilla/ArenaAllocatorExtensions.h"
|
#include "mozilla/ArenaAllocatorExtensions.h"
|
||||||
#include "mozilla/ArenaAllocator.h"
|
#include "mozilla/ArenaAllocator.h"
|
||||||
|
@ -4277,58 +4280,6 @@ static nsCString PrefValueToString(const nsACString& s) { return nsCString(s); }
|
||||||
// We define these methods in a struct which is made friend of Preferences in
|
// We define these methods in a struct which is made friend of Preferences in
|
||||||
// order to access private members.
|
// order to access private members.
|
||||||
struct Internals {
|
struct Internals {
|
||||||
#ifdef MOZ_GECKO_PROFILER
|
|
||||||
struct PreferenceReadMarker {
|
|
||||||
static constexpr Span<const char> MarkerTypeName() {
|
|
||||||
return MakeStringSpan("PreferenceRead");
|
|
||||||
}
|
|
||||||
static void StreamJSONMarkerData(
|
|
||||||
baseprofiler::SpliceableJSONWriter& aWriter,
|
|
||||||
const ProfilerString8View& aPrefName,
|
|
||||||
const Maybe<PrefValueKind>& aPrefKind, PrefType aPrefType,
|
|
||||||
const ProfilerString8View& aPrefValue) {
|
|
||||||
aWriter.StringProperty("prefName", aPrefName);
|
|
||||||
aWriter.StringProperty("prefKind", PrefValueKindToString(aPrefKind));
|
|
||||||
aWriter.StringProperty("prefType", PrefTypeToString(aPrefType));
|
|
||||||
aWriter.StringProperty("prefValue", aPrefValue);
|
|
||||||
}
|
|
||||||
static MarkerSchema MarkerTypeDisplay() {
|
|
||||||
using MS = MarkerSchema;
|
|
||||||
MS schema{MS::Location::markerChart, MS::Location::markerTable};
|
|
||||||
schema.AddKeyLabelFormat("prefName", "Name", MS::Format::string);
|
|
||||||
schema.AddKeyLabelFormat("prefKind", "Kind", MS::Format::string);
|
|
||||||
schema.AddKeyLabelFormat("prefType", "Type", MS::Format::string);
|
|
||||||
schema.AddKeyLabelFormat("prefValue", "Value", MS::Format::string);
|
|
||||||
return schema;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
static Span<const char> PrefValueKindToString(
|
|
||||||
const Maybe<PrefValueKind>& aKind) {
|
|
||||||
if (aKind) {
|
|
||||||
return *aKind == PrefValueKind::Default ? MakeStringSpan("Default")
|
|
||||||
: MakeStringSpan("User");
|
|
||||||
}
|
|
||||||
return "Shared";
|
|
||||||
}
|
|
||||||
|
|
||||||
static Span<const char> PrefTypeToString(PrefType type) {
|
|
||||||
switch (type) {
|
|
||||||
case PrefType::None:
|
|
||||||
return "None";
|
|
||||||
case PrefType::Int:
|
|
||||||
return "Int";
|
|
||||||
case PrefType::Bool:
|
|
||||||
return "Bool";
|
|
||||||
case PrefType::String:
|
|
||||||
return "String";
|
|
||||||
default:
|
|
||||||
MOZ_ASSERT_UNREACHABLE("Unknown preference type.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
#endif // MOZ_GECKO_PROFILER
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static nsresult GetPrefValue(const char* aPrefName, T&& aResult,
|
static nsresult GetPrefValue(const char* aPrefName, T&& aResult,
|
||||||
PrefValueKind aKind) {
|
PrefValueKind aKind) {
|
||||||
|
@ -4340,11 +4291,10 @@ struct Internals {
|
||||||
|
|
||||||
#ifdef MOZ_GECKO_PROFILER
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
if (profiler_feature_active(ProfilerFeature::PreferenceReads)) {
|
if (profiler_feature_active(ProfilerFeature::PreferenceReads)) {
|
||||||
profiler_add_marker(
|
PROFILER_ADD_MARKER_WITH_PAYLOAD(
|
||||||
"PreferenceRead", baseprofiler::category::OTHER_PreferenceRead, {},
|
"PreferenceRead", OTHER_PreferenceRead, PrefMarkerPayload,
|
||||||
PreferenceReadMarker{},
|
(aPrefName, Some(aKind), Some(pref->Type()),
|
||||||
ProfilerString8View::WrapNullTerminatedString(aPrefName),
|
PrefValueToString(aResult), TimeStamp::Now()));
|
||||||
Some(aKind), pref->Type(), PrefValueToString(aResult));
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -4361,12 +4311,10 @@ struct Internals {
|
||||||
|
|
||||||
#ifdef MOZ_GECKO_PROFILER
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
if (profiler_feature_active(ProfilerFeature::PreferenceReads)) {
|
if (profiler_feature_active(ProfilerFeature::PreferenceReads)) {
|
||||||
profiler_add_marker(
|
PROFILER_ADD_MARKER_WITH_PAYLOAD(
|
||||||
"PreferenceRead", baseprofiler::category::OTHER_PreferenceRead, {},
|
"PreferenceRead", OTHER_PreferenceRead, PrefMarkerPayload,
|
||||||
PreferenceReadMarker{},
|
(aName, Nothing() /* indicates Shared */, Some(pref->Type()),
|
||||||
ProfilerString8View::WrapNullTerminatedString(aName),
|
PrefValueToString(aResult), TimeStamp::Now()));
|
||||||
Nothing() /* indicates Shared */, pref->Type(),
|
|
||||||
PrefValueToString(aResult));
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -785,20 +785,13 @@ void ProfileBuffer::StreamMarkersToJSON(SpliceableJSONWriter& aWriter,
|
||||||
MOZ_ASSERT(static_cast<ProfileBufferEntry::KindUnderlyingType>(type) <
|
MOZ_ASSERT(static_cast<ProfileBufferEntry::KindUnderlyingType>(type) <
|
||||||
static_cast<ProfileBufferEntry::KindUnderlyingType>(
|
static_cast<ProfileBufferEntry::KindUnderlyingType>(
|
||||||
ProfileBufferEntry::Kind::MODERN_LIMIT));
|
ProfileBufferEntry::Kind::MODERN_LIMIT));
|
||||||
bool entryWasFullyRead = false;
|
if (type != ProfileBufferEntry::Kind::Marker ||
|
||||||
|
!::mozilla::base_profiler_markers_detail::DeserializeAfterKindAndStream(
|
||||||
if (type == ProfileBufferEntry::Kind::Marker) {
|
aER, aWriter, aThreadId, [&](ProfileChunkedBuffer& aChunkedBuffer) {
|
||||||
entryWasFullyRead = ::mozilla::base_profiler_markers_detail::
|
ProfilerBacktrace backtrace("", &aChunkedBuffer);
|
||||||
DeserializeAfterKindAndStream(
|
backtrace.StreamJSON(aWriter, TimeStamp::ProcessCreation(),
|
||||||
aER, aWriter, aThreadId,
|
aUniqueStacks);
|
||||||
[&](ProfileChunkedBuffer& aChunkedBuffer) {
|
})) {
|
||||||
ProfilerBacktrace backtrace("", &aChunkedBuffer);
|
|
||||||
backtrace.StreamJSON(aWriter, TimeStamp::ProcessCreation(),
|
|
||||||
aUniqueStacks);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!entryWasFullyRead) {
|
|
||||||
// Not a marker, or marker for another thread.
|
// Not a marker, or marker for another thread.
|
||||||
// We probably didn't read the whole entry, so we need to skip to the end.
|
// We probably didn't read the whole entry, so we need to skip to the end.
|
||||||
aER.SetRemainingBytes(0);
|
aER.SetRemainingBytes(0);
|
||||||
|
|
|
@ -29,7 +29,137 @@
|
||||||
|
|
||||||
namespace mozilla::baseprofiler::markers {
|
namespace mozilla::baseprofiler::markers {
|
||||||
|
|
||||||
struct MediaSampleMarker {
|
struct Tracing {
|
||||||
|
static constexpr Span<const char> MarkerTypeName() {
|
||||||
|
return MakeStringSpan("tracing");
|
||||||
|
}
|
||||||
|
static void StreamJSONMarkerData(SpliceableJSONWriter& aWriter,
|
||||||
|
const ProfilerString8View& aCategory) {
|
||||||
|
if (aCategory.Length() != 0) {
|
||||||
|
aWriter.StringProperty("category", aCategory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static MarkerSchema MarkerTypeDisplay() {
|
||||||
|
using MS = MarkerSchema;
|
||||||
|
MS schema{MS::Location::markerChart, MS::Location::markerTable,
|
||||||
|
MS::Location::timelineOverview};
|
||||||
|
schema.AddKeyLabelFormat("category", "Type", MS::Format::string);
|
||||||
|
return schema;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct UserTimingMark {
|
||||||
|
static constexpr Span<const char> MarkerTypeName() {
|
||||||
|
return MakeStringSpan("UserTimingMark");
|
||||||
|
}
|
||||||
|
static void StreamJSONMarkerData(SpliceableJSONWriter& aWriter,
|
||||||
|
const ProfilerString8View& aName) {
|
||||||
|
aWriter.StringProperty("name", aName);
|
||||||
|
aWriter.StringProperty("entryType", "mark");
|
||||||
|
aWriter.NullProperty("startMark");
|
||||||
|
aWriter.NullProperty("endMark");
|
||||||
|
}
|
||||||
|
static MarkerSchema MarkerTypeDisplay() {
|
||||||
|
using MS = MarkerSchema;
|
||||||
|
MS schema{MS::Location::markerChart, MS::Location::markerTable};
|
||||||
|
schema.SetAllLabels("{marker.data.name}");
|
||||||
|
schema.AddStaticLabelValue("Marker", "UserTiming");
|
||||||
|
schema.AddKeyLabelFormat("entryType", "Entry Type", MS::Format::string);
|
||||||
|
schema.AddKeyLabelFormat("name", "Name", MS::Format::string);
|
||||||
|
schema.AddStaticLabelValue(
|
||||||
|
"Description",
|
||||||
|
"UserTimingMark is created using the DOM API performance.mark().");
|
||||||
|
return schema;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct UserTimingMeasure {
|
||||||
|
static constexpr Span<const char> MarkerTypeName() {
|
||||||
|
return MakeStringSpan("UserTimingMeasure");
|
||||||
|
}
|
||||||
|
static void StreamJSONMarkerData(SpliceableJSONWriter& aWriter,
|
||||||
|
const ProfilerString8View& aName,
|
||||||
|
const Maybe<ProfilerString8View>& aStartMark,
|
||||||
|
const Maybe<ProfilerString8View>& aEndMark) {
|
||||||
|
aWriter.StringProperty("name", aName);
|
||||||
|
aWriter.StringProperty("entryType", "measure");
|
||||||
|
|
||||||
|
if (aStartMark.isSome()) {
|
||||||
|
aWriter.StringProperty("startMark", *aStartMark);
|
||||||
|
} else {
|
||||||
|
aWriter.NullProperty("startMark");
|
||||||
|
}
|
||||||
|
if (aEndMark.isSome()) {
|
||||||
|
aWriter.StringProperty("endMark", *aEndMark);
|
||||||
|
} else {
|
||||||
|
aWriter.NullProperty("endMark");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static MarkerSchema MarkerTypeDisplay() {
|
||||||
|
using MS = MarkerSchema;
|
||||||
|
MS schema{MS::Location::markerChart, MS::Location::markerTable};
|
||||||
|
schema.SetAllLabels("{marker.data.name}");
|
||||||
|
schema.AddStaticLabelValue("Marker", "UserTiming");
|
||||||
|
schema.AddKeyLabelFormat("entryType", "Entry Type", MS::Format::string);
|
||||||
|
schema.AddKeyLabelFormat("name", "Name", MS::Format::string);
|
||||||
|
schema.AddKeyLabelFormat("startMark", "Start Mark", MS::Format::string);
|
||||||
|
schema.AddKeyLabelFormat("endMark", "End Mark", MS::Format::string);
|
||||||
|
schema.AddStaticLabelValue("Description",
|
||||||
|
"UserTimingMeasure is created using the DOM API "
|
||||||
|
"performance.measure().");
|
||||||
|
return schema;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Hang {
|
||||||
|
static constexpr Span<const char> MarkerTypeName() {
|
||||||
|
return MakeStringSpan("BHR-detected hang");
|
||||||
|
}
|
||||||
|
static void StreamJSONMarkerData(SpliceableJSONWriter& aWriter) {}
|
||||||
|
static MarkerSchema MarkerTypeDisplay() {
|
||||||
|
using MS = MarkerSchema;
|
||||||
|
MS schema{MS::Location::markerChart, MS::Location::markerTable,
|
||||||
|
MS::Location::timelineOverview};
|
||||||
|
return schema;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LongTask {
|
||||||
|
static constexpr Span<const char> MarkerTypeName() {
|
||||||
|
return MakeStringSpan("MainThreadLongTask");
|
||||||
|
}
|
||||||
|
static void StreamJSONMarkerData(SpliceableJSONWriter& aWriter) {
|
||||||
|
aWriter.StringProperty("category", "LongTask");
|
||||||
|
}
|
||||||
|
static MarkerSchema MarkerTypeDisplay() {
|
||||||
|
using MS = MarkerSchema;
|
||||||
|
MS schema{MS::Location::markerChart, MS::Location::markerTable};
|
||||||
|
schema.AddKeyLabelFormat("category", "Type", MS::Format::string);
|
||||||
|
return schema;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Log {
|
||||||
|
static constexpr Span<const char> MarkerTypeName() {
|
||||||
|
return MakeStringSpan("Log");
|
||||||
|
}
|
||||||
|
static void StreamJSONMarkerData(SpliceableJSONWriter& aWriter,
|
||||||
|
const ProfilerString8View& aModule,
|
||||||
|
const ProfilerString8View& aText) {
|
||||||
|
aWriter.StringProperty("module", aModule);
|
||||||
|
aWriter.StringProperty("name", aText);
|
||||||
|
}
|
||||||
|
static MarkerSchema MarkerTypeDisplay() {
|
||||||
|
using MS = MarkerSchema;
|
||||||
|
MS schema{MS::Location::markerTable};
|
||||||
|
schema.SetTableLabel("({marker.data.module}) {marker.data.name}");
|
||||||
|
schema.AddKeyLabelFormat("module", "Module", MS::Format::string);
|
||||||
|
schema.AddKeyLabelFormat("name", "Name", MS::Format::string);
|
||||||
|
return schema;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MediaSample {
|
||||||
static constexpr Span<const char> MarkerTypeName() {
|
static constexpr Span<const char> MarkerTypeName() {
|
||||||
return MakeStringSpan("MediaSample");
|
return MakeStringSpan("MediaSample");
|
||||||
}
|
}
|
||||||
|
@ -50,18 +180,6 @@ struct MediaSampleMarker {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ContentBuildMarker {
|
|
||||||
static constexpr Span<const char> MarkerTypeName() {
|
|
||||||
return MakeStringSpan("CONTENT_FULL_PAINT_TIME");
|
|
||||||
}
|
|
||||||
static void StreamJSONMarkerData(SpliceableJSONWriter& aWriter) {}
|
|
||||||
static MarkerSchema MarkerTypeDisplay() {
|
|
||||||
using MS = MarkerSchema;
|
|
||||||
MS schema{MS::Location::markerChart, MS::Location::markerTable};
|
|
||||||
return schema;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace mozilla::baseprofiler::markers
|
} // namespace mozilla::baseprofiler::markers
|
||||||
|
|
||||||
#endif // MOZ_GECKO_PROFILER
|
#endif // MOZ_GECKO_PROFILER
|
||||||
|
|
|
@ -160,25 +160,6 @@ struct Text {
|
||||||
return schema;
|
return schema;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Tracing {
|
|
||||||
static constexpr Span<const char> MarkerTypeName() {
|
|
||||||
return MakeStringSpan("tracing");
|
|
||||||
}
|
|
||||||
static void StreamJSONMarkerData(SpliceableJSONWriter& aWriter,
|
|
||||||
const ProfilerString8View& aCategory) {
|
|
||||||
if (aCategory.Length() != 0) {
|
|
||||||
aWriter.StringProperty("category", aCategory);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static MarkerSchema MarkerTypeDisplay() {
|
|
||||||
using MS = MarkerSchema;
|
|
||||||
MS schema{MS::Location::markerChart, MS::Location::markerTable,
|
|
||||||
MS::Location::timelineOverview};
|
|
||||||
schema.AddKeyLabelFormat("category", "Type", MS::Format::string);
|
|
||||||
return schema;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} // namespace mozilla::baseprofiler::markers
|
} // namespace mozilla::baseprofiler::markers
|
||||||
|
|
||||||
// Add a text marker. This macro is safe to use even if MOZ_GECKO_PROFILER is
|
// Add a text marker. This macro is safe to use even if MOZ_GECKO_PROFILER is
|
||||||
|
|
|
@ -129,8 +129,7 @@ class MOZ_STACK_CLASS ProfilerStringView {
|
||||||
Ownership::Reference) {}
|
Ownership::Reference) {}
|
||||||
|
|
||||||
// Implicit constructor from std::string.
|
// Implicit constructor from std::string.
|
||||||
constexpr MOZ_IMPLICIT ProfilerStringView(
|
constexpr MOZ_IMPLICIT ProfilerStringView(const std::string& aString)
|
||||||
const std::basic_string<CHAR>& aString)
|
|
||||||
: ProfilerStringView(aString.data(), aString.length(),
|
: ProfilerStringView(aString.data(), aString.length(),
|
||||||
Ownership::Reference) {}
|
Ownership::Reference) {}
|
||||||
|
|
||||||
|
@ -142,7 +141,7 @@ class MOZ_STACK_CLASS ProfilerStringView {
|
||||||
static constexpr ProfilerStringView WrapNullTerminatedString(
|
static constexpr ProfilerStringView WrapNullTerminatedString(
|
||||||
const CHAR* aString) {
|
const CHAR* aString) {
|
||||||
return ProfilerStringView(
|
return ProfilerStringView(
|
||||||
aString, aString ? std::char_traits<CHAR>::length(aString) : 0,
|
aString, aString ? std::char_traits<char>::length(aString) : 0,
|
||||||
Ownership::Reference);
|
Ownership::Reference);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,8 +182,8 @@ class MOZ_STACK_CLASS ProfilerStringView {
|
||||||
}
|
}
|
||||||
// No `IsOwned...()` because it's a secret, only used internally!
|
// No `IsOwned...()` because it's a secret, only used internally!
|
||||||
|
|
||||||
[[nodiscard]] operator Span<const CHAR>() const {
|
[[nodiscard]] operator Span<const char>() const {
|
||||||
return Span<const CHAR>(Data(), Length());
|
return Span<const char>(Data(), Length());
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -70,8 +70,11 @@ enum class ProfileBufferEntryKind : ProfileBufferEntryKindUnderlyingType {
|
||||||
// Any value starting here does *not* represent a `ProfileBufferEntry` and
|
// Any value starting here does *not* represent a `ProfileBufferEntry` and
|
||||||
// requires separate decoding and handling.
|
// requires separate decoding and handling.
|
||||||
|
|
||||||
// Markers and their data.
|
// Marker data, including payload.
|
||||||
Marker = LEGACY_LIMIT,
|
MarkerData = LEGACY_LIMIT,
|
||||||
|
|
||||||
|
// Markers from 2.0 specs.
|
||||||
|
Marker,
|
||||||
|
|
||||||
// Optional between TimeBeforeCompactStack and CompactStack.
|
// Optional between TimeBeforeCompactStack and CompactStack.
|
||||||
UnresponsiveDurationMs,
|
UnresponsiveDurationMs,
|
||||||
|
|
|
@ -749,15 +749,14 @@ struct ProfileBufferEntryWriter::Serializer<ProfileBufferRawPointer<T>> {
|
||||||
// wrapper necessary.
|
// wrapper necessary.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct ProfileBufferEntryReader::Deserializer<ProfileBufferRawPointer<T>> {
|
struct ProfileBufferEntryReader::Deserializer<ProfileBufferRawPointer<T>> {
|
||||||
static void ReadInto(ProfileBufferEntryReader& aER,
|
static void ReadInto(ProfileBufferEntryReader& aER, T*& aPtr) {
|
||||||
ProfileBufferRawPointer<T>& aPtr) {
|
aER.ReadBytes(&aPtr, sizeof(aPtr));
|
||||||
aER.ReadBytes(&aPtr.mRawPointer, sizeof(aPtr));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static ProfileBufferRawPointer<T> Read(ProfileBufferEntryReader& aER) {
|
static T* Read(ProfileBufferEntryReader& aER) {
|
||||||
ProfileBufferRawPointer<T> rawPointer;
|
T* ptr;
|
||||||
ReadInto(aER, rawPointer);
|
ReadInto(aER, ptr);
|
||||||
return rawPointer;
|
return ptr;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -3014,152 +3014,126 @@ void TestLiteralEmptyStringView() {
|
||||||
printf("TestLiteralEmptyStringView done\n");
|
printf("TestLiteralEmptyStringView done\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename CHAR>
|
|
||||||
void TestProfilerStringView() {
|
void TestProfilerStringView() {
|
||||||
if constexpr (std::is_same_v<CHAR, char>) {
|
printf("TestProfilerStringView...\n");
|
||||||
printf("TestProfilerStringView<char>...\n");
|
|
||||||
} else if constexpr (std::is_same_v<CHAR, char16_t>) {
|
|
||||||
printf("TestProfilerStringView<char16_t>...\n");
|
|
||||||
} else {
|
|
||||||
MOZ_RELEASE_ASSERT(false,
|
|
||||||
"TestProfilerStringView only handles char and char16_t");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Used to verify implicit constructions, as this will normally be used in
|
// Used to verify implicit constructions, as this will normally be used in
|
||||||
// function parameters.
|
// function parameters.
|
||||||
auto BSV = [](mozilla::ProfilerStringView<CHAR>&& aBSV) {
|
auto BS8V = [](mozilla::ProfilerString8View&& aBS8V) {
|
||||||
return std::move(aBSV);
|
return std::move(aBS8V);
|
||||||
};
|
|
||||||
|
|
||||||
// These look like string literals, as expected by some string constructors.
|
|
||||||
const CHAR empty[0 + 1] = {CHAR('\0')};
|
|
||||||
const CHAR hi[2 + 1] = {
|
|
||||||
CHAR('h'),
|
|
||||||
CHAR('i'),
|
|
||||||
CHAR('\0'),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Literal empty string.
|
// Literal empty string.
|
||||||
MOZ_RELEASE_ASSERT(BSV(empty).Data());
|
MOZ_RELEASE_ASSERT(BS8V("").Data());
|
||||||
MOZ_RELEASE_ASSERT(BSV(empty).Data()[0] == CHAR('\0'));
|
MOZ_RELEASE_ASSERT(BS8V("").Data()[0] == '\0');
|
||||||
MOZ_RELEASE_ASSERT(BSV(empty).Length() == 0);
|
MOZ_RELEASE_ASSERT(BS8V("").Length() == 0);
|
||||||
MOZ_RELEASE_ASSERT(BSV(empty).IsLiteral());
|
MOZ_RELEASE_ASSERT(BS8V("").IsLiteral());
|
||||||
MOZ_RELEASE_ASSERT(!BSV(empty).IsReference());
|
MOZ_RELEASE_ASSERT(!BS8V("").IsReference());
|
||||||
|
|
||||||
// Literal non-empty string.
|
// Literal non-empty string.
|
||||||
MOZ_RELEASE_ASSERT(BSV(hi).Data());
|
MOZ_RELEASE_ASSERT(BS8V("hi").Data());
|
||||||
MOZ_RELEASE_ASSERT(BSV(hi).Data()[0] == CHAR('h'));
|
MOZ_RELEASE_ASSERT(BS8V("hi").Data()[0] == 'h');
|
||||||
MOZ_RELEASE_ASSERT(BSV(hi).Data()[1] == CHAR('i'));
|
MOZ_RELEASE_ASSERT(BS8V("hi").Data()[1] == 'i');
|
||||||
MOZ_RELEASE_ASSERT(BSV(hi).Data()[2] == CHAR('\0'));
|
MOZ_RELEASE_ASSERT(BS8V("hi").Data()[2] == '\0');
|
||||||
MOZ_RELEASE_ASSERT(BSV(hi).Length() == 2);
|
MOZ_RELEASE_ASSERT(BS8V("hi").Length() == 2);
|
||||||
MOZ_RELEASE_ASSERT(BSV(hi).IsLiteral());
|
MOZ_RELEASE_ASSERT(BS8V("hi").IsLiteral());
|
||||||
MOZ_RELEASE_ASSERT(!BSV(hi).IsReference());
|
MOZ_RELEASE_ASSERT(!BS8V("hi").IsReference());
|
||||||
|
|
||||||
// std::string_view to a literal empty string.
|
// std::string_view to a literal empty string.
|
||||||
MOZ_RELEASE_ASSERT(BSV(std::basic_string_view<CHAR>(empty)).Data());
|
MOZ_RELEASE_ASSERT(BS8V(std::string_view("")).Data());
|
||||||
MOZ_RELEASE_ASSERT(BSV(std::basic_string_view<CHAR>(empty)).Data()[0] ==
|
MOZ_RELEASE_ASSERT(BS8V(std::string_view("")).Data()[0] == '\0');
|
||||||
CHAR('\0'));
|
MOZ_RELEASE_ASSERT(BS8V(std::string_view("")).Length() == 0);
|
||||||
MOZ_RELEASE_ASSERT(BSV(std::basic_string_view<CHAR>(empty)).Length() == 0);
|
MOZ_RELEASE_ASSERT(!BS8V(std::string_view("")).IsLiteral());
|
||||||
MOZ_RELEASE_ASSERT(!BSV(std::basic_string_view<CHAR>(empty)).IsLiteral());
|
MOZ_RELEASE_ASSERT(BS8V(std::string_view("")).IsReference());
|
||||||
MOZ_RELEASE_ASSERT(BSV(std::basic_string_view<CHAR>(empty)).IsReference());
|
|
||||||
|
|
||||||
// std::string_view to a literal non-empty string.
|
// std::string_view to a literal non-empty string.
|
||||||
MOZ_RELEASE_ASSERT(BSV(std::basic_string_view<CHAR>(hi)).Data());
|
MOZ_RELEASE_ASSERT(BS8V(std::string_view("hi")).Data());
|
||||||
MOZ_RELEASE_ASSERT(BSV(std::basic_string_view<CHAR>(hi)).Data()[0] ==
|
MOZ_RELEASE_ASSERT(BS8V(std::string_view("hi")).Data()[0] == 'h');
|
||||||
CHAR('h'));
|
MOZ_RELEASE_ASSERT(BS8V(std::string_view("hi")).Data()[1] == 'i');
|
||||||
MOZ_RELEASE_ASSERT(BSV(std::basic_string_view<CHAR>(hi)).Data()[1] ==
|
MOZ_RELEASE_ASSERT(BS8V(std::string_view("hi")).Data()[2] == '\0');
|
||||||
CHAR('i'));
|
MOZ_RELEASE_ASSERT(BS8V(std::string_view("hi")).Length() == 2);
|
||||||
MOZ_RELEASE_ASSERT(BSV(std::basic_string_view<CHAR>(hi)).Data()[2] ==
|
MOZ_RELEASE_ASSERT(!BS8V(std::string_view("hi")).IsLiteral());
|
||||||
CHAR('\0'));
|
MOZ_RELEASE_ASSERT(BS8V(std::string_view("hi")).IsReference());
|
||||||
MOZ_RELEASE_ASSERT(BSV(std::basic_string_view<CHAR>(hi)).Length() == 2);
|
|
||||||
MOZ_RELEASE_ASSERT(!BSV(std::basic_string_view<CHAR>(hi)).IsLiteral());
|
|
||||||
MOZ_RELEASE_ASSERT(BSV(std::basic_string_view<CHAR>(hi)).IsReference());
|
|
||||||
|
|
||||||
// Default std::string_view points at nullptr, ProfilerStringView converts it
|
// Default std::string_view points at nullptr, ProfilerStringView converts it
|
||||||
// to the literal empty string.
|
// to the literal empty string.
|
||||||
MOZ_RELEASE_ASSERT(!std::basic_string_view<CHAR>().data());
|
MOZ_RELEASE_ASSERT(!std::string_view().data());
|
||||||
MOZ_RELEASE_ASSERT(BSV(std::basic_string_view<CHAR>()).Data());
|
MOZ_RELEASE_ASSERT(BS8V(std::string_view()).Data());
|
||||||
MOZ_RELEASE_ASSERT(BSV(std::basic_string_view<CHAR>()).Data()[0] ==
|
MOZ_RELEASE_ASSERT(BS8V(std::string_view()).Data()[0] == '\0');
|
||||||
CHAR('\0'));
|
MOZ_RELEASE_ASSERT(BS8V(std::string_view()).Length() == 0);
|
||||||
MOZ_RELEASE_ASSERT(BSV(std::basic_string_view<CHAR>()).Length() == 0);
|
MOZ_RELEASE_ASSERT(BS8V(std::string_view()).IsLiteral());
|
||||||
MOZ_RELEASE_ASSERT(BSV(std::basic_string_view<CHAR>()).IsLiteral());
|
MOZ_RELEASE_ASSERT(!BS8V(std::string_view()).IsReference());
|
||||||
MOZ_RELEASE_ASSERT(!BSV(std::basic_string_view<CHAR>()).IsReference());
|
|
||||||
|
|
||||||
// std::string to a literal empty string.
|
// std::string to a literal empty string.
|
||||||
MOZ_RELEASE_ASSERT(BSV(std::basic_string<CHAR>(empty)).Data());
|
MOZ_RELEASE_ASSERT(BS8V(std::string("")).Data());
|
||||||
MOZ_RELEASE_ASSERT(BSV(std::basic_string<CHAR>(empty)).Data()[0] ==
|
MOZ_RELEASE_ASSERT(BS8V(std::string("")).Data()[0] == '\0');
|
||||||
CHAR('\0'));
|
MOZ_RELEASE_ASSERT(BS8V(std::string("")).Length() == 0);
|
||||||
MOZ_RELEASE_ASSERT(BSV(std::basic_string<CHAR>(empty)).Length() == 0);
|
MOZ_RELEASE_ASSERT(!BS8V(std::string("")).IsLiteral());
|
||||||
MOZ_RELEASE_ASSERT(!BSV(std::basic_string<CHAR>(empty)).IsLiteral());
|
MOZ_RELEASE_ASSERT(BS8V(std::string("")).IsReference());
|
||||||
MOZ_RELEASE_ASSERT(BSV(std::basic_string<CHAR>(empty)).IsReference());
|
|
||||||
|
|
||||||
// std::string to a literal non-empty string.
|
// std::string to a literal non-empty string.
|
||||||
MOZ_RELEASE_ASSERT(BSV(std::basic_string<CHAR>(hi)).Data());
|
MOZ_RELEASE_ASSERT(BS8V(std::string("hi")).Data());
|
||||||
MOZ_RELEASE_ASSERT(BSV(std::basic_string<CHAR>(hi)).Data()[0] == CHAR('h'));
|
MOZ_RELEASE_ASSERT(BS8V(std::string("hi")).Data()[0] == 'h');
|
||||||
MOZ_RELEASE_ASSERT(BSV(std::basic_string<CHAR>(hi)).Data()[1] == CHAR('i'));
|
MOZ_RELEASE_ASSERT(BS8V(std::string("hi")).Data()[1] == 'i');
|
||||||
MOZ_RELEASE_ASSERT(BSV(std::basic_string<CHAR>(hi)).Data()[2] == CHAR('\0'));
|
MOZ_RELEASE_ASSERT(BS8V(std::string("hi")).Data()[2] == '\0');
|
||||||
MOZ_RELEASE_ASSERT(BSV(std::basic_string<CHAR>(hi)).Length() == 2);
|
MOZ_RELEASE_ASSERT(BS8V(std::string("hi")).Length() == 2);
|
||||||
MOZ_RELEASE_ASSERT(!BSV(std::basic_string<CHAR>(hi)).IsLiteral());
|
MOZ_RELEASE_ASSERT(!BS8V(std::string("hi")).IsLiteral());
|
||||||
MOZ_RELEASE_ASSERT(BSV(std::basic_string<CHAR>(hi)).IsReference());
|
MOZ_RELEASE_ASSERT(BS8V(std::string("hi")).IsReference());
|
||||||
|
|
||||||
// Default std::string contains an empty null-terminated string.
|
// Default std::string_view contains an empty null-terminated string.
|
||||||
MOZ_RELEASE_ASSERT(std::basic_string<CHAR>().data());
|
MOZ_RELEASE_ASSERT(std::string().data());
|
||||||
MOZ_RELEASE_ASSERT(BSV(std::basic_string<CHAR>()).Data());
|
MOZ_RELEASE_ASSERT(BS8V(std::string()).Data());
|
||||||
MOZ_RELEASE_ASSERT(BSV(std::basic_string<CHAR>()).Data()[0] == CHAR('\0'));
|
MOZ_RELEASE_ASSERT(BS8V(std::string()).Data()[0] == '\0');
|
||||||
MOZ_RELEASE_ASSERT(BSV(std::basic_string<CHAR>()).Length() == 0);
|
MOZ_RELEASE_ASSERT(BS8V(std::string()).Length() == 0);
|
||||||
MOZ_RELEASE_ASSERT(!BSV(std::basic_string<CHAR>()).IsLiteral());
|
MOZ_RELEASE_ASSERT(!BS8V(std::string()).IsLiteral());
|
||||||
MOZ_RELEASE_ASSERT(BSV(std::basic_string<CHAR>()).IsReference());
|
MOZ_RELEASE_ASSERT(BS8V(std::string()).IsReference());
|
||||||
|
|
||||||
// Class that quacks like nsTString (with Data(), Length(), IsLiteral()), to
|
class FakeNsCString {
|
||||||
// check that ProfilerStringView can read from them.
|
|
||||||
class FakeNsTString {
|
|
||||||
public:
|
public:
|
||||||
FakeNsTString(const CHAR* aData, size_t aLength, bool aIsLiteral)
|
FakeNsCString(const char* aData, size_t aLength, bool aIsLiteral)
|
||||||
: mData(aData), mLength(aLength), mIsLiteral(aIsLiteral) {}
|
: mData(aData), mLength(aLength), mIsLiteral(aIsLiteral) {}
|
||||||
|
|
||||||
const CHAR* Data() const { return mData; }
|
const char* Data() const { return mData; }
|
||||||
size_t Length() const { return mLength; }
|
size_t Length() const { return mLength; }
|
||||||
bool IsLiteral() const { return mIsLiteral; }
|
bool IsLiteral() const { return mIsLiteral; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const CHAR* mData;
|
const char* mData;
|
||||||
size_t mLength;
|
size_t mLength;
|
||||||
bool mIsLiteral;
|
bool mIsLiteral;
|
||||||
};
|
};
|
||||||
|
|
||||||
// FakeNsTString to nullptr.
|
// FakeNsCString to nullptr.
|
||||||
MOZ_RELEASE_ASSERT(BSV(FakeNsTString(nullptr, 0, true)).Data());
|
MOZ_RELEASE_ASSERT(BS8V(FakeNsCString(nullptr, 0, true)).Data());
|
||||||
MOZ_RELEASE_ASSERT(BSV(FakeNsTString(nullptr, 0, true)).Data()[0] ==
|
MOZ_RELEASE_ASSERT(BS8V(FakeNsCString(nullptr, 0, true)).Data()[0] == '\0');
|
||||||
CHAR('\0'));
|
MOZ_RELEASE_ASSERT(BS8V(FakeNsCString(nullptr, 0, true)).Length() == 0);
|
||||||
MOZ_RELEASE_ASSERT(BSV(FakeNsTString(nullptr, 0, true)).Length() == 0);
|
MOZ_RELEASE_ASSERT(BS8V(FakeNsCString(nullptr, 0, true)).IsLiteral());
|
||||||
MOZ_RELEASE_ASSERT(BSV(FakeNsTString(nullptr, 0, true)).IsLiteral());
|
MOZ_RELEASE_ASSERT(!BS8V(FakeNsCString(nullptr, 0, true)).IsReference());
|
||||||
MOZ_RELEASE_ASSERT(!BSV(FakeNsTString(nullptr, 0, true)).IsReference());
|
|
||||||
|
|
||||||
// FakeNsTString to a literal empty string.
|
// FakeNsCString to a literal empty string.
|
||||||
MOZ_RELEASE_ASSERT(BSV(FakeNsTString(empty, 0, true)).Data());
|
MOZ_RELEASE_ASSERT(BS8V(FakeNsCString("", 0, true)).Data());
|
||||||
MOZ_RELEASE_ASSERT(BSV(FakeNsTString(empty, 0, true)).Data()[0] ==
|
MOZ_RELEASE_ASSERT(BS8V(FakeNsCString("", 0, true)).Data()[0] == '\0');
|
||||||
CHAR('\0'));
|
MOZ_RELEASE_ASSERT(BS8V(FakeNsCString("", 0, true)).Length() == 0);
|
||||||
MOZ_RELEASE_ASSERT(BSV(FakeNsTString(empty, 0, true)).Length() == 0);
|
MOZ_RELEASE_ASSERT(BS8V(FakeNsCString("", 0, true)).IsLiteral());
|
||||||
MOZ_RELEASE_ASSERT(BSV(FakeNsTString(empty, 0, true)).IsLiteral());
|
MOZ_RELEASE_ASSERT(!BS8V(FakeNsCString("", 0, true)).IsReference());
|
||||||
MOZ_RELEASE_ASSERT(!BSV(FakeNsTString(empty, 0, true)).IsReference());
|
|
||||||
|
|
||||||
// FakeNsTString to a literal non-empty string.
|
// FakeNsCString to a literal non-empty string.
|
||||||
MOZ_RELEASE_ASSERT(BSV(FakeNsTString(hi, 2, true)).Data());
|
MOZ_RELEASE_ASSERT(BS8V(FakeNsCString("hi", 2, true)).Data());
|
||||||
MOZ_RELEASE_ASSERT(BSV(FakeNsTString(hi, 2, true)).Data()[0] == CHAR('h'));
|
MOZ_RELEASE_ASSERT(BS8V(FakeNsCString("hi", 2, true)).Data()[0] == 'h');
|
||||||
MOZ_RELEASE_ASSERT(BSV(FakeNsTString(hi, 2, true)).Data()[1] == CHAR('i'));
|
MOZ_RELEASE_ASSERT(BS8V(FakeNsCString("hi", 2, true)).Data()[1] == 'i');
|
||||||
MOZ_RELEASE_ASSERT(BSV(FakeNsTString(hi, 2, true)).Data()[2] == CHAR('\0'));
|
MOZ_RELEASE_ASSERT(BS8V(FakeNsCString("hi", 2, true)).Data()[2] == '\0');
|
||||||
MOZ_RELEASE_ASSERT(BSV(FakeNsTString(hi, 2, true)).Length() == 2);
|
MOZ_RELEASE_ASSERT(BS8V(FakeNsCString("hi", 2, true)).Length() == 2);
|
||||||
MOZ_RELEASE_ASSERT(BSV(FakeNsTString(hi, 2, true)).IsLiteral());
|
MOZ_RELEASE_ASSERT(BS8V(FakeNsCString("hi", 2, true)).IsLiteral());
|
||||||
MOZ_RELEASE_ASSERT(!BSV(FakeNsTString(hi, 2, true)).IsReference());
|
MOZ_RELEASE_ASSERT(!BS8V(FakeNsCString("hi", 2, true)).IsReference());
|
||||||
|
|
||||||
// FakeNsTString to a non-literal non-empty string.
|
// FakeNsCString to a non-literal non-empty string.
|
||||||
MOZ_RELEASE_ASSERT(BSV(FakeNsTString(hi, 2, false)).Data());
|
MOZ_RELEASE_ASSERT(BS8V(FakeNsCString("hi", 2, false)).Data());
|
||||||
MOZ_RELEASE_ASSERT(BSV(FakeNsTString(hi, 2, false)).Data()[0] == CHAR('h'));
|
MOZ_RELEASE_ASSERT(BS8V(FakeNsCString("hi", 2, false)).Data()[0] == 'h');
|
||||||
MOZ_RELEASE_ASSERT(BSV(FakeNsTString(hi, 2, false)).Data()[1] == CHAR('i'));
|
MOZ_RELEASE_ASSERT(BS8V(FakeNsCString("hi", 2, false)).Data()[1] == 'i');
|
||||||
MOZ_RELEASE_ASSERT(BSV(FakeNsTString(hi, 2, false)).Data()[2] == CHAR('\0'));
|
MOZ_RELEASE_ASSERT(BS8V(FakeNsCString("hi", 2, false)).Data()[2] == '\0');
|
||||||
MOZ_RELEASE_ASSERT(BSV(FakeNsTString(hi, 2, false)).Length() == 2);
|
MOZ_RELEASE_ASSERT(BS8V(FakeNsCString("hi", 2, false)).Length() == 2);
|
||||||
MOZ_RELEASE_ASSERT(!BSV(FakeNsTString(hi, 2, false)).IsLiteral());
|
MOZ_RELEASE_ASSERT(!BS8V(FakeNsCString("hi", 2, false)).IsLiteral());
|
||||||
MOZ_RELEASE_ASSERT(BSV(FakeNsTString(hi, 2, false)).IsReference());
|
MOZ_RELEASE_ASSERT(BS8V(FakeNsCString("hi", 2, false)).IsReference());
|
||||||
|
|
||||||
// Serialization and deserialization (with ownership).
|
// Serialization and deserialization (with ownership).
|
||||||
constexpr size_t bufferMaxSize = 1024;
|
constexpr size_t bufferMaxSize = 1024;
|
||||||
|
@ -3168,73 +3142,69 @@ void TestProfilerStringView() {
|
||||||
ProfileChunkedBuffer cb(ProfileChunkedBuffer::ThreadSafety::WithMutex, cm);
|
ProfileChunkedBuffer cb(ProfileChunkedBuffer::ThreadSafety::WithMutex, cm);
|
||||||
|
|
||||||
// Literal string, serialized as raw pointer.
|
// Literal string, serialized as raw pointer.
|
||||||
MOZ_RELEASE_ASSERT(cb.PutObject(BSV(hi)));
|
MOZ_RELEASE_ASSERT(cb.PutObject(BS8V("hi")));
|
||||||
{
|
{
|
||||||
unsigned read = 0;
|
unsigned read = 0;
|
||||||
ProfilerStringView<CHAR> outerBSV;
|
ProfilerString8View outerBS8V;
|
||||||
cb.ReadEach([&](ProfileBufferEntryReader& aER) {
|
cb.ReadEach([&](ProfileBufferEntryReader& aER) {
|
||||||
++read;
|
++read;
|
||||||
auto bsv = aER.ReadObject<ProfilerStringView<CHAR>>();
|
auto bs8v = aER.ReadObject<ProfilerString8View>();
|
||||||
MOZ_RELEASE_ASSERT(bsv.Data());
|
MOZ_RELEASE_ASSERT(bs8v.Data());
|
||||||
MOZ_RELEASE_ASSERT(bsv.Data()[0] == CHAR('h'));
|
MOZ_RELEASE_ASSERT(bs8v.Data()[0] == 'h');
|
||||||
MOZ_RELEASE_ASSERT(bsv.Data()[1] == CHAR('i'));
|
MOZ_RELEASE_ASSERT(bs8v.Data()[1] == 'i');
|
||||||
MOZ_RELEASE_ASSERT(bsv.Data()[2] == CHAR('\0'));
|
MOZ_RELEASE_ASSERT(bs8v.Data()[2] == '\0');
|
||||||
MOZ_RELEASE_ASSERT(bsv.Length() == 2);
|
MOZ_RELEASE_ASSERT(bs8v.Length() == 2);
|
||||||
MOZ_RELEASE_ASSERT(bsv.IsLiteral());
|
MOZ_RELEASE_ASSERT(bs8v.IsLiteral());
|
||||||
MOZ_RELEASE_ASSERT(!bsv.IsReference());
|
MOZ_RELEASE_ASSERT(!bs8v.IsReference());
|
||||||
outerBSV = std::move(bsv);
|
outerBS8V = std::move(bs8v);
|
||||||
});
|
});
|
||||||
MOZ_RELEASE_ASSERT(read == 1);
|
MOZ_RELEASE_ASSERT(read == 1);
|
||||||
MOZ_RELEASE_ASSERT(outerBSV.Data());
|
MOZ_RELEASE_ASSERT(outerBS8V.Data());
|
||||||
MOZ_RELEASE_ASSERT(outerBSV.Data()[0] == CHAR('h'));
|
MOZ_RELEASE_ASSERT(outerBS8V.Data()[0] == 'h');
|
||||||
MOZ_RELEASE_ASSERT(outerBSV.Data()[1] == CHAR('i'));
|
MOZ_RELEASE_ASSERT(outerBS8V.Data()[1] == 'i');
|
||||||
MOZ_RELEASE_ASSERT(outerBSV.Data()[2] == CHAR('\0'));
|
MOZ_RELEASE_ASSERT(outerBS8V.Data()[2] == '\0');
|
||||||
MOZ_RELEASE_ASSERT(outerBSV.Length() == 2);
|
MOZ_RELEASE_ASSERT(outerBS8V.Length() == 2);
|
||||||
MOZ_RELEASE_ASSERT(outerBSV.IsLiteral());
|
MOZ_RELEASE_ASSERT(outerBS8V.IsLiteral());
|
||||||
MOZ_RELEASE_ASSERT(!outerBSV.IsReference());
|
MOZ_RELEASE_ASSERT(!outerBS8V.IsReference());
|
||||||
}
|
}
|
||||||
|
|
||||||
cb.Clear();
|
cb.Clear();
|
||||||
|
|
||||||
// Non-literal string, content is serialized.
|
// Non-literal string, content is serialized.
|
||||||
std::basic_string<CHAR> hiString(hi);
|
std::string hiString("hi");
|
||||||
MOZ_RELEASE_ASSERT(cb.PutObject(BSV(hiString)));
|
MOZ_RELEASE_ASSERT(cb.PutObject(BS8V(hiString)));
|
||||||
{
|
{
|
||||||
unsigned read = 0;
|
unsigned read = 0;
|
||||||
ProfilerStringView<CHAR> outerBSV;
|
ProfilerString8View outerBS8V;
|
||||||
cb.ReadEach([&](ProfileBufferEntryReader& aER) {
|
cb.ReadEach([&](ProfileBufferEntryReader& aER) {
|
||||||
++read;
|
++read;
|
||||||
auto bsv = aER.ReadObject<ProfilerStringView<CHAR>>();
|
auto bs8v = aER.ReadObject<ProfilerString8View>();
|
||||||
MOZ_RELEASE_ASSERT(bsv.Data());
|
MOZ_RELEASE_ASSERT(bs8v.Data());
|
||||||
MOZ_RELEASE_ASSERT(bsv.Data() != hiString.data());
|
MOZ_RELEASE_ASSERT(bs8v.Data() != hiString.data());
|
||||||
MOZ_RELEASE_ASSERT(bsv.Data()[0] == CHAR('h'));
|
MOZ_RELEASE_ASSERT(bs8v.Data()[0] == 'h');
|
||||||
MOZ_RELEASE_ASSERT(bsv.Data()[1] == CHAR('i'));
|
MOZ_RELEASE_ASSERT(bs8v.Data()[1] == 'i');
|
||||||
MOZ_RELEASE_ASSERT(bsv.Data()[2] == CHAR('\0'));
|
MOZ_RELEASE_ASSERT(bs8v.Data()[2] == '\0');
|
||||||
MOZ_RELEASE_ASSERT(bsv.Length() == 2);
|
MOZ_RELEASE_ASSERT(bs8v.Length() == 2);
|
||||||
// Special ownership case, neither a literal nor a reference!
|
// Special ownership case, neither a literal nor a reference!
|
||||||
MOZ_RELEASE_ASSERT(!bsv.IsLiteral());
|
MOZ_RELEASE_ASSERT(!bs8v.IsLiteral());
|
||||||
MOZ_RELEASE_ASSERT(!bsv.IsReference());
|
MOZ_RELEASE_ASSERT(!bs8v.IsReference());
|
||||||
// Test move of ownership.
|
// Test move of ownership.
|
||||||
outerBSV = std::move(bsv);
|
outerBS8V = std::move(bs8v);
|
||||||
// NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move)
|
// NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move)
|
||||||
MOZ_RELEASE_ASSERT(bsv.Length() == 0);
|
MOZ_RELEASE_ASSERT(bs8v.Length() == 0);
|
||||||
});
|
});
|
||||||
MOZ_RELEASE_ASSERT(read == 1);
|
MOZ_RELEASE_ASSERT(read == 1);
|
||||||
MOZ_RELEASE_ASSERT(outerBSV.Data());
|
MOZ_RELEASE_ASSERT(outerBS8V.Data());
|
||||||
MOZ_RELEASE_ASSERT(outerBSV.Data() != hiString.data());
|
MOZ_RELEASE_ASSERT(outerBS8V.Data() != hiString.data());
|
||||||
MOZ_RELEASE_ASSERT(outerBSV.Data()[0] == CHAR('h'));
|
MOZ_RELEASE_ASSERT(outerBS8V.Data()[0] == 'h');
|
||||||
MOZ_RELEASE_ASSERT(outerBSV.Data()[1] == CHAR('i'));
|
MOZ_RELEASE_ASSERT(outerBS8V.Data()[1] == 'i');
|
||||||
MOZ_RELEASE_ASSERT(outerBSV.Data()[2] == CHAR('\0'));
|
MOZ_RELEASE_ASSERT(outerBS8V.Data()[2] == '\0');
|
||||||
MOZ_RELEASE_ASSERT(outerBSV.Length() == 2);
|
MOZ_RELEASE_ASSERT(outerBS8V.Length() == 2);
|
||||||
MOZ_RELEASE_ASSERT(!outerBSV.IsLiteral());
|
MOZ_RELEASE_ASSERT(!outerBS8V.IsLiteral());
|
||||||
MOZ_RELEASE_ASSERT(!outerBSV.IsReference());
|
MOZ_RELEASE_ASSERT(!outerBS8V.IsReference());
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr (std::is_same_v<CHAR, char>) {
|
printf("TestProfilerStringView done\n");
|
||||||
printf("TestProfilerStringView<char> done\n");
|
|
||||||
} else if constexpr (std::is_same_v<CHAR, char16_t>) {
|
|
||||||
printf("TestProfilerStringView<char16_t> done\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestProfilerDependencies() {
|
void TestProfilerDependencies() {
|
||||||
|
@ -3254,8 +3224,7 @@ void TestProfilerDependencies() {
|
||||||
TestBlocksRingBufferThreading();
|
TestBlocksRingBufferThreading();
|
||||||
TestBlocksRingBufferSerialization();
|
TestBlocksRingBufferSerialization();
|
||||||
TestLiteralEmptyStringView();
|
TestLiteralEmptyStringView();
|
||||||
TestProfilerStringView<char>();
|
TestProfilerStringView();
|
||||||
TestProfilerStringView<char16_t>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Increase the depth, to a maximum (to avoid too-deep recursion).
|
// Increase the depth, to a maximum (to avoid too-deep recursion).
|
||||||
|
@ -3470,13 +3439,34 @@ void TestProfiler() {
|
||||||
"tracing", mozilla::baseprofiler::category::OTHER, {},
|
"tracing", mozilla::baseprofiler::category::OTHER, {},
|
||||||
mozilla::baseprofiler::markers::Tracing{}, "category"));
|
mozilla::baseprofiler::markers::Tracing{}, "category"));
|
||||||
|
|
||||||
|
MOZ_RELEASE_ASSERT(baseprofiler::AddMarker(
|
||||||
|
"mark", mozilla::baseprofiler::category::OTHER, {},
|
||||||
|
mozilla::baseprofiler::markers::UserTimingMark{}, "mark name"));
|
||||||
|
|
||||||
|
MOZ_RELEASE_ASSERT(baseprofiler::AddMarker(
|
||||||
|
"measure", mozilla::baseprofiler::category::OTHER, {},
|
||||||
|
mozilla::baseprofiler::markers::UserTimingMeasure{}, "measure name",
|
||||||
|
Some(ProfilerString8View("start")), Some(ProfilerString8View("end"))));
|
||||||
|
|
||||||
|
MOZ_RELEASE_ASSERT(
|
||||||
|
baseprofiler::AddMarker("hang", mozilla::baseprofiler::category::OTHER,
|
||||||
|
{}, mozilla::baseprofiler::markers::Hang{}));
|
||||||
|
|
||||||
|
MOZ_RELEASE_ASSERT(baseprofiler::AddMarker(
|
||||||
|
"longtask", mozilla::baseprofiler::category::OTHER, {},
|
||||||
|
mozilla::baseprofiler::markers::LongTask{}));
|
||||||
|
|
||||||
MOZ_RELEASE_ASSERT(baseprofiler::AddMarker(
|
MOZ_RELEASE_ASSERT(baseprofiler::AddMarker(
|
||||||
"text", mozilla::baseprofiler::category::OTHER, {},
|
"text", mozilla::baseprofiler::category::OTHER, {},
|
||||||
mozilla::baseprofiler::markers::Text{}, "text text"));
|
mozilla::baseprofiler::markers::Text{}, "text text"));
|
||||||
|
|
||||||
|
MOZ_RELEASE_ASSERT(baseprofiler::AddMarker(
|
||||||
|
"log", mozilla::baseprofiler::category::OTHER, {},
|
||||||
|
mozilla::baseprofiler::markers::Log{}, "module", "text"));
|
||||||
|
|
||||||
MOZ_RELEASE_ASSERT(baseprofiler::AddMarker(
|
MOZ_RELEASE_ASSERT(baseprofiler::AddMarker(
|
||||||
"media sample", mozilla::baseprofiler::category::OTHER, {},
|
"media sample", mozilla::baseprofiler::category::OTHER, {},
|
||||||
mozilla::baseprofiler::markers::MediaSampleMarker{}, 123, 456));
|
mozilla::baseprofiler::markers::MediaSample{}, 123, 456));
|
||||||
|
|
||||||
printf("Sleep 1s...\n");
|
printf("Sleep 1s...\n");
|
||||||
{
|
{
|
||||||
|
@ -3532,7 +3522,16 @@ void TestProfiler() {
|
||||||
MOZ_RELEASE_ASSERT(profileSV.find("\"markerSchema\": [") != svnpos);
|
MOZ_RELEASE_ASSERT(profileSV.find("\"markerSchema\": [") != svnpos);
|
||||||
MOZ_RELEASE_ASSERT(profileSV.find("\"name\": \"Text\",") != svnpos);
|
MOZ_RELEASE_ASSERT(profileSV.find("\"name\": \"Text\",") != svnpos);
|
||||||
MOZ_RELEASE_ASSERT(profileSV.find("\"name\": \"tracing\",") != svnpos);
|
MOZ_RELEASE_ASSERT(profileSV.find("\"name\": \"tracing\",") != svnpos);
|
||||||
|
MOZ_RELEASE_ASSERT(profileSV.find("\"name\": \"UserTimingMark\",") !=
|
||||||
|
svnpos);
|
||||||
|
MOZ_RELEASE_ASSERT(profileSV.find("\"name\": \"UserTimingMeasure\",") !=
|
||||||
|
svnpos);
|
||||||
|
MOZ_RELEASE_ASSERT(profileSV.find("\"name\": \"BHR-detected hang\",") !=
|
||||||
|
svnpos);
|
||||||
|
MOZ_RELEASE_ASSERT(profileSV.find("\"name\": \"Log\",") != svnpos);
|
||||||
MOZ_RELEASE_ASSERT(profileSV.find("\"name\": \"MediaSample\",") != svnpos);
|
MOZ_RELEASE_ASSERT(profileSV.find("\"name\": \"MediaSample\",") != svnpos);
|
||||||
|
MOZ_RELEASE_ASSERT(profileSV.find("\"name\": \"MainThreadLongTask\",") !=
|
||||||
|
svnpos);
|
||||||
MOZ_RELEASE_ASSERT(profileSV.find("\"display\": [") != svnpos);
|
MOZ_RELEASE_ASSERT(profileSV.find("\"display\": [") != svnpos);
|
||||||
MOZ_RELEASE_ASSERT(profileSV.find("\"marker-chart\"") != svnpos);
|
MOZ_RELEASE_ASSERT(profileSV.find("\"marker-chart\"") != svnpos);
|
||||||
MOZ_RELEASE_ASSERT(profileSV.find("\"marker-table\"") != svnpos);
|
MOZ_RELEASE_ASSERT(profileSV.find("\"marker-table\"") != svnpos);
|
||||||
|
@ -4035,13 +4034,37 @@ void TestPredefinedMarkers() {
|
||||||
mozilla::baseprofiler::category::OTHER, {},
|
mozilla::baseprofiler::category::OTHER, {},
|
||||||
mozilla::baseprofiler::markers::Tracing{}, "category"));
|
mozilla::baseprofiler::markers::Tracing{}, "category"));
|
||||||
|
|
||||||
|
MOZ_RELEASE_ASSERT(mozilla::baseprofiler::AddMarkerToBuffer(
|
||||||
|
buffer, std::string_view("mark"), mozilla::baseprofiler::category::OTHER,
|
||||||
|
{}, mozilla::baseprofiler::markers::UserTimingMark{}, "mark name"));
|
||||||
|
|
||||||
|
MOZ_RELEASE_ASSERT(mozilla::baseprofiler::AddMarkerToBuffer(
|
||||||
|
buffer, std::string_view("measure"),
|
||||||
|
mozilla::baseprofiler::category::OTHER, {},
|
||||||
|
mozilla::baseprofiler::markers::UserTimingMeasure{}, "measure name ",
|
||||||
|
mozilla::Some(mozilla::ProfilerString8View(" start ")),
|
||||||
|
mozilla::Some(mozilla::ProfilerString8View("end"))));
|
||||||
|
|
||||||
|
MOZ_RELEASE_ASSERT(mozilla::baseprofiler::AddMarkerToBuffer(
|
||||||
|
buffer, std::string_view("hang"), mozilla::baseprofiler::category::OTHER,
|
||||||
|
{}, mozilla::baseprofiler::markers::Hang{}));
|
||||||
|
|
||||||
|
MOZ_RELEASE_ASSERT(mozilla::baseprofiler::AddMarkerToBuffer(
|
||||||
|
buffer, std::string_view("long task"),
|
||||||
|
mozilla::baseprofiler::category::OTHER, {},
|
||||||
|
mozilla::baseprofiler::markers::LongTask{}));
|
||||||
|
|
||||||
MOZ_RELEASE_ASSERT(mozilla::baseprofiler::AddMarkerToBuffer(
|
MOZ_RELEASE_ASSERT(mozilla::baseprofiler::AddMarkerToBuffer(
|
||||||
buffer, std::string_view("text"), mozilla::baseprofiler::category::OTHER,
|
buffer, std::string_view("text"), mozilla::baseprofiler::category::OTHER,
|
||||||
{}, mozilla::baseprofiler::markers::Text{}, "text text"));
|
{}, mozilla::baseprofiler::markers::Text{}, "text text"));
|
||||||
|
|
||||||
|
MOZ_RELEASE_ASSERT(mozilla::baseprofiler::AddMarkerToBuffer(
|
||||||
|
buffer, std::string_view("log"), mozilla::baseprofiler::category::OTHER,
|
||||||
|
{}, mozilla::baseprofiler::markers::Log{}, "module", "text"));
|
||||||
|
|
||||||
MOZ_RELEASE_ASSERT(mozilla::baseprofiler::AddMarkerToBuffer(
|
MOZ_RELEASE_ASSERT(mozilla::baseprofiler::AddMarkerToBuffer(
|
||||||
buffer, std::string_view("media"), mozilla::baseprofiler::category::OTHER,
|
buffer, std::string_view("media"), mozilla::baseprofiler::category::OTHER,
|
||||||
{}, mozilla::baseprofiler::markers::MediaSampleMarker{}, 123, 456));
|
{}, mozilla::baseprofiler::markers::MediaSample{}, 123, 456));
|
||||||
|
|
||||||
# ifdef DEBUG
|
# ifdef DEBUG
|
||||||
buffer.Dump();
|
buffer.Dump();
|
||||||
|
|
|
@ -248,7 +248,7 @@ class HttpBaseChannel : public nsHashPropertyBag,
|
||||||
|
|
||||||
using nsIClassifiedChannel::IsThirdPartyTrackingResource;
|
using nsIClassifiedChannel::IsThirdPartyTrackingResource;
|
||||||
|
|
||||||
virtual void SetSource(UniquePtr<ProfileChunkedBuffer> aSource) override {
|
virtual void SetSource(UniqueProfilerBacktrace aSource) override {
|
||||||
mSource = std::move(aSource);
|
mSource = std::move(aSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -756,7 +756,7 @@ class HttpBaseChannel : public nsHashPropertyBag,
|
||||||
Atomic<uint32_t, ReleaseAcquire> mThirdPartyClassificationFlags;
|
Atomic<uint32_t, ReleaseAcquire> mThirdPartyClassificationFlags;
|
||||||
Atomic<uint32_t, ReleaseAcquire> mFlashPluginState;
|
Atomic<uint32_t, ReleaseAcquire> mFlashPluginState;
|
||||||
|
|
||||||
UniquePtr<ProfileChunkedBuffer> mSource;
|
UniqueProfilerBacktrace mSource;
|
||||||
|
|
||||||
uint32_t mLoadFlags;
|
uint32_t mLoadFlags;
|
||||||
uint32_t mCaps;
|
uint32_t mCaps;
|
||||||
|
|
|
@ -67,6 +67,10 @@
|
||||||
# include "GeckoTaskTracer.h"
|
# include "GeckoTaskTracer.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
|
# include "ProfilerMarkerPayload.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
using namespace mozilla::dom;
|
using namespace mozilla::dom;
|
||||||
|
|
|
@ -135,6 +135,10 @@
|
||||||
# include "GeckoTaskTracer.h"
|
# include "GeckoTaskTracer.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
|
# include "ProfilerMarkerPayload.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
using namespace dom;
|
using namespace dom;
|
||||||
|
|
|
@ -501,6 +501,6 @@ interface nsIHttpChannel : nsIIdentChannel
|
||||||
in AString aContentType);
|
in AString aContentType);
|
||||||
|
|
||||||
%{ C++
|
%{ C++
|
||||||
virtual void SetSource(mozilla::UniquePtr<mozilla::ProfileChunkedBuffer> aSource) {}
|
virtual void SetSource(UniqueProfilerBacktrace aSource) {}
|
||||||
%}
|
%}
|
||||||
};
|
};
|
||||||
|
|
|
@ -31,6 +31,10 @@
|
||||||
#include "prinrval.h"
|
#include "prinrval.h"
|
||||||
#include "prthread.h"
|
#include "prthread.h"
|
||||||
|
|
||||||
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
|
# include "ProfilerMarkerPayload.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
// Activate BHR only for one every BHR_BETA_MOD users.
|
// Activate BHR only for one every BHR_BETA_MOD users.
|
||||||
|
@ -530,26 +534,12 @@ void BackgroundHangThread::ReportHang(TimeDuration aHangTime,
|
||||||
// If the profiler is enabled, add a marker.
|
// If the profiler is enabled, add a marker.
|
||||||
#ifdef MOZ_GECKO_PROFILER
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
if (profiler_can_accept_markers()) {
|
if (profiler_can_accept_markers()) {
|
||||||
struct HangMarker {
|
TimeStamp endTime = TimeStamp::Now();
|
||||||
static constexpr Span<const char> MarkerTypeName() {
|
TimeStamp startTime = endTime - aHangTime;
|
||||||
return MakeStringSpan("BHR-detected hang");
|
AUTO_PROFILER_STATS(add_marker_with_HangMarkerPayload);
|
||||||
}
|
profiler_add_marker_for_thread(
|
||||||
static void StreamJSONMarkerData(
|
mStackHelper.GetThreadId(), JS::ProfilingCategoryPair::OTHER,
|
||||||
baseprofiler::SpliceableJSONWriter& aWriter) {}
|
"BHR-detected hang", HangMarkerPayload(startTime, endTime));
|
||||||
static MarkerSchema MarkerTypeDisplay() {
|
|
||||||
using MS = MarkerSchema;
|
|
||||||
MS schema{MS::Location::markerChart, MS::Location::markerTable,
|
|
||||||
MS::Location::timelineOverview};
|
|
||||||
return schema;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const TimeStamp endTime = TimeStamp::NowUnfuzzed();
|
|
||||||
const TimeStamp startTime = endTime - aHangTime;
|
|
||||||
profiler_add_marker("BHR-detected hang", geckoprofiler::category::OTHER,
|
|
||||||
{MarkerThreadId(mStackHelper.GetThreadId()),
|
|
||||||
MarkerTiming::Interval(startTime, endTime)},
|
|
||||||
HangMarker{});
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "ProfileBuffer.h"
|
#include "ProfileBuffer.h"
|
||||||
#include "ProfilerBacktrace.h"
|
#include "ProfilerBacktrace.h"
|
||||||
|
#include "ProfilerMarkerPayload.h"
|
||||||
|
|
||||||
#include "jsapi.h"
|
#include "jsapi.h"
|
||||||
#include "jsfriendapi.h"
|
#include "jsfriendapi.h"
|
||||||
|
@ -635,6 +636,7 @@ class EntryGetter {
|
||||||
// )+
|
// )+
|
||||||
// */
|
// */
|
||||||
// )
|
// )
|
||||||
|
// | MarkerData
|
||||||
// | Marker
|
// | Marker
|
||||||
// | ( /* Counters */
|
// | ( /* Counters */
|
||||||
// CounterId
|
// CounterId
|
||||||
|
@ -1152,23 +1154,78 @@ void ProfileBuffer::StreamMarkersToJSON(SpliceableJSONWriter& aWriter,
|
||||||
MOZ_ASSERT(static_cast<ProfileBufferEntry::KindUnderlyingType>(type) <
|
MOZ_ASSERT(static_cast<ProfileBufferEntry::KindUnderlyingType>(type) <
|
||||||
static_cast<ProfileBufferEntry::KindUnderlyingType>(
|
static_cast<ProfileBufferEntry::KindUnderlyingType>(
|
||||||
ProfileBufferEntry::Kind::MODERN_LIMIT));
|
ProfileBufferEntry::Kind::MODERN_LIMIT));
|
||||||
bool entryWasFullyRead = false;
|
// Code should *return* from the switch if the entry was fully read.
|
||||||
|
// Code should *break* from the switch if the entry was not fully read (we
|
||||||
|
// then need to adjust the reader position to the end of the entry, as
|
||||||
|
// expected by the reader code.)
|
||||||
|
switch (type) {
|
||||||
|
case ProfileBufferEntry::Kind::MarkerData:
|
||||||
|
if (aER.ReadObject<int>() != aThreadId) {
|
||||||
|
break; // Entry not fully read.
|
||||||
|
}
|
||||||
|
aWriter.StartArrayElement();
|
||||||
|
{
|
||||||
|
// Extract the information from the buffer:
|
||||||
|
// Each entry is made up of the following:
|
||||||
|
//
|
||||||
|
// [
|
||||||
|
// ProfileBufferEntry::Kind::MarkerData, <- already read
|
||||||
|
// threadId, <- already read
|
||||||
|
// name, <- next location in entries
|
||||||
|
// startTime,
|
||||||
|
// endTime,
|
||||||
|
// phase,
|
||||||
|
// categoryPair,
|
||||||
|
// payload
|
||||||
|
// ]
|
||||||
|
auto name = aER.ReadObject<std::string>();
|
||||||
|
auto startTime = aER.ReadObject<double>();
|
||||||
|
auto endTime = aER.ReadObject<double>();
|
||||||
|
auto phase = aER.ReadObject<uint8_t>();
|
||||||
|
const JS::ProfilingCategoryPairInfo& info =
|
||||||
|
GetProfilingCategoryPairInfo(
|
||||||
|
static_cast<JS::ProfilingCategoryPair>(
|
||||||
|
aER.ReadObject<uint32_t>()));
|
||||||
|
auto payload = aER.ReadObject<UniquePtr<ProfilerMarkerPayload>>();
|
||||||
|
|
||||||
if (type == ProfileBufferEntry::Kind::Marker) {
|
MOZ_ASSERT(aER.RemainingBytes() == 0);
|
||||||
entryWasFullyRead =
|
|
||||||
mozilla::base_profiler_markers_detail::DeserializeAfterKindAndStream(
|
// Now write this information to JSON with the following schema:
|
||||||
aER, aWriter, aThreadId,
|
// [name, startTime, endTime, phase, category, data]
|
||||||
[&](ProfileChunkedBuffer& aChunkedBuffer) {
|
aUniqueStacks.mUniqueStrings->WriteElement(aWriter, name);
|
||||||
ProfilerBacktrace backtrace("", &aChunkedBuffer);
|
aWriter.DoubleElement(startTime);
|
||||||
backtrace.StreamJSON(aWriter, aProcessStartTime, aUniqueStacks);
|
aWriter.DoubleElement(endTime);
|
||||||
});
|
aWriter.IntElement(phase);
|
||||||
|
aWriter.IntElement(unsigned(info.mCategory));
|
||||||
|
if (payload) {
|
||||||
|
aWriter.StartObjectElement(SpliceableJSONWriter::SingleLineStyle);
|
||||||
|
{
|
||||||
|
payload->StreamPayload(aWriter, aProcessStartTime, aUniqueStacks);
|
||||||
|
}
|
||||||
|
aWriter.EndObject();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
aWriter.EndArray();
|
||||||
|
return; // Entry fully read.
|
||||||
|
|
||||||
|
case ProfileBufferEntry::Kind::Marker:
|
||||||
|
if (mozilla::base_profiler_markers_detail::
|
||||||
|
DeserializeAfterKindAndStream(
|
||||||
|
aER, aWriter, aThreadId,
|
||||||
|
[&](ProfileChunkedBuffer& aChunkedBuffer) {
|
||||||
|
ProfilerBacktrace backtrace("", &aChunkedBuffer);
|
||||||
|
backtrace.StreamJSON(aWriter, aProcessStartTime,
|
||||||
|
aUniqueStacks);
|
||||||
|
})) {
|
||||||
|
return; // Entry fully read.
|
||||||
|
}
|
||||||
|
break; // Entry not fully read.
|
||||||
|
|
||||||
|
default:
|
||||||
|
break; // Entry not fully read.
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!entryWasFullyRead) {
|
aER.SetRemainingBytes(0);
|
||||||
// The entry was not a marker, or it was a marker for another thread.
|
|
||||||
// We probably didn't read the whole entry, so we need to skip to the end.
|
|
||||||
aER.SetRemainingBytes(0);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -37,6 +37,7 @@ size_t RegisteredThread::SizeOfIncludingThis(
|
||||||
// Measurement of the following members may be added later if DMD finds it
|
// Measurement of the following members may be added later if DMD finds it
|
||||||
// is worthwhile:
|
// is worthwhile:
|
||||||
// - mPlatformData
|
// - mPlatformData
|
||||||
|
// - mRacyRegisteredThread.mPendingMarkers
|
||||||
//
|
//
|
||||||
// The following members are not measured:
|
// The following members are not measured:
|
||||||
// - mThreadInfo: because it is non-owning
|
// - mThreadInfo: because it is non-owning
|
||||||
|
|
|
@ -265,6 +265,10 @@ class ThreadIntercept {
|
||||||
// or disabled.
|
// or disabled.
|
||||||
static mozilla::Atomic<bool, mozilla::Relaxed> sAllocationsFeatureEnabled;
|
static mozilla::Atomic<bool, mozilla::Relaxed> sAllocationsFeatureEnabled;
|
||||||
|
|
||||||
|
// The markers will be stored on the main thread. Retain the id to the main
|
||||||
|
// thread of this process here.
|
||||||
|
static mozilla::Atomic<int, mozilla::Relaxed> sMainThreadId;
|
||||||
|
|
||||||
ThreadIntercept() = default;
|
ThreadIntercept() = default;
|
||||||
|
|
||||||
// Only allow consumers to access this information if they run
|
// Only allow consumers to access this information if they run
|
||||||
|
@ -311,9 +315,14 @@ class ThreadIntercept {
|
||||||
|
|
||||||
bool IsBlocked() const { return ThreadIntercept::IsBlocked_(); }
|
bool IsBlocked() const { return ThreadIntercept::IsBlocked_(); }
|
||||||
|
|
||||||
static void EnableAllocationFeature() { sAllocationsFeatureEnabled = true; }
|
static void EnableAllocationFeature(int aMainThreadId) {
|
||||||
|
sAllocationsFeatureEnabled = true;
|
||||||
|
sMainThreadId = aMainThreadId;
|
||||||
|
}
|
||||||
|
|
||||||
static void DisableAllocationFeature() { sAllocationsFeatureEnabled = false; }
|
static void DisableAllocationFeature() { sAllocationsFeatureEnabled = false; }
|
||||||
|
|
||||||
|
static int MainThreadId() { return sMainThreadId; }
|
||||||
};
|
};
|
||||||
|
|
||||||
PROFILER_THREAD_LOCAL(bool) ThreadIntercept::tlsIsBlocked;
|
PROFILER_THREAD_LOCAL(bool) ThreadIntercept::tlsIsBlocked;
|
||||||
|
@ -321,6 +330,8 @@ PROFILER_THREAD_LOCAL(bool) ThreadIntercept::tlsIsBlocked;
|
||||||
mozilla::Atomic<bool, mozilla::Relaxed>
|
mozilla::Atomic<bool, mozilla::Relaxed>
|
||||||
ThreadIntercept::sAllocationsFeatureEnabled(false);
|
ThreadIntercept::sAllocationsFeatureEnabled(false);
|
||||||
|
|
||||||
|
mozilla::Atomic<int, mozilla::Relaxed> ThreadIntercept::sMainThreadId(0);
|
||||||
|
|
||||||
// An object of this class must be created (on the stack) before running any
|
// An object of this class must be created (on the stack) before running any
|
||||||
// code that might allocate.
|
// code that might allocate.
|
||||||
class AutoBlockIntercepts {
|
class AutoBlockIntercepts {
|
||||||
|
@ -378,7 +389,7 @@ static void AllocCallback(void* aPtr, size_t aReqSize) {
|
||||||
gBernoulli->trial(actualSize) &&
|
gBernoulli->trial(actualSize) &&
|
||||||
// Second, attempt to add a marker if the Bernoulli trial passed.
|
// Second, attempt to add a marker if the Bernoulli trial passed.
|
||||||
profiler_add_native_allocation_marker(
|
profiler_add_native_allocation_marker(
|
||||||
static_cast<int64_t>(actualSize),
|
ThreadIntercept::MainThreadId(), static_cast<int64_t>(actualSize),
|
||||||
reinterpret_cast<uintptr_t>(aPtr))) {
|
reinterpret_cast<uintptr_t>(aPtr))) {
|
||||||
MOZ_ASSERT(gAllocationTracker,
|
MOZ_ASSERT(gAllocationTracker,
|
||||||
"gAllocationTracker must be properly installed for the memory "
|
"gAllocationTracker must be properly installed for the memory "
|
||||||
|
@ -421,7 +432,8 @@ static void FreeCallback(void* aPtr) {
|
||||||
"gAllocationTracker must be properly installed for the memory hooks.");
|
"gAllocationTracker must be properly installed for the memory hooks.");
|
||||||
if (gAllocationTracker->RemoveMemoryAddressIfFound(aPtr)) {
|
if (gAllocationTracker->RemoveMemoryAddressIfFound(aPtr)) {
|
||||||
// This size here is negative, indicating a deallocation.
|
// This size here is negative, indicating a deallocation.
|
||||||
profiler_add_native_allocation_marker(signedSize,
|
profiler_add_native_allocation_marker(ThreadIntercept::MainThreadId(),
|
||||||
|
signedSize,
|
||||||
reinterpret_cast<uintptr_t>(aPtr));
|
reinterpret_cast<uintptr_t>(aPtr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -555,7 +567,7 @@ void install_memory_hooks() {
|
||||||
// leak these values.
|
// leak these values.
|
||||||
void remove_memory_hooks() { jemalloc_replace_dynamic(nullptr); }
|
void remove_memory_hooks() { jemalloc_replace_dynamic(nullptr); }
|
||||||
|
|
||||||
void enable_native_allocations() {
|
void enable_native_allocations(int aMainThreadId) {
|
||||||
// The bloat log tracks allocations and deallocations. This can conflict
|
// The bloat log tracks allocations and deallocations. This can conflict
|
||||||
// with the memory hook machinery, as the bloat log creates its own
|
// with the memory hook machinery, as the bloat log creates its own
|
||||||
// allocations. This means we can re-enter inside the bloat log machinery. At
|
// allocations. This means we can re-enter inside the bloat log machinery. At
|
||||||
|
@ -584,7 +596,7 @@ void enable_native_allocations() {
|
||||||
|
|
||||||
EnsureBernoulliIsInstalled();
|
EnsureBernoulliIsInstalled();
|
||||||
EnsureAllocationTrackerIsInstalled();
|
EnsureAllocationTrackerIsInstalled();
|
||||||
ThreadIntercept::EnableAllocationFeature();
|
ThreadIntercept::EnableAllocationFeature(aMainThreadId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is safe to call even if native allocations hasn't been enabled.
|
// This is safe to call even if native allocations hasn't been enabled.
|
||||||
|
|
|
@ -13,7 +13,7 @@ namespace profiler {
|
||||||
|
|
||||||
void install_memory_hooks();
|
void install_memory_hooks();
|
||||||
void remove_memory_hooks();
|
void remove_memory_hooks();
|
||||||
void enable_native_allocations();
|
void enable_native_allocations(int aMainThreadId);
|
||||||
void disable_native_allocations();
|
void disable_native_allocations();
|
||||||
|
|
||||||
} // namespace profiler
|
} // namespace profiler
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
#include "ProfilerChild.h"
|
#include "ProfilerChild.h"
|
||||||
#include "ProfilerCodeAddressService.h"
|
#include "ProfilerCodeAddressService.h"
|
||||||
#include "ProfilerIOInterposeObserver.h"
|
#include "ProfilerIOInterposeObserver.h"
|
||||||
|
#include "ProfilerMarkerPayload.h"
|
||||||
#include "ProfilerParent.h"
|
#include "ProfilerParent.h"
|
||||||
#include "RegisteredThread.h"
|
#include "RegisteredThread.h"
|
||||||
#include "shared-libraries.h"
|
#include "shared-libraries.h"
|
||||||
|
@ -51,7 +52,6 @@
|
||||||
#include "mozilla/AutoProfilerLabel.h"
|
#include "mozilla/AutoProfilerLabel.h"
|
||||||
#include "mozilla/ExtensionPolicyService.h"
|
#include "mozilla/ExtensionPolicyService.h"
|
||||||
#include "mozilla/extensions/WebExtensionPolicy.h"
|
#include "mozilla/extensions/WebExtensionPolicy.h"
|
||||||
#include "mozilla/net/HttpBaseChannel.h" // for net::TimingStruct
|
|
||||||
#include "mozilla/Printf.h"
|
#include "mozilla/Printf.h"
|
||||||
#include "mozilla/ProfileBufferChunkManagerSingle.h"
|
#include "mozilla/ProfileBufferChunkManagerSingle.h"
|
||||||
#include "mozilla/ProfileBufferChunkManagerWithLocalLimit.h"
|
#include "mozilla/ProfileBufferChunkManagerWithLocalLimit.h"
|
||||||
|
@ -1631,6 +1631,44 @@ void ProfilingStackOwner::DumpStackAndCrash() const {
|
||||||
// The name of the main thread.
|
// The name of the main thread.
|
||||||
static const char* const kMainThreadName = "GeckoMain";
|
static const char* const kMainThreadName = "GeckoMain";
|
||||||
|
|
||||||
|
// TODO - It is better to have the marker timing created by the original callers
|
||||||
|
// of the profiler_add_marker API, rather than deduce it from the payload. This
|
||||||
|
// is a bigger code diff for adding MarkerTiming, so do that work in a
|
||||||
|
// follow-up.
|
||||||
|
MarkerTiming get_marker_timing_from_payload(
|
||||||
|
const ProfilerMarkerPayload& aPayload) {
|
||||||
|
const TimeStamp& start = aPayload.GetStartTime();
|
||||||
|
const TimeStamp& end = aPayload.GetEndTime();
|
||||||
|
if (start.IsNull()) {
|
||||||
|
if (end.IsNull()) {
|
||||||
|
// The payload contains no time information, use the current time.
|
||||||
|
return MarkerTiming::InstantAt(TimeStamp::NowUnfuzzed());
|
||||||
|
}
|
||||||
|
return MarkerTiming::IntervalEnd(end);
|
||||||
|
}
|
||||||
|
if (end.IsNull()) {
|
||||||
|
return MarkerTiming::IntervalStart(start);
|
||||||
|
}
|
||||||
|
if (start == end) {
|
||||||
|
return MarkerTiming::InstantAt(start);
|
||||||
|
}
|
||||||
|
return MarkerTiming::Interval(start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the marker to the given buffer with the given information.
|
||||||
|
// This is a unified insertion point for all the markers.
|
||||||
|
static void StoreMarker(ProfileChunkedBuffer& aChunkedBuffer, int aThreadId,
|
||||||
|
const char* aMarkerName,
|
||||||
|
const MarkerTiming& aMarkerTiming,
|
||||||
|
JS::ProfilingCategoryPair aCategoryPair,
|
||||||
|
const ProfilerMarkerPayload* aPayload) {
|
||||||
|
aChunkedBuffer.PutObjects(
|
||||||
|
ProfileBufferEntry::Kind::MarkerData, aThreadId,
|
||||||
|
WrapProfileBufferUnownedCString(aMarkerName),
|
||||||
|
aMarkerTiming.GetStartTime(), aMarkerTiming.GetEndTime(),
|
||||||
|
aMarkerTiming.GetPhase(), static_cast<uint32_t>(aCategoryPair), aPayload);
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
// BEGIN sampling/unwinding code
|
// BEGIN sampling/unwinding code
|
||||||
|
|
||||||
|
@ -2498,7 +2536,7 @@ static void StreamMetaJSCustomObject(
|
||||||
const PreRecordedMetaInformation& aPreRecordedMetaInformation) {
|
const PreRecordedMetaInformation& aPreRecordedMetaInformation) {
|
||||||
MOZ_RELEASE_ASSERT(CorePS::Exists() && ActivePS::Exists(aLock));
|
MOZ_RELEASE_ASSERT(CorePS::Exists() && ActivePS::Exists(aLock));
|
||||||
|
|
||||||
aWriter.IntProperty("version", 22);
|
aWriter.IntProperty("version", 21);
|
||||||
|
|
||||||
// The "startTime" field holds the number of milliseconds since midnight
|
// The "startTime" field holds the number of milliseconds since midnight
|
||||||
// January 1, 1970 GMT. This grotty code computes (Now - (Now -
|
// January 1, 1970 GMT. This grotty code computes (Now - (Now -
|
||||||
|
@ -2744,15 +2782,19 @@ static void CollectJavaThreadProfileData(ProfileBuffer& aProfileBuffer) {
|
||||||
|
|
||||||
if (!text) {
|
if (!text) {
|
||||||
// This marker doesn't have a text.
|
// This marker doesn't have a text.
|
||||||
AddMarkerToBuffer(aProfileBuffer.UnderlyingChunkedBuffer(), markerName,
|
StoreMarker(aProfileBuffer.UnderlyingChunkedBuffer(), threadId,
|
||||||
geckoprofiler::category::JAVA_ANDROID,
|
markerName.get(), timing,
|
||||||
{MarkerThreadId(threadId), std::move(timing)});
|
JS::ProfilingCategoryPair::JAVA_ANDROID, nullptr);
|
||||||
} else {
|
} else {
|
||||||
// This marker has a text.
|
// This marker has a text.
|
||||||
AddMarkerToBuffer(aProfileBuffer.UnderlyingChunkedBuffer(), markerName,
|
nsCString textString = text->ToCString();
|
||||||
geckoprofiler::category::JAVA_ANDROID,
|
const TextMarkerPayload payload(textString, startTime, endTime, Nothing(),
|
||||||
{MarkerThreadId(threadId), std::move(timing)},
|
nullptr);
|
||||||
geckoprofiler::markers::Text{}, text->ToCString());
|
|
||||||
|
// Put the marker inside the buffer.
|
||||||
|
StoreMarker(aProfileBuffer.UnderlyingChunkedBuffer(), threadId,
|
||||||
|
markerName.get(), timing,
|
||||||
|
JS::ProfilingCategoryPair::JAVA_ANDROID, &payload);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4552,7 +4594,7 @@ static void locked_profiler_start(PSLockRef aLock, PowerOfTwo32 aCapacity,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up profiling for each registered thread, if appropriate.
|
// Set up profiling for each registered thread, if appropriate.
|
||||||
bool isMainThreadBeingProfiled = false;
|
Maybe<int> mainThreadId;
|
||||||
int tid = profiler_current_thread_id();
|
int tid = profiler_current_thread_id();
|
||||||
const Vector<UniquePtr<RegisteredThread>>& registeredThreads =
|
const Vector<UniquePtr<RegisteredThread>>& registeredThreads =
|
||||||
CorePS::RegisteredThreads(aLock);
|
CorePS::RegisteredThreads(aLock);
|
||||||
|
@ -4579,7 +4621,7 @@ static void locked_profiler_start(PSLockRef aLock, PowerOfTwo32 aCapacity,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (info->IsMainThread()) {
|
if (info->IsMainThread()) {
|
||||||
isMainThreadBeingProfiled = true;
|
mainThreadId = Some(info->ThreadId());
|
||||||
}
|
}
|
||||||
registeredThread->RacyRegisteredThread().ReinitializeOnResume();
|
registeredThread->RacyRegisteredThread().ReinitializeOnResume();
|
||||||
if (registeredThread->GetJSContext()) {
|
if (registeredThread->GetJSContext()) {
|
||||||
|
@ -4615,8 +4657,8 @@ static void locked_profiler_start(PSLockRef aLock, PowerOfTwo32 aCapacity,
|
||||||
|
|
||||||
#if defined(MOZ_REPLACE_MALLOC) && defined(MOZ_PROFILER_MEMORY)
|
#if defined(MOZ_REPLACE_MALLOC) && defined(MOZ_PROFILER_MEMORY)
|
||||||
if (ActivePS::FeatureNativeAllocations(aLock)) {
|
if (ActivePS::FeatureNativeAllocations(aLock)) {
|
||||||
if (isMainThreadBeingProfiled) {
|
if (mainThreadId.isSome()) {
|
||||||
mozilla::profiler::enable_native_allocations();
|
mozilla::profiler::enable_native_allocations(mainThreadId.value());
|
||||||
} else {
|
} else {
|
||||||
NS_WARNING(
|
NS_WARNING(
|
||||||
"The nativeallocations feature is turned on, but the main thread is "
|
"The nativeallocations feature is turned on, but the main thread is "
|
||||||
|
@ -5025,6 +5067,11 @@ void profiler_remove_sampled_counter(BaseProfilerCount* aCounter) {
|
||||||
CorePS::RemoveCounter(lock, aCounter);
|
CorePS::RemoveCounter(lock, aCounter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void maybelocked_profiler_add_marker_for_thread(
|
||||||
|
int aThreadId, JS::ProfilingCategoryPair aCategoryPair,
|
||||||
|
const char* aMarkerName, const ProfilerMarkerPayload& aPayload,
|
||||||
|
const PSAutoLock* aLockOrNull);
|
||||||
|
|
||||||
ProfilingStack* profiler_register_thread(const char* aName,
|
ProfilingStack* profiler_register_thread(const char* aName,
|
||||||
void* aGuessStackTop) {
|
void* aGuessStackTop) {
|
||||||
DEBUG_LOG("profiler_register_thread(%s)", aName);
|
DEBUG_LOG("profiler_register_thread(%s)", aName);
|
||||||
|
@ -5061,8 +5108,10 @@ ProfilingStack* profiler_register_thread(const char* aName,
|
||||||
text.AppendLiteral("\" attempted to re-register as \"");
|
text.AppendLiteral("\" attempted to re-register as \"");
|
||||||
text.AppendASCII(aName);
|
text.AppendASCII(aName);
|
||||||
text.AppendLiteral("\"");
|
text.AppendLiteral("\"");
|
||||||
PROFILER_MARKER_TEXT("profiler_register_thread again", OTHER_Profiling,
|
maybelocked_profiler_add_marker_for_thread(
|
||||||
MarkerThreadId::MainThread(), text);
|
profiler_main_thread_id(), JS::ProfilingCategoryPair::OTHER_Profiling,
|
||||||
|
"profiler_register_thread again",
|
||||||
|
TextMarkerPayload(text, TimeStamp::NowUnfuzzed()), &lock);
|
||||||
|
|
||||||
return &thread->RacyRegisteredThread().ProfilingStack();
|
return &thread->RacyRegisteredThread().ProfilingStack();
|
||||||
}
|
}
|
||||||
|
@ -5142,8 +5191,10 @@ void profiler_unregister_thread() {
|
||||||
tid != profiler_main_thread_id()) {
|
tid != profiler_main_thread_id()) {
|
||||||
nsCString threadIdString;
|
nsCString threadIdString;
|
||||||
threadIdString.AppendInt(tid);
|
threadIdString.AppendInt(tid);
|
||||||
PROFILER_MARKER_TEXT("profiler_unregister_thread again", OTHER_Profiling,
|
maybelocked_profiler_add_marker_for_thread(
|
||||||
MarkerThreadId::MainThread(), threadIdString);
|
profiler_main_thread_id(), JS::ProfilingCategoryPair::OTHER_Profiling,
|
||||||
|
"profiler_unregister_thread again",
|
||||||
|
TextMarkerPayload(threadIdString, TimeStamp::NowUnfuzzed()), &lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5365,6 +5416,40 @@ void ProfilerBacktraceDestructor::operator()(ProfilerBacktrace* aBacktrace) {
|
||||||
delete aBacktrace;
|
delete aBacktrace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void racy_profiler_add_marker(const char* aMarkerName,
|
||||||
|
JS::ProfilingCategoryPair aCategoryPair,
|
||||||
|
const ProfilerMarkerPayload* aPayload) {
|
||||||
|
MOZ_RELEASE_ASSERT(CorePS::Exists());
|
||||||
|
|
||||||
|
// This function is hot enough that we use RacyFeatures, not ActivePS.
|
||||||
|
if (!profiler_can_accept_markers()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note that it's possible that the above test would change again before we
|
||||||
|
// actually record the marker. Because of this imprecision it's possible to
|
||||||
|
// miss a marker or record one we shouldn't. Either way is not a big deal.
|
||||||
|
|
||||||
|
RacyRegisteredThread* racyRegisteredThread =
|
||||||
|
TLSRegisteredThread::RacyRegisteredThread();
|
||||||
|
if (!racyRegisteredThread || !racyRegisteredThread->IsBeingProfiled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const MarkerTiming markerTiming =
|
||||||
|
aPayload ? get_marker_timing_from_payload(*aPayload)
|
||||||
|
: MarkerTiming::InstantNow();
|
||||||
|
|
||||||
|
StoreMarker(CorePS::CoreBuffer(), racyRegisteredThread->ThreadId(),
|
||||||
|
aMarkerName, markerTiming, aCategoryPair, aPayload);
|
||||||
|
}
|
||||||
|
|
||||||
|
void profiler_add_marker(const char* aMarkerName,
|
||||||
|
JS::ProfilingCategoryPair aCategoryPair,
|
||||||
|
const ProfilerMarkerPayload& aPayload) {
|
||||||
|
racy_profiler_add_marker(aMarkerName, aCategoryPair, &aPayload);
|
||||||
|
}
|
||||||
|
|
||||||
// This is a simplified version of profiler_add_marker that can be easily passed
|
// This is a simplified version of profiler_add_marker that can be easily passed
|
||||||
// into the JS engine.
|
// into the JS engine.
|
||||||
void profiler_add_js_marker(const char* aMarkerName, const char* aMarkerText) {
|
void profiler_add_js_marker(const char* aMarkerName, const char* aMarkerText) {
|
||||||
|
@ -5377,49 +5462,11 @@ void profiler_add_js_allocation_marker(JS::RecordAllocationInfo&& info) {
|
||||||
if (!profiler_can_accept_markers()) {
|
if (!profiler_can_accept_markers()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
AUTO_PROFILER_STATS(add_marker_with_JsAllocationMarkerPayload);
|
||||||
struct JsAllocationMarker {
|
|
||||||
static constexpr mozilla::Span<const char> MarkerTypeName() {
|
|
||||||
return mozilla::MakeStringSpan("JS allocation");
|
|
||||||
}
|
|
||||||
static void StreamJSONMarkerData(
|
|
||||||
mozilla::baseprofiler::SpliceableJSONWriter& aWriter,
|
|
||||||
const mozilla::ProfilerString16View& aTypeName,
|
|
||||||
const mozilla::ProfilerString8View& aClassName,
|
|
||||||
const mozilla::ProfilerString16View& aDescriptiveTypeName,
|
|
||||||
const mozilla::ProfilerString8View& aCoarseType, uint64_t aSize,
|
|
||||||
bool aInNursery) {
|
|
||||||
if (aClassName.Length() != 0) {
|
|
||||||
aWriter.StringProperty("className", aClassName);
|
|
||||||
}
|
|
||||||
if (aTypeName.Length() != 0) {
|
|
||||||
aWriter.StringProperty(
|
|
||||||
"typeName",
|
|
||||||
NS_ConvertUTF16toUTF8(aTypeName.Data(), aTypeName.Length()));
|
|
||||||
}
|
|
||||||
if (aDescriptiveTypeName.Length() != 0) {
|
|
||||||
aWriter.StringProperty(
|
|
||||||
"descriptiveTypeName",
|
|
||||||
NS_ConvertUTF16toUTF8(aDescriptiveTypeName.Data(),
|
|
||||||
aDescriptiveTypeName.Length()));
|
|
||||||
}
|
|
||||||
aWriter.StringProperty("coarseType", aCoarseType);
|
|
||||||
aWriter.IntProperty("size", aSize);
|
|
||||||
aWriter.BoolProperty("inNursery", aInNursery);
|
|
||||||
}
|
|
||||||
static mozilla::MarkerSchema MarkerTypeDisplay() {
|
|
||||||
return mozilla::MarkerSchema::SpecialFrontendLocation{};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
profiler_add_marker(
|
profiler_add_marker(
|
||||||
"JS allocation", geckoprofiler::category::JS, MarkerStack::Capture(),
|
"JS allocation", JS::ProfilingCategoryPair::JS,
|
||||||
JsAllocationMarker{},
|
JsAllocationMarkerPayload(TimeStamp::Now(), std::move(info),
|
||||||
ProfilerString16View::WrapNullTerminatedString(info.typeName),
|
profiler_get_backtrace()));
|
||||||
ProfilerString8View::WrapNullTerminatedString(info.className),
|
|
||||||
ProfilerString16View::WrapNullTerminatedString(info.descriptiveTypeName),
|
|
||||||
ProfilerString8View::WrapNullTerminatedString(info.coarseType), info.size,
|
|
||||||
info.inNursery);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool profiler_is_locked_on_current_thread() {
|
bool profiler_is_locked_on_current_thread() {
|
||||||
|
@ -5434,151 +5481,100 @@ bool profiler_is_locked_on_current_thread() {
|
||||||
CorePS::CoreBuffer().IsThreadSafeAndLockedOnCurrentThread();
|
CorePS::CoreBuffer().IsThreadSafeAndLockedOnCurrentThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr net::TimingStruct scEmptyNetTimingStruct;
|
|
||||||
|
|
||||||
void profiler_add_network_marker(
|
void profiler_add_network_marker(
|
||||||
nsIURI* aURI, const nsACString& aRequestMethod, int32_t aPriority,
|
nsIURI* aURI, const nsACString& aRequestMethod, int32_t aPriority,
|
||||||
uint64_t aChannelId, NetworkLoadType aType, mozilla::TimeStamp aStart,
|
uint64_t aChannelId, NetworkLoadType aType, mozilla::TimeStamp aStart,
|
||||||
mozilla::TimeStamp aEnd, int64_t aCount,
|
mozilla::TimeStamp aEnd, int64_t aCount,
|
||||||
mozilla::net::CacheDisposition aCacheDisposition, uint64_t aInnerWindowID,
|
mozilla::net::CacheDisposition aCacheDisposition, uint64_t aInnerWindowID,
|
||||||
const mozilla::net::TimingStruct* aTimings, nsIURI* aRedirectURI,
|
const mozilla::net::TimingStruct* aTimings, nsIURI* aRedirectURI,
|
||||||
UniquePtr<ProfileChunkedBuffer> aSource,
|
UniqueProfilerBacktrace aSource,
|
||||||
const Maybe<nsDependentCString>& aContentType) {
|
const Maybe<nsDependentCString>& aContentType) {
|
||||||
if (!profiler_can_accept_markers()) {
|
if (!profiler_can_accept_markers()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// These do allocations/frees/etc; avoid if not active
|
||||||
nsAutoCStringN<2048> name;
|
nsAutoCString spec;
|
||||||
name.AppendASCII("Load ");
|
nsAutoCString redirect_spec;
|
||||||
// top 32 bits are process id of the load
|
|
||||||
name.AppendInt(aChannelId & 0xFFFFFFFFu);
|
|
||||||
|
|
||||||
// These can do allocations/frees/etc; avoid if not active
|
|
||||||
nsAutoCStringN<2048> spec;
|
|
||||||
if (aURI) {
|
if (aURI) {
|
||||||
aURI->GetAsciiSpec(spec);
|
aURI->GetAsciiSpec(spec);
|
||||||
name.AppendASCII(": ");
|
|
||||||
name.Append(spec);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsAutoCString redirect_spec;
|
|
||||||
if (aRedirectURI) {
|
if (aRedirectURI) {
|
||||||
aRedirectURI->GetAsciiSpec(redirect_spec);
|
aRedirectURI->GetAsciiSpec(redirect_spec);
|
||||||
}
|
}
|
||||||
|
// top 32 bits are process id of the load
|
||||||
struct NetworkMarker {
|
uint32_t id = static_cast<uint32_t>(aChannelId & 0xFFFFFFFF);
|
||||||
static constexpr Span<const char> MarkerTypeName() {
|
char name[2048];
|
||||||
return MakeStringSpan("Network");
|
SprintfLiteral(name, "Load %d: %s", id, PromiseFlatCString(spec).get());
|
||||||
}
|
AUTO_PROFILER_STATS(add_marker_with_NetworkMarkerPayload);
|
||||||
static void StreamJSONMarkerData(
|
|
||||||
baseprofiler::SpliceableJSONWriter& aWriter, mozilla::TimeStamp aStart,
|
|
||||||
mozilla::TimeStamp aEnd, int64_t aID, const ProfilerString8View& aURI,
|
|
||||||
const ProfilerString8View& aRequestMethod, NetworkLoadType aType,
|
|
||||||
int32_t aPri, int64_t aCount, net::CacheDisposition aCacheDisposition,
|
|
||||||
const net::TimingStruct& aTimings,
|
|
||||||
const ProfilerString8View& aRedirectURI,
|
|
||||||
const ProfilerString8View& aContentType) {
|
|
||||||
// This payload still streams a startTime and endTime property because it
|
|
||||||
// made the migration to MarkerTiming on the front-end easier.
|
|
||||||
baseprofiler::WritePropertyTime(aWriter, "startTime", aStart);
|
|
||||||
baseprofiler::WritePropertyTime(aWriter, "endTime", aEnd);
|
|
||||||
|
|
||||||
aWriter.IntProperty("id", aID);
|
|
||||||
aWriter.StringProperty("status", GetNetworkState(aType));
|
|
||||||
if (Span<const char> cacheString = GetCacheState(aCacheDisposition);
|
|
||||||
!cacheString.IsEmpty()) {
|
|
||||||
aWriter.StringProperty("cache", cacheString);
|
|
||||||
}
|
|
||||||
aWriter.IntProperty("pri", aPri);
|
|
||||||
if (aCount > 0) {
|
|
||||||
aWriter.IntProperty("count", aCount);
|
|
||||||
}
|
|
||||||
if (aURI.Length() != 0) {
|
|
||||||
aWriter.StringProperty("URI", aURI);
|
|
||||||
}
|
|
||||||
if (aRedirectURI.Length() != 0) {
|
|
||||||
aWriter.StringProperty("RedirectURI", aRedirectURI);
|
|
||||||
}
|
|
||||||
aWriter.StringProperty("requestMethod", aRequestMethod);
|
|
||||||
|
|
||||||
if (aContentType.Length() != 0) {
|
|
||||||
aWriter.StringProperty("contentType", aContentType);
|
|
||||||
} else {
|
|
||||||
aWriter.NullProperty("contentType");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aType != NetworkLoadType::LOAD_START) {
|
|
||||||
baseprofiler::WritePropertyTime(aWriter, "domainLookupStart",
|
|
||||||
aTimings.domainLookupStart);
|
|
||||||
baseprofiler::WritePropertyTime(aWriter, "domainLookupEnd",
|
|
||||||
aTimings.domainLookupEnd);
|
|
||||||
baseprofiler::WritePropertyTime(aWriter, "connectStart",
|
|
||||||
aTimings.connectStart);
|
|
||||||
baseprofiler::WritePropertyTime(aWriter, "tcpConnectEnd",
|
|
||||||
aTimings.tcpConnectEnd);
|
|
||||||
baseprofiler::WritePropertyTime(aWriter, "secureConnectionStart",
|
|
||||||
aTimings.secureConnectionStart);
|
|
||||||
baseprofiler::WritePropertyTime(aWriter, "connectEnd",
|
|
||||||
aTimings.connectEnd);
|
|
||||||
baseprofiler::WritePropertyTime(aWriter, "requestStart",
|
|
||||||
aTimings.requestStart);
|
|
||||||
baseprofiler::WritePropertyTime(aWriter, "responseStart",
|
|
||||||
aTimings.responseStart);
|
|
||||||
baseprofiler::WritePropertyTime(aWriter, "responseEnd",
|
|
||||||
aTimings.responseEnd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static MarkerSchema MarkerTypeDisplay() {
|
|
||||||
return MarkerSchema::SpecialFrontendLocation{};
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
static Span<const char> GetNetworkState(NetworkLoadType aType) {
|
|
||||||
switch (aType) {
|
|
||||||
case NetworkLoadType::LOAD_START:
|
|
||||||
return MakeStringSpan("STATUS_START");
|
|
||||||
case NetworkLoadType::LOAD_STOP:
|
|
||||||
return MakeStringSpan("STATUS_STOP");
|
|
||||||
case NetworkLoadType::LOAD_REDIRECT:
|
|
||||||
return MakeStringSpan("STATUS_REDIRECT");
|
|
||||||
default:
|
|
||||||
return MakeStringSpan("");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static Span<const char> GetCacheState(
|
|
||||||
net::CacheDisposition aCacheDisposition) {
|
|
||||||
switch (aCacheDisposition) {
|
|
||||||
case net::kCacheUnresolved:
|
|
||||||
return MakeStringSpan("Unresolved");
|
|
||||||
case net::kCacheHit:
|
|
||||||
return MakeStringSpan("Hit");
|
|
||||||
case net::kCacheHitViaReval:
|
|
||||||
return MakeStringSpan("HitViaReval");
|
|
||||||
case net::kCacheMissedViaReval:
|
|
||||||
return MakeStringSpan("MissedViaReval");
|
|
||||||
case net::kCacheMissed:
|
|
||||||
return MakeStringSpan("Missed");
|
|
||||||
case net::kCacheUnknown:
|
|
||||||
default:
|
|
||||||
return MakeStringSpan("");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
profiler_add_marker(
|
profiler_add_marker(
|
||||||
name, geckoprofiler::category::NETWORK,
|
name, JS::ProfilingCategoryPair::NETWORK,
|
||||||
{MarkerTiming::Interval(aStart, aEnd),
|
NetworkMarkerPayload(static_cast<int64_t>(aChannelId),
|
||||||
MarkerStack::TakeBacktrace(std::move(aSource)),
|
PromiseFlatCString(spec).get(), aRequestMethod,
|
||||||
MarkerInnerWindowId(aInnerWindowID)},
|
aType, aStart, aEnd, aPriority, aCount,
|
||||||
NetworkMarker{}, aStart, aEnd, static_cast<int64_t>(aChannelId), spec,
|
aCacheDisposition, aInnerWindowID, aTimings,
|
||||||
aRequestMethod, aType, aPriority, aCount, aCacheDisposition,
|
PromiseFlatCString(redirect_spec).get(),
|
||||||
aTimings ? *aTimings : scEmptyNetTimingStruct, redirect_spec,
|
std::move(aSource), aContentType));
|
||||||
aContentType ? ProfilerString8View(*aContentType)
|
|
||||||
: ProfilerString8View());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool profiler_add_native_allocation_marker(int64_t aSize,
|
static void maybelocked_profiler_add_marker_for_thread(
|
||||||
|
int aThreadId, JS::ProfilingCategoryPair aCategoryPair,
|
||||||
|
const char* aMarkerName, const ProfilerMarkerPayload& aPayload,
|
||||||
|
const PSAutoLock* aLockOrNull) {
|
||||||
|
MOZ_RELEASE_ASSERT(CorePS::Exists());
|
||||||
|
|
||||||
|
if (!profiler_can_accept_markers()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
auto checkThreadId = [](int aThreadId, const PSAutoLock& aLock) {
|
||||||
|
if (!ActivePS::Exists(aLock)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assert that our thread ID makes sense
|
||||||
|
bool realThread = false;
|
||||||
|
const Vector<UniquePtr<RegisteredThread>>& registeredThreads =
|
||||||
|
CorePS::RegisteredThreads(aLock);
|
||||||
|
for (auto& thread : registeredThreads) {
|
||||||
|
RefPtr<ThreadInfo> info = thread->Info();
|
||||||
|
if (info->ThreadId() == aThreadId) {
|
||||||
|
realThread = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MOZ_ASSERT(realThread, "Invalid thread id");
|
||||||
|
};
|
||||||
|
|
||||||
|
if (aLockOrNull) {
|
||||||
|
checkThreadId(aThreadId, *aLockOrNull);
|
||||||
|
} else {
|
||||||
|
PSAutoLock lock(gPSMutex);
|
||||||
|
checkThreadId(aThreadId, lock);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
StoreMarker(CorePS::CoreBuffer(), aThreadId, aMarkerName,
|
||||||
|
get_marker_timing_from_payload(aPayload), aCategoryPair,
|
||||||
|
&aPayload);
|
||||||
|
}
|
||||||
|
|
||||||
|
void profiler_add_marker_for_thread(int aThreadId,
|
||||||
|
JS::ProfilingCategoryPair aCategoryPair,
|
||||||
|
const char* aMarkerName,
|
||||||
|
const ProfilerMarkerPayload& aPayload) {
|
||||||
|
return maybelocked_profiler_add_marker_for_thread(
|
||||||
|
aThreadId, aCategoryPair, aMarkerName, aPayload, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void profiler_add_marker_for_mainthread(JS::ProfilingCategoryPair aCategoryPair,
|
||||||
|
const char* aMarkerName,
|
||||||
|
const ProfilerMarkerPayload& aPayload) {
|
||||||
|
profiler_add_marker_for_thread(profiler_main_thread_id(), aCategoryPair,
|
||||||
|
aMarkerName, aPayload);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool profiler_add_native_allocation_marker(int aMainThreadId, int64_t aSize,
|
||||||
uintptr_t aMemoryAddress) {
|
uintptr_t aMemoryAddress) {
|
||||||
if (!profiler_can_accept_markers()) {
|
if (!profiler_can_accept_markers()) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -5595,30 +5591,69 @@ bool profiler_add_native_allocation_marker(int64_t aSize,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct NativeAllocationMarker {
|
AUTO_PROFILER_STATS(add_marker_with_NativeAllocationMarkerPayload);
|
||||||
static constexpr mozilla::Span<const char> MarkerTypeName() {
|
maybelocked_profiler_add_marker_for_thread(
|
||||||
return mozilla::MakeStringSpan("Native allocation");
|
aMainThreadId, JS::ProfilingCategoryPair::OTHER, "Native allocation",
|
||||||
}
|
NativeAllocationMarkerPayload(TimeStamp::Now(), aSize, aMemoryAddress,
|
||||||
static void StreamJSONMarkerData(
|
profiler_current_thread_id(),
|
||||||
mozilla::baseprofiler::SpliceableJSONWriter& aWriter, int64_t aSize,
|
profiler_get_backtrace()),
|
||||||
uintptr_t aMemoryAddress, int aThreadId) {
|
nullptr);
|
||||||
aWriter.IntProperty("size", aSize);
|
|
||||||
aWriter.IntProperty("memoryAddress",
|
|
||||||
static_cast<int64_t>(aMemoryAddress));
|
|
||||||
aWriter.IntProperty("threadId", aThreadId);
|
|
||||||
}
|
|
||||||
static mozilla::MarkerSchema MarkerTypeDisplay() {
|
|
||||||
return mozilla::MarkerSchema::SpecialFrontendLocation{};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
profiler_add_marker("Native allocation", geckoprofiler::category::OTHER,
|
|
||||||
{MarkerThreadId::MainThread(), MarkerStack::Capture()},
|
|
||||||
NativeAllocationMarker{}, aSize, aMemoryAddress,
|
|
||||||
profiler_current_thread_id());
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void profiler_tracing_marker(const char* aCategoryString,
|
||||||
|
const char* aMarkerName,
|
||||||
|
JS::ProfilingCategoryPair aCategoryPair,
|
||||||
|
TracingKind aKind,
|
||||||
|
const Maybe<uint64_t>& aInnerWindowID) {
|
||||||
|
MOZ_RELEASE_ASSERT(CorePS::Exists());
|
||||||
|
|
||||||
|
VTUNE_TRACING(aMarkerName, aKind);
|
||||||
|
|
||||||
|
// This function is hot enough that we use RacyFeatures, notActivePS.
|
||||||
|
if (!profiler_can_accept_markers()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AUTO_PROFILER_STATS(add_marker_with_TracingMarkerPayload);
|
||||||
|
profiler_add_marker(
|
||||||
|
aMarkerName, aCategoryPair,
|
||||||
|
TracingMarkerPayload(aCategoryString, aKind, TimeStamp::NowUnfuzzed(),
|
||||||
|
aInnerWindowID));
|
||||||
|
}
|
||||||
|
|
||||||
|
void profiler_tracing_marker(const char* aCategoryString,
|
||||||
|
const char* aMarkerName,
|
||||||
|
JS::ProfilingCategoryPair aCategoryPair,
|
||||||
|
TracingKind aKind, UniqueProfilerBacktrace aCause,
|
||||||
|
const Maybe<uint64_t>& aInnerWindowID) {
|
||||||
|
MOZ_RELEASE_ASSERT(CorePS::Exists());
|
||||||
|
|
||||||
|
VTUNE_TRACING(aMarkerName, aKind);
|
||||||
|
|
||||||
|
// This function is hot enough that we use RacyFeatures, notActivePS.
|
||||||
|
if (!profiler_can_accept_markers()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
profiler_add_marker(
|
||||||
|
aMarkerName, aCategoryPair,
|
||||||
|
TracingMarkerPayload(aCategoryString, aKind, TimeStamp::NowUnfuzzed(),
|
||||||
|
aInnerWindowID, std::move(aCause)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void profiler_add_text_marker(const char* aMarkerName, const nsACString& aText,
|
||||||
|
JS::ProfilingCategoryPair aCategoryPair,
|
||||||
|
const mozilla::TimeStamp& aStartTime,
|
||||||
|
const mozilla::TimeStamp& aEndTime,
|
||||||
|
const mozilla::Maybe<uint64_t>& aInnerWindowID,
|
||||||
|
UniqueProfilerBacktrace aCause) {
|
||||||
|
AUTO_PROFILER_STATS(add_marker_with_TextMarkerPayload);
|
||||||
|
profiler_add_marker(aMarkerName, aCategoryPair,
|
||||||
|
TextMarkerPayload(aText, aStartTime, aEndTime,
|
||||||
|
aInnerWindowID, std::move(aCause)));
|
||||||
|
}
|
||||||
|
|
||||||
void profiler_set_js_context(JSContext* aCx) {
|
void profiler_set_js_context(JSContext* aCx) {
|
||||||
MOZ_ASSERT(aCx);
|
MOZ_ASSERT(aCx);
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ if CONFIG["MOZ_GECKO_PROFILER"]:
|
||||||
"public/GeckoProfilerReporter.h",
|
"public/GeckoProfilerReporter.h",
|
||||||
"public/ProfilerChild.h",
|
"public/ProfilerChild.h",
|
||||||
"public/ProfilerCodeAddressService.h",
|
"public/ProfilerCodeAddressService.h",
|
||||||
|
"public/ProfilerMarkerPayload.h",
|
||||||
"public/ProfilerParent.h",
|
"public/ProfilerParent.h",
|
||||||
"public/shared-libraries.h",
|
"public/shared-libraries.h",
|
||||||
]
|
]
|
||||||
|
@ -26,6 +27,7 @@ if CONFIG["MOZ_GECKO_PROFILER"]:
|
||||||
"core/ProfiledThreadData.cpp",
|
"core/ProfiledThreadData.cpp",
|
||||||
"core/ProfilerBacktrace.cpp",
|
"core/ProfilerBacktrace.cpp",
|
||||||
"core/ProfilerCodeAddressService.cpp",
|
"core/ProfilerCodeAddressService.cpp",
|
||||||
|
"core/ProfilerMarkerPayload.cpp",
|
||||||
"core/RegisteredThread.cpp",
|
"core/RegisteredThread.cpp",
|
||||||
"gecko/ChildProfilerController.cpp",
|
"gecko/ChildProfilerController.cpp",
|
||||||
"gecko/nsProfilerStartParams.cpp",
|
"gecko/nsProfilerStartParams.cpp",
|
||||||
|
|
|
@ -62,6 +62,17 @@
|
||||||
# define AUTO_PROFILER_LABEL_DYNAMIC_FAST(label, dynamicString, categoryPair, \
|
# define AUTO_PROFILER_LABEL_DYNAMIC_FAST(label, dynamicString, categoryPair, \
|
||||||
ctx, flags)
|
ctx, flags)
|
||||||
|
|
||||||
|
# define PROFILER_ADD_MARKER_WITH_PAYLOAD(markerName, categoryPair, \
|
||||||
|
PayloadType, payloadArgs)
|
||||||
|
|
||||||
|
# define PROFILER_TRACING_MARKER(categoryString, markerName, categoryPair, \
|
||||||
|
kind)
|
||||||
|
# define PROFILER_TRACING_MARKER_DOCSHELL(categoryString, markerName, \
|
||||||
|
categoryPair, kind, docshell)
|
||||||
|
# define AUTO_PROFILER_TRACING_MARKER(categoryString, markerName, categoryPair)
|
||||||
|
# define AUTO_PROFILER_TRACING_MARKER_DOCSHELL(categoryString, markerName, \
|
||||||
|
categoryPair, docShell)
|
||||||
|
|
||||||
// Function stubs for when MOZ_GECKO_PROFILER is not defined.
|
// Function stubs for when MOZ_GECKO_PROFILER is not defined.
|
||||||
|
|
||||||
// This won't be used, it's just there to allow the empty definition of
|
// This won't be used, it's just there to allow the empty definition of
|
||||||
|
@ -109,6 +120,7 @@ profiler_capture_backtrace() {
|
||||||
|
|
||||||
class ProfilerBacktrace;
|
class ProfilerBacktrace;
|
||||||
class ProfilerCodeAddressService;
|
class ProfilerCodeAddressService;
|
||||||
|
class ProfilerMarkerPayload;
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
class ProfileBufferControlledChunkManager;
|
class ProfileBufferControlledChunkManager;
|
||||||
class ProfileChunkedBuffer;
|
class ProfileChunkedBuffer;
|
||||||
|
@ -878,19 +890,49 @@ mozilla::Maybe<ProfilerBufferInfo> profiler_get_buffer_info();
|
||||||
ctx, label, dynamicString, JS::ProfilingCategoryPair::categoryPair, \
|
ctx, label, dynamicString, JS::ProfilingCategoryPair::categoryPair, \
|
||||||
flags)
|
flags)
|
||||||
|
|
||||||
|
// `PayloadType` is a sub-class of MarkerPayload, `parenthesizedPayloadArgs` is
|
||||||
|
// the argument list used to construct that `PayloadType`. E.g.:
|
||||||
|
// `PROFILER_ADD_MARKER_WITH_PAYLOAD("Load", DOM, TextMarkerPayload,
|
||||||
|
// ("text", start, end, ds, dsh))`
|
||||||
|
# define PROFILER_ADD_MARKER_WITH_PAYLOAD( \
|
||||||
|
markerName, categoryPair, PayloadType, parenthesizedPayloadArgs) \
|
||||||
|
do { \
|
||||||
|
AUTO_PROFILER_STATS(add_marker_with_##PayloadType); \
|
||||||
|
::profiler_add_marker(markerName, \
|
||||||
|
::JS::ProfilingCategoryPair::categoryPair, \
|
||||||
|
PayloadType parenthesizedPayloadArgs); \
|
||||||
|
} while (false)
|
||||||
|
|
||||||
|
void profiler_add_marker(const char* aMarkerName,
|
||||||
|
JS::ProfilingCategoryPair aCategoryPair,
|
||||||
|
const ProfilerMarkerPayload& aPayload);
|
||||||
|
|
||||||
void profiler_add_js_marker(const char* aMarkerName, const char* aMarkerText);
|
void profiler_add_js_marker(const char* aMarkerName, const char* aMarkerText);
|
||||||
void profiler_add_js_allocation_marker(JS::RecordAllocationInfo&& info);
|
void profiler_add_js_allocation_marker(JS::RecordAllocationInfo&& info);
|
||||||
|
|
||||||
// Returns true or or false depending on whether the marker was actually added
|
// Returns true or or false depending on whether the marker was actually added
|
||||||
// or not.
|
// or not.
|
||||||
bool profiler_add_native_allocation_marker(int64_t aSize,
|
bool profiler_add_native_allocation_marker(int aMainThreadId, int64_t aSize,
|
||||||
uintptr_t aMemoryAddress);
|
uintptr_t aMemorySize);
|
||||||
|
|
||||||
// Returns true if the profiler lock is currently held *on the current thread*.
|
// Returns true if the profiler lock is currently held *on the current thread*.
|
||||||
// This may be used by re-entrant code that may call profiler functions while
|
// This may be used by re-entrant code that may call profiler functions while
|
||||||
// the profiler already has the lock (which would deadlock).
|
// the profiler already has the lock (which would deadlock).
|
||||||
bool profiler_is_locked_on_current_thread();
|
bool profiler_is_locked_on_current_thread();
|
||||||
|
|
||||||
|
// Insert a marker in the profile timeline for a specified thread.
|
||||||
|
void profiler_add_marker_for_thread(int aThreadId,
|
||||||
|
JS::ProfilingCategoryPair aCategoryPair,
|
||||||
|
const char* aMarkerName,
|
||||||
|
const ProfilerMarkerPayload& aPayload);
|
||||||
|
|
||||||
|
// Insert a marker in the profile timeline for the main thread.
|
||||||
|
// This may be used to gather some markers from any thread, that should be
|
||||||
|
// displayed in the main thread track.
|
||||||
|
void profiler_add_marker_for_mainthread(JS::ProfilingCategoryPair aCategoryPair,
|
||||||
|
const char* aMarkerName,
|
||||||
|
const ProfilerMarkerPayload& aPayload);
|
||||||
|
|
||||||
enum class NetworkLoadType { LOAD_START, LOAD_STOP, LOAD_REDIRECT };
|
enum class NetworkLoadType { LOAD_START, LOAD_STOP, LOAD_REDIRECT };
|
||||||
|
|
||||||
void profiler_add_network_marker(
|
void profiler_add_network_marker(
|
||||||
|
@ -899,8 +941,7 @@ void profiler_add_network_marker(
|
||||||
mozilla::TimeStamp aEnd, int64_t aCount,
|
mozilla::TimeStamp aEnd, int64_t aCount,
|
||||||
mozilla::net::CacheDisposition aCacheDisposition, uint64_t aInnerWindowID,
|
mozilla::net::CacheDisposition aCacheDisposition, uint64_t aInnerWindowID,
|
||||||
const mozilla::net::TimingStruct* aTimings = nullptr,
|
const mozilla::net::TimingStruct* aTimings = nullptr,
|
||||||
nsIURI* aRedirectURI = nullptr,
|
nsIURI* aRedirectURI = nullptr, UniqueProfilerBacktrace aSource = nullptr,
|
||||||
mozilla::UniquePtr<mozilla::ProfileChunkedBuffer> aSource = nullptr,
|
|
||||||
const mozilla::Maybe<nsDependentCString>& aContentType =
|
const mozilla::Maybe<nsDependentCString>& aContentType =
|
||||||
mozilla::Nothing());
|
mozilla::Nothing());
|
||||||
|
|
||||||
|
@ -928,6 +969,40 @@ inline mozilla::MarkerInnerWindowId MarkerInnerWindowIdFromDocShell(
|
||||||
return mozilla::MarkerInnerWindowId(*id);
|
return mozilla::MarkerInnerWindowId(*id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Adds a tracing marker to the profile. A no-op if the profiler is inactive.
|
||||||
|
|
||||||
|
# define PROFILER_TRACING_MARKER(categoryString, markerName, categoryPair, \
|
||||||
|
kind) \
|
||||||
|
profiler_tracing_marker(categoryString, markerName, \
|
||||||
|
JS::ProfilingCategoryPair::categoryPair, kind)
|
||||||
|
# define PROFILER_TRACING_MARKER_DOCSHELL(categoryString, markerName, \
|
||||||
|
categoryPair, kind, docShell) \
|
||||||
|
profiler_tracing_marker( \
|
||||||
|
categoryString, markerName, JS::ProfilingCategoryPair::categoryPair, \
|
||||||
|
kind, profiler_get_inner_window_id_from_docshell(docShell))
|
||||||
|
|
||||||
|
void profiler_tracing_marker(
|
||||||
|
const char* aCategoryString, const char* aMarkerName,
|
||||||
|
JS::ProfilingCategoryPair aCategoryPair, TracingKind aKind,
|
||||||
|
const mozilla::Maybe<uint64_t>& aInnerWindowID = mozilla::Nothing());
|
||||||
|
void profiler_tracing_marker(
|
||||||
|
const char* aCategoryString, const char* aMarkerName,
|
||||||
|
JS::ProfilingCategoryPair aCategoryPair, TracingKind aKind,
|
||||||
|
UniqueProfilerBacktrace aCause,
|
||||||
|
const mozilla::Maybe<uint64_t>& aInnerWindowID = mozilla::Nothing());
|
||||||
|
|
||||||
|
// Adds a START/END pair of tracing markers.
|
||||||
|
# define AUTO_PROFILER_TRACING_MARKER(categoryString, markerName, \
|
||||||
|
categoryPair) \
|
||||||
|
mozilla::AutoProfilerTracing PROFILER_RAII( \
|
||||||
|
categoryString, markerName, JS::ProfilingCategoryPair::categoryPair, \
|
||||||
|
mozilla::Nothing())
|
||||||
|
# define AUTO_PROFILER_TRACING_MARKER_DOCSHELL(categoryString, markerName, \
|
||||||
|
categoryPair, docShell) \
|
||||||
|
mozilla::AutoProfilerTracing PROFILER_RAII( \
|
||||||
|
categoryString, markerName, JS::ProfilingCategoryPair::categoryPair, \
|
||||||
|
profiler_get_inner_window_id_from_docshell(docShell))
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
// Output profiles
|
// Output profiles
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
@ -1150,6 +1225,44 @@ class MOZ_RAII AutoProfilerLabel {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class MOZ_RAII AutoProfilerTracing {
|
||||||
|
public:
|
||||||
|
AutoProfilerTracing(const char* aCategoryString, const char* aMarkerName,
|
||||||
|
JS::ProfilingCategoryPair aCategoryPair,
|
||||||
|
const mozilla::Maybe<uint64_t>& aInnerWindowID)
|
||||||
|
: mCategoryString(aCategoryString),
|
||||||
|
mMarkerName(aMarkerName),
|
||||||
|
mCategoryPair(aCategoryPair),
|
||||||
|
mInnerWindowID(aInnerWindowID) {
|
||||||
|
profiler_tracing_marker(mCategoryString, mMarkerName, aCategoryPair,
|
||||||
|
TRACING_INTERVAL_START, mInnerWindowID);
|
||||||
|
}
|
||||||
|
|
||||||
|
AutoProfilerTracing(const char* aCategoryString, const char* aMarkerName,
|
||||||
|
JS::ProfilingCategoryPair aCategoryPair,
|
||||||
|
UniqueProfilerBacktrace aBacktrace,
|
||||||
|
const mozilla::Maybe<uint64_t>& aInnerWindowID)
|
||||||
|
: mCategoryString(aCategoryString),
|
||||||
|
mMarkerName(aMarkerName),
|
||||||
|
mCategoryPair(aCategoryPair),
|
||||||
|
mInnerWindowID(aInnerWindowID) {
|
||||||
|
profiler_tracing_marker(mCategoryString, mMarkerName, aCategoryPair,
|
||||||
|
TRACING_INTERVAL_START, std::move(aBacktrace),
|
||||||
|
mInnerWindowID);
|
||||||
|
}
|
||||||
|
|
||||||
|
~AutoProfilerTracing() {
|
||||||
|
profiler_tracing_marker(mCategoryString, mMarkerName, mCategoryPair,
|
||||||
|
TRACING_INTERVAL_END, mInnerWindowID);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
const char* mCategoryString;
|
||||||
|
const char* mMarkerName;
|
||||||
|
const JS::ProfilingCategoryPair mCategoryPair;
|
||||||
|
const mozilla::Maybe<uint64_t> mInnerWindowID;
|
||||||
|
};
|
||||||
|
|
||||||
// Get the MOZ_PROFILER_STARTUP* environment variables that should be
|
// Get the MOZ_PROFILER_STARTUP* environment variables that should be
|
||||||
// supplied to a child process that is about to be launched, in order
|
// supplied to a child process that is about to be launched, in order
|
||||||
// to make that child process start with the same profiler settings as
|
// to make that child process start with the same profiler settings as
|
||||||
|
|
|
@ -0,0 +1,839 @@
|
||||||
|
/* -*- 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 ProfilerMarkerPayload_h
|
||||||
|
#define ProfilerMarkerPayload_h
|
||||||
|
|
||||||
|
#include "mozilla/Atomics.h"
|
||||||
|
#include "mozilla/Attributes.h"
|
||||||
|
#include "mozilla/ipc/ProtocolUtils.h"
|
||||||
|
#include "mozilla/Maybe.h"
|
||||||
|
#include "mozilla/net/TimingStruct.h"
|
||||||
|
#include "mozilla/Preferences.h"
|
||||||
|
#include "mozilla/ProfileBufferEntrySerialization.h"
|
||||||
|
#include "mozilla/RefPtr.h"
|
||||||
|
#include "mozilla/TimeStamp.h"
|
||||||
|
#include "mozilla/UniquePtr.h"
|
||||||
|
#include "mozilla/UniquePtrExtensions.h"
|
||||||
|
|
||||||
|
#include "nsString.h"
|
||||||
|
#include "nsCRTGlue.h"
|
||||||
|
#include "GeckoProfiler.h"
|
||||||
|
|
||||||
|
#include "js/Utility.h"
|
||||||
|
#include "js/AllocationRecording.h"
|
||||||
|
#include "js/ProfilingFrameIterator.h"
|
||||||
|
#include "gfxASurface.h"
|
||||||
|
#include "mozilla/ServoTraversalStatistics.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace baseprofiler {
|
||||||
|
class SpliceableJSONWriter;
|
||||||
|
} // namespace baseprofiler
|
||||||
|
namespace layers {
|
||||||
|
class Layer;
|
||||||
|
} // namespace layers
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
class UniqueStacks;
|
||||||
|
|
||||||
|
// This is an abstract class that can be implemented to supply data to be
|
||||||
|
// attached with a profiler marker.
|
||||||
|
//
|
||||||
|
// When subclassing this, note that the destructor can be called on any thread,
|
||||||
|
// i.e. not necessarily on the thread that created the object.
|
||||||
|
class ProfilerMarkerPayload {
|
||||||
|
public:
|
||||||
|
explicit ProfilerMarkerPayload(
|
||||||
|
const mozilla::Maybe<uint64_t>& aInnerWindowID = mozilla::Nothing(),
|
||||||
|
UniqueProfilerBacktrace aStack = nullptr)
|
||||||
|
: mCommonProps{mozilla::TimeStamp{}, mozilla::TimeStamp{},
|
||||||
|
std::move(aStack), aInnerWindowID} {}
|
||||||
|
|
||||||
|
ProfilerMarkerPayload(
|
||||||
|
const mozilla::TimeStamp& aStartTime, const mozilla::TimeStamp& aEndTime,
|
||||||
|
const mozilla::Maybe<uint64_t>& aInnerWindowID = mozilla::Nothing(),
|
||||||
|
UniqueProfilerBacktrace aStack = nullptr)
|
||||||
|
: mCommonProps{aStartTime, aEndTime, std::move(aStack), aInnerWindowID} {}
|
||||||
|
|
||||||
|
virtual ~ProfilerMarkerPayload() = default;
|
||||||
|
|
||||||
|
// Compute the number of bytes needed to serialize the `DeserializerTag` and
|
||||||
|
// payload, including in the no-payload (nullptr) case.
|
||||||
|
static mozilla::ProfileBufferEntryWriter::Length TagAndSerializationBytes(
|
||||||
|
const ProfilerMarkerPayload* aPayload) {
|
||||||
|
if (!aPayload) {
|
||||||
|
return sizeof(DeserializerTag);
|
||||||
|
}
|
||||||
|
return aPayload->TagAndSerializationBytes();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Serialize the payload into an EntryWriter, including in the no-payload
|
||||||
|
// (nullptr) case. Must be of the exact size given by
|
||||||
|
// `TagAndSerializationBytes(aPayload)`.
|
||||||
|
static void TagAndSerialize(const ProfilerMarkerPayload* aPayload,
|
||||||
|
mozilla::ProfileBufferEntryWriter& aEntryWriter) {
|
||||||
|
if (!aPayload) {
|
||||||
|
aEntryWriter.WriteObject(DeserializerTag(0));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
aPayload->SerializeTagAndPayload(aEntryWriter);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deserialize a payload from an EntryReader, including in the no-payload
|
||||||
|
// (nullptr) case.
|
||||||
|
static mozilla::UniquePtr<ProfilerMarkerPayload> DeserializeTagAndPayload(
|
||||||
|
mozilla::ProfileBufferEntryReader& aER) {
|
||||||
|
const auto tag = aER.ReadObject<DeserializerTag>();
|
||||||
|
Deserializer deserializer = DeserializerForTag(tag);
|
||||||
|
return deserializer(aER);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void StreamPayload(
|
||||||
|
mozilla::baseprofiler::SpliceableJSONWriter& aWriter,
|
||||||
|
const mozilla::TimeStamp& aProcessStartTime,
|
||||||
|
UniqueStacks& aUniqueStacks) const = 0;
|
||||||
|
|
||||||
|
const mozilla::TimeStamp& GetStartTime() const {
|
||||||
|
return mCommonProps.mStartTime;
|
||||||
|
}
|
||||||
|
const mozilla::TimeStamp& GetEndTime() const { return mCommonProps.mEndTime; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// A `Deserializer` is a free function that can read a serialized payload from
|
||||||
|
// an `EntryReader` and return a reconstructed `ProfilerMarkerPayload`
|
||||||
|
// sub-object (may be null if there was no payload).
|
||||||
|
typedef mozilla::UniquePtr<ProfilerMarkerPayload> (*Deserializer)(
|
||||||
|
mozilla::ProfileBufferEntryReader&);
|
||||||
|
|
||||||
|
// A `DeserializerTag` will be added before the payload, to help select the
|
||||||
|
// correct deserializer when reading back the payload.
|
||||||
|
using DeserializerTag = unsigned char;
|
||||||
|
|
||||||
|
// This needs to be big enough to handle all possible sub-types of
|
||||||
|
// ProfilerMarkerPayload.
|
||||||
|
static constexpr DeserializerTag DeserializerMax = 32;
|
||||||
|
|
||||||
|
// We need an atomic type that can hold a `DeserializerTag`. (Atomic doesn't
|
||||||
|
// work with too-small types.)
|
||||||
|
using DeserializerTagAtomic = int;
|
||||||
|
|
||||||
|
// Number of currently-registered deserializers.
|
||||||
|
static mozilla::Atomic<DeserializerTagAtomic, mozilla::ReleaseAcquire>
|
||||||
|
sDeserializerCount;
|
||||||
|
|
||||||
|
// List of currently-registered deserializers.
|
||||||
|
// sDeserializers[0] is a no-payload deserializer.
|
||||||
|
static Deserializer sDeserializers[DeserializerMax];
|
||||||
|
|
||||||
|
// Get the `DeserializerTag` for a `Deserializer` (which gets registered on
|
||||||
|
// the first call.) Tag 0 means no payload; a null `aDeserializer` gives that
|
||||||
|
// 0 tag.
|
||||||
|
static DeserializerTag TagForDeserializer(Deserializer aDeserializer);
|
||||||
|
|
||||||
|
// Get the `Deserializer` for a given `DeserializerTag`.
|
||||||
|
// Tag 0 is reserved as no-payload deserializer (which returns nullptr).
|
||||||
|
static Deserializer DeserializerForTag(DeserializerTag aTag);
|
||||||
|
|
||||||
|
struct CommonProps {
|
||||||
|
mozilla::TimeStamp mStartTime;
|
||||||
|
mozilla::TimeStamp mEndTime;
|
||||||
|
UniqueProfilerBacktrace mStack;
|
||||||
|
mozilla::Maybe<uint64_t> mInnerWindowID;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Deserializers can use this base constructor.
|
||||||
|
explicit ProfilerMarkerPayload(CommonProps&& aCommonProps)
|
||||||
|
: mCommonProps(std::move(aCommonProps)) {}
|
||||||
|
|
||||||
|
// Serialization/deserialization of common props in ProfilerMarkerPayload.
|
||||||
|
mozilla::ProfileBufferEntryWriter::Length
|
||||||
|
CommonPropsTagAndSerializationBytes() const;
|
||||||
|
void SerializeTagAndCommonProps(
|
||||||
|
DeserializerTag aDeserializerTag,
|
||||||
|
mozilla::ProfileBufferEntryWriter& aEntryWriter) const;
|
||||||
|
static CommonProps DeserializeCommonProps(
|
||||||
|
mozilla::ProfileBufferEntryReader& aEntryReader);
|
||||||
|
|
||||||
|
void StreamType(const char* aMarkerType,
|
||||||
|
mozilla::baseprofiler::SpliceableJSONWriter& aWriter) const;
|
||||||
|
|
||||||
|
void StreamCommonProps(const char* aMarkerType,
|
||||||
|
mozilla::baseprofiler::SpliceableJSONWriter& aWriter,
|
||||||
|
const mozilla::TimeStamp& aProcessStartTime,
|
||||||
|
UniqueStacks& aUniqueStacks) const;
|
||||||
|
void StreamStartEndTime(mozilla::baseprofiler::SpliceableJSONWriter& aWriter,
|
||||||
|
const mozilla::TimeStamp& aProcessStartTime) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Compute the number of bytes needed to serialize payload in
|
||||||
|
// `SerializeTagAndPayload` below.
|
||||||
|
virtual mozilla::ProfileBufferEntryWriter::Length TagAndSerializationBytes()
|
||||||
|
const = 0;
|
||||||
|
|
||||||
|
// Serialize the payload into an EntryWriter.
|
||||||
|
// Must be of the exact size given by `TagAndSerializationBytes()`.
|
||||||
|
virtual void SerializeTagAndPayload(
|
||||||
|
mozilla::ProfileBufferEntryWriter& aEntryWriter) const = 0;
|
||||||
|
|
||||||
|
CommonProps mCommonProps;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DECL_STREAM_PAYLOAD \
|
||||||
|
void StreamPayload(mozilla::baseprofiler::SpliceableJSONWriter& aWriter, \
|
||||||
|
const mozilla::TimeStamp& aProcessStartTime, \
|
||||||
|
UniqueStacks& aUniqueStacks) const override; \
|
||||||
|
static mozilla::UniquePtr<ProfilerMarkerPayload> Deserialize( \
|
||||||
|
mozilla::ProfileBufferEntryReader& aEntryReader); \
|
||||||
|
mozilla::ProfileBufferEntryWriter::Length TagAndSerializationBytes() \
|
||||||
|
const override; \
|
||||||
|
void SerializeTagAndPayload(mozilla::ProfileBufferEntryWriter& aEntryWriter) \
|
||||||
|
const override;
|
||||||
|
|
||||||
|
// TODO: Increase the coverage of tracing markers that include InnerWindowID
|
||||||
|
// information
|
||||||
|
class TracingMarkerPayload : public ProfilerMarkerPayload {
|
||||||
|
public:
|
||||||
|
TracingMarkerPayload(
|
||||||
|
const char* aCategory, TracingKind aKind, const mozilla::TimeStamp& aTime,
|
||||||
|
const mozilla::Maybe<uint64_t>& aInnerWindowID = mozilla::Nothing(),
|
||||||
|
UniqueProfilerBacktrace aCause = nullptr)
|
||||||
|
: ProfilerMarkerPayload((aKind != TracingKind::TRACING_INTERVAL_END)
|
||||||
|
? aTime
|
||||||
|
: mozilla::TimeStamp{},
|
||||||
|
(aKind != TracingKind::TRACING_INTERVAL_START)
|
||||||
|
? aTime
|
||||||
|
: mozilla::TimeStamp{},
|
||||||
|
aInnerWindowID, std::move(aCause)),
|
||||||
|
mCategory(aCategory),
|
||||||
|
mKind(aKind) {}
|
||||||
|
|
||||||
|
TracingMarkerPayload(const char* aCategory, const mozilla::TimeStamp& aStart,
|
||||||
|
const mozilla::TimeStamp& aEnd)
|
||||||
|
: ProfilerMarkerPayload(aStart, aEnd, mozilla::Nothing(), nullptr),
|
||||||
|
mCategory(aCategory),
|
||||||
|
mKind(TRACING_EVENT) {}
|
||||||
|
|
||||||
|
DECL_STREAM_PAYLOAD
|
||||||
|
|
||||||
|
protected:
|
||||||
|
TracingMarkerPayload(CommonProps&& aCommonProps, const char* aCategory,
|
||||||
|
TracingKind aKind)
|
||||||
|
: ProfilerMarkerPayload(std::move(aCommonProps)),
|
||||||
|
mCategory(aCategory),
|
||||||
|
mKind(aKind) {}
|
||||||
|
|
||||||
|
// May be used by derived classes.
|
||||||
|
void SerializeTagAndPayload(
|
||||||
|
DeserializerTag aDeserializerTag,
|
||||||
|
mozilla::ProfileBufferEntryWriter& aEntryWriter) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const char* mCategory;
|
||||||
|
TracingKind mKind;
|
||||||
|
};
|
||||||
|
|
||||||
|
class BudgetMarkerPayload : public ProfilerMarkerPayload {
|
||||||
|
public:
|
||||||
|
BudgetMarkerPayload(const mozilla::TimeStamp& aStartTime,
|
||||||
|
const mozilla::TimeStamp& aEndTime)
|
||||||
|
: ProfilerMarkerPayload(aStartTime, aEndTime) {}
|
||||||
|
|
||||||
|
DECL_STREAM_PAYLOAD
|
||||||
|
|
||||||
|
private:
|
||||||
|
explicit BudgetMarkerPayload(CommonProps&& aCommonProps)
|
||||||
|
: ProfilerMarkerPayload(std::move(aCommonProps)) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class PrefMarkerPayload : public ProfilerMarkerPayload {
|
||||||
|
public:
|
||||||
|
PrefMarkerPayload(const char* aPrefName,
|
||||||
|
const mozilla::Maybe<mozilla::PrefValueKind>& aPrefKind,
|
||||||
|
const mozilla::Maybe<mozilla::PrefType>& aPrefType,
|
||||||
|
const nsCString& aPrefValue,
|
||||||
|
const mozilla::TimeStamp& aPrefAccessTime)
|
||||||
|
: ProfilerMarkerPayload(aPrefAccessTime, aPrefAccessTime),
|
||||||
|
mPrefAccessTime(aPrefAccessTime),
|
||||||
|
mPrefName(aPrefName),
|
||||||
|
mPrefKind(aPrefKind),
|
||||||
|
mPrefType(aPrefType),
|
||||||
|
mPrefValue(aPrefValue) {}
|
||||||
|
|
||||||
|
DECL_STREAM_PAYLOAD
|
||||||
|
|
||||||
|
private:
|
||||||
|
PrefMarkerPayload(CommonProps&& aCommonProps,
|
||||||
|
mozilla::TimeStamp aPrefAccessTime, nsCString&& aPrefName,
|
||||||
|
mozilla::Maybe<mozilla::PrefValueKind>&& aPrefKind,
|
||||||
|
mozilla::Maybe<mozilla::PrefType>&& aPrefType,
|
||||||
|
nsCString&& aPrefValue)
|
||||||
|
: ProfilerMarkerPayload(std::move(aCommonProps)),
|
||||||
|
mPrefAccessTime(aPrefAccessTime),
|
||||||
|
mPrefName(aPrefName),
|
||||||
|
mPrefKind(aPrefKind),
|
||||||
|
mPrefType(aPrefType),
|
||||||
|
mPrefValue(aPrefValue) {}
|
||||||
|
|
||||||
|
mozilla::TimeStamp mPrefAccessTime;
|
||||||
|
nsCString mPrefName;
|
||||||
|
// Nothing means this is a shared preference. Something, on the other hand,
|
||||||
|
// holds an actual PrefValueKind indicating either a Default or User
|
||||||
|
// preference.
|
||||||
|
mozilla::Maybe<mozilla::PrefValueKind> mPrefKind;
|
||||||
|
// Nothing means that the mPrefName preference was not found. Something
|
||||||
|
// contains the type of the preference.
|
||||||
|
mozilla::Maybe<mozilla::PrefType> mPrefType;
|
||||||
|
nsCString mPrefValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
class UserTimingMarkerPayload : public ProfilerMarkerPayload {
|
||||||
|
public:
|
||||||
|
UserTimingMarkerPayload(const nsAString& aName,
|
||||||
|
const mozilla::TimeStamp& aStartTime,
|
||||||
|
const mozilla::Maybe<uint64_t>& aInnerWindowID)
|
||||||
|
: ProfilerMarkerPayload(aStartTime, aStartTime, aInnerWindowID),
|
||||||
|
mEntryType("mark"),
|
||||||
|
mName(aName) {}
|
||||||
|
|
||||||
|
UserTimingMarkerPayload(const nsAString& aName,
|
||||||
|
const mozilla::Maybe<nsString>& aStartMark,
|
||||||
|
const mozilla::Maybe<nsString>& aEndMark,
|
||||||
|
const mozilla::TimeStamp& aStartTime,
|
||||||
|
const mozilla::TimeStamp& aEndTime,
|
||||||
|
const mozilla::Maybe<uint64_t>& aInnerWindowID)
|
||||||
|
: ProfilerMarkerPayload(aStartTime, aEndTime, aInnerWindowID),
|
||||||
|
mEntryType("measure"),
|
||||||
|
mName(aName),
|
||||||
|
mStartMark(aStartMark),
|
||||||
|
mEndMark(aEndMark) {}
|
||||||
|
|
||||||
|
DECL_STREAM_PAYLOAD
|
||||||
|
|
||||||
|
private:
|
||||||
|
UserTimingMarkerPayload(CommonProps&& aCommonProps, const char* aEntryType,
|
||||||
|
nsString&& aName,
|
||||||
|
mozilla::Maybe<nsString>&& aStartMark,
|
||||||
|
mozilla::Maybe<nsString>&& aEndMark)
|
||||||
|
: ProfilerMarkerPayload(std::move(aCommonProps)),
|
||||||
|
mEntryType(aEntryType),
|
||||||
|
mName(std::move(aName)),
|
||||||
|
mStartMark(std::move(aStartMark)),
|
||||||
|
mEndMark(std::move(aEndMark)) {}
|
||||||
|
|
||||||
|
// Either "mark" or "measure".
|
||||||
|
const char* mEntryType;
|
||||||
|
nsString mName;
|
||||||
|
mozilla::Maybe<nsString> mStartMark;
|
||||||
|
mozilla::Maybe<nsString> mEndMark;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Contains the translation applied to a 2d layer so we can track the layer
|
||||||
|
// position at each frame.
|
||||||
|
class LayerTranslationMarkerPayload : public ProfilerMarkerPayload {
|
||||||
|
public:
|
||||||
|
LayerTranslationMarkerPayload(mozilla::layers::Layer* aLayer,
|
||||||
|
mozilla::gfx::Point aPoint,
|
||||||
|
mozilla::TimeStamp aStartTime)
|
||||||
|
: ProfilerMarkerPayload(aStartTime, aStartTime),
|
||||||
|
mLayer(aLayer),
|
||||||
|
mPoint(aPoint) {}
|
||||||
|
|
||||||
|
DECL_STREAM_PAYLOAD
|
||||||
|
|
||||||
|
private:
|
||||||
|
LayerTranslationMarkerPayload(CommonProps&& aCommonProps,
|
||||||
|
mozilla::layers::Layer* aLayer,
|
||||||
|
mozilla::gfx::Point aPoint)
|
||||||
|
: ProfilerMarkerPayload(std::move(aCommonProps)),
|
||||||
|
mLayer(aLayer),
|
||||||
|
mPoint(aPoint) {}
|
||||||
|
|
||||||
|
mozilla::layers::Layer* mLayer;
|
||||||
|
mozilla::gfx::Point mPoint;
|
||||||
|
};
|
||||||
|
|
||||||
|
#include "Units.h" // For ScreenIntPoint
|
||||||
|
|
||||||
|
// Tracks when a vsync occurs according to the HardwareComposer.
|
||||||
|
class VsyncMarkerPayload : public ProfilerMarkerPayload {
|
||||||
|
public:
|
||||||
|
explicit VsyncMarkerPayload(mozilla::TimeStamp aVsyncTimestamp)
|
||||||
|
: ProfilerMarkerPayload(aVsyncTimestamp, aVsyncTimestamp) {}
|
||||||
|
|
||||||
|
DECL_STREAM_PAYLOAD
|
||||||
|
|
||||||
|
private:
|
||||||
|
explicit VsyncMarkerPayload(CommonProps&& aCommonProps)
|
||||||
|
: ProfilerMarkerPayload(std::move(aCommonProps)) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class NetworkMarkerPayload : public ProfilerMarkerPayload {
|
||||||
|
public:
|
||||||
|
NetworkMarkerPayload(int64_t aID, const char* aURI,
|
||||||
|
const nsACString& aRequestMethod, NetworkLoadType aType,
|
||||||
|
const mozilla::TimeStamp& aStartTime,
|
||||||
|
const mozilla::TimeStamp& aEndTime, int32_t aPri,
|
||||||
|
int64_t aCount,
|
||||||
|
mozilla::net::CacheDisposition aCacheDisposition,
|
||||||
|
uint64_t aInnerWindowID,
|
||||||
|
const mozilla::net::TimingStruct* aTimings = nullptr,
|
||||||
|
const char* aRedirectURI = nullptr,
|
||||||
|
UniqueProfilerBacktrace aSource = nullptr,
|
||||||
|
const mozilla::Maybe<nsDependentCString>& aContentType =
|
||||||
|
mozilla::Nothing())
|
||||||
|
: ProfilerMarkerPayload(aStartTime, aEndTime,
|
||||||
|
mozilla::Some(aInnerWindowID),
|
||||||
|
std::move(aSource)),
|
||||||
|
mID(aID),
|
||||||
|
mURI(aURI ? strdup(aURI) : nullptr),
|
||||||
|
mRedirectURI(aRedirectURI && (strlen(aRedirectURI) > 0)
|
||||||
|
? strdup(aRedirectURI)
|
||||||
|
: nullptr),
|
||||||
|
mRequestMethod(aRequestMethod),
|
||||||
|
mType(aType),
|
||||||
|
mPri(aPri),
|
||||||
|
mCount(aCount),
|
||||||
|
mCacheDisposition(aCacheDisposition),
|
||||||
|
mContentType(aContentType) {
|
||||||
|
if (aTimings) {
|
||||||
|
mTimings = *aTimings;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DECL_STREAM_PAYLOAD
|
||||||
|
|
||||||
|
private:
|
||||||
|
NetworkMarkerPayload(CommonProps&& aCommonProps, int64_t aID,
|
||||||
|
mozilla::UniqueFreePtr<char>&& aURI,
|
||||||
|
mozilla::UniqueFreePtr<char>&& aRedirectURI,
|
||||||
|
nsCString&& aRequestMethod, NetworkLoadType aType,
|
||||||
|
int32_t aPri, int64_t aCount,
|
||||||
|
mozilla::net::TimingStruct aTimings,
|
||||||
|
mozilla::net::CacheDisposition aCacheDisposition,
|
||||||
|
mozilla::Maybe<nsAutoCString>&& aContentType)
|
||||||
|
: ProfilerMarkerPayload(std::move(aCommonProps)),
|
||||||
|
mID(aID),
|
||||||
|
mURI(std::move(aURI)),
|
||||||
|
mRedirectURI(std::move(aRedirectURI)),
|
||||||
|
mRequestMethod(std::move(aRequestMethod)),
|
||||||
|
mType(aType),
|
||||||
|
mPri(aPri),
|
||||||
|
mCount(aCount),
|
||||||
|
mTimings(aTimings),
|
||||||
|
mCacheDisposition(aCacheDisposition),
|
||||||
|
mContentType(std::move(aContentType)) {}
|
||||||
|
|
||||||
|
int64_t mID;
|
||||||
|
mozilla::UniqueFreePtr<char> mURI;
|
||||||
|
mozilla::UniqueFreePtr<char> mRedirectURI;
|
||||||
|
// Request method and content type further down are usually short,
|
||||||
|
// e.g., "GET" and "text/html", so we use nsAutoCString to reduce
|
||||||
|
// heap usage; the bigger object size is acceptable here because
|
||||||
|
// markers are short-lived on-stack objects.
|
||||||
|
nsAutoCString mRequestMethod;
|
||||||
|
NetworkLoadType mType;
|
||||||
|
int32_t mPri;
|
||||||
|
int64_t mCount;
|
||||||
|
mozilla::net::TimingStruct mTimings;
|
||||||
|
mozilla::net::CacheDisposition mCacheDisposition;
|
||||||
|
mozilla::Maybe<nsAutoCString> mContentType;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ScreenshotPayload : public ProfilerMarkerPayload {
|
||||||
|
public:
|
||||||
|
explicit ScreenshotPayload(mozilla::TimeStamp aTimeStamp,
|
||||||
|
nsCString&& aScreenshotDataURL,
|
||||||
|
const mozilla::gfx::IntSize& aWindowSize,
|
||||||
|
uintptr_t aWindowIdentifier)
|
||||||
|
: ProfilerMarkerPayload(aTimeStamp, mozilla::TimeStamp()),
|
||||||
|
mScreenshotDataURL(std::move(aScreenshotDataURL)),
|
||||||
|
mWindowSize(aWindowSize),
|
||||||
|
mWindowIdentifier(aWindowIdentifier) {}
|
||||||
|
|
||||||
|
DECL_STREAM_PAYLOAD
|
||||||
|
|
||||||
|
private:
|
||||||
|
ScreenshotPayload(CommonProps&& aCommonProps, nsCString&& aScreenshotDataURL,
|
||||||
|
mozilla::gfx::IntSize aWindowSize,
|
||||||
|
uintptr_t aWindowIdentifier)
|
||||||
|
: ProfilerMarkerPayload(std::move(aCommonProps)),
|
||||||
|
mScreenshotDataURL(std::move(aScreenshotDataURL)),
|
||||||
|
mWindowSize(aWindowSize),
|
||||||
|
mWindowIdentifier(aWindowIdentifier) {}
|
||||||
|
|
||||||
|
nsCString mScreenshotDataURL;
|
||||||
|
mozilla::gfx::IntSize mWindowSize;
|
||||||
|
uintptr_t mWindowIdentifier;
|
||||||
|
};
|
||||||
|
|
||||||
|
class GCSliceMarkerPayload : public ProfilerMarkerPayload {
|
||||||
|
public:
|
||||||
|
GCSliceMarkerPayload(const mozilla::TimeStamp& aStartTime,
|
||||||
|
const mozilla::TimeStamp& aEndTime,
|
||||||
|
JS::UniqueChars&& aTimingJSON)
|
||||||
|
: ProfilerMarkerPayload(aStartTime, aEndTime),
|
||||||
|
mTimingJSON(std::move(aTimingJSON)) {}
|
||||||
|
|
||||||
|
DECL_STREAM_PAYLOAD
|
||||||
|
|
||||||
|
private:
|
||||||
|
GCSliceMarkerPayload(CommonProps&& aCommonProps,
|
||||||
|
JS::UniqueChars&& aTimingJSON)
|
||||||
|
: ProfilerMarkerPayload(std::move(aCommonProps)),
|
||||||
|
mTimingJSON(std::move(aTimingJSON)) {}
|
||||||
|
|
||||||
|
JS::UniqueChars mTimingJSON;
|
||||||
|
};
|
||||||
|
|
||||||
|
class GCMajorMarkerPayload : public ProfilerMarkerPayload {
|
||||||
|
public:
|
||||||
|
GCMajorMarkerPayload(const mozilla::TimeStamp& aStartTime,
|
||||||
|
const mozilla::TimeStamp& aEndTime,
|
||||||
|
JS::UniqueChars&& aTimingJSON)
|
||||||
|
: ProfilerMarkerPayload(aStartTime, aEndTime),
|
||||||
|
mTimingJSON(std::move(aTimingJSON)) {}
|
||||||
|
|
||||||
|
DECL_STREAM_PAYLOAD
|
||||||
|
|
||||||
|
private:
|
||||||
|
GCMajorMarkerPayload(CommonProps&& aCommonProps,
|
||||||
|
JS::UniqueChars&& aTimingJSON)
|
||||||
|
: ProfilerMarkerPayload(std::move(aCommonProps)),
|
||||||
|
mTimingJSON(std::move(aTimingJSON)) {}
|
||||||
|
|
||||||
|
JS::UniqueChars mTimingJSON;
|
||||||
|
};
|
||||||
|
|
||||||
|
class GCMinorMarkerPayload : public ProfilerMarkerPayload {
|
||||||
|
public:
|
||||||
|
GCMinorMarkerPayload(const mozilla::TimeStamp& aStartTime,
|
||||||
|
const mozilla::TimeStamp& aEndTime,
|
||||||
|
JS::UniqueChars&& aTimingData)
|
||||||
|
: ProfilerMarkerPayload(aStartTime, aEndTime),
|
||||||
|
mTimingData(std::move(aTimingData)) {}
|
||||||
|
|
||||||
|
DECL_STREAM_PAYLOAD
|
||||||
|
|
||||||
|
private:
|
||||||
|
GCMinorMarkerPayload(CommonProps&& aCommonProps,
|
||||||
|
JS::UniqueChars&& aTimingData)
|
||||||
|
: ProfilerMarkerPayload(std::move(aCommonProps)),
|
||||||
|
mTimingData(std::move(aTimingData)) {}
|
||||||
|
|
||||||
|
JS::UniqueChars mTimingData;
|
||||||
|
};
|
||||||
|
|
||||||
|
class HangMarkerPayload : public ProfilerMarkerPayload {
|
||||||
|
public:
|
||||||
|
HangMarkerPayload(const mozilla::TimeStamp& aStartTime,
|
||||||
|
const mozilla::TimeStamp& aEndTime)
|
||||||
|
: ProfilerMarkerPayload(aStartTime, aEndTime) {}
|
||||||
|
|
||||||
|
DECL_STREAM_PAYLOAD
|
||||||
|
private:
|
||||||
|
explicit HangMarkerPayload(CommonProps&& aCommonProps)
|
||||||
|
: ProfilerMarkerPayload(std::move(aCommonProps)) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class StyleMarkerPayload : public ProfilerMarkerPayload {
|
||||||
|
public:
|
||||||
|
StyleMarkerPayload(const mozilla::TimeStamp& aStartTime,
|
||||||
|
const mozilla::TimeStamp& aEndTime,
|
||||||
|
UniqueProfilerBacktrace aCause,
|
||||||
|
const mozilla::ServoTraversalStatistics& aStats,
|
||||||
|
const mozilla::Maybe<uint64_t>& aInnerWindowID)
|
||||||
|
: ProfilerMarkerPayload(aStartTime, aEndTime, aInnerWindowID,
|
||||||
|
std::move(aCause)),
|
||||||
|
mStats(aStats) {}
|
||||||
|
|
||||||
|
DECL_STREAM_PAYLOAD
|
||||||
|
|
||||||
|
private:
|
||||||
|
StyleMarkerPayload(CommonProps&& aCommonProps,
|
||||||
|
mozilla::ServoTraversalStatistics aStats)
|
||||||
|
: ProfilerMarkerPayload(std::move(aCommonProps)), mStats(aStats) {}
|
||||||
|
|
||||||
|
mozilla::ServoTraversalStatistics mStats;
|
||||||
|
};
|
||||||
|
|
||||||
|
class LongTaskMarkerPayload : public ProfilerMarkerPayload {
|
||||||
|
public:
|
||||||
|
LongTaskMarkerPayload(const mozilla::TimeStamp& aStartTime,
|
||||||
|
const mozilla::TimeStamp& aEndTime)
|
||||||
|
: ProfilerMarkerPayload(aStartTime, aEndTime) {}
|
||||||
|
|
||||||
|
DECL_STREAM_PAYLOAD
|
||||||
|
|
||||||
|
private:
|
||||||
|
explicit LongTaskMarkerPayload(CommonProps&& aCommonProps)
|
||||||
|
: ProfilerMarkerPayload(std::move(aCommonProps)) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class TimingMarkerPayload : public ProfilerMarkerPayload {
|
||||||
|
public:
|
||||||
|
TimingMarkerPayload(const mozilla::TimeStamp& aStartTime,
|
||||||
|
const mozilla::TimeStamp& aEndTime)
|
||||||
|
: ProfilerMarkerPayload(aStartTime, aEndTime) {}
|
||||||
|
|
||||||
|
DECL_STREAM_PAYLOAD
|
||||||
|
|
||||||
|
private:
|
||||||
|
explicit TimingMarkerPayload(CommonProps&& aCommonProps)
|
||||||
|
: ProfilerMarkerPayload(std::move(aCommonProps)) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class TextMarkerPayload : public ProfilerMarkerPayload {
|
||||||
|
public:
|
||||||
|
TextMarkerPayload(const nsACString& aText,
|
||||||
|
const mozilla::TimeStamp& aStartTime)
|
||||||
|
: ProfilerMarkerPayload(aStartTime, aStartTime), mText(aText) {}
|
||||||
|
|
||||||
|
TextMarkerPayload(const nsACString& aText,
|
||||||
|
const mozilla::TimeStamp& aStartTime,
|
||||||
|
const mozilla::TimeStamp& aEndTime)
|
||||||
|
: ProfilerMarkerPayload(aStartTime, aEndTime), mText(aText) {}
|
||||||
|
|
||||||
|
TextMarkerPayload(const nsACString& aText,
|
||||||
|
const mozilla::TimeStamp& aStartTime,
|
||||||
|
const mozilla::Maybe<uint64_t>& aInnerWindowID)
|
||||||
|
: ProfilerMarkerPayload(aStartTime, aStartTime, aInnerWindowID),
|
||||||
|
mText(aText) {}
|
||||||
|
|
||||||
|
TextMarkerPayload(const nsACString& aText,
|
||||||
|
const mozilla::TimeStamp& aStartTime,
|
||||||
|
const mozilla::TimeStamp& aEndTime,
|
||||||
|
const mozilla::Maybe<uint64_t>& aInnerWindowID,
|
||||||
|
UniqueProfilerBacktrace aCause = nullptr)
|
||||||
|
: ProfilerMarkerPayload(aStartTime, aEndTime, aInnerWindowID,
|
||||||
|
std::move(aCause)),
|
||||||
|
mText(aText) {}
|
||||||
|
|
||||||
|
DECL_STREAM_PAYLOAD
|
||||||
|
|
||||||
|
private:
|
||||||
|
TextMarkerPayload(CommonProps&& aCommonProps, nsCString&& aText)
|
||||||
|
: ProfilerMarkerPayload(std::move(aCommonProps)),
|
||||||
|
mText(std::move(aText)) {}
|
||||||
|
|
||||||
|
nsCString mText;
|
||||||
|
};
|
||||||
|
|
||||||
|
class LogMarkerPayload : public ProfilerMarkerPayload {
|
||||||
|
public:
|
||||||
|
LogMarkerPayload(const char* aModule, const char* aText,
|
||||||
|
const mozilla::TimeStamp& aStartTime)
|
||||||
|
: ProfilerMarkerPayload(aStartTime, aStartTime),
|
||||||
|
mModule(aModule),
|
||||||
|
mText(aText) {}
|
||||||
|
|
||||||
|
LogMarkerPayload(const char* aModule, const char* aText,
|
||||||
|
const mozilla::TimeStamp& aStartTime,
|
||||||
|
const mozilla::TimeStamp& aEndTime)
|
||||||
|
: ProfilerMarkerPayload(aStartTime, aEndTime),
|
||||||
|
mModule(aModule),
|
||||||
|
mText(aText) {}
|
||||||
|
|
||||||
|
DECL_STREAM_PAYLOAD
|
||||||
|
|
||||||
|
private:
|
||||||
|
LogMarkerPayload(CommonProps&& aCommonProps, nsAutoCStringN<32>&& aModule,
|
||||||
|
nsCString&& aText)
|
||||||
|
: ProfilerMarkerPayload(std::move(aCommonProps)),
|
||||||
|
mModule(std::move(aModule)),
|
||||||
|
mText(std::move(aText)) {}
|
||||||
|
|
||||||
|
nsAutoCStringN<32> mModule; // longest known LazyLogModule name is ~24
|
||||||
|
nsCString mText;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MediaSampleMarkerPayload : public ProfilerMarkerPayload {
|
||||||
|
public:
|
||||||
|
MediaSampleMarkerPayload(const int64_t aSampleStartTimeUs,
|
||||||
|
const int64_t aSampleEndTimeUs);
|
||||||
|
DECL_STREAM_PAYLOAD
|
||||||
|
|
||||||
|
private:
|
||||||
|
MediaSampleMarkerPayload(CommonProps&& aCommonProps,
|
||||||
|
const int64_t aSampleStartTimeUs,
|
||||||
|
const int64_t aSampleEndTimeUs);
|
||||||
|
|
||||||
|
int64_t mSampleStartTimeUs;
|
||||||
|
int64_t mSampleEndTimeUs;
|
||||||
|
};
|
||||||
|
|
||||||
|
class JsAllocationMarkerPayload : public ProfilerMarkerPayload {
|
||||||
|
public:
|
||||||
|
JsAllocationMarkerPayload(const mozilla::TimeStamp& aStartTime,
|
||||||
|
JS::RecordAllocationInfo&& aInfo,
|
||||||
|
UniqueProfilerBacktrace aStack)
|
||||||
|
: ProfilerMarkerPayload(aStartTime, aStartTime, mozilla::Nothing(),
|
||||||
|
std::move(aStack)),
|
||||||
|
// Copy the strings, and take ownership of them.
|
||||||
|
mTypeName(aInfo.typeName ? NS_xstrdup(aInfo.typeName) : nullptr),
|
||||||
|
mClassName(aInfo.className ? strdup(aInfo.className) : nullptr),
|
||||||
|
mDescriptiveTypeName(aInfo.descriptiveTypeName
|
||||||
|
? NS_xstrdup(aInfo.descriptiveTypeName)
|
||||||
|
: nullptr),
|
||||||
|
// The coarseType points to a string literal, so does not need to be
|
||||||
|
// duplicated.
|
||||||
|
mCoarseType(aInfo.coarseType),
|
||||||
|
mSize(aInfo.size),
|
||||||
|
mInNursery(aInfo.inNursery) {}
|
||||||
|
|
||||||
|
DECL_STREAM_PAYLOAD
|
||||||
|
|
||||||
|
private:
|
||||||
|
JsAllocationMarkerPayload(
|
||||||
|
CommonProps&& aCommonProps,
|
||||||
|
mozilla::UniqueFreePtr<const char16_t>&& aTypeName,
|
||||||
|
mozilla::UniqueFreePtr<const char>&& aClassName,
|
||||||
|
mozilla::UniqueFreePtr<const char16_t>&& aDescriptiveTypeName,
|
||||||
|
const char* aCoarseType, uint64_t aSize, bool aInNursery)
|
||||||
|
: ProfilerMarkerPayload(std::move(aCommonProps)),
|
||||||
|
mTypeName(std::move(aTypeName)),
|
||||||
|
mClassName(std::move(aClassName)),
|
||||||
|
mDescriptiveTypeName(std::move(aDescriptiveTypeName)),
|
||||||
|
mCoarseType(aCoarseType),
|
||||||
|
mSize(aSize),
|
||||||
|
mInNursery(aInNursery) {}
|
||||||
|
|
||||||
|
mozilla::UniqueFreePtr<const char16_t> mTypeName;
|
||||||
|
mozilla::UniqueFreePtr<const char> mClassName;
|
||||||
|
mozilla::UniqueFreePtr<const char16_t> mDescriptiveTypeName;
|
||||||
|
// Points to a string literal, so does not need to be freed.
|
||||||
|
const char* mCoarseType;
|
||||||
|
|
||||||
|
// The size in bytes of the allocation.
|
||||||
|
uint64_t mSize;
|
||||||
|
|
||||||
|
// Whether or not the allocation is in the nursery or not.
|
||||||
|
bool mInNursery;
|
||||||
|
};
|
||||||
|
|
||||||
|
// This payload is for collecting information about native allocations. There is
|
||||||
|
// a memory hook into malloc and other memory functions that can sample a subset
|
||||||
|
// of the allocations. This information is then stored in this payload.
|
||||||
|
class NativeAllocationMarkerPayload : public ProfilerMarkerPayload {
|
||||||
|
public:
|
||||||
|
NativeAllocationMarkerPayload(const mozilla::TimeStamp& aStartTime,
|
||||||
|
int64_t aSize, uintptr_t aMemoryAddress,
|
||||||
|
int aThreadId, UniqueProfilerBacktrace aStack)
|
||||||
|
: ProfilerMarkerPayload(aStartTime, aStartTime, mozilla::Nothing(),
|
||||||
|
std::move(aStack)),
|
||||||
|
mSize(aSize),
|
||||||
|
mMemoryAddress(aMemoryAddress),
|
||||||
|
mThreadId(aThreadId) {}
|
||||||
|
|
||||||
|
DECL_STREAM_PAYLOAD
|
||||||
|
|
||||||
|
private:
|
||||||
|
NativeAllocationMarkerPayload(CommonProps&& aCommonProps, int64_t aSize,
|
||||||
|
uintptr_t aMemoryAddress, int aThreadId)
|
||||||
|
: ProfilerMarkerPayload(std::move(aCommonProps)),
|
||||||
|
mSize(aSize),
|
||||||
|
mMemoryAddress(aMemoryAddress),
|
||||||
|
mThreadId(aThreadId) {}
|
||||||
|
|
||||||
|
// The size in bytes of the allocation. If the number is negative then it
|
||||||
|
// represents a de-allocation.
|
||||||
|
int64_t mSize;
|
||||||
|
// The memory address of the allocation or de-allocation.
|
||||||
|
uintptr_t mMemoryAddress;
|
||||||
|
|
||||||
|
int mThreadId;
|
||||||
|
};
|
||||||
|
|
||||||
|
class IPCMarkerPayload : public ProfilerMarkerPayload {
|
||||||
|
public:
|
||||||
|
IPCMarkerPayload(int32_t aOtherPid, int32_t aMessageSeqno,
|
||||||
|
IPC::Message::msgid_t aMessageType, mozilla::ipc::Side aSide,
|
||||||
|
mozilla::ipc::MessageDirection aDirection,
|
||||||
|
mozilla::ipc::MessagePhase aPhase, bool aSync,
|
||||||
|
const mozilla::TimeStamp& aStartTime)
|
||||||
|
: ProfilerMarkerPayload(aStartTime, aStartTime),
|
||||||
|
mOtherPid(aOtherPid),
|
||||||
|
mMessageSeqno(aMessageSeqno),
|
||||||
|
mMessageType(aMessageType),
|
||||||
|
mSide(aSide),
|
||||||
|
mDirection(aDirection),
|
||||||
|
mPhase(aPhase),
|
||||||
|
mSync(aSync) {}
|
||||||
|
|
||||||
|
DECL_STREAM_PAYLOAD
|
||||||
|
|
||||||
|
private:
|
||||||
|
IPCMarkerPayload(CommonProps&& aCommonProps, int32_t aOtherPid,
|
||||||
|
int32_t aMessageSeqno, IPC::Message::msgid_t aMessageType,
|
||||||
|
mozilla::ipc::Side aSide,
|
||||||
|
mozilla::ipc::MessageDirection aDirection,
|
||||||
|
mozilla::ipc::MessagePhase aPhase, bool aSync)
|
||||||
|
: ProfilerMarkerPayload(std::move(aCommonProps)),
|
||||||
|
mOtherPid(aOtherPid),
|
||||||
|
mMessageSeqno(aMessageSeqno),
|
||||||
|
mMessageType(aMessageType),
|
||||||
|
mSide(aSide),
|
||||||
|
mDirection(aDirection),
|
||||||
|
mPhase(aPhase),
|
||||||
|
mSync(aSync) {}
|
||||||
|
|
||||||
|
int32_t mOtherPid;
|
||||||
|
int32_t mMessageSeqno;
|
||||||
|
IPC::Message::msgid_t mMessageType;
|
||||||
|
mozilla::ipc::Side mSide;
|
||||||
|
mozilla::ipc::MessageDirection mDirection;
|
||||||
|
mozilla::ipc::MessagePhase mPhase;
|
||||||
|
bool mSync;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
// Serialize a pointed-at ProfilerMarkerPayload, may be null when there are no
|
||||||
|
// payloads.
|
||||||
|
template <>
|
||||||
|
struct ProfileBufferEntryWriter::Serializer<const ProfilerMarkerPayload*> {
|
||||||
|
static Length Bytes(const ProfilerMarkerPayload* aPayload) {
|
||||||
|
return ProfilerMarkerPayload::TagAndSerializationBytes(aPayload);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Write(ProfileBufferEntryWriter& aEW,
|
||||||
|
const ProfilerMarkerPayload* aPayload) {
|
||||||
|
ProfilerMarkerPayload::TagAndSerialize(aPayload, aEW);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Serialize a pointed-at ProfilerMarkerPayload, may be null when there are no
|
||||||
|
// payloads.
|
||||||
|
template <>
|
||||||
|
struct ProfileBufferEntryWriter::Serializer<UniquePtr<ProfilerMarkerPayload>> {
|
||||||
|
static Length Bytes(const UniquePtr<ProfilerMarkerPayload>& aPayload) {
|
||||||
|
return ProfilerMarkerPayload::TagAndSerializationBytes(aPayload.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Write(ProfileBufferEntryWriter& aEW,
|
||||||
|
const UniquePtr<ProfilerMarkerPayload>& aPayload) {
|
||||||
|
ProfilerMarkerPayload::TagAndSerialize(aPayload.get(), aEW);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Deserialize a ProfilerMarkerPayload into a UniquePtr, may be null if there
|
||||||
|
// are no payloads.
|
||||||
|
template <>
|
||||||
|
struct ProfileBufferEntryReader::Deserializer<
|
||||||
|
UniquePtr<ProfilerMarkerPayload>> {
|
||||||
|
static void ReadInto(ProfileBufferEntryReader& aER,
|
||||||
|
UniquePtr<ProfilerMarkerPayload>& aPayload) {
|
||||||
|
aPayload = Read(aER);
|
||||||
|
}
|
||||||
|
|
||||||
|
static UniquePtr<ProfilerMarkerPayload> Read(ProfileBufferEntryReader& aER) {
|
||||||
|
return ProfilerMarkerPayload::DeserializeTagAndPayload(aER);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#endif // ProfilerMarkerPayload_h
|
|
@ -23,16 +23,488 @@
|
||||||
|
|
||||||
#ifdef MOZ_GECKO_PROFILER
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
|
|
||||||
|
# include "gfxASurface.h"
|
||||||
|
# include "js/AllocationRecording.h"
|
||||||
# include "js/ProfilingFrameIterator.h"
|
# include "js/ProfilingFrameIterator.h"
|
||||||
# include "js/Utility.h"
|
# include "js/Utility.h"
|
||||||
|
# include "Layers.h"
|
||||||
|
# include "mozilla/ipc/ProtocolUtils.h"
|
||||||
|
# include "mozilla/net/HttpBaseChannel.h"
|
||||||
# include "mozilla/Preferences.h"
|
# include "mozilla/Preferences.h"
|
||||||
# include "mozilla/ServoTraversalStatistics.h"
|
# include "mozilla/ServoTraversalStatistics.h"
|
||||||
|
|
||||||
namespace geckoprofiler::markers {
|
namespace geckoprofiler::markers {
|
||||||
|
|
||||||
// Import some common markers from mozilla::baseprofiler::markers.
|
// Import some common markers from mozilla::baseprofiler::markers.
|
||||||
using MediaSampleMarker = mozilla::baseprofiler::markers::MediaSampleMarker;
|
using Tracing = mozilla::baseprofiler::markers::Tracing;
|
||||||
using ContentBuildMarker = mozilla::baseprofiler::markers::ContentBuildMarker;
|
using UserTimingMark = mozilla::baseprofiler::markers::UserTimingMark;
|
||||||
|
using UserTimingMeasure = mozilla::baseprofiler::markers::UserTimingMeasure;
|
||||||
|
using Hang = mozilla::baseprofiler::markers::Hang;
|
||||||
|
using LongTask = mozilla::baseprofiler::markers::LongTask;
|
||||||
|
using Log = mozilla::baseprofiler::markers::Log;
|
||||||
|
using MediaSample = mozilla::baseprofiler::markers::MediaSample;
|
||||||
|
|
||||||
|
struct Budget {
|
||||||
|
static constexpr mozilla::Span<const char> MarkerTypeName() {
|
||||||
|
return mozilla::MakeStringSpan("Budget");
|
||||||
|
}
|
||||||
|
static void StreamJSONMarkerData(
|
||||||
|
mozilla::baseprofiler::SpliceableJSONWriter& aWriter) {}
|
||||||
|
static mozilla::MarkerSchema MarkerTypeDisplay() {
|
||||||
|
using MS = mozilla::MarkerSchema;
|
||||||
|
MS schema{MS::Location::markerChart, MS::Location::markerTable};
|
||||||
|
// Nothing outside the defaults.
|
||||||
|
return schema;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Pref {
|
||||||
|
static constexpr mozilla::Span<const char> MarkerTypeName() {
|
||||||
|
return mozilla::MakeStringSpan("PreferenceRead");
|
||||||
|
}
|
||||||
|
static void StreamJSONMarkerData(
|
||||||
|
mozilla::baseprofiler::SpliceableJSONWriter& aWriter,
|
||||||
|
const mozilla::ProfilerString8View& aPrefName,
|
||||||
|
const mozilla::Maybe<mozilla::PrefValueKind>& aPrefKind,
|
||||||
|
const mozilla::Maybe<mozilla::PrefType>& aPrefType,
|
||||||
|
const mozilla::ProfilerString8View& aPrefValue,
|
||||||
|
const mozilla::TimeStamp& aPrefAccessTime) {
|
||||||
|
// TODO: This looks like it's always `Now()`, so it could probably be
|
||||||
|
// removed; but the frontend may need updating first.
|
||||||
|
mozilla::baseprofiler::WritePropertyTime(aWriter, "prefAccessTime",
|
||||||
|
aPrefAccessTime);
|
||||||
|
aWriter.StringProperty("prefName", aPrefName);
|
||||||
|
aWriter.StringProperty("prefKind", PrefValueKindToString(aPrefKind));
|
||||||
|
aWriter.StringProperty("prefType", PrefTypeToString(aPrefType));
|
||||||
|
aWriter.StringProperty("prefValue", aPrefValue);
|
||||||
|
}
|
||||||
|
static mozilla::MarkerSchema MarkerTypeDisplay() {
|
||||||
|
using MS = mozilla::MarkerSchema;
|
||||||
|
MS schema{MS::Location::markerChart, MS::Location::markerTable};
|
||||||
|
schema.AddKeyLabelFormat("prefName", "Name", MS::Format::string);
|
||||||
|
schema.AddKeyLabelFormat("prefKind", "Kind", MS::Format::string);
|
||||||
|
schema.AddKeyLabelFormat("prefType", "Type", MS::Format::string);
|
||||||
|
schema.AddKeyLabelFormat("prefValue", "Value", MS::Format::string);
|
||||||
|
return schema;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static mozilla::Span<const char> PrefValueKindToString(
|
||||||
|
const mozilla::Maybe<mozilla::PrefValueKind>& aKind) {
|
||||||
|
if (aKind) {
|
||||||
|
return *aKind == mozilla::PrefValueKind::Default
|
||||||
|
? mozilla::MakeStringSpan("Default")
|
||||||
|
: mozilla::MakeStringSpan("User");
|
||||||
|
}
|
||||||
|
return "Shared";
|
||||||
|
}
|
||||||
|
|
||||||
|
static mozilla::Span<const char> PrefTypeToString(
|
||||||
|
const mozilla::Maybe<mozilla::PrefType>& type) {
|
||||||
|
if (type) {
|
||||||
|
switch (*type) {
|
||||||
|
case mozilla::PrefType::None:
|
||||||
|
return "None";
|
||||||
|
case mozilla::PrefType::Int:
|
||||||
|
return "Int";
|
||||||
|
case mozilla::PrefType::Bool:
|
||||||
|
return "Bool";
|
||||||
|
case mozilla::PrefType::String:
|
||||||
|
return "String";
|
||||||
|
default:
|
||||||
|
MOZ_ASSERT_UNREACHABLE("Unknown preference type.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "Preference not found";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Contains the translation applied to a 2d layer so we can track the layer
|
||||||
|
// position at each frame.
|
||||||
|
struct LayerTranslation {
|
||||||
|
static constexpr mozilla::Span<const char> MarkerTypeName() {
|
||||||
|
return mozilla::MakeStringSpan("LayerTranslation");
|
||||||
|
}
|
||||||
|
static void StreamJSONMarkerData(
|
||||||
|
mozilla::baseprofiler::SpliceableJSONWriter& aWriter,
|
||||||
|
mozilla::layers::Layer* aLayer, mozilla::gfx::Point aPoint) {
|
||||||
|
const size_t bufferSize = 32;
|
||||||
|
char buffer[bufferSize];
|
||||||
|
SprintfLiteral(buffer, "%p", aLayer);
|
||||||
|
|
||||||
|
aWriter.StringProperty("layer", buffer);
|
||||||
|
aWriter.IntProperty("x", aPoint.x);
|
||||||
|
aWriter.IntProperty("y", aPoint.y);
|
||||||
|
}
|
||||||
|
static mozilla::MarkerSchema MarkerTypeDisplay() {
|
||||||
|
using MS = mozilla::MarkerSchema;
|
||||||
|
MS schema{MS::Location::markerChart, MS::Location::markerTable};
|
||||||
|
schema.AddKeyLabelFormat("layer", "Layer", MS::Format::string);
|
||||||
|
schema.AddKeyLabelFormat("x", "X", MS::Format::integer);
|
||||||
|
schema.AddKeyLabelFormat("y", "Y", MS::Format::integer);
|
||||||
|
return schema;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Tracks when a vsync occurs according to the HardwareComposer.
|
||||||
|
struct Vsync {
|
||||||
|
static constexpr mozilla::Span<const char> MarkerTypeName() {
|
||||||
|
return mozilla::MakeStringSpan("VsyncTimestamp");
|
||||||
|
}
|
||||||
|
static void StreamJSONMarkerData(
|
||||||
|
mozilla::baseprofiler::SpliceableJSONWriter& aWriter) {}
|
||||||
|
static mozilla::MarkerSchema MarkerTypeDisplay() {
|
||||||
|
using MS = mozilla::MarkerSchema;
|
||||||
|
MS schema{MS::Location::markerChart, MS::Location::markerTable};
|
||||||
|
// Nothing outside the defaults.
|
||||||
|
return schema;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Network {
|
||||||
|
static constexpr mozilla::Span<const char> MarkerTypeName() {
|
||||||
|
return mozilla::MakeStringSpan("Network");
|
||||||
|
}
|
||||||
|
static void StreamJSONMarkerData(
|
||||||
|
mozilla::baseprofiler::SpliceableJSONWriter& aWriter, int64_t aID,
|
||||||
|
const mozilla::ProfilerString8View& aURI, NetworkLoadType aType,
|
||||||
|
const mozilla::TimeStamp& aStartTime, const mozilla::TimeStamp& aEndTime,
|
||||||
|
int32_t aPri, int64_t aCount,
|
||||||
|
mozilla::net::CacheDisposition aCacheDisposition, uint64_t aInnerWindowID,
|
||||||
|
const mozilla::net::TimingStruct& aTimings,
|
||||||
|
const mozilla::ProfilerString8View& aRedirectURI,
|
||||||
|
UniqueProfilerBacktrace aSource,
|
||||||
|
const mozilla::ProfilerString8View& aContentType) {
|
||||||
|
// TODO: Remove these Legacy start&end times when frontend is updated.
|
||||||
|
mozilla::baseprofiler::WritePropertyTime(aWriter, "startTime", aStartTime);
|
||||||
|
mozilla::baseprofiler::WritePropertyTime(aWriter, "endTime", aEndTime);
|
||||||
|
|
||||||
|
aWriter.IntProperty("id", aID);
|
||||||
|
mozilla::Span<const char> typeString = GetNetworkState(aType);
|
||||||
|
mozilla::Span<const char> cacheString = GetCacheState(aCacheDisposition);
|
||||||
|
// want to use aUniqueStacks.mUniqueStrings->WriteElement(aWriter,
|
||||||
|
// typeString);
|
||||||
|
aWriter.StringProperty("status", typeString);
|
||||||
|
if (!cacheString.IsEmpty()) {
|
||||||
|
aWriter.StringProperty("cache", cacheString);
|
||||||
|
}
|
||||||
|
aWriter.IntProperty("pri", aPri);
|
||||||
|
if (aCount > 0) {
|
||||||
|
aWriter.IntProperty("count", aCount);
|
||||||
|
}
|
||||||
|
if (aURI.Length() != 0) {
|
||||||
|
aWriter.StringProperty("URI", aURI);
|
||||||
|
}
|
||||||
|
if (aRedirectURI.Length() != 0) {
|
||||||
|
aWriter.StringProperty("RedirectURI", aRedirectURI);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aContentType.Length() != 0) {
|
||||||
|
aWriter.StringProperty("contentType", aContentType);
|
||||||
|
} else {
|
||||||
|
aWriter.NullProperty("contentType");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aType != NetworkLoadType::LOAD_START) {
|
||||||
|
mozilla::baseprofiler::WritePropertyTime(aWriter, "domainLookupStart",
|
||||||
|
aTimings.domainLookupStart);
|
||||||
|
mozilla::baseprofiler::WritePropertyTime(aWriter, "domainLookupEnd",
|
||||||
|
aTimings.domainLookupEnd);
|
||||||
|
mozilla::baseprofiler::WritePropertyTime(aWriter, "connectStart",
|
||||||
|
aTimings.connectStart);
|
||||||
|
mozilla::baseprofiler::WritePropertyTime(aWriter, "tcpConnectEnd",
|
||||||
|
aTimings.tcpConnectEnd);
|
||||||
|
mozilla::baseprofiler::WritePropertyTime(aWriter, "secureConnectionStart",
|
||||||
|
aTimings.secureConnectionStart);
|
||||||
|
mozilla::baseprofiler::WritePropertyTime(aWriter, "connectEnd",
|
||||||
|
aTimings.connectEnd);
|
||||||
|
mozilla::baseprofiler::WritePropertyTime(aWriter, "requestStart",
|
||||||
|
aTimings.requestStart);
|
||||||
|
mozilla::baseprofiler::WritePropertyTime(aWriter, "responseStart",
|
||||||
|
aTimings.responseStart);
|
||||||
|
mozilla::baseprofiler::WritePropertyTime(aWriter, "responseEnd",
|
||||||
|
aTimings.responseEnd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static mozilla::MarkerSchema MarkerTypeDisplay() {
|
||||||
|
return mozilla::MarkerSchema::SpecialFrontendLocation{};
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static mozilla::Span<const char> GetNetworkState(NetworkLoadType aType) {
|
||||||
|
switch (aType) {
|
||||||
|
case NetworkLoadType::LOAD_START:
|
||||||
|
return mozilla::MakeStringSpan("STATUS_START");
|
||||||
|
case NetworkLoadType::LOAD_STOP:
|
||||||
|
return mozilla::MakeStringSpan("STATUS_STOP");
|
||||||
|
case NetworkLoadType::LOAD_REDIRECT:
|
||||||
|
return mozilla::MakeStringSpan("STATUS_REDIRECT");
|
||||||
|
}
|
||||||
|
return mozilla::MakeStringSpan("");
|
||||||
|
}
|
||||||
|
|
||||||
|
static mozilla::Span<const char> GetCacheState(
|
||||||
|
mozilla::net::CacheDisposition aCacheDisposition) {
|
||||||
|
switch (aCacheDisposition) {
|
||||||
|
case mozilla::net::kCacheUnresolved:
|
||||||
|
return mozilla::MakeStringSpan("Unresolved");
|
||||||
|
case mozilla::net::kCacheHit:
|
||||||
|
return mozilla::MakeStringSpan("Hit");
|
||||||
|
case mozilla::net::kCacheHitViaReval:
|
||||||
|
return mozilla::MakeStringSpan("HitViaReval");
|
||||||
|
case mozilla::net::kCacheMissedViaReval:
|
||||||
|
return mozilla::MakeStringSpan("MissedViaReval");
|
||||||
|
case mozilla::net::kCacheMissed:
|
||||||
|
return mozilla::MakeStringSpan("Missed");
|
||||||
|
case mozilla::net::kCacheUnknown:
|
||||||
|
default:
|
||||||
|
return mozilla::MakeStringSpan("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ScreenshotPayload {
|
||||||
|
static constexpr mozilla::Span<const char> MarkerTypeName() {
|
||||||
|
return mozilla::MakeStringSpan("CompositorScreenshot");
|
||||||
|
}
|
||||||
|
static void StreamJSONMarkerData(
|
||||||
|
mozilla::baseprofiler::SpliceableJSONWriter& aWriter,
|
||||||
|
const mozilla::ProfilerString8View& aScreenshotDataURL,
|
||||||
|
const mozilla::gfx::IntSize& aWindowSize, uintptr_t aWindowIdentifier) {
|
||||||
|
// TODO: Use UniqueStacks&Strings
|
||||||
|
// aUniqueStacks.mUniqueStrings->WriteProperty(aWriter, "url",
|
||||||
|
// mScreenshotDataURL.get());
|
||||||
|
aWriter.StringProperty("url", aScreenshotDataURL);
|
||||||
|
|
||||||
|
char hexWindowID[32];
|
||||||
|
SprintfLiteral(hexWindowID, "0x%" PRIXPTR, aWindowIdentifier);
|
||||||
|
aWriter.StringProperty("windowID", hexWindowID);
|
||||||
|
aWriter.DoubleProperty("windowWidth", aWindowSize.width);
|
||||||
|
aWriter.DoubleProperty("windowHeight", aWindowSize.height);
|
||||||
|
}
|
||||||
|
static mozilla::MarkerSchema MarkerTypeDisplay() {
|
||||||
|
return mozilla::MarkerSchema::SpecialFrontendLocation{};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GCSlice {
|
||||||
|
static constexpr mozilla::Span<const char> MarkerTypeName() {
|
||||||
|
return mozilla::MakeStringSpan("GCSlice");
|
||||||
|
}
|
||||||
|
static void StreamJSONMarkerData(
|
||||||
|
mozilla::baseprofiler::SpliceableJSONWriter& aWriter,
|
||||||
|
const mozilla::ProfilerString8View& aTimingJSON) {
|
||||||
|
if (aTimingJSON.Length() != 0) {
|
||||||
|
// TODO: Is SplicedJSONProperty necessary here? (Guessing yes!)
|
||||||
|
// aWriter.SplicedJSONProperty("timings", aTimingJSON);
|
||||||
|
aWriter.StringProperty("timings", aTimingJSON);
|
||||||
|
} else {
|
||||||
|
aWriter.NullProperty("timings");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static mozilla::MarkerSchema MarkerTypeDisplay() {
|
||||||
|
using MS = mozilla::MarkerSchema;
|
||||||
|
MS schema{MS::Location::markerChart, MS::Location::markerTable,
|
||||||
|
MS::Location::timelineMemory};
|
||||||
|
// No display instructions here, there is special handling in the front-end.
|
||||||
|
return schema;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GCMajor {
|
||||||
|
static constexpr mozilla::Span<const char> MarkerTypeName() {
|
||||||
|
return mozilla::MakeStringSpan("GCMajor");
|
||||||
|
}
|
||||||
|
static void StreamJSONMarkerData(
|
||||||
|
mozilla::baseprofiler::SpliceableJSONWriter& aWriter,
|
||||||
|
const mozilla::ProfilerString8View& aTimingJSON) {
|
||||||
|
if (aTimingJSON.Length() != 0) {
|
||||||
|
// TODO: Is SplicedJSONProperty necessary here? (Guessing yes!)
|
||||||
|
// aWriter.SplicedJSONProperty("timings", aTimingJSON);
|
||||||
|
aWriter.StringProperty("timings", aTimingJSON);
|
||||||
|
} else {
|
||||||
|
aWriter.NullProperty("timings");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static mozilla::MarkerSchema MarkerTypeDisplay() {
|
||||||
|
using MS = mozilla::MarkerSchema;
|
||||||
|
MS schema{MS::Location::markerChart, MS::Location::markerTable,
|
||||||
|
MS::Location::timelineMemory};
|
||||||
|
// No display instructions here, there is special handling in the front-end.
|
||||||
|
return schema;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GCMinor {
|
||||||
|
static constexpr mozilla::Span<const char> MarkerTypeName() {
|
||||||
|
return mozilla::MakeStringSpan("GCMinor");
|
||||||
|
}
|
||||||
|
static void StreamJSONMarkerData(
|
||||||
|
mozilla::baseprofiler::SpliceableJSONWriter& aWriter,
|
||||||
|
const mozilla::ProfilerString8View& aTimingJSON) {
|
||||||
|
if (aTimingJSON.Length() != 0) {
|
||||||
|
// TODO: Is SplicedJSONProperty necessary here? (Guessing yes!)
|
||||||
|
// aWriter.SplicedJSONProperty("nursery", aTimingJSON);
|
||||||
|
aWriter.StringProperty("nursery", aTimingJSON);
|
||||||
|
} else {
|
||||||
|
aWriter.NullProperty("nursery");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static mozilla::MarkerSchema MarkerTypeDisplay() {
|
||||||
|
using MS = mozilla::MarkerSchema;
|
||||||
|
MS schema{MS::Location::markerChart, MS::Location::markerTable,
|
||||||
|
MS::Location::timelineMemory};
|
||||||
|
// No display instructions here, there is special handling in the front-end.
|
||||||
|
return schema;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct StyleMarkerPayload {
|
||||||
|
static constexpr mozilla::Span<const char> MarkerTypeName() {
|
||||||
|
return mozilla::MakeStringSpan("Styles");
|
||||||
|
}
|
||||||
|
static void StreamJSONMarkerData(
|
||||||
|
mozilla::baseprofiler::SpliceableJSONWriter& aWriter,
|
||||||
|
const mozilla::ServoTraversalStatistics& aStats) {
|
||||||
|
aWriter.IntProperty("elementsTraversed", aStats.mElementsTraversed);
|
||||||
|
aWriter.IntProperty("elementsStyled", aStats.mElementsStyled);
|
||||||
|
aWriter.IntProperty("elementsMatched", aStats.mElementsMatched);
|
||||||
|
aWriter.IntProperty("stylesShared", aStats.mStylesShared);
|
||||||
|
aWriter.IntProperty("stylesReused", aStats.mStylesReused);
|
||||||
|
}
|
||||||
|
static mozilla::MarkerSchema MarkerTypeDisplay() {
|
||||||
|
using MS = mozilla::MarkerSchema;
|
||||||
|
MS schema{MS::Location::markerChart, MS::Location::markerTable,
|
||||||
|
MS::Location::timelineOverview};
|
||||||
|
schema.AddKeyLabelFormat("elementsTraversed", "Elements traversed",
|
||||||
|
MS::Format::integer);
|
||||||
|
schema.AddKeyLabelFormat("elementsStyled", "Elements styled",
|
||||||
|
MS::Format::integer);
|
||||||
|
schema.AddKeyLabelFormat("elementsMatched", "Elements matched",
|
||||||
|
MS::Format::integer);
|
||||||
|
schema.AddKeyLabelFormat("stylesShared", "Styles shared",
|
||||||
|
MS::Format::integer);
|
||||||
|
schema.AddKeyLabelFormat("stylesReused", "Styles reused",
|
||||||
|
MS::Format::integer);
|
||||||
|
return schema;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class JsAllocationMarkerPayload {
|
||||||
|
static constexpr mozilla::Span<const char> MarkerTypeName() {
|
||||||
|
return mozilla::MakeStringSpan("JS allocation");
|
||||||
|
}
|
||||||
|
static void StreamJSONMarkerData(
|
||||||
|
mozilla::baseprofiler::SpliceableJSONWriter& aWriter,
|
||||||
|
const mozilla::ProfilerString16View& aTypeName,
|
||||||
|
const mozilla::ProfilerString8View& aClassName,
|
||||||
|
const mozilla::ProfilerString16View& aDescriptiveTypeName,
|
||||||
|
const mozilla::ProfilerString8View& aCoarseType, uint64_t aSize,
|
||||||
|
bool aInNursery) {
|
||||||
|
if (aClassName.Length() != 0) {
|
||||||
|
aWriter.StringProperty("className", aClassName);
|
||||||
|
}
|
||||||
|
if (aTypeName.Length() != 0) {
|
||||||
|
aWriter.StringProperty(
|
||||||
|
"typeName",
|
||||||
|
NS_ConvertUTF16toUTF8(aTypeName.Data(), aTypeName.Length()));
|
||||||
|
}
|
||||||
|
if (aDescriptiveTypeName.Length() != 0) {
|
||||||
|
aWriter.StringProperty(
|
||||||
|
"descriptiveTypeName",
|
||||||
|
NS_ConvertUTF16toUTF8(aDescriptiveTypeName.Data(),
|
||||||
|
aDescriptiveTypeName.Length()));
|
||||||
|
}
|
||||||
|
aWriter.StringProperty("coarseType", aCoarseType);
|
||||||
|
aWriter.IntProperty("size", aSize);
|
||||||
|
aWriter.BoolProperty("inNursery", aInNursery);
|
||||||
|
}
|
||||||
|
static mozilla::MarkerSchema MarkerTypeDisplay() {
|
||||||
|
return mozilla::MarkerSchema::SpecialFrontendLocation{};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// This payload is for collecting information about native allocations. There is
|
||||||
|
// a memory hook into malloc and other memory functions that can sample a subset
|
||||||
|
// of the allocations. This information is then stored in this payload.
|
||||||
|
struct NativeAllocationMarkerPayload {
|
||||||
|
static constexpr mozilla::Span<const char> MarkerTypeName() {
|
||||||
|
return mozilla::MakeStringSpan("Native allocation");
|
||||||
|
}
|
||||||
|
static void StreamJSONMarkerData(
|
||||||
|
mozilla::baseprofiler::SpliceableJSONWriter& aWriter, int64_t aSize,
|
||||||
|
uintptr_t aMemoryAddress, int aThreadId) {
|
||||||
|
aWriter.IntProperty("size", aSize);
|
||||||
|
aWriter.IntProperty("memoryAddress", static_cast<int64_t>(aMemoryAddress));
|
||||||
|
aWriter.IntProperty("threadId", aThreadId);
|
||||||
|
}
|
||||||
|
static mozilla::MarkerSchema MarkerTypeDisplay() {
|
||||||
|
return mozilla::MarkerSchema::SpecialFrontendLocation{};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IPCMarkerPayload {
|
||||||
|
static constexpr mozilla::Span<const char> MarkerTypeName() {
|
||||||
|
return mozilla::MakeStringSpan("IPC");
|
||||||
|
}
|
||||||
|
static void StreamJSONMarkerData(
|
||||||
|
mozilla::baseprofiler::SpliceableJSONWriter& aWriter, int32_t aOtherPid,
|
||||||
|
int32_t aMessageSeqno, IPC::Message::msgid_t aMessageType,
|
||||||
|
mozilla::ipc::Side aSide, mozilla::ipc::MessageDirection aDirection,
|
||||||
|
mozilla::ipc::MessagePhase aPhase, bool aSync,
|
||||||
|
const mozilla::TimeStamp& aTime) {
|
||||||
|
// TODO: Remove these Legacy times when frontend is updated.
|
||||||
|
mozilla::baseprofiler::WritePropertyTime(aWriter, "startTime", aTime);
|
||||||
|
mozilla::baseprofiler::WritePropertyTime(aWriter, "endTime", aTime);
|
||||||
|
|
||||||
|
using namespace mozilla::ipc;
|
||||||
|
aWriter.IntProperty("otherPid", aOtherPid);
|
||||||
|
aWriter.IntProperty("messageSeqno", aMessageSeqno);
|
||||||
|
aWriter.StringProperty(
|
||||||
|
"messageType",
|
||||||
|
mozilla::MakeStringSpan(IPC::StringFromIPCMessageType(aMessageType)));
|
||||||
|
aWriter.StringProperty("side", IPCSideToString(aSide));
|
||||||
|
aWriter.StringProperty("direction",
|
||||||
|
aDirection == MessageDirection::eSending
|
||||||
|
? mozilla::MakeStringSpan("sending")
|
||||||
|
: mozilla::MakeStringSpan("receiving"));
|
||||||
|
aWriter.StringProperty("phase", IPCPhaseToString(aPhase));
|
||||||
|
aWriter.BoolProperty("sync", aSync);
|
||||||
|
}
|
||||||
|
static mozilla::MarkerSchema MarkerTypeDisplay() {
|
||||||
|
return mozilla::MarkerSchema::SpecialFrontendLocation{};
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static mozilla::Span<const char> IPCSideToString(mozilla::ipc::Side aSide) {
|
||||||
|
switch (aSide) {
|
||||||
|
case mozilla::ipc::ParentSide:
|
||||||
|
return mozilla::MakeStringSpan("parent");
|
||||||
|
case mozilla::ipc::ChildSide:
|
||||||
|
return mozilla::MakeStringSpan("child");
|
||||||
|
case mozilla::ipc::UnknownSide:
|
||||||
|
return mozilla::MakeStringSpan("unknown");
|
||||||
|
default:
|
||||||
|
MOZ_ASSERT_UNREACHABLE("Invalid IPC side");
|
||||||
|
return mozilla::MakeStringSpan("<invalid IPC side>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static mozilla::Span<const char> IPCPhaseToString(
|
||||||
|
mozilla::ipc::MessagePhase aPhase) {
|
||||||
|
switch (aPhase) {
|
||||||
|
case mozilla::ipc::MessagePhase::Endpoint:
|
||||||
|
return mozilla::MakeStringSpan("endpoint");
|
||||||
|
case mozilla::ipc::MessagePhase::TransferStart:
|
||||||
|
return mozilla::MakeStringSpan("transferStart");
|
||||||
|
case mozilla::ipc::MessagePhase::TransferEnd:
|
||||||
|
return mozilla::MakeStringSpan("transferEnd");
|
||||||
|
default:
|
||||||
|
MOZ_ASSERT_UNREACHABLE("Invalid IPC phase");
|
||||||
|
return mozilla::MakeStringSpan("<invalid IPC phase>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace geckoprofiler::markers
|
} // namespace geckoprofiler::markers
|
||||||
|
|
||||||
|
|
|
@ -44,9 +44,6 @@
|
||||||
# define PROFILER_MARKER(markerName, categoryName, options, MarkerType, ...)
|
# define PROFILER_MARKER(markerName, categoryName, options, MarkerType, ...)
|
||||||
# define PROFILER_MARKER_TEXT(markerName, categoryName, options, text)
|
# define PROFILER_MARKER_TEXT(markerName, categoryName, options, text)
|
||||||
# define AUTO_PROFILER_MARKER_TEXT(markerName, categoryName, options, text)
|
# define AUTO_PROFILER_MARKER_TEXT(markerName, categoryName, options, text)
|
||||||
# define AUTO_PROFILER_TRACING_MARKER(categoryString, markerName, categoryPair)
|
|
||||||
# define AUTO_PROFILER_TRACING_MARKER_DOCSHELL(categoryString, markerName, \
|
|
||||||
categoryPair, docShell)
|
|
||||||
|
|
||||||
#else // ndef MOZ_GECKO_PROFILER
|
#else // ndef MOZ_GECKO_PROFILER
|
||||||
|
|
||||||
|
@ -132,9 +129,8 @@ inline mozilla::ProfileBufferBlockIndex profiler_add_marker(
|
||||||
} while (false)
|
} while (false)
|
||||||
|
|
||||||
namespace geckoprofiler::markers {
|
namespace geckoprofiler::markers {
|
||||||
// Most common marker types. Others are in ProfilerMarkerTypes.h.
|
// Most common marker type. Others are in ProfilerMarkerTypes.h.
|
||||||
using Text = ::mozilla::baseprofiler::markers::Text;
|
using Text = ::mozilla::baseprofiler::markers::Text;
|
||||||
using Tracing = mozilla::baseprofiler::markers::Tracing;
|
|
||||||
} // namespace geckoprofiler::markers
|
} // namespace geckoprofiler::markers
|
||||||
|
|
||||||
// Add a text marker. This macro is safe to use even if MOZ_GECKO_PROFILER is
|
// Add a text marker. This macro is safe to use even if MOZ_GECKO_PROFILER is
|
||||||
|
@ -189,75 +185,6 @@ class MOZ_RAII AutoProfilerTextMarker {
|
||||||
markerName, ::mozilla::baseprofiler::category::categoryName, options, \
|
markerName, ::mozilla::baseprofiler::category::categoryName, options, \
|
||||||
text)
|
text)
|
||||||
|
|
||||||
class MOZ_RAII AutoProfilerTracing {
|
|
||||||
public:
|
|
||||||
AutoProfilerTracing(const char* aCategoryString, const char* aMarkerName,
|
|
||||||
mozilla::MarkerCategory aCategoryPair,
|
|
||||||
const mozilla::Maybe<uint64_t>& aInnerWindowID)
|
|
||||||
: mCategoryString(aCategoryString),
|
|
||||||
mMarkerName(aMarkerName),
|
|
||||||
mCategoryPair(aCategoryPair),
|
|
||||||
mInnerWindowID(aInnerWindowID) {
|
|
||||||
profiler_add_marker(
|
|
||||||
mozilla::ProfilerString8View::WrapNullTerminatedString(mMarkerName),
|
|
||||||
mCategoryPair,
|
|
||||||
{mozilla::MarkerTiming::IntervalStart(),
|
|
||||||
mozilla::MarkerInnerWindowId(mInnerWindowID)},
|
|
||||||
geckoprofiler::markers::Tracing{},
|
|
||||||
mozilla::ProfilerString8View::WrapNullTerminatedString(
|
|
||||||
mCategoryString));
|
|
||||||
}
|
|
||||||
|
|
||||||
AutoProfilerTracing(
|
|
||||||
const char* aCategoryString, const char* aMarkerName,
|
|
||||||
mozilla::MarkerCategory aCategoryPair,
|
|
||||||
mozilla::UniquePtr<mozilla::ProfileChunkedBuffer> aBacktrace,
|
|
||||||
const mozilla::Maybe<uint64_t>& aInnerWindowID)
|
|
||||||
: mCategoryString(aCategoryString),
|
|
||||||
mMarkerName(aMarkerName),
|
|
||||||
mCategoryPair(aCategoryPair),
|
|
||||||
mInnerWindowID(aInnerWindowID) {
|
|
||||||
profiler_add_marker(
|
|
||||||
mozilla::ProfilerString8View::WrapNullTerminatedString(mMarkerName),
|
|
||||||
mCategoryPair,
|
|
||||||
{mozilla::MarkerTiming::IntervalStart(),
|
|
||||||
mozilla::MarkerInnerWindowId(mInnerWindowID),
|
|
||||||
mozilla::MarkerStack::TakeBacktrace(std::move(aBacktrace))},
|
|
||||||
geckoprofiler::markers::Tracing{},
|
|
||||||
mozilla::ProfilerString8View::WrapNullTerminatedString(
|
|
||||||
mCategoryString));
|
|
||||||
}
|
|
||||||
|
|
||||||
~AutoProfilerTracing() {
|
|
||||||
profiler_add_marker(
|
|
||||||
mozilla::ProfilerString8View::WrapNullTerminatedString(mMarkerName),
|
|
||||||
mCategoryPair,
|
|
||||||
{mozilla::MarkerTiming::IntervalEnd(),
|
|
||||||
mozilla::MarkerInnerWindowId(mInnerWindowID)},
|
|
||||||
geckoprofiler::markers::Tracing{},
|
|
||||||
mozilla::ProfilerString8View::WrapNullTerminatedString(
|
|
||||||
mCategoryString));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
const char* mCategoryString;
|
|
||||||
const char* mMarkerName;
|
|
||||||
const mozilla::MarkerCategory mCategoryPair;
|
|
||||||
const mozilla::Maybe<uint64_t> mInnerWindowID;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Adds a START/END pair of tracing markers.
|
|
||||||
# define AUTO_PROFILER_TRACING_MARKER(categoryString, markerName, \
|
|
||||||
categoryPair) \
|
|
||||||
AutoProfilerTracing PROFILER_RAII(categoryString, markerName, \
|
|
||||||
geckoprofiler::category::categoryPair, \
|
|
||||||
mozilla::Nothing())
|
|
||||||
# define AUTO_PROFILER_TRACING_MARKER_DOCSHELL(categoryString, markerName, \
|
|
||||||
categoryPair, docShell) \
|
|
||||||
AutoProfilerTracing PROFILER_RAII( \
|
|
||||||
categoryString, markerName, geckoprofiler::category::categoryPair, \
|
|
||||||
profiler_get_inner_window_id_from_docshell(docShell))
|
|
||||||
|
|
||||||
#endif // nfed MOZ_GECKO_PROFILER else
|
#endif // nfed MOZ_GECKO_PROFILER else
|
||||||
|
|
||||||
#endif // ProfilerMarkers_h
|
#endif // ProfilerMarkers_h
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "mozilla/ProfilerMarkers.h"
|
#include "mozilla/ProfilerMarkers.h"
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "ProfileBuffer.h"
|
#include "ProfileBuffer.h"
|
||||||
|
#include "ProfilerMarkerPayload.h"
|
||||||
|
|
||||||
#include "js/Initialization.h"
|
#include "js/Initialization.h"
|
||||||
#include "js/Printf.h"
|
#include "js/Printf.h"
|
||||||
|
@ -578,6 +579,75 @@ TEST(GeckoProfiler, Pause)
|
||||||
ASSERT_TRUE(!profiler_can_accept_markers());
|
ASSERT_TRUE(!profiler_can_accept_markers());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A class that keeps track of how many instances have been created, streamed,
|
||||||
|
// and destroyed.
|
||||||
|
class GTestMarkerPayload : public ProfilerMarkerPayload {
|
||||||
|
public:
|
||||||
|
explicit GTestMarkerPayload(int aN) : mN(aN) { ++sNumCreated; }
|
||||||
|
|
||||||
|
virtual ~GTestMarkerPayload() { ++sNumDestroyed; }
|
||||||
|
|
||||||
|
DECL_STREAM_PAYLOAD
|
||||||
|
|
||||||
|
private:
|
||||||
|
GTestMarkerPayload(CommonProps&& aCommonProps, int aN)
|
||||||
|
: ProfilerMarkerPayload(std::move(aCommonProps)), mN(aN) {
|
||||||
|
++sNumDeserialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mN;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// The number of GTestMarkerPayload instances that have been created,
|
||||||
|
// streamed, and destroyed.
|
||||||
|
static int sNumCreated;
|
||||||
|
static int sNumSerialized;
|
||||||
|
static int sNumDeserialized;
|
||||||
|
static int sNumStreamed;
|
||||||
|
static int sNumDestroyed;
|
||||||
|
};
|
||||||
|
|
||||||
|
int GTestMarkerPayload::sNumCreated = 0;
|
||||||
|
int GTestMarkerPayload::sNumSerialized = 0;
|
||||||
|
int GTestMarkerPayload::sNumDeserialized = 0;
|
||||||
|
int GTestMarkerPayload::sNumStreamed = 0;
|
||||||
|
int GTestMarkerPayload::sNumDestroyed = 0;
|
||||||
|
|
||||||
|
ProfileBufferEntryWriter::Length GTestMarkerPayload::TagAndSerializationBytes()
|
||||||
|
const {
|
||||||
|
return CommonPropsTagAndSerializationBytes() +
|
||||||
|
ProfileBufferEntryWriter::SumBytes(mN);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GTestMarkerPayload::SerializeTagAndPayload(
|
||||||
|
ProfileBufferEntryWriter& aEntryWriter) const {
|
||||||
|
static const DeserializerTag tag = TagForDeserializer(Deserialize);
|
||||||
|
SerializeTagAndCommonProps(tag, aEntryWriter);
|
||||||
|
aEntryWriter.WriteObject(mN);
|
||||||
|
++sNumSerialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
UniquePtr<ProfilerMarkerPayload> GTestMarkerPayload::Deserialize(
|
||||||
|
ProfileBufferEntryReader& aEntryReader) {
|
||||||
|
ProfilerMarkerPayload::CommonProps props =
|
||||||
|
DeserializeCommonProps(aEntryReader);
|
||||||
|
auto n = aEntryReader.ReadObject<int>();
|
||||||
|
return UniquePtr<ProfilerMarkerPayload>(
|
||||||
|
new GTestMarkerPayload(std::move(props), n));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GTestMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
|
||||||
|
const mozilla::TimeStamp& aStartTime,
|
||||||
|
UniqueStacks& aUniqueStacks) const {
|
||||||
|
StreamCommonProps("gtest", aWriter, aStartTime, aUniqueStacks);
|
||||||
|
char buf[64];
|
||||||
|
int written = SprintfLiteral(buf, "gtest-%d", mN);
|
||||||
|
ASSERT_GT(written, 0);
|
||||||
|
aWriter.IntProperty(mozilla::Span<const char>(buf, size_t(written)), mN);
|
||||||
|
++sNumStreamed;
|
||||||
|
}
|
||||||
|
|
||||||
TEST(GeckoProfiler, Markers)
|
TEST(GeckoProfiler, Markers)
|
||||||
{
|
{
|
||||||
uint32_t features = ProfilerFeature::StackWalk;
|
uint32_t features = ProfilerFeature::StackWalk;
|
||||||
|
@ -586,20 +656,39 @@ TEST(GeckoProfiler, Markers)
|
||||||
profiler_start(PROFILER_DEFAULT_ENTRIES, PROFILER_DEFAULT_INTERVAL, features,
|
profiler_start(PROFILER_DEFAULT_ENTRIES, PROFILER_DEFAULT_INTERVAL, features,
|
||||||
filters, MOZ_ARRAY_LENGTH(filters), 0);
|
filters, MOZ_ARRAY_LENGTH(filters), 0);
|
||||||
|
|
||||||
PROFILER_MARKER("tracing event", OTHER, {}, Tracing, "A");
|
// Used in markers below.
|
||||||
PROFILER_MARKER("tracing start", OTHER, MarkerTiming::IntervalStart(),
|
TimeStamp ts0 = TimeStamp::NowUnfuzzed();
|
||||||
Tracing, "A");
|
|
||||||
PROFILER_MARKER("tracing end", OTHER, MarkerTiming::IntervalEnd(), Tracing,
|
|
||||||
"A");
|
|
||||||
|
|
||||||
auto bt = profiler_capture_backtrace();
|
profiler_tracing_marker("A", "tracing event",
|
||||||
PROFILER_MARKER("tracing event with stack", OTHER,
|
JS::ProfilingCategoryPair::OTHER, TRACING_EVENT);
|
||||||
MarkerStack::TakeBacktrace(std::move(bt)), Tracing, "B");
|
PROFILER_TRACING_MARKER("A", "tracing start", OTHER, TRACING_INTERVAL_START);
|
||||||
|
PROFILER_TRACING_MARKER("A", "tracing end", OTHER, TRACING_INTERVAL_END);
|
||||||
|
|
||||||
|
UniqueProfilerBacktrace bt = profiler_get_backtrace();
|
||||||
|
profiler_tracing_marker("B", "tracing event with stack",
|
||||||
|
JS::ProfilingCategoryPair::OTHER, TRACING_EVENT,
|
||||||
|
std::move(bt));
|
||||||
|
|
||||||
{ AUTO_PROFILER_TRACING_MARKER("C", "auto tracing", OTHER); }
|
{ AUTO_PROFILER_TRACING_MARKER("C", "auto tracing", OTHER); }
|
||||||
|
|
||||||
PROFILER_MARKER_UNTYPED("M1", OTHER, {});
|
PROFILER_MARKER_UNTYPED("M1", OTHER, {});
|
||||||
|
PROFILER_ADD_MARKER_WITH_PAYLOAD("M2", OTHER, TracingMarkerPayload,
|
||||||
|
("C", TRACING_EVENT, ts0));
|
||||||
PROFILER_MARKER_UNTYPED("M3", OTHER, {});
|
PROFILER_MARKER_UNTYPED("M3", OTHER, {});
|
||||||
|
PROFILER_ADD_MARKER_WITH_PAYLOAD(
|
||||||
|
"M4", OTHER, TracingMarkerPayload,
|
||||||
|
("C", TRACING_EVENT, ts0, mozilla::Nothing(), profiler_get_backtrace()));
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
PROFILER_ADD_MARKER_WITH_PAYLOAD("M5", OTHER, GTestMarkerPayload, (i));
|
||||||
|
}
|
||||||
|
// The GTestMarkerPayloads should have been created, serialized, and
|
||||||
|
// destroyed.
|
||||||
|
EXPECT_EQ(GTestMarkerPayload::sNumCreated, 10);
|
||||||
|
EXPECT_EQ(GTestMarkerPayload::sNumSerialized, 10);
|
||||||
|
EXPECT_EQ(GTestMarkerPayload::sNumDeserialized, 0);
|
||||||
|
EXPECT_EQ(GTestMarkerPayload::sNumStreamed, 0);
|
||||||
|
EXPECT_EQ(GTestMarkerPayload::sNumDestroyed, 10);
|
||||||
|
|
||||||
// Create three strings: two that are the maximum allowed length, and one that
|
// Create three strings: two that are the maximum allowed length, and one that
|
||||||
// is one char longer.
|
// is one char longer.
|
||||||
|
@ -674,76 +763,111 @@ TEST(GeckoProfiler, Markers)
|
||||||
|
|
||||||
// Other markers in alphabetical order of payload class names.
|
// Other markers in alphabetical order of payload class names.
|
||||||
|
|
||||||
nsCOMPtr<nsIURI> uri;
|
{
|
||||||
ASSERT_TRUE(
|
const char gcMajorJSON[] = "42";
|
||||||
NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), "http://mozilla.org/"_ns)));
|
const auto len = strlen(gcMajorJSON);
|
||||||
// The marker name will be "Load <aChannelId>: <aURI>".
|
char* buffer =
|
||||||
profiler_add_network_marker(
|
static_cast<char*>(js::SystemAllocPolicy{}.pod_malloc<char>(len + 1));
|
||||||
/* nsIURI* aURI */ uri,
|
strncpy(buffer, gcMajorJSON, len);
|
||||||
/* const nsACString& aRequestMethod */ "GET"_ns,
|
buffer[len] = '\0';
|
||||||
/* int32_t aPriority */ 34,
|
PROFILER_ADD_MARKER_WITH_PAYLOAD("GCMajorMarkerPayload marker", OTHER,
|
||||||
/* uint64_t aChannelId */ 1,
|
GCMajorMarkerPayload,
|
||||||
/* NetworkLoadType aType */ NetworkLoadType::LOAD_START,
|
(ts1, ts2, JS::UniqueChars(buffer)));
|
||||||
/* mozilla::TimeStamp aStart */ ts1,
|
}
|
||||||
/* mozilla::TimeStamp aEnd */ ts2,
|
|
||||||
/* int64_t aCount */ 56,
|
|
||||||
/* mozilla::net::CacheDisposition aCacheDisposition */
|
|
||||||
net::kCacheHit,
|
|
||||||
/* uint64_t aInnerWindowID */ 78
|
|
||||||
/* const mozilla::net::TimingStruct* aTimings = nullptr */
|
|
||||||
/* nsIURI* aRedirectURI = nullptr */
|
|
||||||
/* mozilla::UniquePtr<mozilla::ProfileChunkedBuffer> aSource =
|
|
||||||
nullptr */
|
|
||||||
/* const mozilla::Maybe<nsDependentCString>& aContentType =
|
|
||||||
mozilla::Nothing() */);
|
|
||||||
|
|
||||||
profiler_add_network_marker(
|
{
|
||||||
/* nsIURI* aURI */ uri,
|
const char gcMinorJSON[] = "43";
|
||||||
/* const nsACString& aRequestMethod */ "GET"_ns,
|
const auto len = strlen(gcMinorJSON);
|
||||||
/* int32_t aPriority */ 34,
|
char* buffer =
|
||||||
/* uint64_t aChannelId */ 12,
|
static_cast<char*>(js::SystemAllocPolicy{}.pod_malloc<char>(len + 1));
|
||||||
/* NetworkLoadType aType */ NetworkLoadType::LOAD_STOP,
|
strncpy(buffer, gcMinorJSON, len);
|
||||||
/* mozilla::TimeStamp aStart */ ts1,
|
buffer[len] = '\0';
|
||||||
/* mozilla::TimeStamp aEnd */ ts2,
|
PROFILER_ADD_MARKER_WITH_PAYLOAD("GCMinorMarkerPayload marker", OTHER,
|
||||||
/* int64_t aCount */ 56,
|
GCMinorMarkerPayload,
|
||||||
/* mozilla::net::CacheDisposition aCacheDisposition */
|
(ts1, ts2, JS::UniqueChars(buffer)));
|
||||||
net::kCacheUnresolved,
|
}
|
||||||
/* uint64_t aInnerWindowID */ 78,
|
|
||||||
/* const mozilla::net::TimingStruct* aTimings = nullptr */ nullptr,
|
|
||||||
/* nsIURI* aRedirectURI = nullptr */ nullptr,
|
|
||||||
/* mozilla::UniquePtr<mozilla::ProfileChunkedBuffer> aSource =
|
|
||||||
nullptr */
|
|
||||||
nullptr,
|
|
||||||
/* const mozilla::Maybe<nsDependentCString>& aContentType =
|
|
||||||
mozilla::Nothing() */
|
|
||||||
Some(nsDependentCString("text/html")));
|
|
||||||
|
|
||||||
nsCOMPtr<nsIURI> redirectURI;
|
{
|
||||||
ASSERT_TRUE(NS_SUCCEEDED(
|
const char gcSliceJSON[] = "44";
|
||||||
NS_NewURI(getter_AddRefs(redirectURI), "http://example.com/"_ns)));
|
const auto len = strlen(gcSliceJSON);
|
||||||
profiler_add_network_marker(
|
char* buffer =
|
||||||
/* nsIURI* aURI */ uri,
|
static_cast<char*>(js::SystemAllocPolicy{}.pod_malloc<char>(len + 1));
|
||||||
/* const nsACString& aRequestMethod */ "GET"_ns,
|
strncpy(buffer, gcSliceJSON, len);
|
||||||
/* int32_t aPriority */ 34,
|
buffer[len] = '\0';
|
||||||
/* uint64_t aChannelId */ 123,
|
PROFILER_ADD_MARKER_WITH_PAYLOAD("GCSliceMarkerPayload marker", OTHER,
|
||||||
/* NetworkLoadType aType */ NetworkLoadType::LOAD_REDIRECT,
|
GCSliceMarkerPayload,
|
||||||
/* mozilla::TimeStamp aStart */ ts1,
|
(ts1, ts2, JS::UniqueChars(buffer)));
|
||||||
/* mozilla::TimeStamp aEnd */ ts2,
|
}
|
||||||
/* int64_t aCount */ 56,
|
|
||||||
/* mozilla::net::CacheDisposition aCacheDisposition */
|
PROFILER_ADD_MARKER_WITH_PAYLOAD("HangMarkerPayload marker", OTHER,
|
||||||
net::kCacheUnresolved,
|
HangMarkerPayload, (ts1, ts2));
|
||||||
/* uint64_t aInnerWindowID */ 78,
|
|
||||||
/* const mozilla::net::TimingStruct* aTimings = nullptr */ nullptr,
|
PROFILER_ADD_MARKER_WITH_PAYLOAD("LogMarkerPayload marker", OTHER,
|
||||||
/* nsIURI* aRedirectURI = nullptr */ redirectURI
|
LogMarkerPayload, ("module", "text", ts1));
|
||||||
/* mozilla::UniquePtr<mozilla::ProfileChunkedBuffer> aSource =
|
|
||||||
nullptr */
|
PROFILER_ADD_MARKER_WITH_PAYLOAD("LongTaskMarkerPayload marker", OTHER,
|
||||||
/* const mozilla::Maybe<nsDependentCString>& aContentType =
|
LongTaskMarkerPayload, (ts1, ts2));
|
||||||
mozilla::Nothing() */);
|
|
||||||
|
PROFILER_ADD_MARKER_WITH_PAYLOAD("NativeAllocationMarkerPayload marker",
|
||||||
|
OTHER, NativeAllocationMarkerPayload,
|
||||||
|
(ts1, 9876543210, 1234, 5678, nullptr));
|
||||||
|
|
||||||
|
nsCString requestMethod = "GET"_ns;
|
||||||
|
PROFILER_ADD_MARKER_WITH_PAYLOAD(
|
||||||
|
"NetworkMarkerPayload start marker", OTHER, NetworkMarkerPayload,
|
||||||
|
(1, "http://mozilla.org/", requestMethod, NetworkLoadType::LOAD_START,
|
||||||
|
ts1, ts2, 34, 56, net::kCacheHit, 78));
|
||||||
|
|
||||||
|
PROFILER_ADD_MARKER_WITH_PAYLOAD(
|
||||||
|
"NetworkMarkerPayload stop marker", OTHER, NetworkMarkerPayload,
|
||||||
|
(12, "http://mozilla.org/", requestMethod, NetworkLoadType::LOAD_STOP,
|
||||||
|
ts1, ts2, 34, 56, net::kCacheUnresolved, 78, nullptr, nullptr, nullptr,
|
||||||
|
Some(nsDependentCString("text/html"))));
|
||||||
|
|
||||||
|
PROFILER_ADD_MARKER_WITH_PAYLOAD(
|
||||||
|
"NetworkMarkerPayload redirect marker", OTHER, NetworkMarkerPayload,
|
||||||
|
(123, "http://mozilla.org/", requestMethod,
|
||||||
|
NetworkLoadType::LOAD_REDIRECT, ts1, ts2, 34, 56, net::kCacheUnresolved,
|
||||||
|
78, nullptr, "http://example.com/"));
|
||||||
|
|
||||||
|
PROFILER_ADD_MARKER_WITH_PAYLOAD(
|
||||||
|
"PrefMarkerPayload marker", OTHER, PrefMarkerPayload,
|
||||||
|
("preference name", mozilla::Nothing(), mozilla::Nothing(),
|
||||||
|
"preference value"_ns, ts1));
|
||||||
|
|
||||||
|
nsCString screenshotURL = "url"_ns;
|
||||||
|
PROFILER_ADD_MARKER_WITH_PAYLOAD(
|
||||||
|
"ScreenshotPayload marker", OTHER, ScreenshotPayload,
|
||||||
|
(ts1, std::move(screenshotURL), mozilla::gfx::IntSize(12, 34),
|
||||||
|
uintptr_t(0x45678u)));
|
||||||
|
|
||||||
|
PROFILER_ADD_MARKER_WITH_PAYLOAD("TextMarkerPayload marker 1", OTHER,
|
||||||
|
TextMarkerPayload, ("text"_ns, ts1));
|
||||||
|
|
||||||
|
PROFILER_ADD_MARKER_WITH_PAYLOAD("TextMarkerPayload marker 2", OTHER,
|
||||||
|
TextMarkerPayload, ("text"_ns, ts1, ts2));
|
||||||
|
|
||||||
|
PROFILER_ADD_MARKER_WITH_PAYLOAD("UserTimingMarkerPayload marker mark", OTHER,
|
||||||
|
UserTimingMarkerPayload,
|
||||||
|
(u"mark name"_ns, ts1, mozilla::Nothing()));
|
||||||
|
|
||||||
|
PROFILER_ADD_MARKER_WITH_PAYLOAD(
|
||||||
|
"UserTimingMarkerPayload marker measure", OTHER, UserTimingMarkerPayload,
|
||||||
|
(u"measure name"_ns, Some(u"start mark"_ns), Some(u"end mark"_ns), ts1,
|
||||||
|
ts2, mozilla::Nothing()));
|
||||||
|
|
||||||
|
PROFILER_ADD_MARKER_WITH_PAYLOAD("VsyncMarkerPayload marker", OTHER,
|
||||||
|
VsyncMarkerPayload, (ts1));
|
||||||
|
|
||||||
|
PROFILER_ADD_MARKER_WITH_PAYLOAD(
|
||||||
|
"IPCMarkerPayload marker", IPC, IPCMarkerPayload,
|
||||||
|
(1111, 1, 3 /* PAPZ::Msg_LayerTransforms */, mozilla::ipc::ParentSide,
|
||||||
|
mozilla::ipc::MessageDirection::eSending,
|
||||||
|
mozilla::ipc::MessagePhase::Endpoint, false, ts1));
|
||||||
|
|
||||||
MOZ_RELEASE_ASSERT(profiler_add_marker(
|
MOZ_RELEASE_ASSERT(profiler_add_marker(
|
||||||
"Text in main thread with stack", geckoprofiler::category::OTHER,
|
"Text in main thread with stack", geckoprofiler::category::OTHER,
|
||||||
{MarkerStack::Capture(), MarkerTiming::Interval(ts1, ts2)},
|
MarkerStack::Capture(), geckoprofiler::markers::Text{}, ""));
|
||||||
geckoprofiler::markers::Text{}, ""));
|
|
||||||
MOZ_RELEASE_ASSERT(profiler_add_marker(
|
MOZ_RELEASE_ASSERT(profiler_add_marker(
|
||||||
"Text from main thread with stack", geckoprofiler::category::OTHER,
|
"Text from main thread with stack", geckoprofiler::category::OTHER,
|
||||||
MarkerOptions(MarkerThreadId::MainThread(), MarkerStack::Capture()),
|
MarkerOptions(MarkerThreadId::MainThread(), MarkerStack::Capture()),
|
||||||
|
@ -784,19 +908,52 @@ TEST(GeckoProfiler, Markers)
|
||||||
profiler_add_marker("Tracing", geckoprofiler::category::OTHER, {},
|
profiler_add_marker("Tracing", geckoprofiler::category::OTHER, {},
|
||||||
geckoprofiler::markers::Tracing{}, "category"));
|
geckoprofiler::markers::Tracing{}, "category"));
|
||||||
|
|
||||||
|
MOZ_RELEASE_ASSERT(profiler_add_marker(
|
||||||
|
"UserTimingMark", geckoprofiler::category::OTHER, {},
|
||||||
|
geckoprofiler::markers::UserTimingMark{}, "mark name"));
|
||||||
|
|
||||||
|
MOZ_RELEASE_ASSERT(profiler_add_marker(
|
||||||
|
"UserTimingMeasure", geckoprofiler::category::OTHER, {},
|
||||||
|
geckoprofiler::markers::UserTimingMeasure{}, "measure name",
|
||||||
|
Some(mozilla::ProfilerString8View("start")),
|
||||||
|
Some(mozilla::ProfilerString8View("end"))));
|
||||||
|
|
||||||
|
MOZ_RELEASE_ASSERT(profiler_add_marker("Hang", geckoprofiler::category::OTHER,
|
||||||
|
{}, geckoprofiler::markers::Hang{}));
|
||||||
|
|
||||||
|
MOZ_RELEASE_ASSERT(profiler_add_marker("LongTask",
|
||||||
|
geckoprofiler::category::OTHER, {},
|
||||||
|
geckoprofiler::markers::LongTask{}));
|
||||||
|
|
||||||
MOZ_RELEASE_ASSERT(profiler_add_marker("Text", geckoprofiler::category::OTHER,
|
MOZ_RELEASE_ASSERT(profiler_add_marker("Text", geckoprofiler::category::OTHER,
|
||||||
{}, geckoprofiler::markers::Text{},
|
{}, geckoprofiler::markers::Text{},
|
||||||
"Text text"));
|
"Text text"));
|
||||||
|
|
||||||
MOZ_RELEASE_ASSERT(profiler_add_marker(
|
MOZ_RELEASE_ASSERT(profiler_add_marker("Log", geckoprofiler::category::OTHER,
|
||||||
"MediaSample", geckoprofiler::category::OTHER, {},
|
{}, geckoprofiler::markers::Log{},
|
||||||
geckoprofiler::markers::MediaSampleMarker{}, 123, 456));
|
"module", "log text"));
|
||||||
|
|
||||||
|
MOZ_RELEASE_ASSERT(
|
||||||
|
profiler_add_marker("MediaSample", geckoprofiler::category::OTHER, {},
|
||||||
|
geckoprofiler::markers::MediaSample{}, 123, 456));
|
||||||
|
|
||||||
|
MOZ_RELEASE_ASSERT(profiler_add_marker("Budget",
|
||||||
|
geckoprofiler::category::OTHER, {},
|
||||||
|
geckoprofiler::markers::Budget{}));
|
||||||
|
|
||||||
SpliceableChunkedJSONWriter w;
|
SpliceableChunkedJSONWriter w;
|
||||||
w.Start();
|
w.Start();
|
||||||
EXPECT_TRUE(::profiler_stream_json_for_this_process(w));
|
EXPECT_TRUE(::profiler_stream_json_for_this_process(w));
|
||||||
w.End();
|
w.End();
|
||||||
|
|
||||||
|
// The GTestMarkerPayloads should have been deserialized, streamed, and
|
||||||
|
// destroyed.
|
||||||
|
EXPECT_EQ(GTestMarkerPayload::sNumCreated, 10 + 0);
|
||||||
|
EXPECT_EQ(GTestMarkerPayload::sNumSerialized, 10 + 0);
|
||||||
|
EXPECT_EQ(GTestMarkerPayload::sNumDeserialized, 0 + 10);
|
||||||
|
EXPECT_EQ(GTestMarkerPayload::sNumStreamed, 0 + 10);
|
||||||
|
EXPECT_EQ(GTestMarkerPayload::sNumDestroyed, 10 + 10);
|
||||||
|
|
||||||
UniquePtr<char[]> profile = w.ChunkedWriteFunc().CopyData();
|
UniquePtr<char[]> profile = w.ChunkedWriteFunc().CopyData();
|
||||||
ASSERT_TRUE(!!profile.get());
|
ASSERT_TRUE(!!profile.get());
|
||||||
|
|
||||||
|
@ -809,15 +966,42 @@ TEST(GeckoProfiler, Markers)
|
||||||
S_tracing_auto_tracing_start,
|
S_tracing_auto_tracing_start,
|
||||||
S_tracing_auto_tracing_end,
|
S_tracing_auto_tracing_end,
|
||||||
S_M1,
|
S_M1,
|
||||||
|
S_tracing_M2_C,
|
||||||
S_M3,
|
S_M3,
|
||||||
|
S_tracing_M4_C_stack,
|
||||||
|
S_M5_gtest0,
|
||||||
|
S_M5_gtest1,
|
||||||
|
S_M5_gtest2,
|
||||||
|
S_M5_gtest3,
|
||||||
|
S_M5_gtest4,
|
||||||
|
S_M5_gtest5,
|
||||||
|
S_M5_gtest6,
|
||||||
|
S_M5_gtest7,
|
||||||
|
S_M5_gtest8,
|
||||||
|
S_M5_gtest9,
|
||||||
S_Markers2DefaultEmptyOptions,
|
S_Markers2DefaultEmptyOptions,
|
||||||
S_Markers2DefaultWithOptions,
|
S_Markers2DefaultWithOptions,
|
||||||
S_Markers2ExplicitDefaultEmptyOptions,
|
S_Markers2ExplicitDefaultEmptyOptions,
|
||||||
S_Markers2ExplicitDefaultWithOptions,
|
S_Markers2ExplicitDefaultWithOptions,
|
||||||
S_FirstMarker,
|
S_FirstMarker,
|
||||||
|
S_GCMajorMarkerPayload,
|
||||||
|
S_GCMinorMarkerPayload,
|
||||||
|
S_GCSliceMarkerPayload,
|
||||||
|
S_HangMarkerPayload,
|
||||||
|
S_LogMarkerPayload,
|
||||||
|
S_LongTaskMarkerPayload,
|
||||||
|
S_NativeAllocationMarkerPayload,
|
||||||
S_NetworkMarkerPayload_start,
|
S_NetworkMarkerPayload_start,
|
||||||
S_NetworkMarkerPayload_stop,
|
S_NetworkMarkerPayload_stop,
|
||||||
S_NetworkMarkerPayload_redirect,
|
S_NetworkMarkerPayload_redirect,
|
||||||
|
S_PrefMarkerPayload,
|
||||||
|
S_ScreenshotPayload,
|
||||||
|
S_TextMarkerPayload1,
|
||||||
|
S_TextMarkerPayload2,
|
||||||
|
S_UserTimingMarkerPayload_mark,
|
||||||
|
S_UserTimingMarkerPayload_measure,
|
||||||
|
S_VsyncMarkerPayload,
|
||||||
|
S_IPCMarkerPayload,
|
||||||
S_TextWithStack,
|
S_TextWithStack,
|
||||||
S_TextToMTWithStack,
|
S_TextToMTWithStack,
|
||||||
S_RegThread_TextToMTWithStack,
|
S_RegThread_TextToMTWithStack,
|
||||||
|
@ -1050,6 +1234,7 @@ TEST(GeckoProfiler, Markers)
|
||||||
EXPECT_EQ(typeString, "tracing");
|
EXPECT_EQ(typeString, "tracing");
|
||||||
EXPECT_TIMING_INSTANT;
|
EXPECT_TIMING_INSTANT;
|
||||||
EXPECT_EQ_JSON(payload["category"], String, "A");
|
EXPECT_EQ_JSON(payload["category"], String, "A");
|
||||||
|
EXPECT_TRUE(payload["interval"].isNull());
|
||||||
EXPECT_TRUE(payload["stack"].isNull());
|
EXPECT_TRUE(payload["stack"].isNull());
|
||||||
|
|
||||||
} else if (nameString == "tracing start") {
|
} else if (nameString == "tracing start") {
|
||||||
|
@ -1058,6 +1243,7 @@ TEST(GeckoProfiler, Markers)
|
||||||
EXPECT_EQ(typeString, "tracing");
|
EXPECT_EQ(typeString, "tracing");
|
||||||
EXPECT_TIMING_START;
|
EXPECT_TIMING_START;
|
||||||
EXPECT_EQ_JSON(payload["category"], String, "A");
|
EXPECT_EQ_JSON(payload["category"], String, "A");
|
||||||
|
EXPECT_EQ_JSON(payload["interval"], String, "start");
|
||||||
EXPECT_TRUE(payload["stack"].isNull());
|
EXPECT_TRUE(payload["stack"].isNull());
|
||||||
|
|
||||||
} else if (nameString == "tracing end") {
|
} else if (nameString == "tracing end") {
|
||||||
|
@ -1066,6 +1252,7 @@ TEST(GeckoProfiler, Markers)
|
||||||
EXPECT_EQ(typeString, "tracing");
|
EXPECT_EQ(typeString, "tracing");
|
||||||
EXPECT_TIMING_END;
|
EXPECT_TIMING_END;
|
||||||
EXPECT_EQ_JSON(payload["category"], String, "A");
|
EXPECT_EQ_JSON(payload["category"], String, "A");
|
||||||
|
EXPECT_EQ_JSON(payload["interval"], String, "end");
|
||||||
EXPECT_TRUE(payload["stack"].isNull());
|
EXPECT_TRUE(payload["stack"].isNull());
|
||||||
|
|
||||||
} else if (nameString == "tracing event with stack") {
|
} else if (nameString == "tracing event with stack") {
|
||||||
|
@ -1074,6 +1261,7 @@ TEST(GeckoProfiler, Markers)
|
||||||
EXPECT_EQ(typeString, "tracing");
|
EXPECT_EQ(typeString, "tracing");
|
||||||
EXPECT_TIMING_INSTANT;
|
EXPECT_TIMING_INSTANT;
|
||||||
EXPECT_EQ_JSON(payload["category"], String, "B");
|
EXPECT_EQ_JSON(payload["category"], String, "B");
|
||||||
|
EXPECT_TRUE(payload["interval"].isNull());
|
||||||
EXPECT_TRUE(payload["stack"].isObject());
|
EXPECT_TRUE(payload["stack"].isObject());
|
||||||
|
|
||||||
} else if (nameString == "auto tracing") {
|
} else if (nameString == "auto tracing") {
|
||||||
|
@ -1083,6 +1271,7 @@ TEST(GeckoProfiler, Markers)
|
||||||
EXPECT_EQ(typeString, "tracing");
|
EXPECT_EQ(typeString, "tracing");
|
||||||
EXPECT_TIMING_START;
|
EXPECT_TIMING_START;
|
||||||
EXPECT_EQ_JSON(payload["category"], String, "C");
|
EXPECT_EQ_JSON(payload["category"], String, "C");
|
||||||
|
EXPECT_EQ_JSON(payload["interval"], String, "start");
|
||||||
EXPECT_TRUE(payload["stack"].isNull());
|
EXPECT_TRUE(payload["stack"].isNull());
|
||||||
break;
|
break;
|
||||||
case S_tracing_auto_tracing_end:
|
case S_tracing_auto_tracing_end:
|
||||||
|
@ -1090,6 +1279,7 @@ TEST(GeckoProfiler, Markers)
|
||||||
EXPECT_EQ(typeString, "tracing");
|
EXPECT_EQ(typeString, "tracing");
|
||||||
EXPECT_TIMING_END;
|
EXPECT_TIMING_END;
|
||||||
EXPECT_EQ_JSON(payload["category"], String, "C");
|
EXPECT_EQ_JSON(payload["category"], String, "C");
|
||||||
|
EXPECT_EQ_JSON(payload["interval"], String, "end");
|
||||||
ASSERT_TRUE(payload["stack"].isNull());
|
ASSERT_TRUE(payload["stack"].isNull());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -1098,6 +1288,43 @@ TEST(GeckoProfiler, Markers)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else if (nameString == "M2") {
|
||||||
|
EXPECT_EQ(state, S_tracing_M2_C);
|
||||||
|
state = State(S_tracing_M2_C + 1);
|
||||||
|
EXPECT_EQ(typeString, "tracing");
|
||||||
|
EXPECT_TIMING_INSTANT;
|
||||||
|
EXPECT_EQ_JSON(payload["category"], String, "C");
|
||||||
|
EXPECT_TRUE(payload["interval"].isNull());
|
||||||
|
EXPECT_TRUE(payload["stack"].isNull());
|
||||||
|
|
||||||
|
} else if (nameString == "M4") {
|
||||||
|
EXPECT_EQ(state, S_tracing_M4_C_stack);
|
||||||
|
state = State(S_tracing_M4_C_stack + 1);
|
||||||
|
EXPECT_EQ(typeString, "tracing");
|
||||||
|
EXPECT_TIMING_INSTANT;
|
||||||
|
EXPECT_EQ_JSON(payload["category"], String, "C");
|
||||||
|
EXPECT_TRUE(payload["interval"].isNull());
|
||||||
|
EXPECT_TRUE(payload["stack"].isObject());
|
||||||
|
|
||||||
|
} else if (nameString == "M5") {
|
||||||
|
EXPECT_EQ(typeString, "gtest");
|
||||||
|
// It should only have one more element (apart from "type").
|
||||||
|
ASSERT_EQ(payload.size(), 2u);
|
||||||
|
const auto itEnd = payload.end();
|
||||||
|
for (auto it = payload.begin(); it != itEnd; ++it) {
|
||||||
|
std::string key = it.name();
|
||||||
|
if (key != "type") {
|
||||||
|
const Json::Value& value = *it;
|
||||||
|
ASSERT_TRUE(value.isInt());
|
||||||
|
int valueInt = value.asInt();
|
||||||
|
// We expect `"gtest-<i>" : <i>`.
|
||||||
|
EXPECT_EQ(state, State(S_M5_gtest0 + valueInt));
|
||||||
|
state = State(state + 1);
|
||||||
|
EXPECT_EQ(key,
|
||||||
|
std::string("gtest-") + std::to_string(valueInt));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} else if (nameString ==
|
} else if (nameString ==
|
||||||
"default-templated markers 2.0 with option") {
|
"default-templated markers 2.0 with option") {
|
||||||
// TODO: Remove this when bug 1646714 lands.
|
// TODO: Remove this when bug 1646714 lands.
|
||||||
|
@ -1113,43 +1340,94 @@ TEST(GeckoProfiler, Markers)
|
||||||
ts1Double = marker[START_TIME].asDouble();
|
ts1Double = marker[START_TIME].asDouble();
|
||||||
ts2Double = marker[END_TIME].asDouble();
|
ts2Double = marker[END_TIME].asDouble();
|
||||||
state = State(S_FirstMarker + 1);
|
state = State(S_FirstMarker + 1);
|
||||||
|
} else if (nameString == "GCMajorMarkerPayload marker") {
|
||||||
|
EXPECT_EQ(state, S_GCMajorMarkerPayload);
|
||||||
|
state = State(S_GCMajorMarkerPayload + 1);
|
||||||
|
EXPECT_EQ(typeString, "GCMajor");
|
||||||
|
EXPECT_TIMING_INTERVAL_AT(ts1Double, ts2Double);
|
||||||
|
EXPECT_TRUE(payload["stack"].isNull());
|
||||||
|
EXPECT_EQ_JSON(payload["timings"], Int, 42);
|
||||||
|
|
||||||
} else if (nameString == "Load 1: http://mozilla.org/") {
|
} else if (nameString == "GCMinorMarkerPayload marker") {
|
||||||
|
EXPECT_EQ(state, S_GCMinorMarkerPayload);
|
||||||
|
state = State(S_GCMinorMarkerPayload + 1);
|
||||||
|
EXPECT_EQ(typeString, "GCMinor");
|
||||||
|
EXPECT_TIMING_INTERVAL_AT(ts1Double, ts2Double);
|
||||||
|
EXPECT_TRUE(payload["stack"].isNull());
|
||||||
|
EXPECT_EQ_JSON(payload["nursery"], Int, 43);
|
||||||
|
|
||||||
|
} else if (nameString == "GCSliceMarkerPayload marker") {
|
||||||
|
EXPECT_EQ(state, S_GCSliceMarkerPayload);
|
||||||
|
state = State(S_GCSliceMarkerPayload + 1);
|
||||||
|
EXPECT_EQ(typeString, "GCSlice");
|
||||||
|
EXPECT_TIMING_INTERVAL_AT(ts1Double, ts2Double);
|
||||||
|
EXPECT_TRUE(payload["stack"].isNull());
|
||||||
|
EXPECT_EQ_JSON(payload["timings"], Int, 44);
|
||||||
|
|
||||||
|
} else if (nameString == "HangMarkerPayload marker") {
|
||||||
|
EXPECT_EQ(state, S_HangMarkerPayload);
|
||||||
|
state = State(S_HangMarkerPayload + 1);
|
||||||
|
EXPECT_EQ(typeString, "BHR-detected hang");
|
||||||
|
EXPECT_TIMING_INTERVAL_AT(ts1Double, ts2Double);
|
||||||
|
EXPECT_TRUE(payload["stack"].isNull());
|
||||||
|
|
||||||
|
} else if (nameString == "LogMarkerPayload marker") {
|
||||||
|
EXPECT_EQ(state, S_LogMarkerPayload);
|
||||||
|
state = State(S_LogMarkerPayload + 1);
|
||||||
|
EXPECT_EQ(typeString, "Log");
|
||||||
|
EXPECT_TIMING_INSTANT_AT(ts1Double);
|
||||||
|
EXPECT_TRUE(payload["stack"].isNull());
|
||||||
|
EXPECT_EQ_JSON(payload["name"], String, "text");
|
||||||
|
EXPECT_EQ_JSON(payload["module"], String, "module");
|
||||||
|
|
||||||
|
} else if (nameString == "LongTaskMarkerPayload marker") {
|
||||||
|
EXPECT_EQ(state, S_LongTaskMarkerPayload);
|
||||||
|
state = State(S_LongTaskMarkerPayload + 1);
|
||||||
|
EXPECT_EQ(typeString, "MainThreadLongTask");
|
||||||
|
EXPECT_TIMING_INTERVAL_AT(ts1Double, ts2Double);
|
||||||
|
EXPECT_TRUE(payload["stack"].isNull());
|
||||||
|
EXPECT_EQ_JSON(payload["category"], String, "LongTask");
|
||||||
|
|
||||||
|
} else if (nameString == "NativeAllocationMarkerPayload marker") {
|
||||||
|
EXPECT_EQ(state, S_NativeAllocationMarkerPayload);
|
||||||
|
state = State(S_NativeAllocationMarkerPayload + 1);
|
||||||
|
EXPECT_EQ(typeString, "Native allocation");
|
||||||
|
EXPECT_TIMING_INSTANT_AT(ts1Double);
|
||||||
|
EXPECT_TRUE(payload["stack"].isNull());
|
||||||
|
EXPECT_EQ_JSON(payload["size"], Int64, 9876543210);
|
||||||
|
EXPECT_EQ_JSON(payload["memoryAddress"], Int64, 1234);
|
||||||
|
EXPECT_EQ_JSON(payload["threadId"], Int64, 5678);
|
||||||
|
|
||||||
|
} else if (nameString == "NetworkMarkerPayload start marker") {
|
||||||
EXPECT_EQ(state, S_NetworkMarkerPayload_start);
|
EXPECT_EQ(state, S_NetworkMarkerPayload_start);
|
||||||
state = State(S_NetworkMarkerPayload_start + 1);
|
state = State(S_NetworkMarkerPayload_start + 1);
|
||||||
EXPECT_EQ(typeString, "Network");
|
EXPECT_EQ(typeString, "Network");
|
||||||
EXPECT_EQ_JSON(payload["startTime"], Double, ts1Double);
|
|
||||||
EXPECT_EQ_JSON(payload["endTime"], Double, ts2Double);
|
|
||||||
EXPECT_EQ_JSON(payload["id"], Int64, 1);
|
EXPECT_EQ_JSON(payload["id"], Int64, 1);
|
||||||
EXPECT_EQ_JSON(payload["URI"], String, "http://mozilla.org/");
|
EXPECT_EQ_JSON(payload["URI"], String, "http://mozilla.org/");
|
||||||
EXPECT_EQ_JSON(payload["requestMethod"], String, "GET");
|
EXPECT_EQ_JSON(payload["requestMethod"], String, "GET");
|
||||||
EXPECT_EQ_JSON(payload["pri"], Int64, 34);
|
EXPECT_EQ_JSON(payload["pri"], Int64, 34);
|
||||||
EXPECT_EQ_JSON(payload["count"], Int64, 56);
|
EXPECT_EQ_JSON(payload["count"], Int64, 56);
|
||||||
EXPECT_EQ_JSON(payload["cache"], String, "Hit");
|
EXPECT_EQ_JSON(payload["cache"], String, "Hit");
|
||||||
EXPECT_TRUE(payload["RedirectURI"].isNull());
|
EXPECT_EQ_JSON(payload["RedirectURI"], String, "");
|
||||||
EXPECT_TRUE(payload["contentType"].isNull());
|
EXPECT_TRUE(payload["contentType"].isNull());
|
||||||
|
|
||||||
} else if (nameString == "Load 12: http://mozilla.org/") {
|
} else if (nameString == "NetworkMarkerPayload stop marker") {
|
||||||
EXPECT_EQ(state, S_NetworkMarkerPayload_stop);
|
EXPECT_EQ(state, S_NetworkMarkerPayload_stop);
|
||||||
state = State(S_NetworkMarkerPayload_stop + 1);
|
state = State(S_NetworkMarkerPayload_stop + 1);
|
||||||
EXPECT_EQ(typeString, "Network");
|
EXPECT_EQ(typeString, "Network");
|
||||||
EXPECT_EQ_JSON(payload["startTime"], Double, ts1Double);
|
|
||||||
EXPECT_EQ_JSON(payload["endTime"], Double, ts2Double);
|
|
||||||
EXPECT_EQ_JSON(payload["id"], Int64, 12);
|
EXPECT_EQ_JSON(payload["id"], Int64, 12);
|
||||||
EXPECT_EQ_JSON(payload["URI"], String, "http://mozilla.org/");
|
EXPECT_EQ_JSON(payload["URI"], String, "http://mozilla.org/");
|
||||||
EXPECT_EQ_JSON(payload["requestMethod"], String, "GET");
|
EXPECT_EQ_JSON(payload["requestMethod"], String, "GET");
|
||||||
EXPECT_EQ_JSON(payload["pri"], Int64, 34);
|
EXPECT_EQ_JSON(payload["pri"], Int64, 34);
|
||||||
EXPECT_EQ_JSON(payload["count"], Int64, 56);
|
EXPECT_EQ_JSON(payload["count"], Int64, 56);
|
||||||
EXPECT_EQ_JSON(payload["cache"], String, "Unresolved");
|
EXPECT_EQ_JSON(payload["cache"], String, "Unresolved");
|
||||||
EXPECT_TRUE(payload["RedirectURI"].isNull());
|
EXPECT_EQ_JSON(payload["RedirectURI"], String, "");
|
||||||
EXPECT_EQ_JSON(payload["contentType"], String, "text/html");
|
EXPECT_EQ_JSON(payload["contentType"], String, "text/html");
|
||||||
|
|
||||||
} else if (nameString == "Load 123: http://mozilla.org/") {
|
} else if (nameString == "NetworkMarkerPayload redirect marker") {
|
||||||
EXPECT_EQ(state, S_NetworkMarkerPayload_redirect);
|
EXPECT_EQ(state, S_NetworkMarkerPayload_redirect);
|
||||||
state = State(S_NetworkMarkerPayload_redirect + 1);
|
state = State(S_NetworkMarkerPayload_redirect + 1);
|
||||||
EXPECT_EQ(typeString, "Network");
|
EXPECT_EQ(typeString, "Network");
|
||||||
EXPECT_EQ_JSON(payload["startTime"], Double, ts1Double);
|
|
||||||
EXPECT_EQ_JSON(payload["endTime"], Double, ts2Double);
|
|
||||||
EXPECT_EQ_JSON(payload["id"], Int64, 123);
|
EXPECT_EQ_JSON(payload["id"], Int64, 123);
|
||||||
EXPECT_EQ_JSON(payload["URI"], String, "http://mozilla.org/");
|
EXPECT_EQ_JSON(payload["URI"], String, "http://mozilla.org/");
|
||||||
EXPECT_EQ_JSON(payload["requestMethod"], String, "GET");
|
EXPECT_EQ_JSON(payload["requestMethod"], String, "GET");
|
||||||
|
@ -1160,12 +1438,100 @@ TEST(GeckoProfiler, Markers)
|
||||||
"http://example.com/");
|
"http://example.com/");
|
||||||
EXPECT_TRUE(payload["contentType"].isNull());
|
EXPECT_TRUE(payload["contentType"].isNull());
|
||||||
|
|
||||||
|
} else if (nameString == "PrefMarkerPayload marker") {
|
||||||
|
EXPECT_EQ(state, S_PrefMarkerPayload);
|
||||||
|
state = State(S_PrefMarkerPayload + 1);
|
||||||
|
EXPECT_EQ(typeString, "PreferenceRead");
|
||||||
|
EXPECT_TIMING_INSTANT_AT(ts1Double);
|
||||||
|
EXPECT_TRUE(payload["stack"].isNull());
|
||||||
|
EXPECT_EQ_JSON(payload["prefAccessTime"], Double, ts1Double);
|
||||||
|
EXPECT_EQ_JSON(payload["prefName"], String, "preference name");
|
||||||
|
EXPECT_EQ_JSON(payload["prefKind"], String, "Shared");
|
||||||
|
EXPECT_EQ_JSON(payload["prefType"], String,
|
||||||
|
"Preference not found");
|
||||||
|
EXPECT_EQ_JSON(payload["prefValue"], String,
|
||||||
|
"preference value");
|
||||||
|
|
||||||
|
} else if (nameString == "ScreenshotPayload marker") {
|
||||||
|
EXPECT_EQ(state, S_ScreenshotPayload);
|
||||||
|
state = State(S_ScreenshotPayload + 1);
|
||||||
|
EXPECT_EQ(typeString, "CompositorScreenshot");
|
||||||
|
EXPECT_EQ_STRINGTABLE(payload["url"], "url");
|
||||||
|
EXPECT_EQ_JSON(payload["windowID"], String, "0x45678");
|
||||||
|
EXPECT_EQ_JSON(payload["windowWidth"], Int, 12);
|
||||||
|
EXPECT_EQ_JSON(payload["windowHeight"], Int, 34);
|
||||||
|
|
||||||
|
} else if (nameString == "TextMarkerPayload marker 1") {
|
||||||
|
EXPECT_EQ(state, S_TextMarkerPayload1);
|
||||||
|
state = State(S_TextMarkerPayload1 + 1);
|
||||||
|
EXPECT_EQ(typeString, "Text");
|
||||||
|
EXPECT_TIMING_INSTANT_AT(ts1Double);
|
||||||
|
EXPECT_TRUE(payload["stack"].isNull());
|
||||||
|
EXPECT_EQ_JSON(payload["name"], String, "text");
|
||||||
|
|
||||||
|
} else if (nameString == "TextMarkerPayload marker 2") {
|
||||||
|
EXPECT_EQ(state, S_TextMarkerPayload2);
|
||||||
|
state = State(S_TextMarkerPayload2 + 1);
|
||||||
|
EXPECT_EQ(typeString, "Text");
|
||||||
|
EXPECT_TIMING_INTERVAL_AT(ts1Double, ts2Double);
|
||||||
|
EXPECT_TRUE(payload["stack"].isNull());
|
||||||
|
EXPECT_EQ_JSON(payload["name"], String, "text");
|
||||||
|
|
||||||
|
} else if (nameString == "UserTimingMarkerPayload marker mark") {
|
||||||
|
EXPECT_EQ(state, S_UserTimingMarkerPayload_mark);
|
||||||
|
state = State(S_UserTimingMarkerPayload_mark + 1);
|
||||||
|
EXPECT_EQ(typeString, "UserTiming");
|
||||||
|
EXPECT_TIMING_INSTANT_AT(ts1Double);
|
||||||
|
EXPECT_TRUE(payload["stack"].isNull());
|
||||||
|
EXPECT_EQ_JSON(payload["name"], String, "mark name");
|
||||||
|
EXPECT_EQ_JSON(payload["entryType"], String, "mark");
|
||||||
|
|
||||||
|
} else if (nameString ==
|
||||||
|
"UserTimingMarkerPayload marker measure") {
|
||||||
|
EXPECT_EQ(state, S_UserTimingMarkerPayload_measure);
|
||||||
|
state = State(S_UserTimingMarkerPayload_measure + 1);
|
||||||
|
EXPECT_EQ(typeString, "UserTiming");
|
||||||
|
EXPECT_TIMING_INTERVAL_AT(ts1Double, ts2Double);
|
||||||
|
EXPECT_TRUE(payload["stack"].isNull());
|
||||||
|
EXPECT_EQ_JSON(payload["name"], String, "measure name");
|
||||||
|
EXPECT_EQ_JSON(payload["entryType"], String, "measure");
|
||||||
|
EXPECT_EQ_JSON(payload["startMark"], String, "start mark");
|
||||||
|
EXPECT_EQ_JSON(payload["endMark"], String, "end mark");
|
||||||
|
|
||||||
|
} else if (nameString == "VsyncMarkerPayload marker") {
|
||||||
|
EXPECT_EQ(state, S_VsyncMarkerPayload);
|
||||||
|
state = State(S_VsyncMarkerPayload + 1);
|
||||||
|
EXPECT_EQ(typeString, "VsyncTimestamp");
|
||||||
|
// Timestamp is stored in marker outside of payload.
|
||||||
|
EXPECT_TIMING_INSTANT_AT(ts1Double);
|
||||||
|
EXPECT_TRUE(payload["stack"].isNull());
|
||||||
|
|
||||||
|
} else if (nameString == "IPCMarkerPayload marker") {
|
||||||
|
EXPECT_EQ(state, S_IPCMarkerPayload);
|
||||||
|
state = State(S_IPCMarkerPayload + 1);
|
||||||
|
EXPECT_EQ(typeString, "IPC");
|
||||||
|
EXPECT_TIMING_INSTANT_AT(ts1Double);
|
||||||
|
|
||||||
|
// The startTime and endTime are currently duplicated in the
|
||||||
|
// payload.
|
||||||
|
EXPECT_EQ_JSON(payload["startTime"], Double, ts1Double);
|
||||||
|
EXPECT_EQ_JSON(payload["endTime"], Double, ts1Double);
|
||||||
|
|
||||||
|
EXPECT_TRUE(payload["stack"].isNull());
|
||||||
|
EXPECT_EQ_JSON(payload["otherPid"], Int, 1111);
|
||||||
|
EXPECT_EQ_JSON(payload["messageSeqno"], Int, 1);
|
||||||
|
EXPECT_EQ_JSON(payload["messageType"], String,
|
||||||
|
"PAPZ::Msg_LayerTransforms");
|
||||||
|
EXPECT_EQ_JSON(payload["side"], String, "parent");
|
||||||
|
EXPECT_EQ_JSON(payload["direction"], String, "sending");
|
||||||
|
EXPECT_EQ_JSON(payload["phase"], String, "endpoint");
|
||||||
|
EXPECT_EQ_JSON(payload["sync"], Bool, false);
|
||||||
|
|
||||||
} else if (nameString == "Text in main thread with stack") {
|
} else if (nameString == "Text in main thread with stack") {
|
||||||
EXPECT_EQ(state, S_TextWithStack);
|
EXPECT_EQ(state, S_TextWithStack);
|
||||||
state = State(S_TextWithStack + 1);
|
state = State(S_TextWithStack + 1);
|
||||||
EXPECT_EQ(typeString, "Text");
|
EXPECT_EQ(typeString, "Text");
|
||||||
EXPECT_FALSE(payload["stack"].isNull());
|
EXPECT_FALSE(payload["stack"].isNull());
|
||||||
EXPECT_TIMING_INTERVAL_AT(ts1Double, ts2Double);
|
|
||||||
EXPECT_EQ_JSON(payload["name"], String, "");
|
EXPECT_EQ_JSON(payload["name"], String, "");
|
||||||
|
|
||||||
} else if (nameString == "Text from main thread with stack") {
|
} else if (nameString == "Text from main thread with stack") {
|
||||||
|
@ -1278,6 +1644,70 @@ TEST(GeckoProfiler, Markers)
|
||||||
EXPECT_EQ_JSON(data[0u]["label"], String, "Type");
|
EXPECT_EQ_JSON(data[0u]["label"], String, "Type");
|
||||||
EXPECT_EQ_JSON(data[0u]["format"], String, "string");
|
EXPECT_EQ_JSON(data[0u]["format"], String, "string");
|
||||||
|
|
||||||
|
} else if (nameString == "UserTimingMark") {
|
||||||
|
EXPECT_EQ(display.size(), 2u);
|
||||||
|
EXPECT_EQ(display[0u].asString(), "marker-chart");
|
||||||
|
EXPECT_EQ(display[1u].asString(), "marker-table");
|
||||||
|
|
||||||
|
ASSERT_EQ(data.size(), 4u);
|
||||||
|
|
||||||
|
ASSERT_TRUE(data[0u].isObject());
|
||||||
|
EXPECT_EQ_JSON(data[0u]["label"], String, "Marker");
|
||||||
|
EXPECT_EQ_JSON(data[0u]["value"], String, "UserTiming");
|
||||||
|
|
||||||
|
ASSERT_TRUE(data[1u].isObject());
|
||||||
|
EXPECT_EQ_JSON(data[1u]["key"], String, "entryType");
|
||||||
|
EXPECT_EQ_JSON(data[1u]["label"], String, "Entry Type");
|
||||||
|
EXPECT_EQ_JSON(data[1u]["format"], String, "string");
|
||||||
|
|
||||||
|
ASSERT_TRUE(data[2u].isObject());
|
||||||
|
EXPECT_EQ_JSON(data[2u]["key"], String, "name");
|
||||||
|
EXPECT_EQ_JSON(data[2u]["label"], String, "Name");
|
||||||
|
EXPECT_EQ_JSON(data[2u]["format"], String, "string");
|
||||||
|
|
||||||
|
ASSERT_TRUE(data[3u].isObject());
|
||||||
|
EXPECT_EQ_JSON(data[3u]["label"], String, "Description");
|
||||||
|
EXPECT_EQ_JSON(data[3u]["value"], String,
|
||||||
|
"UserTimingMark is created using the DOM API "
|
||||||
|
"performance.mark().");
|
||||||
|
|
||||||
|
} else if (nameString == "UserTimingMeasure") {
|
||||||
|
EXPECT_EQ(display.size(), 2u);
|
||||||
|
EXPECT_EQ(display[0u].asString(), "marker-chart");
|
||||||
|
EXPECT_EQ(display[1u].asString(), "marker-table");
|
||||||
|
|
||||||
|
ASSERT_EQ(data.size(), 6u);
|
||||||
|
|
||||||
|
ASSERT_TRUE(data[0u].isObject());
|
||||||
|
EXPECT_EQ_JSON(data[0u]["label"], String, "Marker");
|
||||||
|
EXPECT_EQ_JSON(data[0u]["value"], String, "UserTiming");
|
||||||
|
|
||||||
|
ASSERT_TRUE(data[1u].isObject());
|
||||||
|
EXPECT_EQ_JSON(data[1u]["key"], String, "entryType");
|
||||||
|
EXPECT_EQ_JSON(data[1u]["label"], String, "Entry Type");
|
||||||
|
EXPECT_EQ_JSON(data[1u]["format"], String, "string");
|
||||||
|
|
||||||
|
ASSERT_TRUE(data[2u].isObject());
|
||||||
|
EXPECT_EQ_JSON(data[2u]["key"], String, "name");
|
||||||
|
EXPECT_EQ_JSON(data[2u]["label"], String, "Name");
|
||||||
|
EXPECT_EQ_JSON(data[2u]["format"], String, "string");
|
||||||
|
|
||||||
|
ASSERT_TRUE(data[3u].isObject());
|
||||||
|
EXPECT_EQ_JSON(data[3u]["key"], String, "startMark");
|
||||||
|
EXPECT_EQ_JSON(data[3u]["label"], String, "Start Mark");
|
||||||
|
EXPECT_EQ_JSON(data[3u]["format"], String, "string");
|
||||||
|
|
||||||
|
ASSERT_TRUE(data[4u].isObject());
|
||||||
|
EXPECT_EQ_JSON(data[4u]["key"], String, "endMark");
|
||||||
|
EXPECT_EQ_JSON(data[4u]["label"], String, "End Mark");
|
||||||
|
EXPECT_EQ_JSON(data[4u]["format"], String, "string");
|
||||||
|
|
||||||
|
ASSERT_TRUE(data[5u].isObject());
|
||||||
|
EXPECT_EQ_JSON(data[5u]["label"], String, "Description");
|
||||||
|
EXPECT_EQ_JSON(data[5u]["value"], String,
|
||||||
|
"UserTimingMeasure is created using the DOM API "
|
||||||
|
"performance.measure().");
|
||||||
|
|
||||||
} else if (nameString == "BHR-detected hang") {
|
} else if (nameString == "BHR-detected hang") {
|
||||||
EXPECT_EQ(display.size(), 3u);
|
EXPECT_EQ(display.size(), 3u);
|
||||||
EXPECT_EQ(display[0u].asString(), "marker-chart");
|
EXPECT_EQ(display[0u].asString(), "marker-chart");
|
||||||
|
@ -1347,8 +1777,18 @@ TEST(GeckoProfiler, Markers)
|
||||||
// Check that we've got all expected schema.
|
// Check that we've got all expected schema.
|
||||||
EXPECT_TRUE(testedSchemaNames.find("Text") != testedSchemaNames.end());
|
EXPECT_TRUE(testedSchemaNames.find("Text") != testedSchemaNames.end());
|
||||||
EXPECT_TRUE(testedSchemaNames.find("tracing") != testedSchemaNames.end());
|
EXPECT_TRUE(testedSchemaNames.find("tracing") != testedSchemaNames.end());
|
||||||
|
EXPECT_TRUE(testedSchemaNames.find("UserTimingMark") !=
|
||||||
|
testedSchemaNames.end());
|
||||||
|
EXPECT_TRUE(testedSchemaNames.find("UserTimingMeasure") !=
|
||||||
|
testedSchemaNames.end());
|
||||||
|
EXPECT_TRUE(testedSchemaNames.find("BHR-detected hang") !=
|
||||||
|
testedSchemaNames.end());
|
||||||
|
EXPECT_TRUE(testedSchemaNames.find("MainThreadLongTask") !=
|
||||||
|
testedSchemaNames.end());
|
||||||
|
EXPECT_TRUE(testedSchemaNames.find("Log") != testedSchemaNames.end());
|
||||||
EXPECT_TRUE(testedSchemaNames.find("MediaSample") !=
|
EXPECT_TRUE(testedSchemaNames.find("MediaSample") !=
|
||||||
testedSchemaNames.end());
|
testedSchemaNames.end());
|
||||||
|
EXPECT_TRUE(testedSchemaNames.find("Budget") != testedSchemaNames.end());
|
||||||
} // markerSchema
|
} // markerSchema
|
||||||
} // meta
|
} // meta
|
||||||
|
|
||||||
|
@ -1383,27 +1823,70 @@ TEST(GeckoProfiler, Markers)
|
||||||
|
|
||||||
profiler_stop();
|
profiler_stop();
|
||||||
|
|
||||||
|
// Nothing more should have happened to the GTestMarkerPayloads.
|
||||||
|
EXPECT_EQ(GTestMarkerPayload::sNumCreated, 10 + 0 + 0);
|
||||||
|
EXPECT_EQ(GTestMarkerPayload::sNumSerialized, 10 + 0 + 0);
|
||||||
|
EXPECT_EQ(GTestMarkerPayload::sNumDeserialized, 0 + 10 + 0);
|
||||||
|
EXPECT_EQ(GTestMarkerPayload::sNumStreamed, 0 + 10 + 0);
|
||||||
|
EXPECT_EQ(GTestMarkerPayload::sNumDestroyed, 10 + 10 + 0);
|
||||||
|
|
||||||
// Try to add markers while the profiler is stopped.
|
// Try to add markers while the profiler is stopped.
|
||||||
PROFILER_MARKER_UNTYPED("marker after profiler_stop", OTHER);
|
for (int i = 0; i < 10; i++) {
|
||||||
|
PROFILER_ADD_MARKER_WITH_PAYLOAD("M5", OTHER, GTestMarkerPayload, (i));
|
||||||
|
}
|
||||||
|
|
||||||
// Warning: this could be racy
|
// Warning: this could be racy
|
||||||
profiler_start(PROFILER_DEFAULT_ENTRIES, PROFILER_DEFAULT_INTERVAL, features,
|
profiler_start(PROFILER_DEFAULT_ENTRIES, PROFILER_DEFAULT_INTERVAL, features,
|
||||||
filters, MOZ_ARRAY_LENGTH(filters), 0);
|
filters, MOZ_ARRAY_LENGTH(filters), 0);
|
||||||
|
|
||||||
// This last marker shouldn't get streamed.
|
EXPECT_TRUE(::profiler_stream_json_for_this_process(w));
|
||||||
SpliceableChunkedJSONWriter w2;
|
|
||||||
w2.Start();
|
|
||||||
EXPECT_TRUE(::profiler_stream_json_for_this_process(w2));
|
|
||||||
w2.End();
|
|
||||||
UniquePtr<char[]> profile2 = w.ChunkedWriteFunc().CopyData();
|
|
||||||
ASSERT_TRUE(!!profile2.get());
|
|
||||||
EXPECT_TRUE(
|
|
||||||
std::string_view(profile2.get()).find("marker after profiler_stop") ==
|
|
||||||
std::string_view::npos);
|
|
||||||
|
|
||||||
profiler_stop();
|
profiler_stop();
|
||||||
|
|
||||||
|
// The second set of GTestMarkerPayloads should not have been serialized or
|
||||||
|
// streamed.
|
||||||
|
EXPECT_EQ(GTestMarkerPayload::sNumCreated, 10 + 0 + 0 + 10);
|
||||||
|
EXPECT_EQ(GTestMarkerPayload::sNumSerialized, 10 + 0 + 0 + 0);
|
||||||
|
EXPECT_EQ(GTestMarkerPayload::sNumDeserialized, 0 + 10 + 0 + 0);
|
||||||
|
EXPECT_EQ(GTestMarkerPayload::sNumStreamed, 0 + 10 + 0 + 0);
|
||||||
|
EXPECT_EQ(GTestMarkerPayload::sNumDestroyed, 10 + 10 + 0 + 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The duration limit will be removed from Firefox, see bug 1632365.
|
||||||
|
#if 0
|
||||||
|
TEST(GeckoProfiler, DurationLimit)
|
||||||
|
{
|
||||||
|
uint32_t features = ProfilerFeature::StackWalk;
|
||||||
|
const char* filters[] = {"GeckoMain"};
|
||||||
|
|
||||||
|
profiler_start(PROFILER_DEFAULT_ENTRIES, PROFILER_DEFAULT_INTERVAL, features,
|
||||||
|
filters, MOZ_ARRAY_LENGTH(filters), 0, Some(1.5));
|
||||||
|
|
||||||
|
// Clear up the counters after the last test.
|
||||||
|
GTestMarkerPayload::sNumCreated = 0;
|
||||||
|
GTestMarkerPayload::sNumSerialized = 0;
|
||||||
|
GTestMarkerPayload::sNumDeserialized = 0;
|
||||||
|
GTestMarkerPayload::sNumStreamed = 0;
|
||||||
|
GTestMarkerPayload::sNumDestroyed = 0;
|
||||||
|
|
||||||
|
PROFILER_ADD_MARKER_WITH_PAYLOAD("M1", OTHER, GTestMarkerPayload, (1));
|
||||||
|
PR_Sleep(PR_MillisecondsToInterval(1100));
|
||||||
|
PROFILER_ADD_MARKER_WITH_PAYLOAD("M2", OTHER, GTestMarkerPayload, (2));
|
||||||
|
PR_Sleep(PR_MillisecondsToInterval(500));
|
||||||
|
|
||||||
|
SpliceableChunkedJSONWriter w;
|
||||||
|
ASSERT_TRUE(profiler_stream_json_for_this_process(w));
|
||||||
|
|
||||||
|
// Both markers created, serialized, destroyed; Only the first marker should
|
||||||
|
// have been deserialized, streamed, and destroyed again.
|
||||||
|
EXPECT_EQ(GTestMarkerPayload::sNumCreated, 2);
|
||||||
|
EXPECT_EQ(GTestMarkerPayload::sNumSerialized, 2);
|
||||||
|
EXPECT_EQ(GTestMarkerPayload::sNumDeserialized, 1);
|
||||||
|
EXPECT_EQ(GTestMarkerPayload::sNumStreamed, 1);
|
||||||
|
EXPECT_EQ(GTestMarkerPayload::sNumDestroyed, 3);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#define COUNTER_NAME "TestCounter"
|
#define COUNTER_NAME "TestCounter"
|
||||||
#define COUNTER_DESCRIPTION "Test of counters in profiles"
|
#define COUNTER_DESCRIPTION "Test of counters in profiles"
|
||||||
#define COUNTER_NAME2 "Counter2"
|
#define COUNTER_NAME2 "Counter2"
|
||||||
|
|
|
@ -93,6 +93,10 @@
|
||||||
#include "nsStringBuffer.h"
|
#include "nsStringBuffer.h"
|
||||||
#include "nsWrapperCache.h"
|
#include "nsWrapperCache.h"
|
||||||
|
|
||||||
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
|
# include "ProfilerMarkerPayload.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(XP_MACOSX)
|
#if defined(XP_MACOSX)
|
||||||
# include "nsMacUtilsImpl.h"
|
# include "nsMacUtilsImpl.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -988,65 +992,15 @@ void CycleCollectedJSRuntime::GCSliceCallback(JSContext* aContext,
|
||||||
#ifdef MOZ_GECKO_PROFILER
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
if (profiler_thread_is_being_profiled()) {
|
if (profiler_thread_is_being_profiled()) {
|
||||||
if (aProgress == JS::GC_CYCLE_END) {
|
if (aProgress == JS::GC_CYCLE_END) {
|
||||||
struct GCMajorMarker {
|
PROFILER_ADD_MARKER_WITH_PAYLOAD(
|
||||||
static constexpr mozilla::Span<const char> MarkerTypeName() {
|
"GCMajor", GCCC, GCMajorMarkerPayload,
|
||||||
return mozilla::MakeStringSpan("GCMajor");
|
(aDesc.startTime(aContext), aDesc.endTime(aContext),
|
||||||
}
|
aDesc.formatJSONProfiler(aContext)));
|
||||||
static void StreamJSONMarkerData(
|
|
||||||
mozilla::baseprofiler::SpliceableJSONWriter& aWriter,
|
|
||||||
const mozilla::ProfilerString8View& aTimingJSON) {
|
|
||||||
if (aTimingJSON.Length() != 0) {
|
|
||||||
aWriter.SplicedJSONProperty("timings", aTimingJSON);
|
|
||||||
} else {
|
|
||||||
aWriter.NullProperty("timings");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static mozilla::MarkerSchema MarkerTypeDisplay() {
|
|
||||||
using MS = mozilla::MarkerSchema;
|
|
||||||
MS schema{MS::Location::markerChart, MS::Location::markerTable,
|
|
||||||
MS::Location::timelineMemory};
|
|
||||||
// No display instructions here, there is special handling in the
|
|
||||||
// front-end.
|
|
||||||
return schema;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
profiler_add_marker("GCMajor", baseprofiler::category::GCCC,
|
|
||||||
MarkerTiming::Interval(aDesc.startTime(aContext),
|
|
||||||
aDesc.endTime(aContext)),
|
|
||||||
GCMajorMarker{},
|
|
||||||
ProfilerString8View::WrapNullTerminatedString(
|
|
||||||
aDesc.formatJSONProfiler(aContext).get()));
|
|
||||||
} else if (aProgress == JS::GC_SLICE_END) {
|
} else if (aProgress == JS::GC_SLICE_END) {
|
||||||
struct GCSliceMarker {
|
PROFILER_ADD_MARKER_WITH_PAYLOAD(
|
||||||
static constexpr mozilla::Span<const char> MarkerTypeName() {
|
"GCSlice", GCCC, GCSliceMarkerPayload,
|
||||||
return mozilla::MakeStringSpan("GCSlice");
|
(aDesc.lastSliceStart(aContext), aDesc.lastSliceEnd(aContext),
|
||||||
}
|
aDesc.sliceToJSONProfiler(aContext)));
|
||||||
static void StreamJSONMarkerData(
|
|
||||||
mozilla::baseprofiler::SpliceableJSONWriter& aWriter,
|
|
||||||
const mozilla::ProfilerString8View& aTimingJSON) {
|
|
||||||
if (aTimingJSON.Length() != 0) {
|
|
||||||
aWriter.SplicedJSONProperty("timings", aTimingJSON);
|
|
||||||
} else {
|
|
||||||
aWriter.NullProperty("timings");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static mozilla::MarkerSchema MarkerTypeDisplay() {
|
|
||||||
using MS = mozilla::MarkerSchema;
|
|
||||||
MS schema{MS::Location::markerChart, MS::Location::markerTable,
|
|
||||||
MS::Location::timelineMemory};
|
|
||||||
// No display instructions here, there is special handling in the
|
|
||||||
// front-end.
|
|
||||||
return schema;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
profiler_add_marker("GCSlice", baseprofiler::category::GCCC,
|
|
||||||
MarkerTiming::Interval(aDesc.lastSliceStart(aContext),
|
|
||||||
aDesc.lastSliceEnd(aContext)),
|
|
||||||
GCSliceMarker{},
|
|
||||||
ProfilerString8View::WrapNullTerminatedString(
|
|
||||||
aDesc.sliceToJSONProfiler(aContext).get()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1125,35 +1079,10 @@ void CycleCollectedJSRuntime::GCNurseryCollectionCallback(
|
||||||
#ifdef MOZ_GECKO_PROFILER
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
else if (aProgress == JS::GCNurseryProgress::GC_NURSERY_COLLECTION_END &&
|
else if (aProgress == JS::GCNurseryProgress::GC_NURSERY_COLLECTION_END &&
|
||||||
profiler_thread_is_being_profiled()) {
|
profiler_thread_is_being_profiled()) {
|
||||||
struct GCMinorMarker {
|
PROFILER_ADD_MARKER_WITH_PAYLOAD(
|
||||||
static constexpr mozilla::Span<const char> MarkerTypeName() {
|
"GCMinor", GCCC, GCMinorMarkerPayload,
|
||||||
return mozilla::MakeStringSpan("GCMinor");
|
(self->mLatestNurseryCollectionStart, TimeStamp::Now(),
|
||||||
}
|
JS::MinorGcToJSON(aContext)));
|
||||||
static void StreamJSONMarkerData(
|
|
||||||
mozilla::baseprofiler::SpliceableJSONWriter& aWriter,
|
|
||||||
const mozilla::ProfilerString8View& aTimingJSON) {
|
|
||||||
if (aTimingJSON.Length() != 0) {
|
|
||||||
aWriter.SplicedJSONProperty("nursery", aTimingJSON);
|
|
||||||
} else {
|
|
||||||
aWriter.NullProperty("nursery");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static mozilla::MarkerSchema MarkerTypeDisplay() {
|
|
||||||
using MS = mozilla::MarkerSchema;
|
|
||||||
MS schema{MS::Location::markerChart, MS::Location::markerTable,
|
|
||||||
MS::Location::timelineMemory};
|
|
||||||
// No display instructions here, there is special handling in the
|
|
||||||
// front-end.
|
|
||||||
return schema;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
profiler_add_marker(
|
|
||||||
"GCMinor", baseprofiler::category::GCCC,
|
|
||||||
MarkerTiming::IntervalUntilNowFrom(self->mLatestNurseryCollectionStart),
|
|
||||||
GCMinorMarker{},
|
|
||||||
ProfilerString8View::WrapNullTerminatedString(
|
|
||||||
JS::MinorGcToJSON(aContext).get()));
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,9 @@
|
||||||
#include "nsDebugImpl.h"
|
#include "nsDebugImpl.h"
|
||||||
#include "NSPRLogModulesParser.h"
|
#include "NSPRLogModulesParser.h"
|
||||||
#include "LogCommandLineHandler.h"
|
#include "LogCommandLineHandler.h"
|
||||||
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
|
# include "ProfilerMarkerPayload.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "prenv.h"
|
#include "prenv.h"
|
||||||
#ifdef XP_WIN
|
#ifdef XP_WIN
|
||||||
|
@ -416,33 +419,15 @@ class LogModuleManager {
|
||||||
|
|
||||||
#ifdef MOZ_GECKO_PROFILER
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
if (mAddProfilerMarker && profiler_can_accept_markers()) {
|
if (mAddProfilerMarker && profiler_can_accept_markers()) {
|
||||||
struct LogMarker {
|
if (aStart) {
|
||||||
static constexpr Span<const char> MarkerTypeName() {
|
PROFILER_ADD_MARKER_WITH_PAYLOAD(
|
||||||
return MakeStringSpan("Log");
|
"LogMessages", OTHER, LogMarkerPayload,
|
||||||
}
|
(aName, buffToWrite, *aStart, TimeStamp::Now()));
|
||||||
static void StreamJSONMarkerData(
|
} else {
|
||||||
baseprofiler::SpliceableJSONWriter& aWriter,
|
PROFILER_ADD_MARKER_WITH_PAYLOAD(
|
||||||
const ProfilerString8View& aModule,
|
"LogMessages", OTHER, LogMarkerPayload,
|
||||||
const ProfilerString8View& aText) {
|
(aName, buffToWrite, TimeStamp::Now()));
|
||||||
aWriter.StringProperty("module", aModule);
|
}
|
||||||
aWriter.StringProperty("name", aText);
|
|
||||||
}
|
|
||||||
static MarkerSchema MarkerTypeDisplay() {
|
|
||||||
using MS = MarkerSchema;
|
|
||||||
MS schema{MS::Location::markerTable};
|
|
||||||
schema.SetTableLabel("({marker.data.module}) {marker.data.name}");
|
|
||||||
schema.AddKeyLabelFormat("module", "Module", MS::Format::string);
|
|
||||||
schema.AddKeyLabelFormat("name", "Name", MS::Format::string);
|
|
||||||
return schema;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
profiler_add_marker(
|
|
||||||
"LogMessages", geckoprofiler::category::OTHER,
|
|
||||||
aStart ? MarkerTiming::IntervalUntilNowFrom(*aStart)
|
|
||||||
: MarkerTiming::InstantNow(),
|
|
||||||
LogMarker{}, ProfilerString8View::WrapNullTerminatedString(aName),
|
|
||||||
ProfilerString8View::WrapNullTerminatedString(buffToWrite));
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,9 @@
|
||||||
#include "nsThreadSyncDispatch.h"
|
#include "nsThreadSyncDispatch.h"
|
||||||
#include "nsServiceManagerUtils.h"
|
#include "nsServiceManagerUtils.h"
|
||||||
#include "GeckoProfiler.h"
|
#include "GeckoProfiler.h"
|
||||||
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
|
# include "ProfilerMarkerPayload.h"
|
||||||
|
#endif
|
||||||
#include "InputEventStatistics.h"
|
#include "InputEventStatistics.h"
|
||||||
#include "ThreadEventQueue.h"
|
#include "ThreadEventQueue.h"
|
||||||
#include "ThreadEventTarget.h"
|
#include "ThreadEventTarget.h"
|
||||||
|
@ -1521,28 +1524,9 @@ void PerformanceCounterState::MaybeReportAccumulatedTime(TimeStamp aNow) {
|
||||||
|
|
||||||
#ifdef MOZ_GECKO_PROFILER
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
if (profiler_thread_is_being_profiled()) {
|
if (profiler_thread_is_being_profiled()) {
|
||||||
struct LongTaskMarker {
|
PROFILER_ADD_MARKER_WITH_PAYLOAD(
|
||||||
static constexpr Span<const char> MarkerTypeName() {
|
mCurrentRunnableIsIdleRunnable ? "LongIdleTask" : "LongTask", OTHER,
|
||||||
return MakeStringSpan("MainThreadLongTask");
|
LongTaskMarkerPayload, (mCurrentTimeSliceStart, aNow));
|
||||||
}
|
|
||||||
static void StreamJSONMarkerData(
|
|
||||||
baseprofiler::SpliceableJSONWriter& aWriter) {
|
|
||||||
aWriter.StringProperty("category", "LongTask");
|
|
||||||
}
|
|
||||||
static MarkerSchema MarkerTypeDisplay() {
|
|
||||||
using MS = MarkerSchema;
|
|
||||||
MS schema{MS::Location::markerChart, MS::Location::markerTable};
|
|
||||||
schema.AddKeyLabelFormat("category", "Type", MS::Format::string);
|
|
||||||
return schema;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
profiler_add_marker(mCurrentRunnableIsIdleRunnable
|
|
||||||
? ProfilerString8View("LongIdleTask")
|
|
||||||
: ProfilerString8View("LongTask"),
|
|
||||||
geckoprofiler::category::OTHER,
|
|
||||||
MarkerTiming::Interval(mCurrentTimeSliceStart, aNow),
|
|
||||||
LongTaskMarker{});
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче