Backed out 23 changesets (bug 1675409) for build bustages on Preferences.cpp. CLOSED TREE

Backed out changeset c1a131a55767 (bug 1675409)
Backed out changeset 47d210802a5d (bug 1675409)
Backed out changeset e8ebb1c58d30 (bug 1675409)
Backed out changeset 69a1e9aeff2a (bug 1675409)
Backed out changeset 68f330b387a8 (bug 1675409)
Backed out changeset e4750d9ef5a1 (bug 1675409)
Backed out changeset bb6bb71e5ab3 (bug 1675409)
Backed out changeset 988d7f4716df (bug 1675409)
Backed out changeset ca41382e891c (bug 1675409)
Backed out changeset 90f3fbbbbeda (bug 1675409)
Backed out changeset 9b109d61a6f6 (bug 1675409)
Backed out changeset 3dd66abfdaa2 (bug 1675409)
Backed out changeset 44181df5f0db (bug 1675409)
Backed out changeset bb2603d947fc (bug 1675409)
Backed out changeset 97055cf20a56 (bug 1675409)
Backed out changeset f88fcf09de0d (bug 1675409)
Backed out changeset 7963e1c49786 (bug 1675409)
Backed out changeset 4c379c1061c3 (bug 1675409)
Backed out changeset b8be8ae7da63 (bug 1675409)
Backed out changeset 0b90aa89421e (bug 1675409)
Backed out changeset c10fb46467c9 (bug 1675409)
Backed out changeset 894ac233b290 (bug 1675409)
Backed out changeset 075d1d8e34c2 (bug 1675409)
This commit is contained in:
Razvan Maries 2020-11-18 20:06:28 +02:00
Родитель 000fa14fd2
Коммит b7eeb731df
64 изменённых файлов: 4294 добавлений и 1344 удалений

Просмотреть файл

@ -244,6 +244,10 @@
# include "nsIWebBrowserPrint.h"
#endif
#ifdef MOZ_GECKO_PROFILER
# include "ProfilerMarkerPayload.h"
#endif
using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::net;

Просмотреть файл

@ -51,6 +51,9 @@
#include "nsThreadUtils.h"
#include "mozJSComponentLoader.h"
#include "GeckoProfiler.h"
#ifdef MOZ_GECKO_PROFILER
# include "ProfilerMarkerPayload.h"
#endif
#include "nsIException.h"
namespace mozilla::dom {

Просмотреть файл

@ -22,6 +22,9 @@
#include "TimeoutBudgetManager.h"
#include "mozilla/net/WebSocketEventService.h"
#include "mozilla/MediaManager.h"
#ifdef MOZ_GECKO_PROFILER
# include "ProfilerMarkerPayload.h"
#endif
using namespace mozilla;
using namespace mozilla::dom;
@ -151,13 +154,10 @@ void TimeoutManager::MoveIdleToActive() {
int(elapsed.ToMilliseconds()), int(target.ToMilliseconds()),
int(delta.ToMilliseconds()));
// don't have end before start...
PROFILER_MARKER_TEXT(
"setTimeout deferred release", DOM,
MarkerOptions(
MarkerTiming::Interval(
delta.ToMilliseconds() >= 0 ? timeout->When() : now, now),
MarkerInnerWindowId(mWindow.WindowID())),
marker);
PROFILER_ADD_MARKER_WITH_PAYLOAD(
"setTimeout deferred release", DOM, TextMarkerPayload,
(marker, delta.ToMilliseconds() >= 0 ? timeout->When() : now, now,
Some(mWindow.WindowID())));
}
#endif
num++;
@ -906,13 +906,10 @@ void TimeoutManager::RunTimeout(const TimeStamp& aNow,
int(elapsed.ToMilliseconds()), int(target.ToMilliseconds()),
int(delta.ToMilliseconds()), int(runtime.ToMilliseconds()));
// don't have end before start...
PROFILER_MARKER_TEXT(
"setTimeout", DOM,
MarkerOptions(
MarkerTiming::Interval(
delta.ToMilliseconds() >= 0 ? timeout->When() : now, now),
MarkerInnerWindowId(mWindow.WindowID())),
marker);
PROFILER_ADD_MARKER_WITH_PAYLOAD(
"setTimeout", DOM, TextMarkerPayload,
(marker, delta.ToMilliseconds() >= 0 ? timeout->When() : now, now,
Some(mWindow.WindowID())));
}
#endif

Просмотреть файл

