Bug 1675409 - Removed now-unused ProfilerMarkerPayload and all dependencies - r=gregtatum,necko-reviewers

Differential Revision: https://phabricator.services.mozilla.com/D96054
This commit is contained in:
Gerald Squelart 2020-11-17 22:26:20 +00:00
parent 9506ea6302
commit ced008cc9f
21 changed files with 41 additions and 2430 deletions

View File

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

View File

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

View File

@ -22,9 +22,6 @@
#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;

View File

@ -25,7 +25,6 @@
#include "nsPrintfCString.h"
#include "prtime.h"
#ifdef MOZ_GECKO_PROFILER
# include "ProfilerMarkerPayload.h"
# include "mozilla/ProfilerMarkerTypes.h"
#endif

View File

@ -21,9 +21,6 @@
# 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"

View File

@ -28,10 +28,6 @@
#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 {

View File

@ -11,9 +11,6 @@
#include "GeckoProfiler.h"
#include "gfxUtils.h"
#include "nsThreadUtils.h"
#ifdef MOZ_GECKO_PROFILER
# include "ProfilerMarkerPayload.h"
#endif
using namespace mozilla;
using namespace mozilla::gfx;

View File

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

View File

@ -785,13 +785,20 @@ void ProfileBuffer::StreamMarkersToJSON(SpliceableJSONWriter& aWriter,
MOZ_ASSERT(static_cast<ProfileBufferEntry::KindUnderlyingType>(type) <
static_cast<ProfileBufferEntry::KindUnderlyingType>(
ProfileBufferEntry::Kind::MODERN_LIMIT));
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);
})) {
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) {
// 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);

View File

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

View File

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

View File

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

View File

@ -10,7 +10,6 @@
#include "platform.h"
#include "ProfileBuffer.h"
#include "ProfilerBacktrace.h"
#include "ProfilerMarkerPayload.h"
#include "jsapi.h"
#include "jsfriendapi.h"
@ -636,7 +635,6 @@ class EntryGetter {
// )+
// */
// )
// | MarkerData
// | Marker
// | ( /* Counters */
// CounterId
@ -1154,78 +1152,23 @@ void ProfileBuffer::StreamMarkersToJSON(SpliceableJSONWriter& aWriter,
MOZ_ASSERT(static_cast<ProfileBufferEntry::KindUnderlyingType>(type) <
static_cast<ProfileBufferEntry::KindUnderlyingType>(
ProfileBufferEntry::Kind::MODERN_LIMIT));
// 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>>();
bool entryWasFullyRead = false;
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 (type == ProfileBufferEntry::Kind::Marker) {
entryWasFullyRead =
mozilla::base_profiler_markers_detail::DeserializeAfterKindAndStream(
aER, aWriter, aThreadId,
[&](ProfileChunkedBuffer& aChunkedBuffer) {
ProfilerBacktrace backtrace("", &aChunkedBuffer);
backtrace.StreamJSON(aWriter, aProcessStartTime, aUniqueStacks);
});
}
aER.SetRemainingBytes(0);
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);
}
});
}

File diff suppressed because it is too large Load Diff

View File

@ -37,7 +37,6 @@ 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

View File

@ -37,7 +37,6 @@
#include "ProfilerChild.h"
#include "ProfilerCodeAddressService.h"
#include "ProfilerIOInterposeObserver.h"
#include "ProfilerMarkerPayload.h"
#include "ProfilerParent.h"
#include "RegisteredThread.h"
#include "shared-libraries.h"
@ -1632,44 +1631,6 @@ 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
@ -5068,11 +5029,6 @@ 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);
@ -5413,40 +5369,6 @@ 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) {
@ -5663,64 +5585,6 @@ void profiler_add_network_marker(
: ProfilerString8View());
}
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(int64_t aSize,
uintptr_t aMemoryAddress) {
if (!profiler_can_accept_markers()) {

View File

@ -15,7 +15,6 @@ if CONFIG["MOZ_GECKO_PROFILER"]:
"public/GeckoProfilerReporter.h",
"public/ProfilerChild.h",
"public/ProfilerCodeAddressService.h",
"public/ProfilerMarkerPayload.h",
"public/ProfilerParent.h",
"public/shared-libraries.h",
]
@ -27,7 +26,6 @@ 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",

View File

@ -62,9 +62,6 @@
# define AUTO_PROFILER_LABEL_DYNAMIC_FAST(label, dynamicString, categoryPair, \
ctx, flags)
# define PROFILER_ADD_MARKER_WITH_PAYLOAD(markerName, categoryPair, \
PayloadType, payloadArgs)
// 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
@ -112,7 +109,6 @@ profiler_capture_backtrace() {
class ProfilerBacktrace;
class ProfilerCodeAddressService;
class ProfilerMarkerPayload;
namespace mozilla {
class ProfileBufferControlledChunkManager;
class ProfileChunkedBuffer;
@ -882,23 +878,6 @@ 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);
@ -912,19 +891,6 @@ bool profiler_add_native_allocation_marker(int64_t aSize,
// 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(

View File

@ -1,839 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef 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

View File

@ -14,7 +14,6 @@
#include "mozilla/ProfilerMarkers.h"
#include "platform.h"
#include "ProfileBuffer.h"
#include "ProfilerMarkerPayload.h"
#include "js/Initialization.h"
#include "js/Printf.h"
@ -579,75 +578,6 @@ 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;
@ -671,17 +601,6 @@ TEST(GeckoProfiler, Markers)
PROFILER_MARKER_UNTYPED("M1", OTHER, {});
PROFILER_MARKER_UNTYPED("M3", OTHER, {});
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.
static const size_t kMax = ProfileBuffer::kMaxFrameKeyLength;
@ -878,14 +797,6 @@ TEST(GeckoProfiler, Markers)
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());
@ -899,16 +810,6 @@ TEST(GeckoProfiler, Markers)
S_tracing_auto_tracing_end,
S_M1,
S_M3,
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,
@ -1197,25 +1098,6 @@ TEST(GeckoProfiler, Markers)
break;
}
} 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.
@ -1501,70 +1383,27 @@ 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.
for (int i = 0; i < 10; i++) {
PROFILER_ADD_MARKER_WITH_PAYLOAD("M5", OTHER, GTestMarkerPayload, (i));
}
PROFILER_MARKER_UNTYPED("marker after profiler_stop", OTHER);
// Warning: this could be racy
profiler_start(PROFILER_DEFAULT_ENTRIES, PROFILER_DEFAULT_INTERVAL, features,
filters, MOZ_ARRAY_LENGTH(filters), 0);
EXPECT_TRUE(::profiler_stream_json_for_this_process(w));
// 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);
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"

View File

@ -93,10 +93,6 @@
#include "nsStringBuffer.h"
#include "nsWrapperCache.h"
#ifdef MOZ_GECKO_PROFILER
# include "ProfilerMarkerPayload.h"
#endif
#if defined(XP_MACOSX)
# include "nsMacUtilsImpl.h"
#endif