@ -25,7 +25,7 @@
#include "nsPrintfCString.h"
#include "prtime.h"
#ifdef MOZ_GECKO_PROFILER
# include "mozilla/ProfilerMarkerTypes.h"
# include "ProfilerMarkerPayload.h"
#endif
using namespace mozilla;
@ -116,18 +116,14 @@ void nsDOMNavigationTiming::NotifyUnloadAccepted(nsIURI* aOldURI) {
void nsDOMNavigationTiming::NotifyUnloadEventStart() {
mUnloadStart = TimeStamp::Now();
PROFILER_MARKER("Unload", NETWORK,
MarkerOptions(MarkerTiming::IntervalStart(),
MarkerInnerWindowIdFromDocShell(mDocShell)),
Tracing, "Navigation");
PROFILER_TRACING_MARKER_DOCSHELL("Navigation", "Unload", NETWORK,
TRACING_INTERVAL_START, mDocShell);
}
void nsDOMNavigationTiming::NotifyUnloadEventEnd() {
mUnloadEnd = TimeStamp::Now();
PROFILER_MARKER("Unload", NETWORK,
MarkerOptions(MarkerTiming::IntervalEnd(),
MarkerInnerWindowIdFromDocShell(mDocShell)),
Tracing, "Navigation");
PROFILER_TRACING_MARKER_DOCSHELL("Navigation", "Unload", NETWORK,
TRACING_INTERVAL_END, mDocShell);
}
void nsDOMNavigationTiming::NotifyLoadEventStart() {
@ -136,10 +132,8 @@ void nsDOMNavigationTiming::NotifyLoadEventStart() {
}
mLoadEventStart = TimeStamp::Now();
PROFILER_MARKER("Load", NETWORK,
MarkerOptions(MarkerTiming::IntervalStart(),
MarkerInnerWindowIdFromDocShell(mDocShell)),
Tracing, "Navigation");
PROFILER_TRACING_MARKER_DOCSHELL("Navigation", "Load", NETWORK,
TRACING_INTERVAL_START, mDocShell);
if (IsTopLevelContentDocumentInContentProcess()) {
mLoadEventStartForTelemetry = TimeStamp::Now();
@ -169,10 +163,8 @@ void nsDOMNavigationTiming::NotifyLoadEventEnd() {
}
mLoadEventEnd = TimeStamp::Now();
PROFILER_MARKER("Load", NETWORK,
MarkerOptions(MarkerTiming::IntervalEnd(),
MarkerInnerWindowIdFromDocShell(mDocShell)),
Tracing, "Navigation");
PROFILER_TRACING_MARKER_DOCSHELL("Navigation", "Load", NETWORK,
TRACING_INTERVAL_END, mDocShell);
if (IsTopLevelContentDocumentInContentProcess()) {
#ifdef MOZ_GECKO_PROFILER
@ -187,13 +179,10 @@ void nsDOMNavigationTiming::NotifyLoadEventEnd() {
"Document %s loaded after %dms, load event duration %dms", spec.get(),
int(elapsed.ToMilliseconds()), int(duration.ToMilliseconds()));
PAGELOAD_LOG(("%s", marker.get()));
PROFILER_MARKER_TEXT(
"DocumentLoad", DOM,
MarkerOptions(
MarkerTiming::Interval(mNavigationStart, mLoadEventEnd),
MarkerInnerWindowId(
profiler_get_inner_window_id_from_docshell(mDocShell))),
marker);
PROFILER_ADD_MARKER_WITH_PAYLOAD(
"DocumentLoad", DOM, TextMarkerPayload,
(marker, mNavigationStart, mLoadEventEnd,
profiler_get_inner_window_id_from_docshell(mDocShell)));
}
#endif
TimeStamp loadEventEnd = TimeStamp::Now();
@ -252,10 +241,8 @@ void nsDOMNavigationTiming::NotifyDOMContentLoadedStart(nsIURI* aURI) {
mLoadedURI = aURI;
mDOMContentLoadedEventStart = TimeStamp::Now();
PROFILER_MARKER("DOMContentLoaded", NETWORK,
MarkerOptions(MarkerTiming::IntervalStart(),
MarkerInnerWindowIdFromDocShell(mDocShell)),
Tracing, "Navigation");
PROFILER_TRACING_MARKER_DOCSHELL("Navigation", "DOMContentLoaded", NETWORK,
TRACING_INTERVAL_START, mDocShell);
if (IsTopLevelContentDocumentInContentProcess()) {
TimeStamp now = TimeStamp::Now();
@ -286,10 +273,8 @@ void nsDOMNavigationTiming::NotifyDOMContentLoadedEnd(nsIURI* aURI) {
mLoadedURI = aURI;
mDOMContentLoadedEventEnd = TimeStamp::Now();
PROFILER_MARKER("DOMContentLoaded", NETWORK,
MarkerOptions(MarkerTiming::IntervalEnd(),
MarkerInnerWindowIdFromDocShell(mDocShell)),
Tracing, "Navigation");
PROFILER_TRACING_MARKER_DOCSHELL("Navigation", "DOMContentLoaded", NETWORK,
TRACING_INTERVAL_END, mDocShell);
if (IsTopLevelContentDocumentInContentProcess()) {
Telemetry::AccumulateTimeDelta(Telemetry::TIME_TO_DOM_CONTENT_LOADED_END_MS,
@ -392,13 +377,10 @@ void nsDOMNavigationTiming::TTITimeout(nsITimer* aTimer) {
int(elapsed.ToMilliseconds()),
int(elapsedLongTask.ToMilliseconds()), spec.get());
PROFILER_MARKER_TEXT(
"TimeToFirstInteractive (TTFI)", DOM,
MarkerOptions(
MarkerTiming::Interval(mNavigationStart, mTTFI),
MarkerInnerWindowId(
profiler_get_inner_window_id_from_docshell(mDocShell))),
marker);
PROFILER_ADD_MARKER_WITH_PAYLOAD(
"TimeToFirstInteractive (TTFI)", DOM, TextMarkerPayload,
(marker, mNavigationStart, mTTFI,
profiler_get_inner_window_id_from_docshell(mDocShell)));
}
#endif
}
@ -428,13 +410,10 @@ void nsDOMNavigationTiming::NotifyNonBlankPaintForRootContentDocument() {
: "this tab was inactive some of the time between navigation start "
"and first non-blank paint");
PAGELOAD_LOG(("%s", marker.get()));
PROFILER_MARKER_TEXT(
"FirstNonBlankPaint", DOM,
MarkerOptions(
MarkerTiming::Interval(mNavigationStart, mNonBlankPaint),
MarkerInnerWindowId(
profiler_get_inner_window_id_from_docshell(mDocShell))),
marker);
PROFILER_ADD_MARKER_WITH_PAYLOAD(
"FirstNonBlankPaint", DOM, TextMarkerPayload,
(marker, mNavigationStart, mNonBlankPaint,
profiler_get_inner_window_id_from_docshell(mDocShell)));
}
#endif
@ -480,13 +459,10 @@ void nsDOMNavigationTiming::NotifyContentfulPaintForRootContentDocument(
: "this tab was inactive some of the time between navigation start "
"and first non-blank paint");
PAGELOAD_LOG(("%s", marker.get()));
PROFILER_MARKER_TEXT(
"FirstContentfulPaint", DOM,
MarkerOptions(
MarkerTiming::Interval(mNavigationStart, mContentfulPaint),
MarkerInnerWindowId(
profiler_get_inner_window_id_from_docshell(mDocShell))),
marker);
PROFILER_ADD_MARKER_WITH_PAYLOAD(
"FirstContentfulPaint", DOM, TextMarkerPayload,
(marker, mNavigationStart, mContentfulPaint,
profiler_get_inner_window_id_from_docshell(mDocShell)));
}
#endif
@ -532,13 +508,10 @@ void nsDOMNavigationTiming::NotifyDOMContentFlushedForRootContentDocument() {
: "this tab was inactive some of the time between navigation start "
"and DOMContentFlushed");
PAGELOAD_LOG(("%s", marker.get()));
PROFILER_MARKER_TEXT(
"DOMContentFlushed", DOM,
MarkerOptions(
MarkerTiming::Interval(mNavigationStart, mDOMContentFlushed),
MarkerInnerWindowId(
profiler_get_inner_window_id_from_docshell(mDocShell))),
marker);
PROFILER_ADD_MARKER_WITH_PAYLOAD(
"DOMContentFlushed", DOM, TextMarkerPayload,
(marker, mNavigationStart, mDOMContentFlushed,
profiler_get_inner_window_id_from_docshell(mDocShell)));
}
#endif
}

Просмотреть файл

@ -1039,6 +1039,10 @@ nsresult EventDispatcher::Dispatch(nsISupports* aTarget,
struct DOMEventMarker {
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");
}
static void StreamJSONMarkerData(

Просмотреть файл

@ -21,6 +21,9 @@
# include "mozilla/a11y/PDocAccessible.h"
#endif
#include "GeckoProfiler.h"
#ifdef MOZ_GECKO_PROFILER
# include "ProfilerMarkerPayload.h"
#endif
#include "GMPServiceParent.h"
#include "HandlerServiceParent.h"
#include "IHistory.h"
@ -915,7 +918,9 @@ already_AddRefed<ContentParent> ContentParent::GetUsedBrowserProcess(
if (profiler_thread_is_being_profiled()) {
nsPrintfCString marker("Reused process %u",
(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
MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
@ -954,7 +959,9 @@ already_AddRefed<ContentParent> ContentParent::GetUsedBrowserProcess(
if (profiler_thread_is_being_profiled()) {
nsPrintfCString marker("Recycled process %u (%p)",
(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
MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
@ -977,7 +984,9 @@ already_AddRefed<ContentParent> ContentParent::GetUsedBrowserProcess(
if (profiler_thread_is_being_profiled()) {
nsPrintfCString marker("Assigned preallocated process %u",
(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
MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
@ -2414,10 +2423,9 @@ bool ContentParent::LaunchSubprocessResolve(bool aIsSync,
nsPrintfCString marker("Process start%s for %u",
mIsAPreallocBlocker ? " (immediate)" : "",
(unsigned int)ChildID());
PROFILER_MARKER_TEXT(
mIsAPreallocBlocker ? ProfilerString8View("Process Immediate Launch")
: ProfilerString8View("Process Launch"),
DOM, MarkerTiming::Interval(mLaunchTS, launchResumeTS), marker);
PROFILER_ADD_MARKER_WITH_PAYLOAD(
mIsAPreallocBlocker ? "Process Immediate Launch" : "Process Launch",
DOM, TextMarkerPayload, (marker, mLaunchTS, launchResumeTS));
}
#endif

Просмотреть файл

@ -16,6 +16,9 @@
#include "mozilla/MathAlgorithms.h"
#include "mozilla/Sprintf.h"
#include "GeckoProfiler.h"
#ifdef MOZ_GECKO_PROFILER
# include "ProfilerMarkerPayload.h"
#endif
#include "MPSCQueue.h"
#if defined(_WIN32)
@ -196,41 +199,24 @@ class AsyncLogger {
}
#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;
while (mMessageQueueProfiler.Pop(&message) && mRunning) {
if (message.mPhase != TracingPhase::COMPLETE) {
profiler_add_marker(
ProfilerString8View::WrapNullTerminatedString(message.mName),
geckoprofiler::category::MEDIA_RT,
{MarkerThreadId(message.mTID),
(message.mPhase == TracingPhase::BEGIN)
? MarkerTiming::IntervalStart(message.mTimestamp)
: MarkerTiming::IntervalEnd(message.mTimestamp)},
Budget{});
TracingKind kind = message.mPhase == TracingPhase::BEGIN
? TracingKind::TRACING_INTERVAL_START
: TracingKind::TRACING_INTERVAL_END;
TracingMarkerPayload payload("media", kind, message.mTimestamp);
profiler_add_marker_for_thread(
message.mTID, JS::ProfilingCategoryPair::MEDIA_RT,
message.mName, payload);
} else {
profiler_add_marker(
ProfilerString8View::WrapNullTerminatedString(message.mName),
geckoprofiler::category::MEDIA_RT,
{MarkerThreadId(message.mTID),
MarkerTiming::Interval(
message.mTimestamp,
message.mTimestamp + TimeDuration::FromMicroseconds(
message.mDurationUs))},
Budget{});
mozilla::TimeStamp end =
message.mTimestamp +
TimeDuration::FromMicroseconds(message.mDurationUs);
BudgetMarkerPayload payload(message.mTimestamp, end);
profiler_add_marker_for_thread(
message.mTID, JS::ProfilingCategoryPair::MEDIA_RT,
message.mName, payload);
}
}
}

Просмотреть файл

@ -27,7 +27,6 @@
#include "AudioSegment.h"
#include "DOMMediaStream.h"
#include "ImageContainer.h"
#include "GeckoProfiler.h"
#include "MediaDecoder.h"
#include "MediaDecoderStateMachine.h"
#include "MediaShutdownManager.h"
@ -39,8 +38,17 @@
#include "VideoUtils.h"
#ifdef MOZ_GECKO_PROFILER
# include "mozilla/ProfilerMarkerTypes.h"
#endif // MOZ_GECKO_PROFILER
# include "ProfilerMarkerPayload.h"
# 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 {
@ -2851,9 +2859,8 @@ void MediaDecoderStateMachine::PushAudio(AudioData* aSample) {
MOZ_ASSERT(OnTaskQueue());
MOZ_ASSERT(aSample);
AudioQueue().Push(aSample);
PROFILER_MARKER("MDSM::PushAudio", MEDIA_PLAYBACK, {}, MediaSampleMarker,
aSample->mTime.ToMicroseconds(),
aSample->GetEndTime().ToMicroseconds());
MDSM_SAMPLE_MARKER("MDSM::PushAudio", aSample->mTime.ToMicroseconds(),
aSample->GetEndTime().ToMicroseconds());
}
void MediaDecoderStateMachine::PushVideo(VideoData* aSample) {
@ -2861,9 +2868,8 @@ void MediaDecoderStateMachine::PushVideo(VideoData* aSample) {
MOZ_ASSERT(aSample);
aSample->mFrameID = ++mCurrentFrameID;
VideoQueue().Push(aSample);
PROFILER_MARKER("MDSM::PushVideo", MEDIA_PLAYBACK, {}, MediaSampleMarker,
aSample->mTime.ToMicroseconds(),
aSample->GetEndTime().ToMicroseconds());
MDSM_SAMPLE_MARKER("MDSM::PushVideo", aSample->mTime.ToMicroseconds(),
aSample->GetEndTime().ToMicroseconds());
}
void MediaDecoderStateMachine::OnAudioPopped(const RefPtr<AudioData>& aSample) {
@ -3463,8 +3469,8 @@ bool MediaDecoderStateMachine::HasLowBufferedData(const TimeUnit& aThreshold) {
void MediaDecoderStateMachine::DecodeError(const MediaResult& aError) {
MOZ_ASSERT(OnTaskQueue());
LOGE("Decode error: %s", aError.Description().get());
PROFILER_MARKER_TEXT("MDSM::DecodeError", MEDIA_PLAYBACK, {},
aError.Description());
MDSM_ERROR_MARKER("MDSM::DecodeError", aError.Description(),
TimeStamp::NowUnfuzzed());
// Notify the decode error and MediaDecoder will shut down MDSM.
mOnPlaybackErrorEvent.Notify(aError);
}

Просмотреть файл

@ -42,6 +42,15 @@ mozilla::LazyLogModule gMediaDemuxerLog("MediaDemuxer");
DDMOZ_LOG(sFormatDecoderLog, mozilla::LogLevel::Verbose, "::%s: " arg, \
__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
namespace mozilla {
@ -1922,7 +1931,8 @@ void MediaFormatReader::HandleDemuxedSamples(
nsPrintfCString markerString(
"%s stream id changed from:%" PRIu32 " to:%" PRIu32,
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());
if (aTrack == TrackInfo::kVideoTrack) {
@ -3140,5 +3150,6 @@ void MediaFormatReader::OnFirstDemuxFailed(TrackInfo::TrackType aType,
} // namespace mozilla
#undef NS_DispatchToMainThread
#undef MEDIA_FORMAT_READER_STATUS_MARKER
#undef LOGV
#undef LOG

Просмотреть файл

@ -12,11 +12,28 @@
#include "mozilla/CheckedInt.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/IntegerPrintfMacros.h"
#include "mozilla/ProfilerMarkerTypes.h"
#include "mozilla/StaticPrefs_media.h"
#include "mozilla/StaticPrefs_dom.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 {
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",
mCurrentData->mTime.ToMicroseconds(),
mCurrentData->Frames() - mCursor->Available(), framesToPop);
#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
PROFILER_AUDIO_MARKER("PlayAudio", mCurrentData);
UniquePtr<AudioStream::Chunk> chunk =
MakeUnique<Chunk>(mCurrentData, framesToPop, mCursor->Ptr());

Просмотреть файл

@ -16,7 +16,6 @@
#include "VideoUtils.h"
#include "mozilla/IntegerPrintfMacros.h"
#include "mozilla/ProfilerMarkerTypes.h"
#include "mozilla/StaticPrefs_browser.h"
#include "mozilla/StaticPrefs_media.h"
@ -30,6 +29,15 @@ extern mozilla::LazyLogModule gMediaDecoderLog;
#define VSINK_LOG_V(x, ...) \
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 {
using namespace mozilla::layers;
@ -455,9 +463,8 @@ void VideoSink::RenderVideoFrames(int32_t aMaxFrames, int64_t aClockTime,
frame->mTime.ToMicroseconds(), frame->mFrameID,
VideoQueue().GetSize());
if (!wasSent) {
PROFILER_MARKER("PlayVideo", MEDIA_PLAYBACK, {}, MediaSampleMarker,
frame->mTime.ToMicroseconds(),
frame->GetEndTime().ToMicroseconds());
VSINK_ADD_PROFILER_MARKER("PlayVideo", frame->mTime.ToMicroseconds(),
frame->GetEndTime().ToMicroseconds());
}
}
@ -496,9 +503,8 @@ void VideoSink::UpdateRenderedVideoFrames() {
VSINK_LOG_V("discarding video frame mTime=%" PRId64
" clock_time=%" PRId64,
frame->mTime.ToMicroseconds(), clockTime.ToMicroseconds());
PROFILER_MARKER("DiscardVideo", MEDIA_PLAYBACK, {}, MediaSampleMarker,
frame->mTime.ToMicroseconds(),
frame->GetEndTime().ToMicroseconds());
VSINK_ADD_PROFILER_MARKER("DiscardVideo", frame->mTime.ToMicroseconds(),
frame->GetEndTime().ToMicroseconds());
}
}

Просмотреть файл

@ -27,7 +27,6 @@
#include "mozilla/WindowsVersion.h"
#include "mozilla/gfx/gfxVars.h"
#include "mozilla/mscom/EnsureMTA.h"
#include "mozilla/ProfilerMarkers.h"
#include "nsComponentManagerUtils.h"
#include "nsIXULRuntime.h"
#include "nsIXULRuntime.h" // for BrowserTabsRemoteAutostart
@ -37,19 +36,28 @@
#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;
namespace mozilla {
// Helper function to add a profile marker and log at the same time.
static void MOZ_FORMAT_PRINTF(2, 3)
WmfDeocderModuleMarkerAndLog(const ProfilerString8View& aMarkerTag,
const char* aFormat, ...) {
WmfDeocderModuleMarkerAndLog(const char* aTag, const char* aFormat, ...) {
va_list ap;
va_start(ap, aFormat);
const nsVprintfCString markerString(aFormat, ap);
va_end(ap);
PROFILER_MARKER_TEXT(aMarkerTag, MEDIA_PLAYBACK, {}, markerString);
WFM_DECODER_MODULE_STATUS_MARKER(aTag, markerString,
TimeStamp::NowUnfuzzed());
LOG("%s", markerString.get());
}

Просмотреть файл

@ -9,7 +9,6 @@
#include "VideoUtils.h"
#include "WMFUtils.h"
#include "mozilla/Logging.h"
#include "mozilla/ProfilerMarkers.h"
#include "mozilla/SyncRunnable.h"
#include "mozilla/TaskQueue.h"
#include "mozilla/Telemetry.h"
@ -17,6 +16,15 @@
#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 {
WMFMediaDataDecoder::WMFMediaDataDecoder(MFTManager* aMFTManager)
@ -94,7 +102,8 @@ RefPtr<MediaDataDecoder::DecodePromise> WMFMediaDataDecoder::ProcessError(
"reason: %s",
GetDescriptionName().get(), aReason);
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
// NS_ERROR_DOM_MEDIA_NEED_NEW_DECODER to get the latest device. Maybe retry

Просмотреть файл

@ -13,10 +13,18 @@
#include "MediaInfo.h"
#include "PDMFactory.h"
#include "VPXDecoder.h"
#include "mozilla/ProfilerMarkers.h"
#include "mozilla/StaticPrefs_media.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 {
// 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;
UpdateConfigFromExtraData(extra_data);
PROFILER_MARKER_TEXT("H264 Stream Change", MEDIA_PLAYBACK, {},
"H264ChangeMonitor::CheckForChange has detected a "
"change in the stream and will request a new decoder");
MEDIA_CHANGE_MONITOR_STATUS_MARKER(
"H264 Stream Change",
"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;
}
@ -194,10 +204,11 @@ class VPXChangeMonitor : public MediaChangeMonitor::CodecChangeMonitor {
mCurrentConfig.SetImageRect(
gfx::IntRect(0, 0, info.mImage.width, info.mImage.height));
PROFILER_MARKER_TEXT(
"VPX Stream Change", MEDIA_PLAYBACK, {},
MEDIA_CHANGE_MONITOR_STATUS_MARKER(
"VPX Stream Change",
"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;
}
mInfo = Some(info);
@ -744,3 +755,5 @@ void MediaChangeMonitor::FlushThenShutdownDecoder(
}
} // namespace mozilla
#undef MEDIA_CHANGE_MONITOR_STATUS_MARKER

Просмотреть файл

@ -28,6 +28,10 @@
#include "mozilla/dom/WorkerPrivate.h"
#include "mozilla/dom/WorkerRunnable.h"
#ifdef MOZ_GECKO_PROFILER
# include "ProfilerMarkerPayload.h"
#endif
#define PERFLOG(msg, ...) printf_stderr(msg, ##__VA_ARGS__)
namespace mozilla::dom {
@ -212,53 +216,6 @@ void Performance::ClearUserEntries(const Optional<nsAString>& aEntryName,
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) {
// We add nothing when 'privacy.resistFingerprinting' is on.
if (nsContentUtils::ShouldResistFingerprinting()) {
@ -280,9 +237,8 @@ void Performance::Mark(const nsAString& aName, ErrorResult& aRv) {
if (GetOwner()) {
innerWindowId = Some(GetOwner()->WindowID());
}
profiler_add_marker("UserTiming", geckoprofiler::category::DOM,
MarkerInnerWindowId(innerWindowId), UserTimingMarker{},
aName, /* aIsMeasure */ false, Nothing{}, Nothing{});
PROFILER_ADD_MARKER_WITH_PAYLOAD("UserTiming", DOM, UserTimingMarkerPayload,
(aName, TimeStamp::Now(), innerWindowId));
}
#endif
}
@ -376,11 +332,9 @@ void Performance::Measure(const nsAString& aName,
if (GetOwner()) {
innerWindowId = Some(GetOwner()->WindowID());
}
profiler_add_marker("UserTiming", geckoprofiler::category::DOM,
{MarkerTiming::Interval(startTimeStamp, endTimeStamp),
MarkerInnerWindowId(innerWindowId)},
UserTimingMarker{}, aName, /* aIsMeasure */ true,
startMark, endMark);
PROFILER_ADD_MARKER_WITH_PAYLOAD("UserTiming", DOM, UserTimingMarkerPayload,
(aName, startMark, endMark, startTimeStamp,
endTimeStamp, innerWindowId));
}
#endif
}

Просмотреть файл

@ -24,7 +24,6 @@
#include "js/SourceText.h"
#include "js/Utility.h"
#include "xpcpublic.h"
#include "GeckoProfiler.h"
#include "nsCycleCollectionParticipant.h"
#include "nsIContent.h"
#include "nsJSUtils.h"
@ -84,6 +83,10 @@
#include "nsIScriptError.h"
#include "nsIAsyncOutputStream.h"
#ifdef MOZ_GECKO_PROFILER
# include "ProfilerMarkerPayload.h"
#endif
using JS::SourceText;
using mozilla::Telemetry::LABELS_DOM_SCRIPT_PRELOAD_RESULT;
@ -2177,7 +2180,7 @@ NotifyOffThreadScriptLoadCompletedRunnable::Run() {
#ifdef MOZ_GECKO_PROFILER
if (profiler_is_active()) {
ProfilerString8View scriptSourceString;
const char* scriptSourceString;
if (request->IsTextSource()) {
scriptSourceString = "ScriptCompileOffThread";
} else if (request->IsBinASTSource()) {
@ -2189,11 +2192,10 @@ NotifyOffThreadScriptLoadCompletedRunnable::Run() {
nsAutoCString profilerLabelString;
GetProfilerLabelForRequest(request, profilerLabelString);
PROFILER_MARKER_TEXT(
scriptSourceString, JS,
MarkerTiming::Interval(request->mOffThreadParseStartTime,
request->mOffThreadParseStopTime),
profilerLabelString);
PROFILER_ADD_MARKER_WITH_PAYLOAD(
scriptSourceString, JS, TextMarkerPayload,
(profilerLabelString, request->mOffThreadParseStartTime,
request->mOffThreadParseStopTime));
}
#endif

Просмотреть файл

@ -2458,7 +2458,7 @@ nsresult XMLHttpRequestMainThread::CreateChannel() {
rv = httpChannel->SetRequestMethod(mRequestMethod);
NS_ENSURE_SUCCESS(rv, rv);
httpChannel->SetSource(profiler_capture_backtrace());
httpChannel->SetSource(profiler_get_backtrace());
// Set the initiator type
nsCOMPtr<nsITimedChannel> timedChannel(do_QueryInterface(httpChannel));
@ -3240,8 +3240,7 @@ void XMLHttpRequestMainThread::SetOriginStack(
mOriginStack = std::move(aOriginStack);
}
void XMLHttpRequestMainThread::SetSource(
UniquePtr<ProfileChunkedBuffer> aSource) {
void XMLHttpRequestMainThread::SetSource(UniqueProfilerBacktrace aSource) {
if (!mChannel) {
return;
}

Просмотреть файл

@ -396,7 +396,7 @@ class XMLHttpRequestMainThread final : public XMLHttpRequest,
void SetOriginStack(UniquePtr<SerializedStackHolder> aOriginStack);
void SetSource(UniquePtr<ProfileChunkedBuffer> aSource);
void SetSource(UniqueProfilerBacktrace aSource);
virtual uint16_t ErrorCode() const override {
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
// purposes.
UniquePtr<ProfileChunkedBuffer> mSource;
UniqueProfilerBacktrace mSource;
public:
OpenRunnable(WorkerPrivate* aWorkerPrivate, Proxy* aProxy,
@ -664,7 +664,7 @@ class OpenRunnable final : public WorkerThreadProxySyncRunnable {
XMLHttpRequestResponseType aResponseType,
const nsString& aMimeTypeOverride,
UniquePtr<SerializedStackHolder> aOriginStack,
UniquePtr<ProfileChunkedBuffer> aSource = nullptr)
UniqueProfilerBacktrace aSource = nullptr)
: WorkerThreadProxySyncRunnable(aWorkerPrivate, aProxy),
mMethod(aMethod),
mURL(aURL),
@ -1741,7 +1741,7 @@ void XMLHttpRequestWorker::Open(const nsACString& aMethod,
mWorkerPrivate, mProxy, aMethod, aUrl, aUser, aPassword,
mBackgroundRequest, mWithCredentials, mTimeout, mResponseType,
alsoOverrideMimeType ? mMimeTypeOverride : VoidString(), std::move(stack),
profiler_capture_backtrace());
profiler_get_backtrace());
++mProxy->mOpenCount;
runnable->Dispatch(Canceling, aRv);

Просмотреть файл

@ -11,6 +11,9 @@
#include "GeckoProfiler.h"
#include "gfxUtils.h"
#include "nsThreadUtils.h"
#ifdef MOZ_GECKO_PROFILER
# include "ProfilerMarkerPayload.h"
#endif
using namespace mozilla;
using namespace mozilla::gfx;
@ -81,32 +84,12 @@ void ProfilerScreenshots::SubmitScreenshot(
nullptr, &dataURL);
if (NS_SUCCEEDED(rv)) {
// Add a marker with the data URL.
struct ScreenshotMarker {
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) {
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);
AUTO_PROFILER_STATS(add_marker_with_ScreenshotPayload);
profiler_add_marker_for_thread(
sourceThread, JS::ProfilingCategoryPair::GRAPHICS,
"CompositorScreenshot",
ScreenshotPayload(timeStamp, std::move(dataURL), originalSize,
windowIdentifier));
}
}

Просмотреть файл

@ -40,6 +40,10 @@
#include <vector>
#include "GeckoProfiler.h" // for GeckoProfiler
#ifdef MOZ_GECKO_PROFILER
# include "ProfilerMarkerPayload.h" // for LayerTranslationMarkerPayload
#endif
static mozilla::LazyLogModule sGfxCullLog("gfx.culling");
#define CULLING_LOG(...) MOZ_LOG(sGfxCullLog, LogLevel::Debug, (__VA_ARGS__))
@ -99,37 +103,9 @@ static void PrintUniformityInfo(Layer* aLayer) {
}
Point translation = transform.As2D().GetTranslation();
// Contains the translation applied to a 2d layer so we can track the layer
// position at each frame.
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);
PROFILER_ADD_MARKER_WITH_PAYLOAD("LayerTranslation", GRAPHICS,
LayerTranslationMarkerPayload,
(aLayer, translation, TimeStamp::Now()));
#endif
}

Просмотреть файл

@ -90,6 +90,9 @@
#include "mozilla/HalTypes.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/Telemetry.h"
#ifdef MOZ_GECKO_PROFILER
# include "ProfilerMarkerPayload.h"
#endif
#include "mozilla/VsyncDispatcher.h"
#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
# include "VsyncSource.h"
@ -2173,23 +2176,8 @@ already_AddRefed<IAPZCTreeManager> CompositorBridgeParent::GetAPZCTreeManager(
static void InsertVsyncProfilerMarker(TimeStamp aVsyncTimestamp) {
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
if (profiler_thread_is_being_profiled()) {
// Tracks when a vsync occurs according to the HardwareComposer.
struct VsyncMarker {
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{});
PROFILER_ADD_MARKER_WITH_PAYLOAD("VsyncTimestamp", GRAPHICS,
VsyncMarkerPayload, (aVsyncTimestamp));
}
}
#endif
@ -2754,23 +2742,42 @@ int32_t RecordContentFrameTime(
#ifdef MOZ_GECKO_PROFILER
if (profiler_can_accept_markers()) {
struct ContentFrameMarker {
static constexpr Span<const char> MarkerTypeName() {
return MakeStringSpan("CONTENT_FRAME_TIME");
class ContentFramePayload : public ProfilerMarkerPayload {
public:
ContentFramePayload(const mozilla::TimeStamp& aStartTime,
const mozilla::TimeStamp& aEndTime)
: ProfilerMarkerPayload(aStartTime, aEndTime) {}
mozilla::ProfileBufferEntryWriter::Length TagAndSerializationBytes()
const override {
return CommonPropsTagAndSerializationBytes();
}
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;
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_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)));
}
};
profiler_add_marker("CONTENT_FRAME_TIME", geckoprofiler::category::GRAPHICS,
MarkerTiming::Interval(aTxnStart, aCompositeEnd),
ContentFrameMarker{});
AUTO_PROFILER_STATS(add_marker_with_ContentFramePayload);
profiler_add_marker_for_thread(
profiler_current_thread_id(), JS::ProfilingCategoryPair::GRAPHICS,
"CONTENT_FRAME_TIME", ContentFramePayload(aTxnStart, aCompositeEnd));
}
#endif

Просмотреть файл

@ -39,7 +39,7 @@
#include "mozilla/StaticPtr.h"
#include "mozilla/Telemetry.h"
#ifdef MOZ_GECKO_PROFILER
# include "mozilla/BaseProfilerMarkerTypes.h"
# include "ProfilerMarkerPayload.h"
#endif
namespace mozilla {
@ -372,10 +372,43 @@ void ContentCompositorBridgeParent::ShadowLayersUpdated(
auto endTime = TimeStamp::Now();
#ifdef MOZ_GECKO_PROFILER
if (profiler_can_accept_markers()) {
profiler_add_marker(
"CONTENT_FULL_PAINT_TIME", geckoprofiler::category::GRAPHICS,
MarkerTiming::Interval(aInfo.transactionStart(), endTime),
baseprofiler::markers::ContentBuildMarker{});
class ContentBuildPayload : public ProfilerMarkerPayload {
public:
ContentBuildPayload(const mozilla::TimeStamp& aStartTime,
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
Telemetry::Accumulate(

Просмотреть файл

@ -45,7 +45,7 @@
#endif
#ifdef MOZ_GECKO_PROFILER
# include "mozilla/ProfilerMarkerTypes.h"
# include "ProfilerMarkerPayload.h"
#endif
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) {
PROFILER_MARKER(mozilla::ProfilerString8View::WrapNullTerminatedString(name),
GRAPHICS, mozilla::MarkerTiming::IntervalStart(), Tracing,
"WebRender");
#ifdef MOZ_GECKO_PROFILER
profiler_tracing_marker("WebRender", name,
JS::ProfilingCategoryPair::GRAPHICS,
TRACING_INTERVAL_START);
#endif
}
void gecko_profiler_end_marker(const char* name) {
PROFILER_MARKER(mozilla::ProfilerString8View::WrapNullTerminatedString(name),
GRAPHICS, mozilla::MarkerTiming::IntervalEnd(), Tracing,
"WebRender");
#ifdef MOZ_GECKO_PROFILER
profiler_tracing_marker("WebRender", name,
JS::ProfilingCategoryPair::GRAPHICS,
TRACING_INTERVAL_END);
#endif
}
void gecko_profiler_event_marker(const char* name) {
PROFILER_MARKER(mozilla::ProfilerString8View::WrapNullTerminatedString(name),
GRAPHICS, {}, Tracing, "WebRender");
#ifdef MOZ_GECKO_PROFILER
profiler_tracing_marker("WebRender", name,
JS::ProfilingCategoryPair::GRAPHICS, TRACING_EVENT);
#endif
}
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();
#ifdef MOZ_GECKO_PROFILER
if (profiler_can_accept_markers()) {
profiler_add_marker("CONTENT_FULL_PAINT_TIME",
geckoprofiler::category::GRAPHICS,
MarkerTiming::Interval(startTime, endTime),
baseprofiler::markers::ContentBuildMarker{});
class ContentFullPaintPayload : public ProfilerMarkerPayload {
public:
ContentFullPaintPayload(const mozilla::TimeStamp& aStartTime,
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
Telemetry::Accumulate(

Просмотреть файл

@ -17,6 +17,10 @@
#include "mozilla/webrender/RenderThread.h"
#include "mozilla/widget/CompositorWidget.h"
#ifdef MOZ_GECKO_PROFILER
# include "ProfilerMarkerPayload.h"
#endif
namespace mozilla {
namespace wr {

Просмотреть файл

@ -8,6 +8,10 @@
#include "chrome/common/ipc_message.h"
#ifdef MOZ_GECKO_PROFILER
# include "ProfilerMarkerPayload.h"
#endif
namespace IPC {
void AddIPCProfilerMarker(const Message& aMessage, int32_t aOtherPid,
@ -21,12 +25,11 @@ void AddIPCProfilerMarker(const Message& aMessage, int32_t aOtherPid,
return;
}
// The current timestamp must be given to the `IPCMarker` payload.
const mozilla::TimeStamp now = mozilla::TimeStamp::NowUnfuzzed();
PROFILER_MARKER("IPC", IPC, mozilla::MarkerTiming::InstantAt(now),
IPCMarker, now, now, aOtherPid, aMessage.seqno(),
aMessage.type(), mozilla::ipc::UnknownSide, aDirection,
aPhase, aMessage.is_sync());
PROFILER_ADD_MARKER_WITH_PAYLOAD(
"IPC", IPC, IPCMarkerPayload,
(aOtherPid, aMessage.seqno(), aMessage.type(),
mozilla::ipc::UnknownSide, aDirection, aPhase, aMessage.is_sync(),
mozilla::TimeStamp::NowUnfuzzed()));
}
#endif
}

Просмотреть файл

@ -37,6 +37,10 @@
using namespace mozilla::tasktracer;
#endif
#ifdef MOZ_GECKO_PROFILER
# include "ProfilerMarkerPayload.h"
#endif
// Undo the damage done by mozzconf.h
#undef compress
@ -2785,11 +2789,11 @@ void MessageChannel::AddProfilerMarker(const IPC::Message& aMessage,
if (profiler_feature_active(ProfilerFeature::IPCMessages)) {
int32_t pid = mListener->OtherPidMaybeInvalid();
if (pid != kInvalidProcessId) {
// The current timestamp must be given to the `IPCMarker` payload.
const TimeStamp now = TimeStamp::NowUnfuzzed();
PROFILER_MARKER("IPC", IPC, MarkerTiming::InstantAt(now), IPCMarker, now,
now, pid, aMessage.seqno(), aMessage.type(), mSide,
aDirection, MessagePhase::Endpoint, aMessage.is_sync());
PROFILER_ADD_MARKER_WITH_PAYLOAD(
"IPC", IPC, IPCMarkerPayload,
(pid, aMessage.seqno(), aMessage.type(), mSide, aDirection,
MessagePhase::Endpoint, aMessage.is_sync(),
TimeStamp::NowUnfuzzed()));
}
}
#endif

Просмотреть файл

@ -29,10 +29,6 @@
#include "MessageLink.h"
#include "mozilla/ipc/Transport.h"
#ifdef MOZ_GECKO_PROFILER
# include "mozilla/ProfilerMarkersPrerequisites.h"
#endif
class nsIEventTarget;
namespace mozilla {
@ -883,74 +879,4 @@ struct ParamTraits<mozilla::ipc::ResponseRejectReason>
mozilla::ipc::ResponseRejectReason::EndGuard_> {};
} // 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

Просмотреть файл

@ -23,10 +23,6 @@
#include <objbase.h>
#include <objidlbase.h>
#ifdef MOZ_GECKO_PROFILER
# include "mozilla/ProfilerMarkerTypes.h"
#endif
// {9DBE6B28-E5E7-4FDE-AF00-9404604E74DC}
static const GUID GUID_MozProfilerMarkerExtension = {
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()) {
nsAutoCString markerName;
BuildMarkerName(aIid, markerName);
PROFILER_MARKER(markerName, IPC, mozilla::MarkerTiming::IntervalStart(),
Tracing, "MSCOM");
PROFILER_TRACING_MARKER("MSCOM", markerName.get(), IPC,
TRACING_INTERVAL_START);
}
if (aOutDataSize) {
@ -154,8 +150,8 @@ void ProfilerMarkerChannelHook::ClientNotify(REFGUID aExtensionId, REFIID aIid,
if (NS_IsMainThread() && aExtensionId == GUID_MozProfilerMarkerExtension) {
nsAutoCString markerName;
BuildMarkerName(aIid, markerName);
PROFILER_MARKER(markerName, IPC, mozilla::MarkerTiming::IntervalEnd(),
Tracing, "MSCOM");
PROFILER_TRACING_MARKER("MSCOM", markerName.get(), IPC,
TRACING_INTERVAL_END);
}
}

Просмотреть файл

@ -63,6 +63,9 @@
#include "nsIXULRuntime.h"
#include "nsJSPrincipals.h"
#include "ExpandedPrincipal.h"
#ifdef MOZ_GECKO_PROFILER
# include "ProfilerMarkerPayload.h"
#endif
#if defined(XP_LINUX) && !defined(ANDROID)
// For getrlimit and min/max.
@ -588,7 +591,9 @@ bool XPCJSContext::InterruptCallback(JSContext* cx) {
if (const char* file = scriptFilename.get()) {
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

Просмотреть файл

@ -8,15 +8,16 @@
#define mozilla_AutoProfilerStyleMarker_h
#include "mozilla/Attributes.h"
#include "mozilla/ProfilerMarkers.h"
#include "mozilla/ServoTraversalStatistics.h"
#include "mozilla/TimeStamp.h"
#include "GeckoProfiler.h"
#include "ProfilerMarkerPayload.h"
namespace mozilla {
class MOZ_RAII AutoProfilerStyleMarker {
public:
explicit AutoProfilerStyleMarker(UniquePtr<ProfileChunkedBuffer> aCause,
explicit AutoProfilerStyleMarker(UniqueProfilerBacktrace aCause,
const Maybe<uint64_t>& aInnerWindowID)
: mActive(profiler_can_accept_markers()),
mStartTime(TimeStamp::Now()),
@ -35,57 +36,17 @@ class MOZ_RAII AutoProfilerStyleMarker {
if (!mActive) {
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;
profiler_add_marker("Styles", geckoprofiler::category::LAYOUT,
{MarkerTiming::IntervalUntilNowFrom(mStartTime),
MarkerStack::TakeBacktrace(std::move(mCause)),
MarkerInnerWindowId(mInnerWindowID)},
StyleMarker{},
ServoTraversalStatistics::sSingleton.mElementsTraversed,
ServoTraversalStatistics::sSingleton.mElementsStyled,
ServoTraversalStatistics::sSingleton.mElementsMatched,
ServoTraversalStatistics::sSingleton.mStylesShared,
ServoTraversalStatistics::sSingleton.mStylesReused);
PROFILER_ADD_MARKER_WITH_PAYLOAD(
"Styles", LAYOUT, StyleMarkerPayload,
(mStartTime, TimeStamp::Now(), std::move(mCause),
ServoTraversalStatistics::sSingleton, mInnerWindowID));
}
private:
bool mActive;
TimeStamp mStartTime;
UniquePtr<ProfileChunkedBuffer> mCause;
UniqueProfilerBacktrace mCause;
Maybe<uint64_t> mInnerWindowID;
};

Просмотреть файл

@ -9565,7 +9565,7 @@ bool PresShell::DoReflow(nsIFrame* target, bool aInterruptible,
innerWindowID = Some(window->WindowID());
}
AutoProfilerTracing tracingLayoutFlush(
"Paint", "Reflow", geckoprofiler::category::LAYOUT,
"Paint", "Reflow", JS::ProfilingCategoryPair::LAYOUT,
std::move(mReflowCause), innerWindowID);
mReflowCause = nullptr;
#endif

Просмотреть файл

@ -2861,8 +2861,8 @@ class PresShell final : public nsStubDocumentObserver,
// 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
// one that caused a call to SetNeedStyleFlush() / SetNeedLayoutFlush()).
UniquePtr<ProfileChunkedBuffer> mStyleCause;
UniquePtr<ProfileChunkedBuffer> mReflowCause;
UniqueProfilerBacktrace mStyleCause;
UniqueProfilerBacktrace mReflowCause;
#endif
nsTArray<UniquePtr<DelayedEvent>> mDelayedEvents;

Просмотреть файл

@ -23,7 +23,7 @@ void PresShell::SetNeedLayoutFlush() {
#ifdef MOZ_GECKO_PROFILER
if (!mReflowCause) {
mReflowCause = profiler_capture_backtrace();
mReflowCause = profiler_get_backtrace();
}
#endif
@ -40,7 +40,7 @@ void PresShell::SetNeedStyleFlush() {
#ifdef MOZ_GECKO_PROFILER
if (!mStyleCause) {
mStyleCause = profiler_capture_backtrace();
mStyleCause = profiler_get_backtrace();
}
#endif

Просмотреть файл

@ -129,10 +129,6 @@
#include "nsTextNode.h"
#include "ActiveLayerTracker.h"
#ifdef MOZ_GECKO_PROFILER
# include "mozilla/ProfilerMarkerTypes.h"
#endif
using namespace mozilla;
using namespace mozilla::dom;
@ -8198,8 +8194,9 @@ static nsIFrame* FindPreviousNonWhitespaceSibling(nsIFrame* aFrame) {
bool nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval(
nsIFrame* aFrame) {
#define TRACE(reason) \
PROFILER_MARKER("MaybeRecreateContainerForFrameRemoval: " reason, LAYOUT, \
{}, Tracing, "Layout")
PROFILER_TRACING_MARKER("Layout", \
"MaybeRecreateContainerForFrameRemoval: " reason, \
LAYOUT, TRACING_EVENT)
MOZ_ASSERT(aFrame, "Must have a frame");
MOZ_ASSERT(aFrame->GetParent(), "Frame shouldn't be root");
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
// detect this by checking FrameConstructionItems in WipeContainingBlock().
// Otherwise, we would have already wiped the multi-column containing block.
PROFILER_MARKER("Reframe multi-column after constructing frame list",
LAYOUT, {}, Tracing, "Layout");
PROFILER_TRACING_MARKER(
"Layout", "Reframe multi-column after constructing frame list", LAYOUT,
TRACING_EVENT);
// aFrameList can contain placeholder frames. In order to destroy their
// 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) {
#define TRACE(reason) \
PROFILER_MARKER("WipeInsertionParent: " reason, LAYOUT, {}, Tracing, \
"Layout");
#define TRACE(reason) \
PROFILER_TRACING_MARKER("Layout", "WipeInsertionParent: " reason, LAYOUT, \
TRACING_EVENT)
const LayoutFrameType frameType = aFrame->Type();
@ -11110,9 +11108,9 @@ bool nsCSSFrameConstructor::WipeContainingBlock(
nsFrameConstructorState& aState, nsIFrame* aContainingBlock,
nsIFrame* aFrame, FrameConstructionItemList& aItems, bool aIsAppend,
nsIFrame* aPrevSibling) {
#define TRACE(reason) \
PROFILER_MARKER("WipeContainingBlock: " reason, LAYOUT, {}, Tracing, \
"Layout");
#define TRACE(reason) \
PROFILER_TRACING_MARKER("Layout", "WipeContainingBlock: " reason, LAYOUT, \
TRACING_EVENT)
if (aItems.IsEmpty()) {
return false;

Просмотреть файл

@ -2064,8 +2064,9 @@ void nsRefreshDriver::Tick(VsyncId aId, TimeStamp aNowTime) {
// On top level content pages keep the timer running initially so that we
// paint the page soon enough.
if (ShouldKeepTimerRunningWhileWaitingForFirstContentfulPaint()) {
PROFILER_MARKER("RefreshDriver waiting for first contentful paint",
GRAPHICS, {}, Tracing, "Paint");
PROFILER_TRACING_MARKER(
"Paint", "RefreshDriver waiting for first contentful paint", GRAPHICS,
TRACING_EVENT);
} else {
StopTimer();
}

Просмотреть файл

@ -14,6 +14,9 @@
#include "base/basictypes.h"
#include "GeckoProfiler.h"
#ifdef MOZ_GECKO_PROFILER
# include "ProfilerMarkerPayload.h"
#endif
#include "MainThreadUtils.h"
#include "mozilla/ArenaAllocatorExtensions.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
// order to access private members.
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>
static nsresult GetPrefValue(const char* aPrefName, T&& aResult,
PrefValueKind aKind) {
@ -4340,11 +4291,10 @@ struct Internals {
#ifdef MOZ_GECKO_PROFILER
if (profiler_feature_active(ProfilerFeature::PreferenceReads)) {
profiler_add_marker(
"PreferenceRead", baseprofiler::category::OTHER_PreferenceRead, {},
PreferenceReadMarker{},
ProfilerString8View::WrapNullTerminatedString(aPrefName),
Some(aKind), pref->Type(), PrefValueToString(aResult));
PROFILER_ADD_MARKER_WITH_PAYLOAD(
"PreferenceRead", OTHER_PreferenceRead, PrefMarkerPayload,
(aPrefName, Some(aKind), Some(pref->Type()),
PrefValueToString(aResult), TimeStamp::Now()));
}
#endif
}
@ -4361,12 +4311,10 @@ struct Internals {
#ifdef MOZ_GECKO_PROFILER
if (profiler_feature_active(ProfilerFeature::PreferenceReads)) {
profiler_add_marker(
"PreferenceRead", baseprofiler::category::OTHER_PreferenceRead, {},
PreferenceReadMarker{},
ProfilerString8View::WrapNullTerminatedString(aName),
Nothing() /* indicates Shared */, pref->Type(),
PrefValueToString(aResult));
PROFILER_ADD_MARKER_WITH_PAYLOAD(
"PreferenceRead", OTHER_PreferenceRead, PrefMarkerPayload,
(aName, Nothing() /* indicates Shared */, Some(pref->Type()),
PrefValueToString(aResult), TimeStamp::Now()));
}
#endif
}

Просмотреть файл

@ -785,20 +785,13 @@ void ProfileBuffer::StreamMarkersToJSON(SpliceableJSONWriter& aWriter,
MOZ_ASSERT(static_cast<ProfileBufferEntry::KindUnderlyingType>(type) <
static_cast<ProfileBufferEntry::KindUnderlyingType>(
ProfileBufferEntry::Kind::MODERN_LIMIT));
bool entryWasFullyRead = false;
if (type == ProfileBufferEntry::Kind::Marker) {
entryWasFullyRead = ::mozilla::base_profiler_markers_detail::
DeserializeAfterKindAndStream(
aER, aWriter, aThreadId,
[&](ProfileChunkedBuffer& aChunkedBuffer) {
ProfilerBacktrace backtrace("", &aChunkedBuffer);
backtrace.StreamJSON(aWriter, TimeStamp::ProcessCreation(),
aUniqueStacks);
});
}
if (!entryWasFullyRead) {
if (type != ProfileBufferEntry::Kind::Marker ||
!::mozilla::base_profiler_markers_detail::DeserializeAfterKindAndStream(
aER, aWriter, aThreadId, [&](ProfileChunkedBuffer& aChunkedBuffer) {
ProfilerBacktrace backtrace("", &aChunkedBuffer);
backtrace.StreamJSON(aWriter, TimeStamp::ProcessCreation(),
aUniqueStacks);
})) {
// Not a marker, or marker for another thread.
// We probably didn't read the whole entry, so we need to skip to the end.
aER.SetRemainingBytes(0);

Просмотреть файл

@ -29,7 +29,137 @@
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() {
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
#endif // MOZ_GECKO_PROFILER

Просмотреть файл

@ -160,25 +160,6 @@ struct Text {
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
// 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) {}
// Implicit constructor from std::string.
constexpr MOZ_IMPLICIT ProfilerStringView(
const std::basic_string<CHAR>& aString)
constexpr MOZ_IMPLICIT ProfilerStringView(const std::string& aString)
: ProfilerStringView(aString.data(), aString.length(),
Ownership::Reference) {}
@ -142,7 +141,7 @@ class MOZ_STACK_CLASS ProfilerStringView {
static constexpr ProfilerStringView WrapNullTerminatedString(
const CHAR* aString) {
return ProfilerStringView(
aString, aString ? std::char_traits<CHAR>::length(aString) : 0,
aString, aString ? std::char_traits<char>::length(aString) : 0,
Ownership::Reference);
}
@ -183,8 +182,8 @@ class MOZ_STACK_CLASS ProfilerStringView {
}
// No `IsOwned...()` because it's a secret, only used internally!
[[nodiscard]] operator Span<const CHAR>() const {
return Span<const CHAR>(Data(), Length());
[[nodiscard]] operator Span<const char>() const {
return Span<const char>(Data(), Length());
}
private:

Просмотреть файл

@ -70,8 +70,11 @@ enum class ProfileBufferEntryKind : ProfileBufferEntryKindUnderlyingType {
// Any value starting here does *not* represent a `ProfileBufferEntry` and
// requires separate decoding and handling.
// Markers and their data.
Marker = LEGACY_LIMIT,
// Marker data, including payload.
MarkerData = LEGACY_LIMIT,
// Markers from 2.0 specs.
Marker,
// Optional between TimeBeforeCompactStack and CompactStack.
UnresponsiveDurationMs,

Просмотреть файл

@ -749,15 +749,14 @@ struct ProfileBufferEntryWriter::Serializer<ProfileBufferRawPointer<T>> {
// wrapper necessary.
template <typename T>
struct ProfileBufferEntryReader::Deserializer<ProfileBufferRawPointer<T>> {
static void ReadInto(ProfileBufferEntryReader& aER,
ProfileBufferRawPointer<T>& aPtr) {
aER.ReadBytes(&aPtr.mRawPointer, sizeof(aPtr));
static void ReadInto(ProfileBufferEntryReader& aER, T*& aPtr) {
aER.ReadBytes(&aPtr, sizeof(aPtr));
}
static ProfileBufferRawPointer<T> Read(ProfileBufferEntryReader& aER) {
ProfileBufferRawPointer<T> rawPointer;
ReadInto(aER, rawPointer);
return rawPointer;
static T* Read(ProfileBufferEntryReader& aER) {
T* ptr;
ReadInto(aER, ptr);
return ptr;
}
};

Просмотреть файл

@ -3014,152 +3014,126 @@ void TestLiteralEmptyStringView() {
printf("TestLiteralEmptyStringView done\n");
}
template <typename CHAR>
void TestProfilerStringView() {
if constexpr (std::is_same_v<CHAR, char>) {
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");
}
printf("TestProfilerStringView...\n");
// Used to verify implicit constructions, as this will normally be used in
// function parameters.
auto BSV = [](mozilla::ProfilerStringView<CHAR>&& aBSV) {
return std::move(aBSV);
};
// 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'),
auto BS8V = [](mozilla::ProfilerString8View&& aBS8V) {
return std::move(aBS8V);
};
// Literal empty string.
MOZ_RELEASE_ASSERT(BSV(empty).Data());
MOZ_RELEASE_ASSERT(BSV(empty).Data()[0] == CHAR('\0'));
MOZ_RELEASE_ASSERT(BSV(empty).Length() == 0);
MOZ_RELEASE_ASSERT(BSV(empty).IsLiteral());
MOZ_RELEASE_ASSERT(!BSV(empty).IsReference());
MOZ_RELEASE_ASSERT(BS8V("").Data());
MOZ_RELEASE_ASSERT(BS8V("").Data()[0] == '\0');
MOZ_RELEASE_ASSERT(BS8V("").Length() == 0);
MOZ_RELEASE_ASSERT(BS8V("").IsLiteral());
MOZ_RELEASE_ASSERT(!BS8V("").IsReference());
// Literal non-empty string.
MOZ_RELEASE_ASSERT(BSV(hi).Data());
MOZ_RELEASE_ASSERT(BSV(hi).Data()[0] == CHAR('h'));
MOZ_RELEASE_ASSERT(BSV(hi).Data()[1] == CHAR('i'));
MOZ_RELEASE_ASSERT(BSV(hi).Data()[2] == CHAR('\0'));
MOZ_RELEASE_ASSERT(BSV(hi).Length() == 2);
MOZ_RELEASE_ASSERT(BSV(hi).IsLiteral());
MOZ_RELEASE_ASSERT(!BSV(hi).IsReference());
MOZ_RELEASE_ASSERT(BS8V("hi").Data());
MOZ_RELEASE_ASSERT(BS8V("hi").Data()[0] == 'h');
MOZ_RELEASE_ASSERT(BS8V("hi").Data()[1] == 'i');
MOZ_RELEASE_ASSERT(BS8V("hi").Data()[2] == '\0');
MOZ_RELEASE_ASSERT(BS8V("hi").Length() == 2);
MOZ_RELEASE_ASSERT(BS8V("hi").IsLiteral());
MOZ_RELEASE_ASSERT(!BS8V("hi").IsReference());
// std::string_view to a literal empty string.
MOZ_RELEASE_ASSERT(BSV(std::basic_string_view<CHAR>(empty)).Data());
MOZ_RELEASE_ASSERT(BSV(std::basic_string_view<CHAR>(empty)).Data()[0] ==
CHAR('\0'));
MOZ_RELEASE_ASSERT(BSV(std::basic_string_view<CHAR>(empty)).Length() == 0);
MOZ_RELEASE_ASSERT(!BSV(std::basic_string_view<CHAR>(empty)).IsLiteral());
MOZ_RELEASE_ASSERT(BSV(std::basic_string_view<CHAR>(empty)).IsReference());
MOZ_RELEASE_ASSERT(BS8V(std::string_view("")).Data());
MOZ_RELEASE_ASSERT(BS8V(std::string_view("")).Data()[0] == '\0');
MOZ_RELEASE_ASSERT(BS8V(std::string_view("")).Length() == 0);
MOZ_RELEASE_ASSERT(!BS8V(std::string_view("")).IsLiteral());
MOZ_RELEASE_ASSERT(BS8V(std::string_view("")).IsReference());
// std::string_view to a literal non-empty string.
MOZ_RELEASE_ASSERT(BSV(std::basic_string_view<CHAR>(hi)).Data());
MOZ_RELEASE_ASSERT(BSV(std::basic_string_view<CHAR>(hi)).Data()[0] ==
CHAR('h'));
MOZ_RELEASE_ASSERT(BSV(std::basic_string_view<CHAR>(hi)).Data()[1] ==
CHAR('i'));
MOZ_RELEASE_ASSERT(BSV(std::basic_string_view<CHAR>(hi)).Data()[2] ==
CHAR('\0'));
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());
MOZ_RELEASE_ASSERT(BS8V(std::string_view("hi")).Data());
MOZ_RELEASE_ASSERT(BS8V(std::string_view("hi")).Data()[0] == 'h');
MOZ_RELEASE_ASSERT(BS8V(std::string_view("hi")).Data()[1] == 'i');
MOZ_RELEASE_ASSERT(BS8V(std::string_view("hi")).Data()[2] == '\0');
MOZ_RELEASE_ASSERT(BS8V(std::string_view("hi")).Length() == 2);
MOZ_RELEASE_ASSERT(!BS8V(std::string_view("hi")).IsLiteral());
MOZ_RELEASE_ASSERT(BS8V(std::string_view("hi")).IsReference());
// Default std::string_view points at nullptr, ProfilerStringView converts it
// to the literal empty string.
MOZ_RELEASE_ASSERT(!std::basic_string_view<CHAR>().data());
MOZ_RELEASE_ASSERT(BSV(std::basic_string_view<CHAR>()).Data());
MOZ_RELEASE_ASSERT(BSV(std::basic_string_view<CHAR>()).Data()[0] ==
CHAR('\0'));
MOZ_RELEASE_ASSERT(BSV(std::basic_string_view<CHAR>()).Length() == 0);
MOZ_RELEASE_ASSERT(BSV(std::basic_string_view<CHAR>()).IsLiteral());
MOZ_RELEASE_ASSERT(!BSV(std::basic_string_view<CHAR>()).IsReference());
MOZ_RELEASE_ASSERT(!std::string_view().data());
MOZ_RELEASE_ASSERT(BS8V(std::string_view()).Data());
MOZ_RELEASE_ASSERT(BS8V(std::string_view()).Data()[0] == '\0');
MOZ_RELEASE_ASSERT(BS8V(std::string_view()).Length() == 0);
MOZ_RELEASE_ASSERT(BS8V(std::string_view()).IsLiteral());
MOZ_RELEASE_ASSERT(!BS8V(std::string_view()).IsReference());
// std::string to a literal empty string.
MOZ_RELEASE_ASSERT(BSV(std::basic_string<CHAR>(empty)).Data());
MOZ_RELEASE_ASSERT(BSV(std::basic_string<CHAR>(empty)).Data()[0] ==
CHAR('\0'));
MOZ_RELEASE_ASSERT(BSV(std::basic_string<CHAR>(empty)).Length() == 0);
MOZ_RELEASE_ASSERT(!BSV(std::basic_string<CHAR>(empty)).IsLiteral());
MOZ_RELEASE_ASSERT(BSV(std::basic_string<CHAR>(empty)).IsReference());
MOZ_RELEASE_ASSERT(BS8V(std::string("")).Data());
MOZ_RELEASE_ASSERT(BS8V(std::string("")).Data()[0] == '\0');
MOZ_RELEASE_ASSERT(BS8V(std::string("")).Length() == 0);
MOZ_RELEASE_ASSERT(!BS8V(std::string("")).IsLiteral());
MOZ_RELEASE_ASSERT(BS8V(std::string("")).IsReference());
// std::string to a literal non-empty string.
MOZ_RELEASE_ASSERT(BSV(std::basic_string<CHAR>(hi)).Data());
MOZ_RELEASE_ASSERT(BSV(std::basic_string<CHAR>(hi)).Data()[0] == CHAR('h'));
MOZ_RELEASE_ASSERT(BSV(std::basic_string<CHAR>(hi)).Data()[1] == CHAR('i'));
MOZ_RELEASE_ASSERT(BSV(std::basic_string<CHAR>(hi)).Data()[2] == CHAR('\0'));
MOZ_RELEASE_ASSERT(BSV(std::basic_string<CHAR>(hi)).Length() == 2);
MOZ_RELEASE_ASSERT(!BSV(std::basic_string<CHAR>(hi)).IsLiteral());
MOZ_RELEASE_ASSERT(BSV(std::basic_string<CHAR>(hi)).IsReference());
MOZ_RELEASE_ASSERT(BS8V(std::string("hi")).Data());
MOZ_RELEASE_ASSERT(BS8V(std::string("hi")).Data()[0] == 'h');
MOZ_RELEASE_ASSERT(BS8V(std::string("hi")).Data()[1] == 'i');
MOZ_RELEASE_ASSERT(BS8V(std::string("hi")).Data()[2] == '\0');
MOZ_RELEASE_ASSERT(BS8V(std::string("hi")).Length() == 2);
MOZ_RELEASE_ASSERT(!BS8V(std::string("hi")).IsLiteral());
MOZ_RELEASE_ASSERT(BS8V(std::string("hi")).IsReference());
// Default std::string contains an empty null-terminated string.
MOZ_RELEASE_ASSERT(std::basic_string<CHAR>().data());
MOZ_RELEASE_ASSERT(BSV(std::basic_string<CHAR>()).Data());
MOZ_RELEASE_ASSERT(BSV(std::basic_string<CHAR>()).Data()[0] == CHAR('\0'));
MOZ_RELEASE_ASSERT(BSV(std::basic_string<CHAR>()).Length() == 0);
MOZ_RELEASE_ASSERT(!BSV(std::basic_string<CHAR>()).IsLiteral());
MOZ_RELEASE_ASSERT(BSV(std::basic_string<CHAR>()).IsReference());
// Default std::string_view contains an empty null-terminated string.
MOZ_RELEASE_ASSERT(std::string().data());
MOZ_RELEASE_ASSERT(BS8V(std::string()).Data());
MOZ_RELEASE_ASSERT(BS8V(std::string()).Data()[0] == '\0');
MOZ_RELEASE_ASSERT(BS8V(std::string()).Length() == 0);
MOZ_RELEASE_ASSERT(!BS8V(std::string()).IsLiteral());
MOZ_RELEASE_ASSERT(BS8V(std::string()).IsReference());
// Class that quacks like nsTString (with Data(), Length(), IsLiteral()), to
// check that ProfilerStringView can read from them.
class FakeNsTString {
class FakeNsCString {
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) {}
const CHAR* Data() const { return mData; }
const char* Data() const { return mData; }
size_t Length() const { return mLength; }
bool IsLiteral() const { return mIsLiteral; }
private:
const CHAR* mData;
const char* mData;
size_t mLength;
bool mIsLiteral;
};
// FakeNsTString to nullptr.
MOZ_RELEASE_ASSERT(BSV(FakeNsTString(nullptr, 0, true)).Data());
MOZ_RELEASE_ASSERT(BSV(FakeNsTString(nullptr, 0, true)).Data()[0] ==
CHAR('\0'));
MOZ_RELEASE_ASSERT(BSV(FakeNsTString(nullptr, 0, true)).Length() == 0);
MOZ_RELEASE_ASSERT(BSV(FakeNsTString(nullptr, 0, true)).IsLiteral());
MOZ_RELEASE_ASSERT(!BSV(FakeNsTString(nullptr, 0, true)).IsReference());
// FakeNsCString to nullptr.
MOZ_RELEASE_ASSERT(BS8V(FakeNsCString(nullptr, 0, true)).Data());
MOZ_RELEASE_ASSERT(BS8V(FakeNsCString(nullptr, 0, true)).Data()[0] == '\0');
MOZ_RELEASE_ASSERT(BS8V(FakeNsCString(nullptr, 0, true)).Length() == 0);
MOZ_RELEASE_ASSERT(BS8V(FakeNsCString(nullptr, 0, true)).IsLiteral());
MOZ_RELEASE_ASSERT(!BS8V(FakeNsCString(nullptr, 0, true)).IsReference());
// FakeNsTString to a literal empty string.
MOZ_RELEASE_ASSERT(BSV(FakeNsTString(empty, 0, true)).Data());
MOZ_RELEASE_ASSERT(BSV(FakeNsTString(empty, 0, true)).Data()[0] ==
CHAR('\0'));
MOZ_RELEASE_ASSERT(BSV(FakeNsTString(empty, 0, true)).Length() == 0);
MOZ_RELEASE_ASSERT(BSV(FakeNsTString(empty, 0, true)).IsLiteral());
MOZ_RELEASE_ASSERT(!BSV(FakeNsTString(empty, 0, true)).IsReference());
// FakeNsCString to a literal empty string.
MOZ_RELEASE_ASSERT(BS8V(FakeNsCString("", 0, true)).Data());
MOZ_RELEASE_ASSERT(BS8V(FakeNsCString("", 0, true)).Data()[0] == '\0');
MOZ_RELEASE_ASSERT(BS8V(FakeNsCString("", 0, true)).Length() == 0);
MOZ_RELEASE_ASSERT(BS8V(FakeNsCString("", 0, true)).IsLiteral());
MOZ_RELEASE_ASSERT(!BS8V(FakeNsCString("", 0, true)).IsReference());
// FakeNsTString to a literal non-empty string.
MOZ_RELEASE_ASSERT(BSV(FakeNsTString(hi, 2, true)).Data());
MOZ_RELEASE_ASSERT(BSV(FakeNsTString(hi, 2, true)).Data()[0] == CHAR('h'));
MOZ_RELEASE_ASSERT(BSV(FakeNsTString(hi, 2, true)).Data()[1] == CHAR('i'));
MOZ_RELEASE_ASSERT(BSV(FakeNsTString(hi, 2, true)).Data()[2] == CHAR('\0'));
MOZ_RELEASE_ASSERT(BSV(FakeNsTString(hi, 2, true)).Length() == 2);
MOZ_RELEASE_ASSERT(BSV(FakeNsTString(hi, 2, true)).IsLiteral());
MOZ_RELEASE_ASSERT(!BSV(FakeNsTString(hi, 2, true)).IsReference());
// FakeNsCString to a literal non-empty string.
MOZ_RELEASE_ASSERT(BS8V(FakeNsCString("hi", 2, true)).Data());
MOZ_RELEASE_ASSERT(BS8V(FakeNsCString("hi", 2, true)).Data()[0] == 'h');
MOZ_RELEASE_ASSERT(BS8V(FakeNsCString("hi", 2, true)).Data()[1] == 'i');
MOZ_RELEASE_ASSERT(BS8V(FakeNsCString("hi", 2, true)).Data()[2] == '\0');
MOZ_RELEASE_ASSERT(BS8V(FakeNsCString("hi", 2, true)).Length() == 2);
MOZ_RELEASE_ASSERT(BS8V(FakeNsCString("hi", 2, true)).IsLiteral());
MOZ_RELEASE_ASSERT(!BS8V(FakeNsCString("hi", 2, true)).IsReference());
// FakeNsTString to a non-literal non-empty string.
MOZ_RELEASE_ASSERT(BSV(FakeNsTString(hi, 2, false)).Data());
MOZ_RELEASE_ASSERT(BSV(FakeNsTString(hi, 2, false)).Data()[0] == CHAR('h'));
MOZ_RELEASE_ASSERT(BSV(FakeNsTString(hi, 2, false)).Data()[1] == CHAR('i'));
MOZ_RELEASE_ASSERT(BSV(FakeNsTString(hi, 2, false)).Data()[2] == CHAR('\0'));
MOZ_RELEASE_ASSERT(BSV(FakeNsTString(hi, 2, false)).Length() == 2);
MOZ_RELEASE_ASSERT(!BSV(FakeNsTString(hi, 2, false)).IsLiteral());
MOZ_RELEASE_ASSERT(BSV(FakeNsTString(hi, 2, false)).IsReference());
// FakeNsCString to a non-literal non-empty string.
MOZ_RELEASE_ASSERT(BS8V(FakeNsCString("hi", 2, false)).Data());
MOZ_RELEASE_ASSERT(BS8V(FakeNsCString("hi", 2, false)).Data()[0] == 'h');
MOZ_RELEASE_ASSERT(BS8V(FakeNsCString("hi", 2, false)).Data()[1] == 'i');
MOZ_RELEASE_ASSERT(BS8V(FakeNsCString("hi", 2, false)).Data()[2] == '\0');
MOZ_RELEASE_ASSERT(BS8V(FakeNsCString("hi", 2, false)).Length() == 2);
MOZ_RELEASE_ASSERT(!BS8V(FakeNsCString("hi", 2, false)).IsLiteral());
MOZ_RELEASE_ASSERT(BS8V(FakeNsCString("hi", 2, false)).IsReference());
// Serialization and deserialization (with ownership).
constexpr size_t bufferMaxSize = 1024;
@ -3168,73 +3142,69 @@ void TestProfilerStringView() {
ProfileChunkedBuffer cb(ProfileChunkedBuffer::ThreadSafety::WithMutex, cm);
// Literal string, serialized as raw pointer.
MOZ_RELEASE_ASSERT(cb.PutObject(BSV(hi)));
MOZ_RELEASE_ASSERT(cb.PutObject(BS8V("hi")));
{
unsigned read = 0;
ProfilerStringView<CHAR> outerBSV;
ProfilerString8View outerBS8V;
cb.ReadEach([&](ProfileBufferEntryReader& aER) {
++read;
auto bsv = aER.ReadObject<ProfilerStringView<CHAR>>();
MOZ_RELEASE_ASSERT(bsv.Data());
MOZ_RELEASE_ASSERT(bsv.Data()[0] == CHAR('h'));
MOZ_RELEASE_ASSERT(bsv.Data()[1] == CHAR('i'));
MOZ_RELEASE_ASSERT(bsv.Data()[2] == CHAR('\0'));
MOZ_RELEASE_ASSERT(bsv.Length() == 2);
MOZ_RELEASE_ASSERT(bsv.IsLiteral());
MOZ_RELEASE_ASSERT(!bsv.IsReference());
outerBSV = std::move(bsv);
auto bs8v = aER.ReadObject<ProfilerString8View>();
MOZ_RELEASE_ASSERT(bs8v.Data());
MOZ_RELEASE_ASSERT(bs8v.Data()[0] == 'h');
MOZ_RELEASE_ASSERT(bs8v.Data()[1] == 'i');
MOZ_RELEASE_ASSERT(bs8v.Data()[2] == '\0');
MOZ_RELEASE_ASSERT(bs8v.Length() == 2);
MOZ_RELEASE_ASSERT(bs8v.IsLiteral());
MOZ_RELEASE_ASSERT(!bs8v.IsReference());
outerBS8V = std::move(bs8v);
});
MOZ_RELEASE_ASSERT(read == 1);
MOZ_RELEASE_ASSERT(outerBSV.Data());
MOZ_RELEASE_ASSERT(outerBSV.Data()[0] == CHAR('h'));
MOZ_RELEASE_ASSERT(outerBSV.Data()[1] == CHAR('i'));
MOZ_RELEASE_ASSERT(outerBSV.Data()[2] == CHAR('\0'));
MOZ_RELEASE_ASSERT(outerBSV.Length() == 2);
MOZ_RELEASE_ASSERT(outerBSV.IsLiteral());
MOZ_RELEASE_ASSERT(!outerBSV.IsReference());
MOZ_RELEASE_ASSERT(outerBS8V.Data());
MOZ_RELEASE_ASSERT(outerBS8V.Data()[0] == 'h');
MOZ_RELEASE_ASSERT(outerBS8V.Data()[1] == 'i');
MOZ_RELEASE_ASSERT(outerBS8V.Data()[2] == '\0');
MOZ_RELEASE_ASSERT(outerBS8V.Length() == 2);
MOZ_RELEASE_ASSERT(outerBS8V.IsLiteral());
MOZ_RELEASE_ASSERT(!outerBS8V.IsReference());
}
cb.Clear();
// Non-literal string, content is serialized.
std::basic_string<CHAR> hiString(hi);
MOZ_RELEASE_ASSERT(cb.PutObject(BSV(hiString)));
std::string hiString("hi");
MOZ_RELEASE_ASSERT(cb.PutObject(BS8V(hiString)));
{
unsigned read = 0;
ProfilerStringView<CHAR> outerBSV;
ProfilerString8View outerBS8V;
cb.ReadEach([&](ProfileBufferEntryReader& aER) {
++read;
auto bsv = aER.ReadObject<ProfilerStringView<CHAR>>();
MOZ_RELEASE_ASSERT(bsv.Data());
MOZ_RELEASE_ASSERT(bsv.Data() != hiString.data());
MOZ_RELEASE_ASSERT(bsv.Data()[0] == CHAR('h'));
MOZ_RELEASE_ASSERT(bsv.Data()[1] == CHAR('i'));
MOZ_RELEASE_ASSERT(bsv.Data()[2] == CHAR('\0'));
MOZ_RELEASE_ASSERT(bsv.Length() == 2);
auto bs8v = aER.ReadObject<ProfilerString8View>();
MOZ_RELEASE_ASSERT(bs8v.Data());
MOZ_RELEASE_ASSERT(bs8v.Data() != hiString.data());
MOZ_RELEASE_ASSERT(bs8v.Data()[0] == 'h');
MOZ_RELEASE_ASSERT(bs8v.Data()[1] == 'i');
MOZ_RELEASE_ASSERT(bs8v.Data()[2] == '\0');
MOZ_RELEASE_ASSERT(bs8v.Length() == 2);
// Special ownership case, neither a literal nor a reference!
MOZ_RELEASE_ASSERT(!bsv.IsLiteral());
MOZ_RELEASE_ASSERT(!bsv.IsReference());
MOZ_RELEASE_ASSERT(!bs8v.IsLiteral());
MOZ_RELEASE_ASSERT(!bs8v.IsReference());
// Test move of ownership.
outerBSV = std::move(bsv);
outerBS8V = std::move(bs8v);
// 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(outerBSV.Data());
MOZ_RELEASE_ASSERT(outerBSV.Data() != hiString.data());
MOZ_RELEASE_ASSERT(outerBSV.Data()[0] == CHAR('h'));
MOZ_RELEASE_ASSERT(outerBSV.Data()[1] == CHAR('i'));
MOZ_RELEASE_ASSERT(outerBSV.Data()[2] == CHAR('\0'));
MOZ_RELEASE_ASSERT(outerBSV.Length() == 2);
MOZ_RELEASE_ASSERT(!outerBSV.IsLiteral());
MOZ_RELEASE_ASSERT(!outerBSV.IsReference());
MOZ_RELEASE_ASSERT(outerBS8V.Data());
MOZ_RELEASE_ASSERT(outerBS8V.Data() != hiString.data());
MOZ_RELEASE_ASSERT(outerBS8V.Data()[0] == 'h');
MOZ_RELEASE_ASSERT(outerBS8V.Data()[1] == 'i');
MOZ_RELEASE_ASSERT(outerBS8V.Data()[2] == '\0');
MOZ_RELEASE_ASSERT(outerBS8V.Length() == 2);
MOZ_RELEASE_ASSERT(!outerBS8V.IsLiteral());
MOZ_RELEASE_ASSERT(!outerBS8V.IsReference());
}
if constexpr (std::is_same_v<CHAR, char>) {
printf("TestProfilerStringView<char> done\n");
} else if constexpr (std::is_same_v<CHAR, char16_t>) {
printf("TestProfilerStringView<char16_t> done\n");
}
printf("TestProfilerStringView done\n");
}
void TestProfilerDependencies() {
@ -3254,8 +3224,7 @@ void TestProfilerDependencies() {
TestBlocksRingBufferThreading();
TestBlocksRingBufferSerialization();
TestLiteralEmptyStringView();
TestProfilerStringView<char>();
TestProfilerStringView<char16_t>();
TestProfilerStringView();
}
// Increase the depth, to a maximum (to avoid too-deep recursion).
@ -3470,13 +3439,34 @@ void TestProfiler() {
"tracing", mozilla::baseprofiler::category::OTHER, {},
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(
"text", mozilla::baseprofiler::category::OTHER, {},
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(
"media sample", mozilla::baseprofiler::category::OTHER, {},
mozilla::baseprofiler::markers::MediaSampleMarker{}, 123, 456));
mozilla::baseprofiler::markers::MediaSample{}, 123, 456));
printf("Sleep 1s...\n");
{
@ -3532,7 +3522,16 @@ void TestProfiler() {
MOZ_RELEASE_ASSERT(profileSV.find("\"markerSchema\": [") != svnpos);
MOZ_RELEASE_ASSERT(profileSV.find("\"name\": \"Text\",") != 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\": \"MainThreadLongTask\",") !=
svnpos);
MOZ_RELEASE_ASSERT(profileSV.find("\"display\": [") != svnpos);
MOZ_RELEASE_ASSERT(profileSV.find("\"marker-chart\"") != svnpos);
MOZ_RELEASE_ASSERT(profileSV.find("\"marker-table\"") != svnpos);
@ -4035,13 +4034,37 @@ void TestPredefinedMarkers() {
mozilla::baseprofiler::category::OTHER, {},
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(
buffer, std::string_view("text"), mozilla::baseprofiler::category::OTHER,
{}, 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(
buffer, std::string_view("media"), mozilla::baseprofiler::category::OTHER,
{}, mozilla::baseprofiler::markers::MediaSampleMarker{}, 123, 456));
{}, mozilla::baseprofiler::markers::MediaSample{}, 123, 456));
# ifdef DEBUG
buffer.Dump();

Просмотреть файл

@ -248,7 +248,7 @@ class HttpBaseChannel : public nsHashPropertyBag,
using nsIClassifiedChannel::IsThirdPartyTrackingResource;
virtual void SetSource(UniquePtr<ProfileChunkedBuffer> aSource) override {
virtual void SetSource(UniqueProfilerBacktrace aSource) override {
mSource = std::move(aSource);
}
@ -756,7 +756,7 @@ class HttpBaseChannel : public nsHashPropertyBag,
Atomic<uint32_t, ReleaseAcquire> mThirdPartyClassificationFlags;
Atomic<uint32_t, ReleaseAcquire> mFlashPluginState;
UniquePtr<ProfileChunkedBuffer> mSource;
UniqueProfilerBacktrace mSource;
uint32_t mLoadFlags;
uint32_t mCaps;

Просмотреть файл

@ -67,6 +67,10 @@
# include "GeckoTaskTracer.h"
#endif
#ifdef MOZ_GECKO_PROFILER
# include "ProfilerMarkerPayload.h"
#endif
#include <functional>
using namespace mozilla::dom;

Просмотреть файл

@ -135,6 +135,10 @@
# include "GeckoTaskTracer.h"
#endif
#ifdef MOZ_GECKO_PROFILER
# include "ProfilerMarkerPayload.h"
#endif
namespace mozilla {
using namespace dom;

Просмотреть файл

@ -501,6 +501,6 @@ interface nsIHttpChannel : nsIIdentChannel
in AString aContentType);
%{ C++
virtual void SetSource(mozilla::UniquePtr<mozilla::ProfileChunkedBuffer> aSource) {}
virtual void SetSource(UniqueProfilerBacktrace aSource) {}
%}
};

Просмотреть файл

@ -31,6 +31,10 @@
#include "prinrval.h"
#include "prthread.h"
#ifdef MOZ_GECKO_PROFILER
# include "ProfilerMarkerPayload.h"
#endif
#include <algorithm>
// 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.
#ifdef MOZ_GECKO_PROFILER
if (profiler_can_accept_markers()) {
struct HangMarker {
static constexpr Span<const char> MarkerTypeName() {
return MakeStringSpan("BHR-detected hang");
}
static void StreamJSONMarkerData(
baseprofiler::SpliceableJSONWriter& aWriter) {}
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{});
TimeStamp endTime = TimeStamp::Now();
TimeStamp startTime = endTime - aHangTime;
AUTO_PROFILER_STATS(add_marker_with_HangMarkerPayload);
profiler_add_marker_for_thread(
mStackHelper.GetThreadId(), JS::ProfilingCategoryPair::OTHER,
"BHR-detected hang", HangMarkerPayload(startTime, endTime));
}
#endif
}

Просмотреть файл

@ -10,6 +10,7 @@
#include "platform.h"
#include "ProfileBuffer.h"
#include "ProfilerBacktrace.h"
#include "ProfilerMarkerPayload.h"
#include "jsapi.h"
#include "jsfriendapi.h"
@ -635,6 +636,7 @@ class EntryGetter {
// )+
// */
// )
// | MarkerData
// | Marker
// | ( /* Counters */
// CounterId
@ -1152,23 +1154,78 @@ void ProfileBuffer::StreamMarkersToJSON(SpliceableJSONWriter& aWriter,
MOZ_ASSERT(static_cast<ProfileBufferEntry::KindUnderlyingType>(type) <
static_cast<ProfileBufferEntry::KindUnderlyingType>(
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) {
entryWasFullyRead =
mozilla::base_profiler_markers_detail::DeserializeAfterKindAndStream(
aER, aWriter, aThreadId,
[&](ProfileChunkedBuffer& aChunkedBuffer) {
ProfilerBacktrace backtrace("", &aChunkedBuffer);
backtrace.StreamJSON(aWriter, aProcessStartTime, aUniqueStacks);
});
MOZ_ASSERT(aER.RemainingBytes() == 0);
// Now write this information to JSON with the following schema:
// [name, startTime, endTime, phase, category, data]
aUniqueStacks.mUniqueStrings->WriteElement(aWriter, name);
aWriter.DoubleElement(startTime);
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) {
// 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);
}
aER.SetRemainingBytes(0);
});
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -37,6 +37,7 @@ size_t RegisteredThread::SizeOfIncludingThis(
// Measurement of the following members may be added later if DMD finds it
// is worthwhile:
// - mPlatformData
// - mRacyRegisteredThread.mPendingMarkers
//
// The following members are not measured:
// - mThreadInfo: because it is non-owning

Просмотреть файл

@ -265,6 +265,10 @@ class ThreadIntercept {
// or disabled.
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;
// Only allow consumers to access this information if they run
@ -311,9 +315,14 @@ class ThreadIntercept {
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 int MainThreadId() { return sMainThreadId; }
};
PROFILER_THREAD_LOCAL(bool) ThreadIntercept::tlsIsBlocked;
@ -321,6 +330,8 @@ PROFILER_THREAD_LOCAL(bool) ThreadIntercept::tlsIsBlocked;
mozilla::Atomic<bool, mozilla::Relaxed>
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
// code that might allocate.
class AutoBlockIntercepts {
@ -378,7 +389,7 @@ static void AllocCallback(void* aPtr, size_t aReqSize) {
gBernoulli->trial(actualSize) &&
// Second, attempt to add a marker if the Bernoulli trial passed.
profiler_add_native_allocation_marker(
static_cast<int64_t>(actualSize),
ThreadIntercept::MainThreadId(), static_cast<int64_t>(actualSize),
reinterpret_cast<uintptr_t>(aPtr))) {
MOZ_ASSERT(gAllocationTracker,
"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.");
if (gAllocationTracker->RemoveMemoryAddressIfFound(aPtr)) {
// 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));
}
}
@ -555,7 +567,7 @@ void install_memory_hooks() {
// leak these values.
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
// 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
@ -584,7 +596,7 @@ void enable_native_allocations() {
EnsureBernoulliIsInstalled();
EnsureAllocationTrackerIsInstalled();
ThreadIntercept::EnableAllocationFeature();
ThreadIntercept::EnableAllocationFeature(aMainThreadId);
}
// This is safe to call even if native allocations hasn't been enabled.

Просмотреть файл

@ -13,7 +13,7 @@ namespace profiler {
void install_memory_hooks();
void remove_memory_hooks();
void enable_native_allocations();
void enable_native_allocations(int aMainThreadId);
void disable_native_allocations();
} // namespace profiler

Просмотреть файл

@ -37,6 +37,7 @@
#include "ProfilerChild.h"
#include "ProfilerCodeAddressService.h"
#include "ProfilerIOInterposeObserver.h"
#include "ProfilerMarkerPayload.h"
#include "ProfilerParent.h"
#include "RegisteredThread.h"
#include "shared-libraries.h"
@ -51,7 +52,6 @@
#include "mozilla/AutoProfilerLabel.h"
#include "mozilla/ExtensionPolicyService.h"
#include "mozilla/extensions/WebExtensionPolicy.h"
#include "mozilla/net/HttpBaseChannel.h" // for net::TimingStruct
#include "mozilla/Printf.h"
#include "mozilla/ProfileBufferChunkManagerSingle.h"
#include "mozilla/ProfileBufferChunkManagerWithLocalLimit.h"
@ -1631,6 +1631,44 @@ void ProfilingStackOwner::DumpStackAndCrash() const {
// The name of the main thread.
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
@ -2744,15 +2782,19 @@ static void CollectJavaThreadProfileData(ProfileBuffer& aProfileBuffer) {
if (!text) {
// This marker doesn't have a text.
AddMarkerToBuffer(aProfileBuffer.UnderlyingChunkedBuffer(), markerName,
geckoprofiler::category::JAVA_ANDROID,
{MarkerThreadId(threadId), std::move(timing)});
StoreMarker(aProfileBuffer.UnderlyingChunkedBuffer(), threadId,
markerName.get(), timing,
JS::ProfilingCategoryPair::JAVA_ANDROID, nullptr);
} else {
// This marker has a text.
AddMarkerToBuffer(aProfileBuffer.UnderlyingChunkedBuffer(), markerName,
geckoprofiler::category::JAVA_ANDROID,
{MarkerThreadId(threadId), std::move(timing)},
geckoprofiler::markers::Text{}, text->ToCString());
nsCString textString = text->ToCString();
const TextMarkerPayload payload(textString, startTime, endTime, Nothing(),
nullptr);
// Put the marker inside the buffer.
StoreMarker(aProfileBuffer.UnderlyingChunkedBuffer(), threadId,
markerName.get(), timing,
JS::ProfilingCategoryPair::JAVA_ANDROID, &payload);
}
}
}
@ -4552,9 +4594,7 @@ static void locked_profiler_start(PSLockRef aLock, PowerOfTwo32 aCapacity,
}
// Set up profiling for each registered thread, if appropriate.
#if defined(MOZ_REPLACE_MALLOC) && defined(MOZ_PROFILER_MEMORY)
bool isMainThreadBeingProfiled = false;
#endif
Maybe<int> mainThreadId;
int tid = profiler_current_thread_id();
const Vector<UniquePtr<RegisteredThread>>& registeredThreads =
CorePS::RegisteredThreads(aLock);
@ -4580,11 +4620,9 @@ static void locked_profiler_start(PSLockRef aLock, PowerOfTwo32 aCapacity,
TriggerPollJSSamplingOnMainThread();
}
}
#if defined(MOZ_REPLACE_MALLOC) && defined(MOZ_PROFILER_MEMORY)
if (info->IsMainThread()) {
isMainThreadBeingProfiled = true;
mainThreadId = Some(info->ThreadId());
}
#endif
registeredThread->RacyRegisteredThread().ReinitializeOnResume();
if (registeredThread->GetJSContext()) {
profiledThreadData->NotifyReceivedJSContext(0);
@ -4619,8 +4657,8 @@ static void locked_profiler_start(PSLockRef aLock, PowerOfTwo32 aCapacity,
#if defined(MOZ_REPLACE_MALLOC) && defined(MOZ_PROFILER_MEMORY)
if (ActivePS::FeatureNativeAllocations(aLock)) {
if (isMainThreadBeingProfiled) {
mozilla::profiler::enable_native_allocations();
if (mainThreadId.isSome()) {
mozilla::profiler::enable_native_allocations(mainThreadId.value());
} else {
NS_WARNING(
"The nativeallocations feature is turned on, but the main thread is "
@ -5029,6 +5067,11 @@ void profiler_remove_sampled_counter(BaseProfilerCount* 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,
void* aGuessStackTop) {
DEBUG_LOG("profiler_register_thread(%s)", aName);
@ -5065,8 +5108,10 @@ ProfilingStack* profiler_register_thread(const char* aName,
text.AppendLiteral("\" attempted to re-register as \"");
text.AppendASCII(aName);
text.AppendLiteral("\"");
PROFILER_MARKER_TEXT("profiler_register_thread again", OTHER_Profiling,
MarkerThreadId::MainThread(), text);
maybelocked_profiler_add_marker_for_thread(
profiler_main_thread_id(), JS::ProfilingCategoryPair::OTHER_Profiling,
"profiler_register_thread again",
TextMarkerPayload(text, TimeStamp::NowUnfuzzed()), &lock);
return &thread->RacyRegisteredThread().ProfilingStack();
}
@ -5146,8 +5191,10 @@ void profiler_unregister_thread() {
tid != profiler_main_thread_id()) {
nsCString threadIdString;
threadIdString.AppendInt(tid);
PROFILER_MARKER_TEXT("profiler_unregister_thread again", OTHER_Profiling,
MarkerThreadId::MainThread(), threadIdString);
maybelocked_profiler_add_marker_for_thread(
profiler_main_thread_id(), JS::ProfilingCategoryPair::OTHER_Profiling,
"profiler_unregister_thread again",
TextMarkerPayload(threadIdString, TimeStamp::NowUnfuzzed()), &lock);
}
}
}
@ -5369,6 +5416,40 @@ void ProfilerBacktraceDestructor::operator()(ProfilerBacktrace* 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
// into the JS engine.
void profiler_add_js_marker(const char* aMarkerName, const char* aMarkerText) {
@ -5381,49 +5462,11 @@ void profiler_add_js_allocation_marker(JS::RecordAllocationInfo&& info) {
if (!profiler_can_accept_markers()) {
return;
}
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{};
}
};
AUTO_PROFILER_STATS(add_marker_with_JsAllocationMarkerPayload);
profiler_add_marker(
"JS allocation", geckoprofiler::category::JS, MarkerStack::Capture(),
JsAllocationMarker{},
ProfilerString16View::WrapNullTerminatedString(info.typeName),
ProfilerString8View::WrapNullTerminatedString(info.className),
ProfilerString16View::WrapNullTerminatedString(info.descriptiveTypeName),
ProfilerString8View::WrapNullTerminatedString(info.coarseType), info.size,
info.inNursery);
"JS allocation", JS::ProfilingCategoryPair::JS,
JsAllocationMarkerPayload(TimeStamp::Now(), std::move(info),
profiler_get_backtrace()));
}
bool profiler_is_locked_on_current_thread() {
@ -5438,154 +5481,100 @@ bool profiler_is_locked_on_current_thread() {
CorePS::CoreBuffer().IsThreadSafeAndLockedOnCurrentThread();
}
static constexpr net::TimingStruct scEmptyNetTimingStruct;
void profiler_add_network_marker(
nsIURI* aURI, const nsACString& aRequestMethod, int32_t aPriority,
uint64_t aChannelId, NetworkLoadType aType, mozilla::TimeStamp aStart,
mozilla::TimeStamp aEnd, int64_t aCount,
mozilla::net::CacheDisposition aCacheDisposition, uint64_t aInnerWindowID,
const mozilla::net::TimingStruct* aTimings, nsIURI* aRedirectURI,
UniquePtr<ProfileChunkedBuffer> aSource,
UniqueProfilerBacktrace aSource,
const Maybe<nsDependentCString>& aContentType) {
if (!profiler_can_accept_markers()) {
return;
}
nsAutoCStringN<2048> name;
name.AppendASCII("Load ");
// 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;
// These do allocations/frees/etc; avoid if not active
nsAutoCString spec;
nsAutoCString redirect_spec;
if (aURI) {
aURI->GetAsciiSpec(spec);
name.AppendASCII(": ");
name.Append(spec);
}
nsAutoCString redirect_spec;
if (aRedirectURI) {
aRedirectURI->GetAsciiSpec(redirect_spec);
}
struct NetworkMarker {
static constexpr Span<const char> MarkerTypeName() {
return MakeStringSpan("Network");
}
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:
MOZ_ASSERT(false, "Unexpected NetworkLoadType enum value.");
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:
return MakeStringSpan("");
default:
MOZ_ASSERT(false, "Unexpected CacheDisposition enum value.");
return MakeStringSpan("");
}
}
};
// top 32 bits are process id of the load
uint32_t id = static_cast<uint32_t>(aChannelId & 0xFFFFFFFF);
char name[2048];
SprintfLiteral(name, "Load %d: %s", id, PromiseFlatCString(spec).get());
AUTO_PROFILER_STATS(add_marker_with_NetworkMarkerPayload);
profiler_add_marker(
name, geckoprofiler::category::NETWORK,
{MarkerTiming::Interval(aStart, aEnd),
MarkerStack::TakeBacktrace(std::move(aSource)),
MarkerInnerWindowId(aInnerWindowID)},
NetworkMarker{}, aStart, aEnd, static_cast<int64_t>(aChannelId), spec,
aRequestMethod, aType, aPriority, aCount, aCacheDisposition,
aTimings ? *aTimings : scEmptyNetTimingStruct, redirect_spec,
aContentType ? ProfilerString8View(*aContentType)
: ProfilerString8View());
name, JS::ProfilingCategoryPair::NETWORK,
NetworkMarkerPayload(static_cast<int64_t>(aChannelId),
PromiseFlatCString(spec).get(), aRequestMethod,
aType, aStart, aEnd, aPriority, aCount,
aCacheDisposition, aInnerWindowID, aTimings,
PromiseFlatCString(redirect_spec).get(),
std::move(aSource), aContentType));
}
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) {
if (!profiler_can_accept_markers()) {
return false;
@ -5602,30 +5591,69 @@ bool profiler_add_native_allocation_marker(int64_t aSize,
return false;
}
struct NativeAllocationMarker {
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{};
}
};
profiler_add_marker("Native allocation", geckoprofiler::category::OTHER,
{MarkerThreadId::MainThread(), MarkerStack::Capture()},
NativeAllocationMarker{}, aSize, aMemoryAddress,
profiler_current_thread_id());
AUTO_PROFILER_STATS(add_marker_with_NativeAllocationMarkerPayload);
maybelocked_profiler_add_marker_for_thread(
aMainThreadId, JS::ProfilingCategoryPair::OTHER, "Native allocation",
NativeAllocationMarkerPayload(TimeStamp::Now(), aSize, aMemoryAddress,
profiler_current_thread_id(),
profiler_get_backtrace()),
nullptr);
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) {
MOZ_ASSERT(aCx);

Просмотреть файл

@ -15,6 +15,7 @@ if CONFIG["MOZ_GECKO_PROFILER"]:
"public/GeckoProfilerReporter.h",
"public/ProfilerChild.h",
"public/ProfilerCodeAddressService.h",
"public/ProfilerMarkerPayload.h",
"public/ProfilerParent.h",
"public/shared-libraries.h",
]
@ -26,6 +27,7 @@ if CONFIG["MOZ_GECKO_PROFILER"]:
"core/ProfiledThreadData.cpp",
"core/ProfilerBacktrace.cpp",
"core/ProfilerCodeAddressService.cpp",
"core/ProfilerMarkerPayload.cpp",
"core/RegisteredThread.cpp",
"gecko/ChildProfilerController.cpp",
"gecko/nsProfilerStartParams.cpp",

Просмотреть файл

@ -62,6 +62,17 @@
# define AUTO_PROFILER_LABEL_DYNAMIC_FAST(label, dynamicString, categoryPair, \
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.
// 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 ProfilerCodeAddressService;
class ProfilerMarkerPayload;
namespace mozilla {
class ProfileBufferControlledChunkManager;
class ProfileChunkedBuffer;
@ -878,19 +890,49 @@ mozilla::Maybe<ProfilerBufferInfo> profiler_get_buffer_info();
ctx, label, dynamicString, JS::ProfilingCategoryPair::categoryPair, \
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_allocation_marker(JS::RecordAllocationInfo&& info);
// Returns true or or false depending on whether the marker was actually added
// or not.
bool profiler_add_native_allocation_marker(int64_t aSize,
uintptr_t aMemoryAddress);
bool profiler_add_native_allocation_marker(int aMainThreadId, int64_t aSize,
uintptr_t aMemorySize);
// 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
// the profiler already has the lock (which would deadlock).
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 };
void profiler_add_network_marker(
@ -899,8 +941,7 @@ void profiler_add_network_marker(
mozilla::TimeStamp aEnd, int64_t aCount,
mozilla::net::CacheDisposition aCacheDisposition, uint64_t aInnerWindowID,
const mozilla::net::TimingStruct* aTimings = nullptr,
nsIURI* aRedirectURI = nullptr,
mozilla::UniquePtr<mozilla::ProfileChunkedBuffer> aSource = nullptr,
nsIURI* aRedirectURI = nullptr, UniqueProfilerBacktrace aSource = nullptr,
const mozilla::Maybe<nsDependentCString>& aContentType =
mozilla::Nothing());
@ -928,6 +969,40 @@ inline mozilla::MarkerInnerWindowId MarkerInnerWindowIdFromDocShell(
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
//---------------------------------------------------------------------------
@ -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
// 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

Просмотреть файл

@ -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
# include "gfxASurface.h"
# include "js/AllocationRecording.h"
# include "js/ProfilingFrameIterator.h"
# include "js/Utility.h"
# include "Layers.h"
# include "mozilla/ipc/ProtocolUtils.h"
# include "mozilla/net/HttpBaseChannel.h"
# include "mozilla/Preferences.h"
# include "mozilla/ServoTraversalStatistics.h"
namespace geckoprofiler::markers {
// Import some common markers from mozilla::baseprofiler::markers.
using MediaSampleMarker = mozilla::baseprofiler::markers::MediaSampleMarker;
using ContentBuildMarker = mozilla::baseprofiler::markers::ContentBuildMarker;
using Tracing = mozilla::baseprofiler::markers::Tracing;
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

Просмотреть файл

@ -44,9 +44,6 @@
# define PROFILER_MARKER(markerName, categoryName, options, MarkerType, ...)
# define 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
@ -132,9 +129,8 @@ inline mozilla::ProfileBufferBlockIndex profiler_add_marker(
} while (false)
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 Tracing = mozilla::baseprofiler::markers::Tracing;
} // namespace geckoprofiler::markers
// 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, \
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 // ProfilerMarkers_h

Просмотреть файл

@ -14,6 +14,7 @@
#include "mozilla/ProfilerMarkers.h"
#include "platform.h"
#include "ProfileBuffer.h"
#include "ProfilerMarkerPayload.h"
#include "js/Initialization.h"
#include "js/Printf.h"
@ -578,6 +579,75 @@ TEST(GeckoProfiler, Pause)
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)
{
uint32_t features = ProfilerFeature::StackWalk;
@ -586,20 +656,39 @@ TEST(GeckoProfiler, Markers)
profiler_start(PROFILER_DEFAULT_ENTRIES, PROFILER_DEFAULT_INTERVAL, features,
filters, MOZ_ARRAY_LENGTH(filters), 0);
PROFILER_MARKER("tracing event", OTHER, {}, Tracing, "A");
PROFILER_MARKER("tracing start", OTHER, MarkerTiming::IntervalStart(),
Tracing, "A");
PROFILER_MARKER("tracing end", OTHER, MarkerTiming::IntervalEnd(), Tracing,
"A");
// Used in markers below.
TimeStamp ts0 = TimeStamp::NowUnfuzzed();
auto bt = profiler_capture_backtrace();
PROFILER_MARKER("tracing event with stack", OTHER,
MarkerStack::TakeBacktrace(std::move(bt)), Tracing, "B");
profiler_tracing_marker("A", "tracing event",
JS::ProfilingCategoryPair::OTHER, TRACING_EVENT);
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); }
PROFILER_MARKER_UNTYPED("M1", OTHER, {});
PROFILER_ADD_MARKER_WITH_PAYLOAD("M2", OTHER, TracingMarkerPayload,
("C", TRACING_EVENT, ts0));
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
// is one char longer.
@ -674,76 +763,111 @@ TEST(GeckoProfiler, Markers)
// Other markers in alphabetical order of payload class names.
nsCOMPtr<nsIURI> uri;
ASSERT_TRUE(
NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), "http://mozilla.org/"_ns)));
// The marker name will be "Load <aChannelId>: <aURI>".
profiler_add_network_marker(
/* nsIURI* aURI */ uri,
/* const nsACString& aRequestMethod */ "GET"_ns,
/* int32_t aPriority */ 34,
/* uint64_t aChannelId */ 1,
/* NetworkLoadType aType */ NetworkLoadType::LOAD_START,
/* 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() */);
{
const char gcMajorJSON[] = "42";
const auto len = strlen(gcMajorJSON);
char* buffer =
static_cast<char*>(js::SystemAllocPolicy{}.pod_malloc<char>(len + 1));
strncpy(buffer, gcMajorJSON, len);
buffer[len] = '\0';
PROFILER_ADD_MARKER_WITH_PAYLOAD("GCMajorMarkerPayload marker", OTHER,
GCMajorMarkerPayload,
(ts1, ts2, JS::UniqueChars(buffer)));
}
profiler_add_network_marker(
/* nsIURI* aURI */ uri,
/* const nsACString& aRequestMethod */ "GET"_ns,
/* int32_t aPriority */ 34,
/* uint64_t aChannelId */ 12,
/* NetworkLoadType aType */ NetworkLoadType::LOAD_STOP,
/* mozilla::TimeStamp aStart */ ts1,
/* mozilla::TimeStamp aEnd */ ts2,
/* int64_t aCount */ 56,
/* mozilla::net::CacheDisposition aCacheDisposition */
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")));
{
const char gcMinorJSON[] = "43";
const auto len = strlen(gcMinorJSON);
char* buffer =
static_cast<char*>(js::SystemAllocPolicy{}.pod_malloc<char>(len + 1));
strncpy(buffer, gcMinorJSON, len);
buffer[len] = '\0';
PROFILER_ADD_MARKER_WITH_PAYLOAD("GCMinorMarkerPayload marker", OTHER,
GCMinorMarkerPayload,
(ts1, ts2, JS::UniqueChars(buffer)));
}
nsCOMPtr<nsIURI> redirectURI;
ASSERT_TRUE(NS_SUCCEEDED(
NS_NewURI(getter_AddRefs(redirectURI), "http://example.com/"_ns)));
profiler_add_network_marker(
/* nsIURI* aURI */ uri,
/* const nsACString& aRequestMethod */ "GET"_ns,
/* int32_t aPriority */ 34,
/* uint64_t aChannelId */ 123,
/* NetworkLoadType aType */ NetworkLoadType::LOAD_REDIRECT,
/* mozilla::TimeStamp aStart */ ts1,
/* mozilla::TimeStamp aEnd */ ts2,
/* int64_t aCount */ 56,
/* mozilla::net::CacheDisposition aCacheDisposition */
net::kCacheUnresolved,
/* uint64_t aInnerWindowID */ 78,
/* const mozilla::net::TimingStruct* aTimings = nullptr */ nullptr,
/* nsIURI* aRedirectURI = nullptr */ redirectURI
/* mozilla::UniquePtr<mozilla::ProfileChunkedBuffer> aSource =
nullptr */
/* const mozilla::Maybe<nsDependentCString>& aContentType =
mozilla::Nothing() */);
{
const char gcSliceJSON[] = "44";
const auto len = strlen(gcSliceJSON);
char* buffer =
static_cast<char*>(js::SystemAllocPolicy{}.pod_malloc<char>(len + 1));
strncpy(buffer, gcSliceJSON, len);
buffer[len] = '\0';
PROFILER_ADD_MARKER_WITH_PAYLOAD("GCSliceMarkerPayload marker", OTHER,
GCSliceMarkerPayload,
(ts1, ts2, JS::UniqueChars(buffer)));
}
PROFILER_ADD_MARKER_WITH_PAYLOAD("HangMarkerPayload marker", OTHER,
HangMarkerPayload, (ts1, ts2));
PROFILER_ADD_MARKER_WITH_PAYLOAD("LogMarkerPayload marker", OTHER,
LogMarkerPayload, ("module", "text", ts1));
PROFILER_ADD_MARKER_WITH_PAYLOAD("LongTaskMarkerPayload marker", OTHER,
LongTaskMarkerPayload, (ts1, ts2));
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(
"Text in main thread with stack", geckoprofiler::category::OTHER,
{MarkerStack::Capture(), MarkerTiming::Interval(ts1, ts2)},
geckoprofiler::markers::Text{}, ""));
MarkerStack::Capture(), geckoprofiler::markers::Text{}, ""));
MOZ_RELEASE_ASSERT(profiler_add_marker(
"Text from main thread with stack", geckoprofiler::category::OTHER,
MarkerOptions(MarkerThreadId::MainThread(), MarkerStack::Capture()),
@ -784,19 +908,52 @@ TEST(GeckoProfiler, Markers)
profiler_add_marker("Tracing", geckoprofiler::category::OTHER, {},
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,
{}, geckoprofiler::markers::Text{},
"Text text"));
MOZ_RELEASE_ASSERT(profiler_add_marker(
"MediaSample", geckoprofiler::category::OTHER, {},
geckoprofiler::markers::MediaSampleMarker{}, 123, 456));
MOZ_RELEASE_ASSERT(profiler_add_marker("Log", geckoprofiler::category::OTHER,
{}, geckoprofiler::markers::Log{},
"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;
w.Start();
EXPECT_TRUE(::profiler_stream_json_for_this_process(w));
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();
ASSERT_TRUE(!!profile.get());
@ -809,15 +966,42 @@ TEST(GeckoProfiler, Markers)
S_tracing_auto_tracing_start,
S_tracing_auto_tracing_end,
S_M1,
S_tracing_M2_C,
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_Markers2DefaultWithOptions,
S_Markers2ExplicitDefaultEmptyOptions,
S_Markers2ExplicitDefaultWithOptions,
S_FirstMarker,
S_GCMajorMarkerPayload,
S_GCMinorMarkerPayload,
S_GCSliceMarkerPayload,
S_HangMarkerPayload,
S_LogMarkerPayload,
S_LongTaskMarkerPayload,
S_NativeAllocationMarkerPayload,
S_NetworkMarkerPayload_start,
S_NetworkMarkerPayload_stop,
S_NetworkMarkerPayload_redirect,
S_PrefMarkerPayload,
S_ScreenshotPayload,
S_TextMarkerPayload1,
S_TextMarkerPayload2,
S_UserTimingMarkerPayload_mark,
S_UserTimingMarkerPayload_measure,
S_VsyncMarkerPayload,
S_IPCMarkerPayload,
S_TextWithStack,
S_TextToMTWithStack,
S_RegThread_TextToMTWithStack,
@ -1050,6 +1234,7 @@ TEST(GeckoProfiler, Markers)
EXPECT_EQ(typeString, "tracing");
EXPECT_TIMING_INSTANT;
EXPECT_EQ_JSON(payload["category"], String, "A");
EXPECT_TRUE(payload["interval"].isNull());
EXPECT_TRUE(payload["stack"].isNull());
} else if (nameString == "tracing start") {
@ -1058,6 +1243,7 @@ TEST(GeckoProfiler, Markers)
EXPECT_EQ(typeString, "tracing");
EXPECT_TIMING_START;
EXPECT_EQ_JSON(payload["category"], String, "A");
EXPECT_EQ_JSON(payload["interval"], String, "start");
EXPECT_TRUE(payload["stack"].isNull());
} else if (nameString == "tracing end") {
@ -1066,6 +1252,7 @@ TEST(GeckoProfiler, Markers)
EXPECT_EQ(typeString, "tracing");
EXPECT_TIMING_END;
EXPECT_EQ_JSON(payload["category"], String, "A");
EXPECT_EQ_JSON(payload["interval"], String, "end");
EXPECT_TRUE(payload["stack"].isNull());
} else if (nameString == "tracing event with stack") {
@ -1074,6 +1261,7 @@ TEST(GeckoProfiler, Markers)
EXPECT_EQ(typeString, "tracing");
EXPECT_TIMING_INSTANT;
EXPECT_EQ_JSON(payload["category"], String, "B");
EXPECT_TRUE(payload["interval"].isNull());
EXPECT_TRUE(payload["stack"].isObject());
} else if (nameString == "auto tracing") {
@ -1083,6 +1271,7 @@ TEST(GeckoProfiler, Markers)
EXPECT_EQ(typeString, "tracing");
EXPECT_TIMING_START;
EXPECT_EQ_JSON(payload["category"], String, "C");
EXPECT_EQ_JSON(payload["interval"], String, "start");
EXPECT_TRUE(payload["stack"].isNull());
break;
case S_tracing_auto_tracing_end:
@ -1090,6 +1279,7 @@ TEST(GeckoProfiler, Markers)
EXPECT_EQ(typeString, "tracing");
EXPECT_TIMING_END;
EXPECT_EQ_JSON(payload["category"], String, "C");
EXPECT_EQ_JSON(payload["interval"], String, "end");
ASSERT_TRUE(payload["stack"].isNull());
break;
default:
@ -1098,6 +1288,43 @@ TEST(GeckoProfiler, Markers)
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 ==
"default-templated markers 2.0 with option") {
// TODO: Remove this when bug 1646714 lands.
@ -1113,43 +1340,94 @@ TEST(GeckoProfiler, Markers)
ts1Double = marker[START_TIME].asDouble();
ts2Double = marker[END_TIME].asDouble();
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);
state = State(S_NetworkMarkerPayload_start + 1);
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["URI"], String, "http://mozilla.org/");
EXPECT_EQ_JSON(payload["requestMethod"], String, "GET");
EXPECT_EQ_JSON(payload["pri"], Int64, 34);
EXPECT_EQ_JSON(payload["count"], Int64, 56);
EXPECT_EQ_JSON(payload["cache"], String, "Hit");
EXPECT_TRUE(payload["RedirectURI"].isNull());
EXPECT_EQ_JSON(payload["RedirectURI"], String, "");
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);
state = State(S_NetworkMarkerPayload_stop + 1);
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["URI"], String, "http://mozilla.org/");
EXPECT_EQ_JSON(payload["requestMethod"], String, "GET");
EXPECT_EQ_JSON(payload["pri"], Int64, 34);
EXPECT_EQ_JSON(payload["count"], Int64, 56);
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");
} else if (nameString == "Load 123: http://mozilla.org/") {
} else if (nameString == "NetworkMarkerPayload redirect marker") {
EXPECT_EQ(state, S_NetworkMarkerPayload_redirect);
state = State(S_NetworkMarkerPayload_redirect + 1);
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["URI"], String, "http://mozilla.org/");
EXPECT_EQ_JSON(payload["requestMethod"], String, "GET");
@ -1160,12 +1438,100 @@ TEST(GeckoProfiler, Markers)
"http://example.com/");
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") {
EXPECT_EQ(state, S_TextWithStack);
state = State(S_TextWithStack + 1);
EXPECT_EQ(typeString, "Text");
EXPECT_FALSE(payload["stack"].isNull());
EXPECT_TIMING_INTERVAL_AT(ts1Double, ts2Double);
EXPECT_EQ_JSON(payload["name"], String, "");
} 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]["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") {
EXPECT_EQ(display.size(), 3u);
EXPECT_EQ(display[0u].asString(), "marker-chart");
@ -1347,8 +1777,18 @@ TEST(GeckoProfiler, Markers)
// Check that we've got all expected schema.
EXPECT_TRUE(testedSchemaNames.find("Text") != 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") !=
testedSchemaNames.end());
EXPECT_TRUE(testedSchemaNames.find("Budget") != testedSchemaNames.end());
} // markerSchema
} // meta
@ -1383,27 +1823,70 @@ TEST(GeckoProfiler, Markers)
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.
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
profiler_start(PROFILER_DEFAULT_ENTRIES, PROFILER_DEFAULT_INTERVAL, features,
filters, MOZ_ARRAY_LENGTH(filters), 0);
// This last marker shouldn't get streamed.
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);
EXPECT_TRUE(::profiler_stream_json_for_this_process(w));
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_DESCRIPTION "Test of counters in profiles"
#define COUNTER_NAME2 "Counter2"

Просмотреть файл

@ -93,6 +93,10 @@
#include "nsStringBuffer.h"
#include "nsWrapperCache.h"
#ifdef MOZ_GECKO_PROFILER
# include "ProfilerMarkerPayload.h"
#endif
#if defined(XP_MACOSX)
# include "nsMacUtilsImpl.h"
#endif
@ -988,65 +992,15 @@ void CycleCollectedJSRuntime::GCSliceCallback(JSContext* aContext,
#ifdef MOZ_GECKO_PROFILER
if (profiler_thread_is_being_profiled()) {
if (aProgress == JS::GC_CYCLE_END) {
struct GCMajorMarker {
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) {
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()));
PROFILER_ADD_MARKER_WITH_PAYLOAD(
"GCMajor", GCCC, GCMajorMarkerPayload,
(aDesc.startTime(aContext), aDesc.endTime(aContext),
aDesc.formatJSONProfiler(aContext)));
} else if (aProgress == JS::GC_SLICE_END) {
struct GCSliceMarker {
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) {
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()));
PROFILER_ADD_MARKER_WITH_PAYLOAD(
"GCSlice", GCCC, GCSliceMarkerPayload,
(aDesc.lastSliceStart(aContext), aDesc.lastSliceEnd(aContext),
aDesc.sliceToJSONProfiler(aContext)));
}
}
#endif
@ -1125,35 +1079,10 @@ void CycleCollectedJSRuntime::GCNurseryCollectionCallback(
#ifdef MOZ_GECKO_PROFILER
else if (aProgress == JS::GCNurseryProgress::GC_NURSERY_COLLECTION_END &&
profiler_thread_is_being_profiled()) {
struct GCMinorMarker {
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) {
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()));
PROFILER_ADD_MARKER_WITH_PAYLOAD(
"GCMinor", GCCC, GCMinorMarkerPayload,
(self->mLatestNurseryCollectionStart, TimeStamp::Now(),
JS::MinorGcToJSON(aContext)));
}
#endif

Просмотреть файл

@ -23,6 +23,9 @@
#include "nsDebugImpl.h"
#include "NSPRLogModulesParser.h"
#include "LogCommandLineHandler.h"
#ifdef MOZ_GECKO_PROFILER
# include "ProfilerMarkerPayload.h"
#endif
#include "prenv.h"
#ifdef XP_WIN
@ -416,33 +419,15 @@ class LogModuleManager {
#ifdef MOZ_GECKO_PROFILER
if (mAddProfilerMarker && profiler_can_accept_markers()) {
struct LogMarker {
static constexpr Span<const char> MarkerTypeName() {
return MakeStringSpan("Log");
}
static void StreamJSONMarkerData(
baseprofiler::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;
}
};
profiler_add_marker(
"LogMessages", geckoprofiler::category::OTHER,
aStart ? MarkerTiming::IntervalUntilNowFrom(*aStart)
: MarkerTiming::InstantNow(),
LogMarker{}, ProfilerString8View::WrapNullTerminatedString(aName),
ProfilerString8View::WrapNullTerminatedString(buffToWrite));
if (aStart) {
PROFILER_ADD_MARKER_WITH_PAYLOAD(
"LogMessages", OTHER, LogMarkerPayload,
(aName, buffToWrite, *aStart, TimeStamp::Now()));
} else {
PROFILER_ADD_MARKER_WITH_PAYLOAD(
"LogMessages", OTHER, LogMarkerPayload,
(aName, buffToWrite, TimeStamp::Now()));
}
}
#endif

Просмотреть файл

@ -42,6 +42,9 @@
#include "nsThreadSyncDispatch.h"
#include "nsServiceManagerUtils.h"
#include "GeckoProfiler.h"
#ifdef MOZ_GECKO_PROFILER
# include "ProfilerMarkerPayload.h"
#endif
#include "InputEventStatistics.h"
#include "ThreadEventQueue.h"
#include "ThreadEventTarget.h"
@ -1521,28 +1524,9 @@ void PerformanceCounterState::MaybeReportAccumulatedTime(TimeStamp aNow) {
#ifdef MOZ_GECKO_PROFILER
if (profiler_thread_is_being_profiled()) {
struct LongTaskMarker {
static constexpr Span<const char> MarkerTypeName() {
return MakeStringSpan("MainThreadLongTask");
}
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{});
PROFILER_ADD_MARKER_WITH_PAYLOAD(
mCurrentRunnableIsIdleRunnable ? "LongIdleTask" : "LongTask", OTHER,
LongTaskMarkerPayload, (mCurrentTimeSliceStart, aNow));
}
#endif
}