Bug 1575448 - De/serialize ProfilerMarkerPayload derived objects - r=gregtatum

Payloads will serialize themselves into a `BlocksRingBuffer` entry when first
captured.
Later they will be deserialized, to stream JSON for the output profile.

Differential Revision: https://phabricator.services.mozilla.com/D43428

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Gerald Squelart 2019-09-17 01:51:41 +00:00
Родитель 64f0dcdf95
Коммит 5b86107991
11 изменённых файлов: 1850 добавлений и 166 удалений

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

@ -54,9 +54,32 @@ class VideoFrameMarkerPayload : public ProfilerMarkerPayload {
mAudioPositionUs(aAudioPositionUs),
mVideoFrameTimeUs(aVideoFrameTimeUs) {}
BlocksRingBuffer::Length TagAndSerializationBytes() const override {
return CommonPropsTagAndSerializationBytes() +
BlocksRingBuffer::SumBytes(mAudioPositionUs, mVideoFrameTimeUs);
}
void SerializeTagAndPayload(
BlocksRingBuffer::EntryWriter& aEntryWriter) const override {
static const DeserializerTag tag = TagForDeserializer(Deserialize);
SerializeTagAndCommonProps(tag, aEntryWriter);
aEntryWriter.WriteObject(mAudioPositionUs);
aEntryWriter.WriteObject(mVideoFrameTimeUs);
}
static UniquePtr<ProfilerMarkerPayload> Deserialize(
BlocksRingBuffer::EntryReader& aEntryReader) {
ProfilerMarkerPayload::CommonProps props =
DeserializeCommonProps(aEntryReader);
auto audioPositionUs = aEntryReader.ReadObject<int64_t>();
auto videoFrameTimeUs = aEntryReader.ReadObject<int64_t>();
return UniquePtr<ProfilerMarkerPayload>(new VideoFrameMarkerPayload(
std::move(props), audioPositionUs, videoFrameTimeUs));
}
void StreamPayload(SpliceableJSONWriter& aWriter,
const TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks) {
UniqueStacks& aUniqueStacks) const override {
StreamCommonProps("UpdateRenderVideoFrames", aWriter, aProcessStartTime,
aUniqueStacks);
aWriter.IntProperty("audio", mAudioPositionUs);
@ -64,6 +87,12 @@ class VideoFrameMarkerPayload : public ProfilerMarkerPayload {
}
private:
VideoFrameMarkerPayload(CommonProps&& aCommonProps, int64_t aAudioPositionUs,
int64_t aVideoFrameTimeUs)
: ProfilerMarkerPayload(std::move(aCommonProps)),
mAudioPositionUs(aAudioPositionUs),
mVideoFrameTimeUs(aVideoFrameTimeUs) {}
int64_t mAudioPositionUs;
int64_t mVideoFrameTimeUs;
};

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

@ -2530,12 +2530,32 @@ int32_t RecordContentFrameTime(
ContentFramePayload(const mozilla::TimeStamp& aStartTime,
const mozilla::TimeStamp& aEndTime)
: ProfilerMarkerPayload(aStartTime, aEndTime) {}
virtual void StreamPayload(SpliceableJSONWriter& aWriter,
const TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks) override {
mozilla::BlocksRingBuffer::Length TagAndSerializationBytes()
const override {
return CommonPropsTagAndSerializationBytes();
}
void SerializeTagAndPayload(
mozilla::BlocksRingBuffer::EntryWriter& aEntryWriter) const override {
static const DeserializerTag tag = TagForDeserializer(Deserialize);
SerializeTagAndCommonProps(tag, aEntryWriter);
}
void StreamPayload(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::BlocksRingBuffer::EntryReader& aEntryReader) {
ProfilerMarkerPayload::CommonProps props =
DeserializeCommonProps(aEntryReader);
return UniquePtr<ProfilerMarkerPayload>(
new ContentFramePayload(std::move(props)));
}
};
AUTO_PROFILER_STATS(add_marker_with_ContentFramePayload);
profiler_add_marker_for_thread(

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

@ -367,12 +367,32 @@ void ContentCompositorBridgeParent::ShadowLayersUpdated(
ContentBuildPayload(const mozilla::TimeStamp& aStartTime,
const mozilla::TimeStamp& aEndTime)
: ProfilerMarkerPayload(aStartTime, aEndTime) {}
virtual void StreamPayload(SpliceableJSONWriter& aWriter,
const TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks) override {
mozilla::BlocksRingBuffer::Length TagAndSerializationBytes()
const override {
return CommonPropsTagAndSerializationBytes();
}
void SerializeTagAndPayload(
mozilla::BlocksRingBuffer::EntryWriter& aEntryWriter) const override {
static const DeserializerTag tag = TagForDeserializer(Deserialize);
SerializeTagAndCommonProps(tag, aEntryWriter);
}
void StreamPayload(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::BlocksRingBuffer::EntryReader& 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(

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

@ -211,12 +211,34 @@ class SceneBuiltNotification : public wr::NotificationHandler {
ContentFullPaintPayload(const mozilla::TimeStamp& aStartTime,
const mozilla::TimeStamp& aEndTime)
: ProfilerMarkerPayload(aStartTime, aEndTime) {}
mozilla::BlocksRingBuffer::Length TagAndSerializationBytes()
const override {
return CommonPropsTagAndSerializationBytes();
}
void SerializeTagAndPayload(
mozilla::BlocksRingBuffer::EntryWriter& aEntryWriter)
const override {
static const DeserializerTag tag =
TagForDeserializer(Deserialize);
SerializeTagAndCommonProps(tag, aEntryWriter);
}
void StreamPayload(SpliceableJSONWriter& aWriter,
const TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks) override {
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::BlocksRingBuffer::EntryReader& aEntryReader) {
ProfilerMarkerPayload::CommonProps props =
DeserializeCommonProps(aEntryReader);
return UniquePtr<ProfilerMarkerPayload>(
new ContentFullPaintPayload(std::move(props)));
}
};
AUTO_PROFILER_STATS(add_marker_with_ContentFullPaintPayload);

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

@ -21,6 +21,77 @@
namespace mozilla {
namespace baseprofiler {
static UniquePtr<ProfilerMarkerPayload> DeserializeNothing(
mozilla::BlocksRingBuffer::EntryReader&) {
return nullptr;
}
// Number of currently-registered deserializers.
// Starting at 1 for the initial `DeserializeNothing`.
// static
Atomic<ProfilerMarkerPayload::DeserializerTagAtomic, ReleaseAcquire,
recordreplay::Behavior::DontPreserve>
ProfilerMarkerPayload::sDeserializerCount{1};
// Initialize `sDeserializers` with `DeserializeNothing` at index 0, all others
// are nullptrs.
// static
ProfilerMarkerPayload::Deserializer
ProfilerMarkerPayload::sDeserializers[DeserializerMax] = {
DeserializeNothing};
// static
ProfilerMarkerPayload::DeserializerTag
ProfilerMarkerPayload::TagForDeserializer(
ProfilerMarkerPayload::Deserializer aDeserializer) {
if (!aDeserializer) {
return 0;
}
// Start first search at index 0.
DeserializerTagAtomic start = 0;
for (;;) {
// Read the current count of deserializers.
const DeserializerTagAtomic tagCount = sDeserializerCount;
if (tagCount == 0) {
// Someone else is currently writing into the array, loop around until we
// get a valid count.
continue;
}
for (DeserializerTagAtomic i = start; i < tagCount; ++i) {
if (sDeserializers[i] == aDeserializer) {
// Deserializer already registered, return its tag.
return static_cast<ProfilerMarkerPayload::DeserializerTag>(i);
}
}
// Not found yet, let's register this new deserializer.
// Make sure we haven't reached the limit yet.
MOZ_RELEASE_ASSERT(tagCount < DeserializerMax);
// Reserve `tagCount` as an index, if not already claimed:
// If `sDeserializerCount` is still at our previously-read `tagCount`,
// replace it with a special 0 value to indicate a write.
if (sDeserializerCount.compareExchange(tagCount, 0)) {
// Here we own the `tagCount` index, write the deserializer there.
sDeserializers[tagCount] = aDeserializer;
// And publish by writing the real new count (1 past our index).
sDeserializerCount = tagCount + 1;
return static_cast<ProfilerMarkerPayload::DeserializerTag>(tagCount);
}
// Someone else beat us to grab an index, and it could be for the same
// deserializer! So let's just try searching starting from our recorded
// `tagCount` (and maybe attempting again to register). It should be rare
// enough and quick enough that it won't impact performances.
start = tagCount;
}
}
// static
ProfilerMarkerPayload::Deserializer ProfilerMarkerPayload::DeserializerForTag(
ProfilerMarkerPayload::DeserializerTag aTag) {
MOZ_RELEASE_ASSERT(aTag < DeserializerMax);
MOZ_RELEASE_ASSERT(aTag < sDeserializerCount);
return sDeserializers[aTag];
}
static void MOZ_ALWAYS_INLINE WriteTime(SpliceableJSONWriter& aWriter,
const TimeStamp& aProcessStartTime,
const TimeStamp& aTime,
@ -31,14 +102,47 @@ static void MOZ_ALWAYS_INLINE WriteTime(SpliceableJSONWriter& aWriter,
}
void ProfilerMarkerPayload::StreamType(const char* aMarkerType,
SpliceableJSONWriter& aWriter) {
SpliceableJSONWriter& aWriter) const {
MOZ_ASSERT(aMarkerType);
aWriter.StringProperty("type", aMarkerType);
}
BlocksRingBuffer::Length
ProfilerMarkerPayload::CommonPropsTagAndSerializationBytes() const {
return sizeof(DeserializerTag) +
BlocksRingBuffer::SumBytes(mCommonProps.mStartTime,
mCommonProps.mEndTime, mCommonProps.mStack,
mCommonProps.mDocShellId,
mCommonProps.mDocShellHistoryId);
}
void ProfilerMarkerPayload::SerializeTagAndCommonProps(
DeserializerTag aDeserializerTag,
BlocksRingBuffer::EntryWriter& aEntryWriter) const {
aEntryWriter.WriteObject(aDeserializerTag);
aEntryWriter.WriteObject(mCommonProps.mStartTime);
aEntryWriter.WriteObject(mCommonProps.mEndTime);
aEntryWriter.WriteObject(mCommonProps.mStack);
aEntryWriter.WriteObject(mCommonProps.mDocShellId);
aEntryWriter.WriteObject(mCommonProps.mDocShellHistoryId);
}
// static
ProfilerMarkerPayload::CommonProps
ProfilerMarkerPayload::DeserializeCommonProps(
BlocksRingBuffer::EntryReader& aEntryReader) {
CommonProps props;
aEntryReader.ReadIntoObject(props.mStartTime);
aEntryReader.ReadIntoObject(props.mEndTime);
aEntryReader.ReadIntoObject(props.mStack);
aEntryReader.ReadIntoObject(props.mDocShellId);
aEntryReader.ReadIntoObject(props.mDocShellHistoryId);
return props;
}
void ProfilerMarkerPayload::StreamCommonProps(
const char* aMarkerType, SpliceableJSONWriter& aWriter,
const TimeStamp& aProcessStartTime, UniqueStacks& aUniqueStacks) {
const TimeStamp& aProcessStartTime, UniqueStacks& aUniqueStacks) const {
StreamType(aMarkerType, aWriter);
WriteTime(aWriter, aProcessStartTime, mCommonProps.mStartTime, "startTime");
WriteTime(aWriter, aProcessStartTime, mCommonProps.mEndTime, "endTime");
@ -59,9 +163,52 @@ void ProfilerMarkerPayload::StreamCommonProps(
}
}
TracingMarkerPayload::TracingMarkerPayload(
const char* aCategory, TracingKind aKind,
const Maybe<std::string>& aDocShellId,
const Maybe<uint32_t>& aDocShellHistoryId, UniqueProfilerBacktrace aCause)
: ProfilerMarkerPayload(aDocShellId, aDocShellHistoryId, std::move(aCause)),
mCategory(aCategory),
mKind(aKind) {}
TracingMarkerPayload::TracingMarkerPayload(CommonProps&& aCommonProps,
const char* aCategory,
TracingKind aKind)
: ProfilerMarkerPayload(std::move(aCommonProps)),
mCategory(aCategory),
mKind(aKind) {}
TracingMarkerPayload::~TracingMarkerPayload() = default;
BlocksRingBuffer::Length TracingMarkerPayload::TagAndSerializationBytes()
const {
return CommonPropsTagAndSerializationBytes() +
BlocksRingBuffer::SumBytes(WrapBlocksRingBufferRawPointer(mCategory),
mKind);
}
void TracingMarkerPayload::SerializeTagAndPayload(
BlocksRingBuffer::EntryWriter& aEntryWriter) const {
static const DeserializerTag tag = TagForDeserializer(Deserialize);
SerializeTagAndCommonProps(tag, aEntryWriter);
aEntryWriter.WriteObject(WrapBlocksRingBufferRawPointer(mCategory));
aEntryWriter.WriteObject(mKind);
}
// static
UniquePtr<ProfilerMarkerPayload> TracingMarkerPayload::Deserialize(
BlocksRingBuffer::EntryReader& aEntryReader) {
ProfilerMarkerPayload::CommonProps props =
DeserializeCommonProps(aEntryReader);
const char* category = aEntryReader.ReadObject<const char*>();
TracingKind kind = aEntryReader.ReadObject<TracingKind>();
return UniquePtr<ProfilerMarkerPayload>(
new TracingMarkerPayload(std::move(props), category, kind));
}
void TracingMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
const TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks) {
UniqueStacks& aUniqueStacks) const {
StreamCommonProps("tracing", aWriter, aProcessStartTime, aUniqueStacks);
if (mCategory) {
@ -75,20 +222,135 @@ void TracingMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
}
}
FileIOMarkerPayload::FileIOMarkerPayload(const char* aOperation,
const char* aSource,
const char* aFilename,
const TimeStamp& aStartTime,
const TimeStamp& aEndTime,
UniqueProfilerBacktrace aStack)
: ProfilerMarkerPayload(aStartTime, aEndTime, Nothing(), Nothing(),
std::move(aStack)),
mSource(aSource),
mOperation(aOperation ? strdup(aOperation) : nullptr),
mFilename(aFilename ? strdup(aFilename) : nullptr) {
MOZ_ASSERT(aSource);
}
FileIOMarkerPayload::FileIOMarkerPayload(CommonProps&& aCommonProps,
const char* aSource,
UniqueFreePtr<char>&& aOperation,
UniqueFreePtr<char>&& aFilename)
: ProfilerMarkerPayload(std::move(aCommonProps)),
mSource(aSource),
mOperation(std::move(aOperation)),
mFilename(std::move(aFilename)) {}
FileIOMarkerPayload::~FileIOMarkerPayload() = default;
BlocksRingBuffer::Length FileIOMarkerPayload::TagAndSerializationBytes() const {
return CommonPropsTagAndSerializationBytes() +
BlocksRingBuffer::SumBytes(WrapBlocksRingBufferRawPointer(mSource),
mOperation, mFilename);
}
void FileIOMarkerPayload::SerializeTagAndPayload(
BlocksRingBuffer::EntryWriter& aEntryWriter) const {
static const DeserializerTag tag = TagForDeserializer(Deserialize);
SerializeTagAndCommonProps(tag, aEntryWriter);
aEntryWriter.WriteObject(WrapBlocksRingBufferRawPointer(mSource));
aEntryWriter.WriteObject(mOperation);
aEntryWriter.WriteObject(mFilename);
}
// static
UniquePtr<ProfilerMarkerPayload> FileIOMarkerPayload::Deserialize(
BlocksRingBuffer::EntryReader& aEntryReader) {
ProfilerMarkerPayload::CommonProps props =
DeserializeCommonProps(aEntryReader);
auto source = aEntryReader.ReadObject<const char*>();
auto operation = aEntryReader.ReadObject<UniqueFreePtr<char>>();
auto filename = aEntryReader.ReadObject<UniqueFreePtr<char>>();
return UniquePtr<ProfilerMarkerPayload>(new FileIOMarkerPayload(
std::move(props), source, std::move(operation), std::move(filename)));
}
void FileIOMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
const TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks) {
UniqueStacks& aUniqueStacks) const {
StreamCommonProps("FileIO", aWriter, aProcessStartTime, aUniqueStacks);
aWriter.StringProperty("operation", mOperation.get());
aWriter.StringProperty("source", mSource);
if (mFilename) {
if (mFilename && *mFilename) {
aWriter.StringProperty("filename", mFilename.get());
}
}
UserTimingMarkerPayload::UserTimingMarkerPayload(
const std::string& aName, const TimeStamp& aStartTime,
const Maybe<std::string>& aDocShellId,
const Maybe<uint32_t>& aDocShellHistoryId)
: ProfilerMarkerPayload(aStartTime, aStartTime, aDocShellId,
aDocShellHistoryId),
mEntryType("mark"),
mName(aName) {}
UserTimingMarkerPayload::UserTimingMarkerPayload(
const std::string& aName, const Maybe<std::string>& aStartMark,
const Maybe<std::string>& aEndMark, const TimeStamp& aStartTime,
const TimeStamp& aEndTime, const Maybe<std::string>& aDocShellId,
const Maybe<uint32_t>& aDocShellHistoryId)
: ProfilerMarkerPayload(aStartTime, aEndTime, aDocShellId,
aDocShellHistoryId),
mEntryType("measure"),
mName(aName),
mStartMark(aStartMark),
mEndMark(aEndMark) {}
UserTimingMarkerPayload::UserTimingMarkerPayload(
CommonProps&& aCommonProps, const char* aEntryType, std::string&& aName,
Maybe<std::string>&& aStartMark, Maybe<std::string>&& aEndMark)
: ProfilerMarkerPayload(std::move(aCommonProps)),
mEntryType(aEntryType),
mName(std::move(aName)),
mStartMark(std::move(aStartMark)),
mEndMark(std::move(aEndMark)) {}
UserTimingMarkerPayload::~UserTimingMarkerPayload() = default;
BlocksRingBuffer::Length UserTimingMarkerPayload::TagAndSerializationBytes()
const {
return CommonPropsTagAndSerializationBytes() +
BlocksRingBuffer::SumBytes(WrapBlocksRingBufferRawPointer(mEntryType),
mName, mStartMark, mEndMark);
}
void UserTimingMarkerPayload::SerializeTagAndPayload(
BlocksRingBuffer::EntryWriter& aEntryWriter) const {
static const DeserializerTag tag = TagForDeserializer(Deserialize);
SerializeTagAndCommonProps(tag, aEntryWriter);
aEntryWriter.WriteObject(WrapBlocksRingBufferRawPointer(mEntryType));
aEntryWriter.WriteObject(mName);
aEntryWriter.WriteObject(mStartMark);
aEntryWriter.WriteObject(mEndMark);
}
// static
UniquePtr<ProfilerMarkerPayload> UserTimingMarkerPayload::Deserialize(
BlocksRingBuffer::EntryReader& aEntryReader) {
ProfilerMarkerPayload::CommonProps props =
DeserializeCommonProps(aEntryReader);
auto entryType = aEntryReader.ReadObject<const char*>();
auto name = aEntryReader.ReadObject<std::string>();
auto startMark = aEntryReader.ReadObject<Maybe<std::string>>();
auto endMark = aEntryReader.ReadObject<Maybe<std::string>>();
return UniquePtr<ProfilerMarkerPayload>(
new UserTimingMarkerPayload(std::move(props), entryType, std::move(name),
std::move(startMark), std::move(endMark)));
}
void UserTimingMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
const TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks) {
UniqueStacks& aUniqueStacks) const {
StreamCommonProps("UserTiming", aWriter, aProcessStartTime, aUniqueStacks);
aWriter.StringProperty("name", mName.c_str());
aWriter.StringProperty("entryType", mEntryType);
@ -105,31 +367,181 @@ void UserTimingMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
}
}
TextMarkerPayload::TextMarkerPayload(const std::string& aText,
const TimeStamp& aStartTime)
: ProfilerMarkerPayload(aStartTime, aStartTime), mText(aText) {}
TextMarkerPayload::TextMarkerPayload(const std::string& aText,
const TimeStamp& aStartTime,
const TimeStamp& aEndTime)
: ProfilerMarkerPayload(aStartTime, aEndTime), mText(aText) {}
TextMarkerPayload::TextMarkerPayload(const std::string& aText,
const TimeStamp& aStartTime,
const Maybe<std::string>& aDocShellId,
const Maybe<uint32_t>& aDocShellHistoryId)
: ProfilerMarkerPayload(aStartTime, aStartTime, aDocShellId,
aDocShellHistoryId),
mText(aText) {}
TextMarkerPayload::TextMarkerPayload(const std::string& aText,
const TimeStamp& aStartTime,
const TimeStamp& aEndTime,
const Maybe<std::string>& aDocShellId,
const Maybe<uint32_t>& aDocShellHistoryId,
UniqueProfilerBacktrace aCause)
: ProfilerMarkerPayload(aStartTime, aEndTime, aDocShellId,
aDocShellHistoryId, std::move(aCause)),
mText(aText) {}
TextMarkerPayload::TextMarkerPayload(CommonProps&& aCommonProps,
std::string&& aText)
: ProfilerMarkerPayload(std::move(aCommonProps)), mText(std::move(aText)) {}
TextMarkerPayload::~TextMarkerPayload() = default;
BlocksRingBuffer::Length TextMarkerPayload::TagAndSerializationBytes() const {
return CommonPropsTagAndSerializationBytes() +
BlocksRingBuffer::SumBytes(mText);
}
void TextMarkerPayload::SerializeTagAndPayload(
BlocksRingBuffer::EntryWriter& aEntryWriter) const {
static const DeserializerTag tag = TagForDeserializer(Deserialize);
SerializeTagAndCommonProps(tag, aEntryWriter);
aEntryWriter.WriteObject(mText);
}
// static
UniquePtr<ProfilerMarkerPayload> TextMarkerPayload::Deserialize(
BlocksRingBuffer::EntryReader& aEntryReader) {
ProfilerMarkerPayload::CommonProps props =
DeserializeCommonProps(aEntryReader);
auto text = aEntryReader.ReadObject<std::string>();
return UniquePtr<ProfilerMarkerPayload>(
new TextMarkerPayload(std::move(props), std::move(text)));
}
void TextMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
const TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks) {
UniqueStacks& aUniqueStacks) const {
StreamCommonProps("Text", aWriter, aProcessStartTime, aUniqueStacks);
aWriter.StringProperty("name", mText.c_str());
}
LogMarkerPayload::LogMarkerPayload(const char* aModule, const char* aText,
const TimeStamp& aStartTime)
: ProfilerMarkerPayload(aStartTime, aStartTime),
mModule(aModule),
mText(aText) {}
LogMarkerPayload::LogMarkerPayload(CommonProps&& aCommonProps,
std::string&& aModule, std::string&& aText)
: ProfilerMarkerPayload(std::move(aCommonProps)),
mModule(std::move(aModule)),
mText(std::move(aText)) {}
LogMarkerPayload::~LogMarkerPayload() = default;
BlocksRingBuffer::Length LogMarkerPayload::TagAndSerializationBytes() const {
return CommonPropsTagAndSerializationBytes() +
BlocksRingBuffer::SumBytes(mModule, mText);
}
void LogMarkerPayload::SerializeTagAndPayload(
BlocksRingBuffer::EntryWriter& aEntryWriter) const {
static const DeserializerTag tag = TagForDeserializer(Deserialize);
SerializeTagAndCommonProps(tag, aEntryWriter);
aEntryWriter.WriteObject(mModule);
aEntryWriter.WriteObject(mText);
}
// static
UniquePtr<ProfilerMarkerPayload> LogMarkerPayload::Deserialize(
BlocksRingBuffer::EntryReader& aEntryReader) {
ProfilerMarkerPayload::CommonProps props =
DeserializeCommonProps(aEntryReader);
auto module = aEntryReader.ReadObject<std::string>();
auto text = aEntryReader.ReadObject<std::string>();
return UniquePtr<ProfilerMarkerPayload>(new LogMarkerPayload(
std::move(props), std::move(module), std::move(text)));
}
void LogMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
const TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks) {
UniqueStacks& aUniqueStacks) const {
StreamCommonProps("Log", aWriter, aProcessStartTime, aUniqueStacks);
aWriter.StringProperty("name", mText.c_str());
aWriter.StringProperty("module", mModule.c_str());
}
HangMarkerPayload::HangMarkerPayload(const TimeStamp& aStartTime,
const TimeStamp& aEndTime)
: ProfilerMarkerPayload(aStartTime, aEndTime) {}
HangMarkerPayload::HangMarkerPayload(CommonProps&& aCommonProps)
: ProfilerMarkerPayload(std::move(aCommonProps)) {}
HangMarkerPayload::~HangMarkerPayload() = default;
BlocksRingBuffer::Length HangMarkerPayload::TagAndSerializationBytes() const {
return CommonPropsTagAndSerializationBytes();
}
void HangMarkerPayload::SerializeTagAndPayload(
BlocksRingBuffer::EntryWriter& aEntryWriter) const {
static const DeserializerTag tag = TagForDeserializer(Deserialize);
SerializeTagAndCommonProps(tag, aEntryWriter);
}
// static
UniquePtr<ProfilerMarkerPayload> HangMarkerPayload::Deserialize(
BlocksRingBuffer::EntryReader& aEntryReader) {
ProfilerMarkerPayload::CommonProps props =
DeserializeCommonProps(aEntryReader);
return UniquePtr<ProfilerMarkerPayload>(
new HangMarkerPayload(std::move(props)));
}
void HangMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
const TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks) {
UniqueStacks& aUniqueStacks) const {
StreamCommonProps("BHR-detected hang", aWriter, aProcessStartTime,
aUniqueStacks);
}
LongTaskMarkerPayload::LongTaskMarkerPayload(const TimeStamp& aStartTime,
const TimeStamp& aEndTime)
: ProfilerMarkerPayload(aStartTime, aEndTime) {}
LongTaskMarkerPayload::LongTaskMarkerPayload(CommonProps&& aCommonProps)
: ProfilerMarkerPayload(std::move(aCommonProps)) {}
LongTaskMarkerPayload::~LongTaskMarkerPayload() = default;
BlocksRingBuffer::Length LongTaskMarkerPayload::TagAndSerializationBytes()
const {
return CommonPropsTagAndSerializationBytes();
}
void LongTaskMarkerPayload::SerializeTagAndPayload(
BlocksRingBuffer::EntryWriter& aEntryWriter) const {
static const DeserializerTag tag = TagForDeserializer(Deserialize);
SerializeTagAndCommonProps(tag, aEntryWriter);
}
// static
UniquePtr<ProfilerMarkerPayload> LongTaskMarkerPayload::Deserialize(
BlocksRingBuffer::EntryReader& aEntryReader) {
ProfilerMarkerPayload::CommonProps props =
DeserializeCommonProps(aEntryReader);
return UniquePtr<ProfilerMarkerPayload>(
new LongTaskMarkerPayload(std::move(props)));
}
void LongTaskMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
const TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks) {
UniqueStacks& aUniqueStacks) const {
StreamCommonProps("MainThreadLongTask", aWriter, aProcessStartTime,
aUniqueStacks);
aWriter.StringProperty("category", "LongTask");

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

@ -13,7 +13,9 @@
# error Do not #include this header when MOZ_BASE_PROFILER is not #defined.
#endif
#include "mozilla/Atomics.h"
#include "mozilla/Attributes.h"
#include "mozilla/BlocksRingBuffer.h"
#include "mozilla/Maybe.h"
#include "mozilla/RefPtr.h"
#include "mozilla/TimeStamp.h"
@ -49,13 +51,81 @@ class ProfilerMarkerPayload {
virtual ~ProfilerMarkerPayload() {}
// Compute the number of bytes needed to serialize the `DeserializerTag` and
// payload, including in the no-payload (nullptr) case.
static BlocksRingBuffer::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,
BlocksRingBuffer::EntryWriter& 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 UniquePtr<ProfilerMarkerPayload> DeserializeTagAndPayload(
mozilla::BlocksRingBuffer::EntryReader& aER) {
const auto tag = aER.ReadObject<DeserializerTag>();
Deserializer deserializer = DeserializerForTag(tag);
return deserializer(aER);
}
virtual void StreamPayload(SpliceableJSONWriter& aWriter,
const TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks) = 0;
UniqueStacks& aUniqueStacks) const = 0;
TimeStamp GetStartTime() const { return mCommonProps.mStartTime; }
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 UniquePtr<ProfilerMarkerPayload> (*Deserializer)(
BlocksRingBuffer::EntryReader&);
// 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 Atomic<DeserializerTagAtomic, ReleaseAcquire,
recordreplay::Behavior::DontPreserve>
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.
MFBT_API static DeserializerTag TagForDeserializer(
Deserializer aDeserializer);
// Get the `Deserializer` for a given `DeserializerTag`.
// Tag 0 is reserved as no-payload deserializer (which returns nullptr).
MFBT_API static Deserializer DeserializerForTag(DeserializerTag aTag);
struct CommonProps {
TimeStamp mStartTime;
TimeStamp mEndTime;
@ -64,62 +134,89 @@ class ProfilerMarkerPayload {
Maybe<uint32_t> mDocShellHistoryId;
};
// Deserializers can use this base constructor.
explicit ProfilerMarkerPayload(CommonProps&& aCommonProps)
: mCommonProps(std::move(aCommonProps)) {}
// Serialization/deserialization of common props in ProfilerMarkerPayload.
MFBT_API BlocksRingBuffer::Length CommonPropsTagAndSerializationBytes() const;
MFBT_API void SerializeTagAndCommonProps(
DeserializerTag aDeserializerTag,
BlocksRingBuffer::EntryWriter& aEntryWriter) const;
MFBT_API static CommonProps DeserializeCommonProps(
BlocksRingBuffer::EntryReader& aEntryReader);
MFBT_API void StreamType(const char* aMarkerType,
SpliceableJSONWriter& aWriter);
SpliceableJSONWriter& aWriter) const;
MFBT_API void StreamCommonProps(const char* aMarkerType,
SpliceableJSONWriter& aWriter,
const TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks);
UniqueStacks& aUniqueStacks) const;
private:
// Compute the number of bytes needed to serialize the `DeserializerTag` and
// payload in `SerializeTagAndPayload` below.
virtual BlocksRingBuffer::Length TagAndSerializationBytes() const = 0;
// Serialize the `DeserializerTag` and payload into an EntryWriter.
// Must be of the exact size given by `TagAndSerializationBytes()`.
virtual void SerializeTagAndPayload(
BlocksRingBuffer::EntryWriter& aEntryWriter) const = 0;
CommonProps mCommonProps;
};
#define DECL_BASE_STREAM_PAYLOAD \
virtual void StreamPayload( \
::mozilla::baseprofiler::SpliceableJSONWriter& aWriter, \
const ::mozilla::TimeStamp& aProcessStartTime, \
::mozilla::baseprofiler::UniqueStacks& aUniqueStacks) override;
#define DECL_BASE_STREAM_PAYLOAD \
MFBT_API void StreamPayload( \
::mozilla::baseprofiler::SpliceableJSONWriter& aWriter, \
const ::mozilla::TimeStamp& aProcessStartTime, \
::mozilla::baseprofiler::UniqueStacks& aUniqueStacks) const override; \
static UniquePtr<ProfilerMarkerPayload> Deserialize( \
BlocksRingBuffer::EntryReader& aEntryReader); \
MFBT_API BlocksRingBuffer::Length TagAndSerializationBytes() const override; \
MFBT_API void SerializeTagAndPayload( \
BlocksRingBuffer::EntryWriter& aEntryWriter) const override;
// TODO: Increase the coverage of tracing markers that include DocShell
// information
class TracingMarkerPayload : public ProfilerMarkerPayload {
public:
TracingMarkerPayload(const char* aCategory, TracingKind aKind,
const Maybe<std::string>& aDocShellId = Nothing(),
const Maybe<uint32_t>& aDocShellHistoryId = Nothing(),
UniqueProfilerBacktrace aCause = nullptr)
: ProfilerMarkerPayload(aDocShellId, aDocShellHistoryId,
std::move(aCause)),
mCategory(aCategory),
mKind(aKind) {}
MFBT_API TracingMarkerPayload(
const char* aCategory, TracingKind aKind,
const Maybe<std::string>& aDocShellId = Nothing(),
const Maybe<uint32_t>& aDocShellHistoryId = Nothing(),
UniqueProfilerBacktrace aCause = nullptr);
MFBT_API ~TracingMarkerPayload() override;
DECL_BASE_STREAM_PAYLOAD
private:
MFBT_API TracingMarkerPayload(CommonProps&& aCommonProps,
const char* aCategory, TracingKind aKind);
const char* mCategory;
TracingKind mKind;
};
class FileIOMarkerPayload : public ProfilerMarkerPayload {
public:
FileIOMarkerPayload(const char* aOperation, const char* aSource,
const char* aFilename, const TimeStamp& aStartTime,
const TimeStamp& aEndTime, UniqueProfilerBacktrace aStack)
: ProfilerMarkerPayload(aStartTime, aEndTime, Nothing(), Nothing(),
std::move(aStack)),
mSource(aSource),
mOperation(aOperation ? strdup(aOperation) : nullptr),
mFilename(aFilename ? strdup(aFilename) : nullptr) {
MOZ_ASSERT(aSource);
}
MFBT_API FileIOMarkerPayload(const char* aOperation, const char* aSource,
const char* aFilename,
const TimeStamp& aStartTime,
const TimeStamp& aEndTime,
UniqueProfilerBacktrace aStack);
MFBT_API ~FileIOMarkerPayload() override;
DECL_BASE_STREAM_PAYLOAD
private:
MFBT_API FileIOMarkerPayload(CommonProps&& aCommonProps, const char* aSource,
UniqueFreePtr<char>&& aOperation,
UniqueFreePtr<char>&& aFilename);
const char* mSource;
UniqueFreePtr<char> mOperation;
UniqueFreePtr<char> mFilename;
@ -127,31 +224,29 @@ class FileIOMarkerPayload : public ProfilerMarkerPayload {
class UserTimingMarkerPayload : public ProfilerMarkerPayload {
public:
UserTimingMarkerPayload(const std::string& aName, const TimeStamp& aStartTime,
const Maybe<std::string>& aDocShellId,
const Maybe<uint32_t>& aDocShellHistoryId)
: ProfilerMarkerPayload(aStartTime, aStartTime, aDocShellId,
aDocShellHistoryId),
mEntryType("mark"),
mName(aName) {}
MFBT_API UserTimingMarkerPayload(const std::string& aName,
const TimeStamp& aStartTime,
const Maybe<std::string>& aDocShellId,
const Maybe<uint32_t>& aDocShellHistoryId);
UserTimingMarkerPayload(const std::string& aName,
const Maybe<std::string>& aStartMark,
const Maybe<std::string>& aEndMark,
const TimeStamp& aStartTime,
const TimeStamp& aEndTime,
const Maybe<std::string>& aDocShellId,
const Maybe<uint32_t>& aDocShellHistoryId)
: ProfilerMarkerPayload(aStartTime, aEndTime, aDocShellId,
aDocShellHistoryId),
mEntryType("measure"),
mName(aName),
mStartMark(aStartMark),
mEndMark(aEndMark) {}
MFBT_API UserTimingMarkerPayload(const std::string& aName,
const Maybe<std::string>& aStartMark,
const Maybe<std::string>& aEndMark,
const TimeStamp& aStartTime,
const TimeStamp& aEndTime,
const Maybe<std::string>& aDocShellId,
const Maybe<uint32_t>& aDocShellHistoryId);
MFBT_API ~UserTimingMarkerPayload() override;
DECL_BASE_STREAM_PAYLOAD
private:
MFBT_API UserTimingMarkerPayload(CommonProps&& aCommonProps,
const char* aEntryType, std::string&& aName,
Maybe<std::string>&& aStartMark,
Maybe<std::string>&& aEndMark);
// Either "mark" or "measure".
const char* mEntryType;
std::string mName;
@ -161,68 +256,114 @@ class UserTimingMarkerPayload : public ProfilerMarkerPayload {
class HangMarkerPayload : public ProfilerMarkerPayload {
public:
HangMarkerPayload(const TimeStamp& aStartTime, const TimeStamp& aEndTime)
: ProfilerMarkerPayload(aStartTime, aEndTime) {}
MFBT_API HangMarkerPayload(const TimeStamp& aStartTime,
const TimeStamp& aEndTime);
MFBT_API ~HangMarkerPayload() override;
DECL_BASE_STREAM_PAYLOAD
private:
MFBT_API explicit HangMarkerPayload(CommonProps&& aCommonProps);
};
class LongTaskMarkerPayload : public ProfilerMarkerPayload {
public:
LongTaskMarkerPayload(const TimeStamp& aStartTime, const TimeStamp& aEndTime)
: ProfilerMarkerPayload(aStartTime, aEndTime) {}
MFBT_API LongTaskMarkerPayload(const TimeStamp& aStartTime,
const TimeStamp& aEndTime);
DECL_BASE_STREAM_PAYLOAD
};
class TextMarkerPayload : public ProfilerMarkerPayload {
public:
TextMarkerPayload(const std::string& aText, const TimeStamp& aStartTime)
: ProfilerMarkerPayload(aStartTime, aStartTime), mText(aText) {}
TextMarkerPayload(const std::string& aText, const TimeStamp& aStartTime,
const TimeStamp& aEndTime)
: ProfilerMarkerPayload(aStartTime, aEndTime), mText(aText) {}
TextMarkerPayload(const std::string& aText, const TimeStamp& aStartTime,
const Maybe<std::string>& aDocShellId,
const Maybe<uint32_t>& aDocShellHistoryId)
: ProfilerMarkerPayload(aStartTime, aStartTime, aDocShellId,
aDocShellHistoryId),
mText(aText) {}
TextMarkerPayload(const std::string& aText, const TimeStamp& aStartTime,
const TimeStamp& aEndTime,
const Maybe<std::string>& aDocShellId,
const Maybe<uint32_t>& aDocShellHistoryId,
UniqueProfilerBacktrace aCause = nullptr)
: ProfilerMarkerPayload(aStartTime, aEndTime, aDocShellId,
aDocShellHistoryId, std::move(aCause)),
mText(aText) {}
MFBT_API ~LongTaskMarkerPayload() override;
DECL_BASE_STREAM_PAYLOAD
private:
MFBT_API explicit LongTaskMarkerPayload(CommonProps&& aCommonProps);
};
class TextMarkerPayload : public ProfilerMarkerPayload {
public:
MFBT_API TextMarkerPayload(const std::string& aText,
const TimeStamp& aStartTime);
MFBT_API TextMarkerPayload(const std::string& aText,
const TimeStamp& aStartTime,
const TimeStamp& aEndTime);
MFBT_API TextMarkerPayload(const std::string& aText,
const TimeStamp& aStartTime,
const Maybe<std::string>& aDocShellId,
const Maybe<uint32_t>& aDocShellHistoryId);
MFBT_API TextMarkerPayload(const std::string& aText,
const TimeStamp& aStartTime,
const TimeStamp& aEndTime,
const Maybe<std::string>& aDocShellId,
const Maybe<uint32_t>& aDocShellHistoryId,
UniqueProfilerBacktrace aCause = nullptr);
MFBT_API ~TextMarkerPayload() override;
DECL_BASE_STREAM_PAYLOAD
private:
MFBT_API TextMarkerPayload(CommonProps&& aCommonProps, std::string&& aText);
std::string mText;
};
class LogMarkerPayload : public ProfilerMarkerPayload {
public:
LogMarkerPayload(const char* aModule, const char* aText,
const TimeStamp& aStartTime)
: ProfilerMarkerPayload(aStartTime, aStartTime),
mModule(aModule),
mText(aText) {}
MFBT_API LogMarkerPayload(const char* aModule, const char* aText,
const TimeStamp& aStartTime);
MFBT_API ~LogMarkerPayload() override;
DECL_BASE_STREAM_PAYLOAD
private:
MFBT_API LogMarkerPayload(CommonProps&& aCommonProps, std::string&& aModule,
std::string&& aText);
std::string mModule; // longest known LazyLogModule name is ~24
std::string mText;
};
} // namespace baseprofiler
// Serialize a pointed-at ProfilerMarkerPayload, may be null when there are no
// payloads.
template <>
struct BlocksRingBuffer::Serializer<
UniquePtr<baseprofiler::ProfilerMarkerPayload>> {
static Length Bytes(
const UniquePtr<baseprofiler::ProfilerMarkerPayload>& aPayload) {
return baseprofiler::ProfilerMarkerPayload::TagAndSerializationBytes(
aPayload.get());
}
static void Write(
EntryWriter& aEW,
const UniquePtr<baseprofiler::ProfilerMarkerPayload>& aPayload) {
baseprofiler::ProfilerMarkerPayload::TagAndSerialize(aPayload.get(), aEW);
}
};
// Deserialize a ProfilerMarkerPayload into a UniquePtr, may be null if there
// are no payloads.
template <>
struct BlocksRingBuffer::Deserializer<
UniquePtr<baseprofiler::ProfilerMarkerPayload>> {
static void ReadInto(
EntryReader& aER,
UniquePtr<baseprofiler::ProfilerMarkerPayload>& aPayload) {
aPayload = Read(aER);
}
static UniquePtr<baseprofiler::ProfilerMarkerPayload> Read(EntryReader& aER) {
return baseprofiler::ProfilerMarkerPayload::DeserializeTagAndPayload(aER);
}
};
} // namespace mozilla
#endif // BaseProfilerMarkerPayload_h

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

@ -8,6 +8,8 @@
#ifdef MOZ_BASE_PROFILER
# include "BaseProfileJSONWriter.h"
# include "BaseProfilerMarkerPayload.h"
# include "mozilla/BlocksRingBuffer.h"
# include "mozilla/leb128iterator.h"
# include "mozilla/ModuloBuffer.h"
@ -1364,6 +1366,102 @@ void TestBlocksRingBufferSerialization() {
printf("TestBlocksRingBufferSerialization done\n");
}
class BaseTestMarkerPayload : public baseprofiler::ProfilerMarkerPayload {
public:
explicit BaseTestMarkerPayload(int aData) : mData(aData) {}
int GetData() const { return mData; }
// Exploded DECL_BASE_STREAM_PAYLOAD, but without `MFBT_API`s.
static UniquePtr<ProfilerMarkerPayload> Deserialize(
BlocksRingBuffer::EntryReader& aEntryReader);
BlocksRingBuffer::Length TagAndSerializationBytes() const override;
void SerializeTagAndPayload(
BlocksRingBuffer::EntryWriter& aEntryWriter) const override;
void StreamPayload(
::mozilla::baseprofiler::SpliceableJSONWriter& aWriter,
const ::mozilla::TimeStamp& aProcessStartTime,
::mozilla::baseprofiler::UniqueStacks& aUniqueStacks) const override;
private:
BaseTestMarkerPayload(CommonProps&& aProps, int aData)
: baseprofiler::ProfilerMarkerPayload(std::move(aProps)), mData(aData) {}
int mData;
};
// static
UniquePtr<baseprofiler::ProfilerMarkerPayload>
BaseTestMarkerPayload::Deserialize(
BlocksRingBuffer::EntryReader& aEntryReader) {
CommonProps props = DeserializeCommonProps(aEntryReader);
int data = aEntryReader.ReadObject<int>();
return UniquePtr<baseprofiler::ProfilerMarkerPayload>(
new BaseTestMarkerPayload(std::move(props), data));
}
BlocksRingBuffer::Length BaseTestMarkerPayload::TagAndSerializationBytes()
const {
return CommonPropsTagAndSerializationBytes() + sizeof(int);
}
void BaseTestMarkerPayload::SerializeTagAndPayload(
BlocksRingBuffer::EntryWriter& aEntryWriter) const {
static const DeserializerTag tag = TagForDeserializer(Deserialize);
SerializeTagAndCommonProps(tag, aEntryWriter);
aEntryWriter.WriteObject(mData);
}
void BaseTestMarkerPayload::StreamPayload(
baseprofiler::SpliceableJSONWriter& aWriter,
const TimeStamp& aProcessStartTime,
baseprofiler::UniqueStacks& aUniqueStacks) const {
aWriter.IntProperty("data", mData);
}
void TestProfilerMarkerSerialization() {
printf("TestProfilerMarkerSerialization...\n");
constexpr uint32_t MBSize = 256;
uint8_t buffer[MBSize * 3];
for (size_t i = 0; i < MBSize * 3; ++i) {
buffer[i] = uint8_t('A' + i);
}
BlocksRingBuffer rb(BlocksRingBuffer::ThreadSafety::WithMutex,
&buffer[MBSize], MakePowerOfTwo32<MBSize>());
constexpr int data = 42;
{
UniquePtr<baseprofiler::ProfilerMarkerPayload> testPayload{
new BaseTestMarkerPayload(data)};
rb.PutObject(testPayload);
}
int read = 0;
rb.ReadEach([&](BlocksRingBuffer::EntryReader& aER) {
UniquePtr<baseprofiler::ProfilerMarkerPayload> payload =
aER.ReadObject<UniquePtr<baseprofiler::ProfilerMarkerPayload>>();
MOZ_RELEASE_ASSERT(!!payload);
++read;
BaseTestMarkerPayload* testPayload =
static_cast<BaseTestMarkerPayload*>(payload.get());
MOZ_RELEASE_ASSERT(testPayload);
MOZ_RELEASE_ASSERT(testPayload->GetData() == data);
});
MOZ_RELEASE_ASSERT(read == 1);
// Everything around the sub-buffer should be unchanged.
for (size_t i = 0; i < MBSize; ++i) {
MOZ_RELEASE_ASSERT(buffer[i] == uint8_t('A' + i));
}
for (size_t i = MBSize * 2; i < MBSize * 3; ++i) {
MOZ_RELEASE_ASSERT(buffer[i] == uint8_t('A' + i));
}
printf("TestProfilerMarkerSerialization done\n");
}
// Increase the depth, to a maximum (to avoid too-deep recursion).
static constexpr size_t NextDepth(size_t aDepth) {
constexpr size_t MAX_DEPTH = 128;
@ -1419,6 +1517,7 @@ void TestProfiler() {
TestBlocksRingBufferUnderlyingBufferChanges();
TestBlocksRingBufferThreading();
TestBlocksRingBufferSerialization();
TestProfilerMarkerSerialization();
{
printf("profiler_init()...\n");
@ -1499,6 +1598,53 @@ void TestProfiler() {
threadCancelFib.join();
}
// Just making sure all payloads know how to (de)serialize and stream.
baseprofiler::profiler_add_marker(
"TracingMarkerPayload", baseprofiler::ProfilingCategoryPair::OTHER,
MakeUnique<baseprofiler::TracingMarkerPayload>(
"category", baseprofiler::TRACING_EVENT));
auto cause =
# if defined(__linux__) || defined(__ANDROID__)
// Currently disabled on these platforms, so just return a null.
decltype(baseprofiler::profiler_get_backtrace()){};
# else
baseprofiler::profiler_get_backtrace();
# endif
baseprofiler::profiler_add_marker(
"FileIOMarkerPayload", baseprofiler::ProfilingCategoryPair::OTHER,
MakeUnique<baseprofiler::FileIOMarkerPayload>(
"operation", "source", "filename", TimeStamp::NowUnfuzzed(),
TimeStamp::NowUnfuzzed(), std::move(cause)));
baseprofiler::profiler_add_marker(
"UserTimingMarkerPayload", baseprofiler::ProfilingCategoryPair::OTHER,
MakeUnique<baseprofiler::UserTimingMarkerPayload>(
"name", TimeStamp::NowUnfuzzed(), Nothing{}, Nothing{}));
baseprofiler::profiler_add_marker(
"HangMarkerPayload", baseprofiler::ProfilingCategoryPair::OTHER,
MakeUnique<baseprofiler::HangMarkerPayload>(TimeStamp::NowUnfuzzed(),
TimeStamp::NowUnfuzzed()));
baseprofiler::profiler_add_marker(
"LongTaskMarkerPayload", baseprofiler::ProfilingCategoryPair::OTHER,
MakeUnique<baseprofiler::LongTaskMarkerPayload>(
TimeStamp::NowUnfuzzed(), TimeStamp::NowUnfuzzed()));
{
std::string s = "text payload";
baseprofiler::profiler_add_marker(
"TextMarkerPayload", baseprofiler::ProfilingCategoryPair::OTHER,
MakeUnique<baseprofiler::TextMarkerPayload>(
s, TimeStamp::NowUnfuzzed(), TimeStamp::NowUnfuzzed()));
}
baseprofiler::profiler_add_marker(
"LogMarkerPayload", baseprofiler::ProfilingCategoryPair::OTHER,
MakeUnique<baseprofiler::LogMarkerPayload>("module", "text",
TimeStamp::NowUnfuzzed()));
printf("Sleep 1s...\n");
{
AUTO_BASE_PROFILER_THREAD_SLEEP;

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

@ -61,11 +61,11 @@ template <>
struct BlocksRingBuffer::Serializer<ProfilerBacktrace> {
static Length Bytes(const ProfilerBacktrace& aBacktrace) {
if (!aBacktrace.mProfileBuffer) {
return 1;
return ULEB128Size<Length>(0);
}
auto bufferBytes = SumBytes(*aBacktrace.mBlocksRingBuffer);
if (bufferBytes == 0) {
return 1;
return ULEB128Size<Length>(0);
}
return bufferBytes +
SumBytes(aBacktrace.mThreadId,
@ -88,7 +88,7 @@ struct BlocksRingBuffer::Serializer<UniquePtr<ProfilerBacktrace, Destructor>> {
static Length Bytes(
const UniquePtr<ProfilerBacktrace, Destructor>& aBacktrace) {
if (!aBacktrace) {
return 1;
return ULEB128Size<Length>(0);
}
return SumBytes(*aBacktrace);
}

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

@ -12,6 +12,7 @@
#include "gfxASurface.h"
#include "Layers.h"
#include "mozilla/BlocksRingBufferGeckoExtensions.h"
#include "mozilla/Maybe.h"
#include "mozilla/net/HttpBaseChannel.h"
#include "mozilla/Preferences.h"
@ -21,6 +22,76 @@
using namespace mozilla;
static UniquePtr<ProfilerMarkerPayload> DeserializeNothing(
BlocksRingBuffer::EntryReader&) {
return nullptr;
}
// Starting at 1 for the initial `DeserializeNothing`.
// static
Atomic<ProfilerMarkerPayload::DeserializerTagAtomic, ReleaseAcquire,
recordreplay::Behavior::DontPreserve>
ProfilerMarkerPayload::sDeserializerCount{1};
// Initialize `sDeserializers` with `DeserializeNothing` at index 0, all others
// are nullptrs.
// static
ProfilerMarkerPayload::Deserializer
ProfilerMarkerPayload::sDeserializers[DeserializerMax] = {
DeserializeNothing};
// static
ProfilerMarkerPayload::DeserializerTag
ProfilerMarkerPayload::TagForDeserializer(
ProfilerMarkerPayload::Deserializer aDeserializer) {
if (!aDeserializer) {
return 0;
}
// Start first search at index 0.
DeserializerTagAtomic start = 0;
for (;;) {
// Read the current count of deserializers.
const DeserializerTagAtomic tagCount = sDeserializerCount;
if (tagCount == 0) {
// Someone else is currently writing into the array, loop around until we
// get a valid count.
continue;
}
for (DeserializerTagAtomic i = start; i < tagCount; ++i) {
if (sDeserializers[i] == aDeserializer) {
// Deserializer already registered, return its tag.
return static_cast<ProfilerMarkerPayload::DeserializerTag>(i);
}
}
// Not found yet, let's register this new deserializer.
// Make sure we haven't reached the limit yet.
MOZ_RELEASE_ASSERT(tagCount < DeserializerMax);
// Reserve `tagCount` as an index, if not already claimed:
// If `sDeserializerCount` is still at our previously-read `tagCount`,
// replace it with a special 0 value to indicate a write.
if (sDeserializerCount.compareExchange(tagCount, 0)) {
// Here we own the `tagCount` index, write the deserializer there.
sDeserializers[tagCount] = aDeserializer;
// And publish by writing the real new count (1 past our index).
sDeserializerCount = tagCount + 1;
return static_cast<ProfilerMarkerPayload::DeserializerTag>(tagCount);
}
// Someone else beat us to grab an index, and it could be for the same
// deserializer! So let's just try searching starting from our recorded
// `tagCount` (and maybe attempting again to register). It should be rare
// enough and quick enough that it won't impact performances.
start = tagCount;
}
}
// static
ProfilerMarkerPayload::Deserializer ProfilerMarkerPayload::DeserializerForTag(
ProfilerMarkerPayload::DeserializerTag aTag) {
MOZ_RELEASE_ASSERT(aTag < DeserializerMax);
MOZ_RELEASE_ASSERT(aTag < sDeserializerCount);
return sDeserializers[aTag];
}
static void MOZ_ALWAYS_INLINE WriteTime(SpliceableJSONWriter& aWriter,
const TimeStamp& aProcessStartTime,
const TimeStamp& aTime,
@ -31,14 +102,47 @@ static void MOZ_ALWAYS_INLINE WriteTime(SpliceableJSONWriter& aWriter,
}
void ProfilerMarkerPayload::StreamType(const char* aMarkerType,
SpliceableJSONWriter& aWriter) {
SpliceableJSONWriter& aWriter) const {
MOZ_ASSERT(aMarkerType);
aWriter.StringProperty("type", aMarkerType);
}
BlocksRingBuffer::Length
ProfilerMarkerPayload::CommonPropsTagAndSerializationBytes() const {
return sizeof(DeserializerTag) +
BlocksRingBuffer::SumBytes(mCommonProps.mStartTime,
mCommonProps.mEndTime, mCommonProps.mStack,
mCommonProps.mDocShellId,
mCommonProps.mDocShellHistoryId);
}
void ProfilerMarkerPayload::SerializeTagAndCommonProps(
DeserializerTag aDeserializerTag,
BlocksRingBuffer::EntryWriter& aEntryWriter) const {
aEntryWriter.WriteObject(aDeserializerTag);
aEntryWriter.WriteObject(mCommonProps.mStartTime);
aEntryWriter.WriteObject(mCommonProps.mEndTime);
aEntryWriter.WriteObject(mCommonProps.mStack);
aEntryWriter.WriteObject(mCommonProps.mDocShellId);
aEntryWriter.WriteObject(mCommonProps.mDocShellHistoryId);
}
// static
ProfilerMarkerPayload::CommonProps
ProfilerMarkerPayload::DeserializeCommonProps(
BlocksRingBuffer::EntryReader& aEntryReader) {
CommonProps props;
aEntryReader.ReadIntoObject(props.mStartTime);
aEntryReader.ReadIntoObject(props.mEndTime);
aEntryReader.ReadIntoObject(props.mStack);
aEntryReader.ReadIntoObject(props.mDocShellId);
aEntryReader.ReadIntoObject(props.mDocShellHistoryId);
return props;
}
void ProfilerMarkerPayload::StreamCommonProps(
const char* aMarkerType, SpliceableJSONWriter& aWriter,
const TimeStamp& aProcessStartTime, UniqueStacks& aUniqueStacks) {
const TimeStamp& aProcessStartTime, UniqueStacks& aUniqueStacks) const {
StreamType(aMarkerType, aWriter);
WriteTime(aWriter, aProcessStartTime, mCommonProps.mStartTime, "startTime");
WriteTime(aWriter, aProcessStartTime, mCommonProps.mEndTime, "endTime");
@ -60,9 +164,41 @@ void ProfilerMarkerPayload::StreamCommonProps(
}
}
BlocksRingBuffer::Length TracingMarkerPayload::TagAndSerializationBytes()
const {
return CommonPropsTagAndSerializationBytes() +
BlocksRingBuffer::SumBytes(WrapBlocksRingBufferRawPointer(mCategory),
mKind);
}
void TracingMarkerPayload::SerializeTagAndPayload(
BlocksRingBuffer::EntryWriter& aEntryWriter) const {
static const DeserializerTag tag = TagForDeserializer(Deserialize);
SerializeTagAndPayload(tag, aEntryWriter);
}
void TracingMarkerPayload::SerializeTagAndPayload(
DeserializerTag aDeserializerTag,
BlocksRingBuffer::EntryWriter& aEntryWriter) const {
SerializeTagAndCommonProps(aDeserializerTag, aEntryWriter);
aEntryWriter.WriteObject(WrapBlocksRingBufferRawPointer(mCategory));
aEntryWriter.WriteObject(mKind);
}
// static
UniquePtr<ProfilerMarkerPayload> TracingMarkerPayload::Deserialize(
BlocksRingBuffer::EntryReader& aEntryReader) {
ProfilerMarkerPayload::CommonProps props =
DeserializeCommonProps(aEntryReader);
const char* category = aEntryReader.ReadObject<const char*>();
TracingKind kind = aEntryReader.ReadObject<TracingKind>();
return UniquePtr<ProfilerMarkerPayload>(
new TracingMarkerPayload(std::move(props), category, kind));
}
void TracingMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
const TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks) {
UniqueStacks& aUniqueStacks) const {
StreamCommonProps("tracing", aWriter, aProcessStartTime, aUniqueStacks);
if (mCategory) {
@ -76,9 +212,36 @@ void TracingMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
}
}
BlocksRingBuffer::Length FileIOMarkerPayload::TagAndSerializationBytes() const {
return CommonPropsTagAndSerializationBytes() +
BlocksRingBuffer::SumBytes(WrapBlocksRingBufferRawPointer(mSource),
mOperation, mFilename);
}
void FileIOMarkerPayload::SerializeTagAndPayload(
BlocksRingBuffer::EntryWriter& aEntryWriter) const {
static const DeserializerTag tag = TagForDeserializer(Deserialize);
SerializeTagAndCommonProps(tag, aEntryWriter);
aEntryWriter.WriteObject(WrapBlocksRingBufferRawPointer(mSource));
aEntryWriter.WriteObject(mOperation);
aEntryWriter.WriteObject(mFilename);
}
// static
UniquePtr<ProfilerMarkerPayload> FileIOMarkerPayload::Deserialize(
BlocksRingBuffer::EntryReader& aEntryReader) {
ProfilerMarkerPayload::CommonProps props =
DeserializeCommonProps(aEntryReader);
auto source = aEntryReader.ReadObject<const char*>();
auto operation = aEntryReader.ReadObject<UniqueFreePtr<char>>();
auto filename = aEntryReader.ReadObject<UniqueFreePtr<char>>();
return UniquePtr<ProfilerMarkerPayload>(new FileIOMarkerPayload(
std::move(props), source, std::move(operation), std::move(filename)));
}
void FileIOMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
const TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks) {
UniqueStacks& aUniqueStacks) const {
StreamCommonProps("FileIO", aWriter, aProcessStartTime, aUniqueStacks);
aWriter.StringProperty("operation", mOperation.get());
aWriter.StringProperty("source", mSource);
@ -87,9 +250,40 @@ void FileIOMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
}
}
BlocksRingBuffer::Length UserTimingMarkerPayload::TagAndSerializationBytes()
const {
return CommonPropsTagAndSerializationBytes() +
BlocksRingBuffer::SumBytes(WrapBlocksRingBufferRawPointer(mEntryType),
mName, mStartMark, mEndMark);
}
void UserTimingMarkerPayload::SerializeTagAndPayload(
BlocksRingBuffer::EntryWriter& aEntryWriter) const {
static const DeserializerTag tag = TagForDeserializer(Deserialize);
SerializeTagAndCommonProps(tag, aEntryWriter);
aEntryWriter.WriteObject(WrapBlocksRingBufferRawPointer(mEntryType));
aEntryWriter.WriteObject(mName);
aEntryWriter.WriteObject(mStartMark);
aEntryWriter.WriteObject(mEndMark);
}
// static
UniquePtr<ProfilerMarkerPayload> UserTimingMarkerPayload::Deserialize(
BlocksRingBuffer::EntryReader& aEntryReader) {
ProfilerMarkerPayload::CommonProps props =
DeserializeCommonProps(aEntryReader);
auto entryType = aEntryReader.ReadObject<const char*>();
auto name = aEntryReader.ReadObject<nsString>();
auto startMark = aEntryReader.ReadObject<Maybe<nsString>>();
auto endMark = aEntryReader.ReadObject<Maybe<nsString>>();
return UniquePtr<ProfilerMarkerPayload>(
new UserTimingMarkerPayload(std::move(props), entryType, std::move(name),
std::move(startMark), std::move(endMark)));
}
void UserTimingMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
const TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks) {
UniqueStacks& aUniqueStacks) const {
StreamCommonProps("UserTiming", aWriter, aProcessStartTime, aUniqueStacks);
aWriter.StringProperty("name", NS_ConvertUTF16toUTF8(mName).get());
aWriter.StringProperty("entryType", mEntryType);
@ -108,24 +302,99 @@ void UserTimingMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
}
}
BlocksRingBuffer::Length TextMarkerPayload::TagAndSerializationBytes() const {
return CommonPropsTagAndSerializationBytes() +
BlocksRingBuffer::SumBytes(mText);
}
void TextMarkerPayload::SerializeTagAndPayload(
BlocksRingBuffer::EntryWriter& aEntryWriter) const {
static const DeserializerTag tag = TagForDeserializer(Deserialize);
SerializeTagAndCommonProps(tag, aEntryWriter);
aEntryWriter.WriteObject(mText);
}
// static
UniquePtr<ProfilerMarkerPayload> TextMarkerPayload::Deserialize(
BlocksRingBuffer::EntryReader& aEntryReader) {
ProfilerMarkerPayload::CommonProps props =
DeserializeCommonProps(aEntryReader);
auto text = aEntryReader.ReadObject<nsCString>();
return UniquePtr<ProfilerMarkerPayload>(
new TextMarkerPayload(std::move(props), std::move(text)));
}
void TextMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
const TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks) {
UniqueStacks& aUniqueStacks) const {
StreamCommonProps("Text", aWriter, aProcessStartTime, aUniqueStacks);
aWriter.StringProperty("name", mText.get());
}
BlocksRingBuffer::Length LogMarkerPayload::TagAndSerializationBytes() const {
return CommonPropsTagAndSerializationBytes() +
BlocksRingBuffer::SumBytes(mModule, mText);
}
void LogMarkerPayload::SerializeTagAndPayload(
BlocksRingBuffer::EntryWriter& aEntryWriter) const {
static const DeserializerTag tag = TagForDeserializer(Deserialize);
SerializeTagAndCommonProps(tag, aEntryWriter);
aEntryWriter.WriteObject(mModule);
aEntryWriter.WriteObject(mText);
}
// static
UniquePtr<ProfilerMarkerPayload> LogMarkerPayload::Deserialize(
BlocksRingBuffer::EntryReader& aEntryReader) {
ProfilerMarkerPayload::CommonProps props =
DeserializeCommonProps(aEntryReader);
auto module = aEntryReader.ReadObject<nsAutoCStringN<32>>();
auto text = aEntryReader.ReadObject<nsCString>();
return UniquePtr<ProfilerMarkerPayload>(new LogMarkerPayload(
std::move(props), std::move(module), std::move(text)));
}
void LogMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
const TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks) {
UniqueStacks& aUniqueStacks) const {
StreamCommonProps("Log", aWriter, aProcessStartTime, aUniqueStacks);
aWriter.StringProperty("name", mText.get());
aWriter.StringProperty("module", mModule.get());
}
BlocksRingBuffer::Length DOMEventMarkerPayload::TagAndSerializationBytes()
const {
return TracingMarkerPayload::TagAndSerializationBytes() +
BlocksRingBuffer::SumBytes(mTimeStamp, mEventType);
}
void DOMEventMarkerPayload::SerializeTagAndPayload(
BlocksRingBuffer::EntryWriter& aEntryWriter) const {
static const DeserializerTag tag = TagForDeserializer(Deserialize);
// Let our parent class serialize our tag with its payload.
TracingMarkerPayload::SerializeTagAndPayload(tag, aEntryWriter);
// Then write our extra data.
aEntryWriter.WriteObject(mTimeStamp);
aEntryWriter.WriteObject(mEventType);
}
// static
UniquePtr<ProfilerMarkerPayload> DOMEventMarkerPayload::Deserialize(
BlocksRingBuffer::EntryReader& aEntryReader) {
ProfilerMarkerPayload::CommonProps props =
DeserializeCommonProps(aEntryReader);
const char* category = aEntryReader.ReadObject<const char*>();
TracingKind kind = aEntryReader.ReadObject<TracingKind>();
auto timeStamp = aEntryReader.ReadObject<TimeStamp>();
auto eventType = aEntryReader.ReadObject<nsString>();
return UniquePtr<ProfilerMarkerPayload>(new DOMEventMarkerPayload(
std::move(props), category, kind, timeStamp, std::move(eventType)));
}
void DOMEventMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
const TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks) {
UniqueStacks& aUniqueStacks) const {
TracingMarkerPayload::StreamPayload(aWriter, aProcessStartTime,
aUniqueStacks);
@ -133,15 +402,46 @@ void DOMEventMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
aWriter.StringProperty("eventType", NS_ConvertUTF16toUTF8(mEventType).get());
}
static const char* PrefValueKindToString(
const mozilla::Maybe<PrefValueKind>& aKind) {
BlocksRingBuffer::Length PrefMarkerPayload::TagAndSerializationBytes() const {
return CommonPropsTagAndSerializationBytes() +
BlocksRingBuffer::SumBytes(mPrefAccessTime, mPrefName, mPrefKind,
mPrefType, mPrefValue);
}
void PrefMarkerPayload::SerializeTagAndPayload(
BlocksRingBuffer::EntryWriter& aEntryWriter) const {
static const DeserializerTag tag = TagForDeserializer(Deserialize);
SerializeTagAndCommonProps(tag, aEntryWriter);
aEntryWriter.WriteObject(mPrefAccessTime);
aEntryWriter.WriteObject(mPrefName);
aEntryWriter.WriteObject(mPrefKind);
aEntryWriter.WriteObject(mPrefType);
aEntryWriter.WriteObject(mPrefValue);
}
// static
UniquePtr<ProfilerMarkerPayload> PrefMarkerPayload::Deserialize(
BlocksRingBuffer::EntryReader& aEntryReader) {
ProfilerMarkerPayload::CommonProps props =
DeserializeCommonProps(aEntryReader);
auto prefAccessTime = aEntryReader.ReadObject<TimeStamp>();
auto prefName = aEntryReader.ReadObject<nsCString>();
auto prefKind = aEntryReader.ReadObject<Maybe<PrefValueKind>>();
auto prefType = aEntryReader.ReadObject<Maybe<PrefType>>();
auto prefValue = aEntryReader.ReadObject<nsCString>();
return UniquePtr<ProfilerMarkerPayload>(new PrefMarkerPayload(
std::move(props), prefAccessTime, std::move(prefName),
std::move(prefKind), std::move(prefType), std::move(prefValue)));
}
static const char* PrefValueKindToString(const Maybe<PrefValueKind>& aKind) {
if (aKind) {
return *aKind == PrefValueKind::Default ? "Default" : "User";
}
return "Shared";
}
static const char* PrefTypeToString(const mozilla::Maybe<PrefType>& type) {
static const char* PrefTypeToString(const Maybe<PrefType>& type) {
if (type) {
switch (*type) {
case PrefType::None:
@ -161,7 +461,7 @@ static const char* PrefTypeToString(const mozilla::Maybe<PrefType>& type) {
void PrefMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
const TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks) {
UniqueStacks& aUniqueStacks) const {
StreamCommonProps("PreferenceRead", aWriter, aProcessStartTime,
aUniqueStacks);
WriteTime(aWriter, aProcessStartTime, mPrefAccessTime, "prefAccessTime");
@ -171,9 +471,35 @@ void PrefMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
aWriter.StringProperty("prefValue", mPrefValue.get());
}
BlocksRingBuffer::Length
LayerTranslationMarkerPayload::TagAndSerializationBytes() const {
return CommonPropsTagAndSerializationBytes() +
BlocksRingBuffer::SumBytes(WrapBlocksRingBufferRawPointer(mLayer),
mPoint);
}
void LayerTranslationMarkerPayload::SerializeTagAndPayload(
BlocksRingBuffer::EntryWriter& aEntryWriter) const {
static const DeserializerTag tag = TagForDeserializer(Deserialize);
SerializeTagAndCommonProps(tag, aEntryWriter);
aEntryWriter.WriteObject(WrapBlocksRingBufferRawPointer(mLayer));
aEntryWriter.WriteObject(mPoint);
}
// static
UniquePtr<ProfilerMarkerPayload> LayerTranslationMarkerPayload::Deserialize(
BlocksRingBuffer::EntryReader& aEntryReader) {
ProfilerMarkerPayload::CommonProps props =
DeserializeCommonProps(aEntryReader);
auto layer = aEntryReader.ReadObject<layers::Layer*>();
auto point = aEntryReader.ReadObject<gfx::Point>();
return UniquePtr<ProfilerMarkerPayload>(
new LayerTranslationMarkerPayload(std::move(props), layer, point));
}
void LayerTranslationMarkerPayload::StreamPayload(
SpliceableJSONWriter& aWriter, const TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks) {
UniqueStacks& aUniqueStacks) const {
StreamType("LayerTranslation", aWriter);
const size_t bufferSize = 32;
char buffer[bufferSize];
@ -184,12 +510,70 @@ void LayerTranslationMarkerPayload::StreamPayload(
aWriter.IntProperty("y", mPoint.y);
}
BlocksRingBuffer::Length VsyncMarkerPayload::TagAndSerializationBytes() const {
return CommonPropsTagAndSerializationBytes();
}
void VsyncMarkerPayload::SerializeTagAndPayload(
BlocksRingBuffer::EntryWriter& aEntryWriter) const {
static const DeserializerTag tag = TagForDeserializer(Deserialize);
SerializeTagAndCommonProps(tag, aEntryWriter);
}
// static
UniquePtr<ProfilerMarkerPayload> VsyncMarkerPayload::Deserialize(
BlocksRingBuffer::EntryReader& aEntryReader) {
ProfilerMarkerPayload::CommonProps props =
DeserializeCommonProps(aEntryReader);
return UniquePtr<ProfilerMarkerPayload>(
new VsyncMarkerPayload(std::move(props)));
}
void VsyncMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
const TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks) {
UniqueStacks& aUniqueStacks) const {
StreamType("VsyncTimestamp", aWriter);
}
BlocksRingBuffer::Length NetworkMarkerPayload::TagAndSerializationBytes()
const {
return CommonPropsTagAndSerializationBytes() +
BlocksRingBuffer::SumBytes(mID, mURI, mRedirectURI, mType, mPri,
mCount, mTimings, mCacheDisposition);
}
void NetworkMarkerPayload::SerializeTagAndPayload(
BlocksRingBuffer::EntryWriter& aEntryWriter) const {
static const DeserializerTag tag = TagForDeserializer(Deserialize);
SerializeTagAndCommonProps(tag, aEntryWriter);
aEntryWriter.WriteObject(mID);
aEntryWriter.WriteObject(mURI);
aEntryWriter.WriteObject(mRedirectURI);
aEntryWriter.WriteObject(mType);
aEntryWriter.WriteObject(mPri);
aEntryWriter.WriteObject(mCount);
aEntryWriter.WriteObject(mTimings);
aEntryWriter.WriteObject(mCacheDisposition);
}
// static
UniquePtr<ProfilerMarkerPayload> NetworkMarkerPayload::Deserialize(
BlocksRingBuffer::EntryReader& aEntryReader) {
ProfilerMarkerPayload::CommonProps props =
DeserializeCommonProps(aEntryReader);
auto id = aEntryReader.ReadObject<int64_t>();
auto uri = aEntryReader.ReadObject<UniqueFreePtr<char>>();
auto redirectURI = aEntryReader.ReadObject<UniqueFreePtr<char>>();
auto type = aEntryReader.ReadObject<NetworkLoadType>();
auto pri = aEntryReader.ReadObject<int32_t>();
auto count = aEntryReader.ReadObject<int64_t>();
auto timings = aEntryReader.ReadObject<net::TimingStruct>();
auto cacheDisposition = aEntryReader.ReadObject<net::CacheDisposition>();
return UniquePtr<ProfilerMarkerPayload>(new NetworkMarkerPayload(
std::move(props), id, std::move(uri), std::move(redirectURI), type, pri,
count, timings, cacheDisposition));
}
static const char* GetNetworkState(NetworkLoadType aType) {
switch (aType) {
case NetworkLoadType::LOAD_START:
@ -202,20 +586,19 @@ static const char* GetNetworkState(NetworkLoadType aType) {
return "";
}
static const char* GetCacheState(
mozilla::net::CacheDisposition aCacheDisposition) {
static const char* GetCacheState(net::CacheDisposition aCacheDisposition) {
switch (aCacheDisposition) {
case mozilla::net::kCacheUnresolved:
case net::kCacheUnresolved:
return "Unresolved";
case mozilla::net::kCacheHit:
case net::kCacheHit:
return "Hit";
case mozilla::net::kCacheHitViaReval:
case net::kCacheHitViaReval:
return "HitViaReval";
case mozilla::net::kCacheMissedViaReval:
case net::kCacheMissedViaReval:
return "MissedViaReval";
case mozilla::net::kCacheMissed:
case net::kCacheMissed:
return "Missed";
case mozilla::net::kCacheUnknown:
case net::kCacheUnknown:
default:
return nullptr;
}
@ -223,7 +606,7 @@ static const char* GetCacheState(
void NetworkMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
const TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks) {
UniqueStacks& aUniqueStacks) const {
StreamCommonProps("Network", aWriter, aProcessStartTime, aUniqueStacks);
aWriter.IntProperty("id", mID);
const char* typeString = GetNetworkState(mType);
@ -264,9 +647,37 @@ void NetworkMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
}
}
BlocksRingBuffer::Length ScreenshotPayload::TagAndSerializationBytes() const {
return CommonPropsTagAndSerializationBytes() +
BlocksRingBuffer::SumBytes(mScreenshotDataURL, mWindowSize,
mWindowIdentifier);
}
void ScreenshotPayload::SerializeTagAndPayload(
BlocksRingBuffer::EntryWriter& aEntryWriter) const {
static const DeserializerTag tag = TagForDeserializer(Deserialize);
SerializeTagAndCommonProps(tag, aEntryWriter);
aEntryWriter.WriteObject(mScreenshotDataURL);
aEntryWriter.WriteObject(mWindowSize);
aEntryWriter.WriteObject(mWindowIdentifier);
}
// static
UniquePtr<ProfilerMarkerPayload> ScreenshotPayload::Deserialize(
BlocksRingBuffer::EntryReader& aEntryReader) {
ProfilerMarkerPayload::CommonProps props =
DeserializeCommonProps(aEntryReader);
auto screenshotDataURL = aEntryReader.ReadObject<nsCString>();
auto windowSize = aEntryReader.ReadObject<gfx::IntSize>();
auto windowIdentifier = aEntryReader.ReadObject<uintptr_t>();
return UniquePtr<ProfilerMarkerPayload>(
new ScreenshotPayload(std::move(props), std::move(screenshotDataURL),
windowSize, windowIdentifier));
}
void ScreenshotPayload::StreamPayload(SpliceableJSONWriter& aWriter,
const TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks) {
UniqueStacks& aUniqueStacks) const {
StreamType("CompositorScreenshot", aWriter);
aUniqueStacks.mUniqueStrings->WriteProperty(aWriter, "url",
mScreenshotDataURL.get());
@ -278,9 +689,32 @@ void ScreenshotPayload::StreamPayload(SpliceableJSONWriter& aWriter,
aWriter.DoubleProperty("windowHeight", mWindowSize.height);
}
BlocksRingBuffer::Length GCSliceMarkerPayload::TagAndSerializationBytes()
const {
return CommonPropsTagAndSerializationBytes() +
BlocksRingBuffer::SumBytes(mTimingJSON);
}
void GCSliceMarkerPayload::SerializeTagAndPayload(
BlocksRingBuffer::EntryWriter& aEntryWriter) const {
static const DeserializerTag tag = TagForDeserializer(Deserialize);
SerializeTagAndCommonProps(tag, aEntryWriter);
aEntryWriter.WriteObject(mTimingJSON);
}
// static
UniquePtr<ProfilerMarkerPayload> GCSliceMarkerPayload::Deserialize(
BlocksRingBuffer::EntryReader& aEntryReader) {
ProfilerMarkerPayload::CommonProps props =
DeserializeCommonProps(aEntryReader);
auto timingJSON = aEntryReader.ReadObject<JS::UniqueChars>();
return UniquePtr<ProfilerMarkerPayload>(
new GCSliceMarkerPayload(std::move(props), std::move(timingJSON)));
}
void GCSliceMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
const TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks) {
UniqueStacks& aUniqueStacks) const {
MOZ_ASSERT(mTimingJSON);
StreamCommonProps("GCSlice", aWriter, aProcessStartTime, aUniqueStacks);
if (mTimingJSON) {
@ -290,9 +724,32 @@ void GCSliceMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
}
}
BlocksRingBuffer::Length GCMajorMarkerPayload::TagAndSerializationBytes()
const {
return CommonPropsTagAndSerializationBytes() +
BlocksRingBuffer::SumBytes(mTimingJSON);
}
void GCMajorMarkerPayload::SerializeTagAndPayload(
BlocksRingBuffer::EntryWriter& aEntryWriter) const {
static const DeserializerTag tag = TagForDeserializer(Deserialize);
SerializeTagAndCommonProps(tag, aEntryWriter);
aEntryWriter.WriteObject(mTimingJSON);
}
// static
UniquePtr<ProfilerMarkerPayload> GCMajorMarkerPayload::Deserialize(
BlocksRingBuffer::EntryReader& aEntryReader) {
ProfilerMarkerPayload::CommonProps props =
DeserializeCommonProps(aEntryReader);
auto timingJSON = aEntryReader.ReadObject<JS::UniqueChars>();
return UniquePtr<ProfilerMarkerPayload>(
new GCMajorMarkerPayload(std::move(props), std::move(timingJSON)));
}
void GCMajorMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
const TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks) {
UniqueStacks& aUniqueStacks) const {
MOZ_ASSERT(mTimingJSON);
StreamCommonProps("GCMajor", aWriter, aProcessStartTime, aUniqueStacks);
if (mTimingJSON) {
@ -302,9 +759,32 @@ void GCMajorMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
}
}
BlocksRingBuffer::Length GCMinorMarkerPayload::TagAndSerializationBytes()
const {
return CommonPropsTagAndSerializationBytes() +
BlocksRingBuffer::SumBytes(mTimingData);
}
void GCMinorMarkerPayload::SerializeTagAndPayload(
BlocksRingBuffer::EntryWriter& aEntryWriter) const {
static const DeserializerTag tag = TagForDeserializer(Deserialize);
SerializeTagAndCommonProps(tag, aEntryWriter);
aEntryWriter.WriteObject(mTimingData);
}
// static
UniquePtr<ProfilerMarkerPayload> GCMinorMarkerPayload::Deserialize(
BlocksRingBuffer::EntryReader& aEntryReader) {
ProfilerMarkerPayload::CommonProps props =
DeserializeCommonProps(aEntryReader);
auto timingData = aEntryReader.ReadObject<JS::UniqueChars>();
return UniquePtr<ProfilerMarkerPayload>(
new GCMinorMarkerPayload(std::move(props), std::move(timingData)));
}
void GCMinorMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
const TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks) {
UniqueStacks& aUniqueStacks) const {
MOZ_ASSERT(mTimingData);
StreamCommonProps("GCMinor", aWriter, aProcessStartTime, aUniqueStacks);
if (mTimingData) {
@ -314,16 +794,57 @@ void GCMinorMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
}
}
BlocksRingBuffer::Length HangMarkerPayload::TagAndSerializationBytes() const {
return CommonPropsTagAndSerializationBytes();
}
void HangMarkerPayload::SerializeTagAndPayload(
BlocksRingBuffer::EntryWriter& aEntryWriter) const {
static const DeserializerTag tag = TagForDeserializer(Deserialize);
SerializeTagAndCommonProps(tag, aEntryWriter);
}
// static
UniquePtr<ProfilerMarkerPayload> HangMarkerPayload::Deserialize(
BlocksRingBuffer::EntryReader& aEntryReader) {
ProfilerMarkerPayload::CommonProps props =
DeserializeCommonProps(aEntryReader);
return UniquePtr<ProfilerMarkerPayload>(
new HangMarkerPayload(std::move(props)));
}
void HangMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
const TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks) {
UniqueStacks& aUniqueStacks) const {
StreamCommonProps("BHR-detected hang", aWriter, aProcessStartTime,
aUniqueStacks);
}
BlocksRingBuffer::Length StyleMarkerPayload::TagAndSerializationBytes() const {
return CommonPropsTagAndSerializationBytes() +
BlocksRingBuffer::SumBytes(mStats);
}
void StyleMarkerPayload::SerializeTagAndPayload(
BlocksRingBuffer::EntryWriter& aEntryWriter) const {
static const DeserializerTag tag = TagForDeserializer(Deserialize);
SerializeTagAndCommonProps(tag, aEntryWriter);
aEntryWriter.WriteObject(mStats);
}
// static
UniquePtr<ProfilerMarkerPayload> StyleMarkerPayload::Deserialize(
BlocksRingBuffer::EntryReader& aEntryReader) {
ProfilerMarkerPayload::CommonProps props =
DeserializeCommonProps(aEntryReader);
auto stats = aEntryReader.ReadObject<ServoTraversalStatistics>();
return UniquePtr<ProfilerMarkerPayload>(
new StyleMarkerPayload(std::move(props), stats));
}
void StyleMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
const TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks) {
UniqueStacks& aUniqueStacks) const {
StreamCommonProps("Styles", aWriter, aProcessStartTime, aUniqueStacks);
aWriter.StringProperty("category", "Paint");
aWriter.IntProperty("elementsTraversed", mStats.mElementsTraversed);
@ -333,17 +854,80 @@ void StyleMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
aWriter.IntProperty("stylesReused", mStats.mStylesReused);
}
BlocksRingBuffer::Length LongTaskMarkerPayload::TagAndSerializationBytes()
const {
return CommonPropsTagAndSerializationBytes();
}
void LongTaskMarkerPayload::SerializeTagAndPayload(
BlocksRingBuffer::EntryWriter& aEntryWriter) const {
static const DeserializerTag tag = TagForDeserializer(Deserialize);
SerializeTagAndCommonProps(tag, aEntryWriter);
}
// static
UniquePtr<ProfilerMarkerPayload> LongTaskMarkerPayload::Deserialize(
BlocksRingBuffer::EntryReader& aEntryReader) {
ProfilerMarkerPayload::CommonProps props =
DeserializeCommonProps(aEntryReader);
return UniquePtr<ProfilerMarkerPayload>(
new LongTaskMarkerPayload(std::move(props)));
}
void LongTaskMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
const TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks) {
UniqueStacks& aUniqueStacks) const {
StreamCommonProps("MainThreadLongTask", aWriter, aProcessStartTime,
aUniqueStacks);
aWriter.StringProperty("category", "LongTask");
}
UniqueFreePtr<const char16_t> mTypeName;
UniqueFreePtr<const char> mClassName;
UniqueFreePtr<const char16_t> mDescriptiveTypeName;
const char* mCoarseType;
uint64_t mSize;
bool mInNursery;
BlocksRingBuffer::Length JsAllocationMarkerPayload::TagAndSerializationBytes()
const {
return CommonPropsTagAndSerializationBytes() +
BlocksRingBuffer::SumBytes(mTypeName, mClassName, mDescriptiveTypeName,
mCoarseType, mSize, mInNursery);
}
void JsAllocationMarkerPayload::SerializeTagAndPayload(
BlocksRingBuffer::EntryWriter& aEntryWriter) const {
static const DeserializerTag tag = TagForDeserializer(Deserialize);
SerializeTagAndCommonProps(tag, aEntryWriter);
aEntryWriter.WriteObject(mTypeName);
aEntryWriter.WriteObject(mClassName);
aEntryWriter.WriteObject(mDescriptiveTypeName);
aEntryWriter.WriteObject(WrapBlocksRingBufferRawPointer(mCoarseType));
aEntryWriter.WriteObject(mSize);
aEntryWriter.WriteObject(mInNursery);
}
// static
UniquePtr<ProfilerMarkerPayload> JsAllocationMarkerPayload::Deserialize(
BlocksRingBuffer::EntryReader& aEntryReader) {
ProfilerMarkerPayload::CommonProps props =
DeserializeCommonProps(aEntryReader);
auto typeName = aEntryReader.ReadObject<UniqueFreePtr<const char16_t>>();
auto className = aEntryReader.ReadObject<UniqueFreePtr<const char>>();
auto descriptiveTypeName =
aEntryReader.ReadObject<UniqueFreePtr<const char16_t>>();
auto coarseType = aEntryReader.ReadObject<const char*>();
auto size = aEntryReader.ReadObject<uint64_t>();
auto inNursery = aEntryReader.ReadObject<bool>();
return UniquePtr<ProfilerMarkerPayload>(new JsAllocationMarkerPayload(
std::move(props), std::move(typeName), std::move(className),
std::move(descriptiveTypeName), coarseType, size, inNursery));
}
void JsAllocationMarkerPayload::StreamPayload(
SpliceableJSONWriter& aWriter, const TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks) {
UniqueStacks& aUniqueStacks) const {
StreamCommonProps("JS allocation", aWriter, aProcessStartTime, aUniqueStacks);
if (mClassName) {

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

@ -7,6 +7,7 @@
#ifndef ProfilerMarkerPayload_h
#define ProfilerMarkerPayload_h
#include "mozilla/Atomics.h"
#include "mozilla/Attributes.h"
#include "mozilla/BlocksRingBuffer.h"
#include "mozilla/Maybe.h"
@ -61,13 +62,81 @@ class ProfilerMarkerPayload {
virtual ~ProfilerMarkerPayload() {}
// Compute the number of bytes needed to serialize the `DeserializerTag` and
// payload, including in the no-payload (nullptr) case.
static mozilla::BlocksRingBuffer::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::BlocksRingBuffer::EntryWriter& 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::BlocksRingBuffer::EntryReader& aER) {
const auto tag = aER.ReadObject<DeserializerTag>();
Deserializer deserializer = DeserializerForTag(tag);
return deserializer(aER);
}
virtual void StreamPayload(SpliceableJSONWriter& aWriter,
const mozilla::TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks) = 0;
UniqueStacks& aUniqueStacks) const = 0;
mozilla::TimeStamp GetStartTime() const { return mCommonProps.mStartTime; }
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::BlocksRingBuffer::EntryReader&);
// 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,
mozilla::recordreplay::Behavior::DontPreserve>
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;
@ -76,22 +145,47 @@ class ProfilerMarkerPayload {
mozilla::Maybe<uint32_t> mDocShellHistoryId;
};
// Deserializers can use this base constructor.
explicit ProfilerMarkerPayload(CommonProps&& aCommonProps)
: mCommonProps(std::move(aCommonProps)) {}
void StreamType(const char* aMarkerType, SpliceableJSONWriter& aWriter);
// Serialization/deserialization of common props in ProfilerMarkerPayload.
mozilla::BlocksRingBuffer::Length CommonPropsTagAndSerializationBytes() const;
void SerializeTagAndCommonProps(
DeserializerTag aDeserializerTag,
mozilla::BlocksRingBuffer::EntryWriter& aEntryWriter) const;
static CommonProps DeserializeCommonProps(
mozilla::BlocksRingBuffer::EntryReader& aEntryReader);
void StreamType(const char* aMarkerType, SpliceableJSONWriter& aWriter) const;
void StreamCommonProps(const char* aMarkerType, SpliceableJSONWriter& aWriter,
const mozilla::TimeStamp& aProcessStartTime,
UniqueStacks& aUniqueStacks);
UniqueStacks& aUniqueStacks) const;
private:
// Compute the number of bytes needed to serialize payload in
// `SerializeTagAndPayload` below.
virtual mozilla::BlocksRingBuffer::Length TagAndSerializationBytes()
const = 0;
// Serialize the payload into an EntryWriter.
// Must be of the exact size given by `TagAndSerializationBytes()`.
virtual void SerializeTagAndPayload(
mozilla::BlocksRingBuffer::EntryWriter& aEntryWriter) const = 0;
CommonProps mCommonProps;
};
#define DECL_STREAM_PAYLOAD \
virtual void StreamPayload(SpliceableJSONWriter& aWriter, \
const mozilla::TimeStamp& aProcessStartTime, \
UniqueStacks& aUniqueStacks) override;
#define DECL_STREAM_PAYLOAD \
void StreamPayload(SpliceableJSONWriter& aWriter, \
const mozilla::TimeStamp& aProcessStartTime, \
UniqueStacks& aUniqueStacks) const override; \
static mozilla::UniquePtr<ProfilerMarkerPayload> Deserialize( \
mozilla::BlocksRingBuffer::EntryReader& aEntryReader); \
mozilla::BlocksRingBuffer::Length TagAndSerializationBytes() const override; \
void SerializeTagAndPayload( \
mozilla::BlocksRingBuffer::EntryWriter& aEntryWriter) const override;
// TODO: Increase the coverage of tracing markers that include DocShell
// information
@ -109,6 +203,18 @@ class TracingMarkerPayload : public ProfilerMarkerPayload {
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::BlocksRingBuffer::EntryWriter& aEntryWriter) const;
private:
const char* mCategory;
TracingKind mKind;
@ -132,6 +238,14 @@ class FileIOMarkerPayload : public ProfilerMarkerPayload {
DECL_STREAM_PAYLOAD
private:
FileIOMarkerPayload(CommonProps&& aCommonProps, const char* aSource,
mozilla::UniqueFreePtr<char>&& aOperation,
mozilla::UniqueFreePtr<char>&& aFilename)
: ProfilerMarkerPayload(std::move(aCommonProps)),
mSource(aSource),
mOperation(std::move(aOperation)),
mFilename(std::move(aFilename)) {}
const char* mSource;
mozilla::UniqueFreePtr<char> mOperation;
mozilla::UniqueFreePtr<char> mFilename;
@ -151,6 +265,13 @@ class DOMEventMarkerPayload : public TracingMarkerPayload {
DECL_STREAM_PAYLOAD
private:
DOMEventMarkerPayload(CommonProps&& aCommonProps, const char* aCategory,
TracingKind aKind, mozilla::TimeStamp aTimeStamp,
nsString aEventType)
: TracingMarkerPayload(std::move(aCommonProps), aCategory, aKind),
mTimeStamp(aTimeStamp),
mEventType(aEventType) {}
mozilla::TimeStamp mTimeStamp;
nsString mEventType;
};
@ -172,6 +293,18 @@ class PrefMarkerPayload : public ProfilerMarkerPayload {
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,
@ -212,6 +345,16 @@ class UserTimingMarkerPayload : public ProfilerMarkerPayload {
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;
@ -233,6 +376,13 @@ class LayerTranslationMarkerPayload : public ProfilerMarkerPayload {
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;
};
@ -246,6 +396,10 @@ class VsyncMarkerPayload : public ProfilerMarkerPayload {
: ProfilerMarkerPayload(aVsyncTimestamp, aVsyncTimestamp) {}
DECL_STREAM_PAYLOAD
private:
explicit VsyncMarkerPayload(CommonProps&& aCommonProps)
: ProfilerMarkerPayload(std::move(aCommonProps)) {}
};
class NetworkMarkerPayload : public ProfilerMarkerPayload {
@ -277,6 +431,22 @@ class NetworkMarkerPayload : public ProfilerMarkerPayload {
DECL_STREAM_PAYLOAD
private:
NetworkMarkerPayload(CommonProps&& aCommonProps, int64_t aID,
mozilla::UniqueFreePtr<char>&& aURI,
mozilla::UniqueFreePtr<char>&& aRedirectURI,
NetworkLoadType aType, int32_t aPri, int64_t aCount,
mozilla::net::TimingStruct aTimings,
mozilla::net::CacheDisposition aCacheDisposition)
: ProfilerMarkerPayload(std::move(aCommonProps)),
mID(aID),
mURI(std::move(aURI)),
mRedirectURI(std::move(aRedirectURI)),
mType(aType),
mPri(aPri),
mCount(aCount),
mTimings(aTimings),
mCacheDisposition(aCacheDisposition) {}
int64_t mID;
mozilla::UniqueFreePtr<char> mURI;
mozilla::UniqueFreePtr<char> mRedirectURI;
@ -301,6 +471,14 @@ class ScreenshotPayload : public ProfilerMarkerPayload {
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;
@ -317,6 +495,11 @@ class GCSliceMarkerPayload : public ProfilerMarkerPayload {
DECL_STREAM_PAYLOAD
private:
GCSliceMarkerPayload(CommonProps&& aCommonProps,
JS::UniqueChars&& aTimingJSON)
: ProfilerMarkerPayload(std::move(aCommonProps)),
mTimingJSON(std::move(aTimingJSON)) {}
JS::UniqueChars mTimingJSON;
};
@ -331,6 +514,11 @@ class GCMajorMarkerPayload : public ProfilerMarkerPayload {
DECL_STREAM_PAYLOAD
private:
GCMajorMarkerPayload(CommonProps&& aCommonProps,
JS::UniqueChars&& aTimingJSON)
: ProfilerMarkerPayload(std::move(aCommonProps)),
mTimingJSON(std::move(aTimingJSON)) {}
JS::UniqueChars mTimingJSON;
};
@ -345,6 +533,11 @@ class GCMinorMarkerPayload : public ProfilerMarkerPayload {
DECL_STREAM_PAYLOAD
private:
GCMinorMarkerPayload(CommonProps&& aCommonProps,
JS::UniqueChars&& aTimingData)
: ProfilerMarkerPayload(std::move(aCommonProps)),
mTimingData(std::move(aTimingData)) {}
JS::UniqueChars mTimingData;
};
@ -356,6 +549,8 @@ class HangMarkerPayload : public ProfilerMarkerPayload {
DECL_STREAM_PAYLOAD
private:
explicit HangMarkerPayload(CommonProps&& aCommonProps)
: ProfilerMarkerPayload(std::move(aCommonProps)) {}
};
class StyleMarkerPayload : public ProfilerMarkerPayload {
@ -373,6 +568,10 @@ class StyleMarkerPayload : public ProfilerMarkerPayload {
DECL_STREAM_PAYLOAD
private:
StyleMarkerPayload(CommonProps&& aCommonProps,
mozilla::ServoTraversalStatistics aStats)
: ProfilerMarkerPayload(std::move(aCommonProps)), mStats(aStats) {}
mozilla::ServoTraversalStatistics mStats;
};
@ -383,6 +582,10 @@ class LongTaskMarkerPayload : public ProfilerMarkerPayload {
: ProfilerMarkerPayload(aStartTime, aEndTime) {}
DECL_STREAM_PAYLOAD
private:
explicit LongTaskMarkerPayload(CommonProps&& aCommonProps)
: ProfilerMarkerPayload(std::move(aCommonProps)) {}
};
class TextMarkerPayload : public ProfilerMarkerPayload {
@ -417,6 +620,10 @@ class TextMarkerPayload : public ProfilerMarkerPayload {
DECL_STREAM_PAYLOAD
private:
TextMarkerPayload(CommonProps&& aCommonProps, nsCString&& aText)
: ProfilerMarkerPayload(std::move(aCommonProps)),
mText(std::move(aText)) {}
nsCString mText;
};
@ -431,6 +638,12 @@ class LogMarkerPayload : public ProfilerMarkerPayload {
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;
};
@ -457,6 +670,20 @@ class JsAllocationMarkerPayload : public ProfilerMarkerPayload {
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;
@ -470,4 +697,36 @@ class JsAllocationMarkerPayload : public ProfilerMarkerPayload {
bool mInNursery;
};
namespace mozilla {
// Serialize a pointed-at ProfilerMarkerPayload, may be null when there are no
// payloads.
template <>
struct BlocksRingBuffer::Serializer<UniquePtr<ProfilerMarkerPayload>> {
static Length Bytes(const UniquePtr<ProfilerMarkerPayload>& aPayload) {
return ProfilerMarkerPayload::TagAndSerializationBytes(aPayload.get());
}
static void Write(EntryWriter& 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 BlocksRingBuffer::Deserializer<UniquePtr<ProfilerMarkerPayload>> {
static void ReadInto(EntryReader& aER,
UniquePtr<ProfilerMarkerPayload>& aPayload) {
aPayload = Read(aER);
}
static UniquePtr<ProfilerMarkerPayload> Read(EntryReader& aER) {
return ProfilerMarkerPayload::DeserializeTagAndPayload(aER);
}
};
} // namespace mozilla
#endif // ProfilerMarkerPayload_h

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

@ -493,35 +493,68 @@ TEST(GeckoProfiler, Pause)
// and destroyed.
class GTestMarkerPayload : public ProfilerMarkerPayload {
public:
explicit GTestMarkerPayload(int aN) : mN(aN) { sNumCreated++; }
explicit GTestMarkerPayload(int aN) : mN(aN) { ++sNumCreated; }
virtual ~GTestMarkerPayload() { sNumDestroyed++; }
virtual ~GTestMarkerPayload() { ++sNumDestroyed; }
virtual void StreamPayload(SpliceableJSONWriter& aWriter,
const mozilla::TimeStamp& aStartTime,
UniqueStacks& aUniqueStacks) override {
StreamCommonProps("gtest", aWriter, aStartTime, aUniqueStacks);
char buf[64];
SprintfLiteral(buf, "gtest-%d", mN);
aWriter.IntProperty(buf, mN);
sNumStreamed++;
}
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;
BlocksRingBuffer::Length GTestMarkerPayload::TagAndSerializationBytes() const {
return CommonPropsTagAndSerializationBytes() + BlocksRingBuffer::SumBytes(mN);
}
void GTestMarkerPayload::SerializeTagAndPayload(
BlocksRingBuffer::EntryWriter& aEntryWriter) const {
static const DeserializerTag tag = TagForDeserializer(Deserialize);
SerializeTagAndCommonProps(tag, aEntryWriter);
aEntryWriter.WriteObject(mN);
++sNumSerialized;
}
// static
UniquePtr<ProfilerMarkerPayload> GTestMarkerPayload::Deserialize(
BlocksRingBuffer::EntryReader& 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];
SprintfLiteral(buf, "gtest-%d", mN);
aWriter.IntProperty(buf, mN);
++sNumStreamed;
}
TEST(GeckoProfiler, Markers)
{
uint32_t features = ProfilerFeature::StackWalk;
@ -552,6 +585,12 @@ TEST(GeckoProfiler, Markers)
for (int i = 0; i < 10; i++) {
PROFILER_ADD_MARKER_WITH_PAYLOAD("M5", OTHER, GTestMarkerPayload, (i));
}
// The GTestMarkerPayloads should have only been created.
ASSERT_EQ(GTestMarkerPayload::sNumCreated, 10);
ASSERT_EQ(GTestMarkerPayload::sNumSerialized, 0);
ASSERT_EQ(GTestMarkerPayload::sNumDeserialized, 0);
ASSERT_EQ(GTestMarkerPayload::sNumStreamed, 0);
ASSERT_EQ(GTestMarkerPayload::sNumDestroyed, 0);
// Create two strings: one that is the maximum allowed length, and one that
// is one char longer.
@ -580,11 +619,12 @@ TEST(GeckoProfiler, Markers)
UniquePtr<char[]> profile = w.WriteFunc()->CopyData();
// The GTestMarkerPayloads should have been created and streamed, but not yet
// destroyed.
ASSERT_TRUE(GTestMarkerPayload::sNumCreated == 10);
ASSERT_TRUE(GTestMarkerPayload::sNumStreamed == 10);
ASSERT_TRUE(GTestMarkerPayload::sNumDestroyed == 0);
// The GTestMarkerPayloads should have been streamed.
ASSERT_EQ(GTestMarkerPayload::sNumCreated, 10 + 0);
ASSERT_EQ(GTestMarkerPayload::sNumSerialized, 0 + 0);
ASSERT_EQ(GTestMarkerPayload::sNumDeserialized, 0 + 0);
ASSERT_EQ(GTestMarkerPayload::sNumStreamed, 0 + 10);
ASSERT_EQ(GTestMarkerPayload::sNumDestroyed, 0 + 0);
for (int i = 0; i < 10; i++) {
char buf[64];
SprintfLiteral(buf, "\"gtest-%d\"", i);
@ -634,7 +674,11 @@ TEST(GeckoProfiler, Markers)
profiler_stop();
// The GTestMarkerPayloads should have been destroyed.
ASSERT_TRUE(GTestMarkerPayload::sNumDestroyed == 10);
ASSERT_EQ(GTestMarkerPayload::sNumCreated, 10 + 0 + 0);
ASSERT_EQ(GTestMarkerPayload::sNumSerialized, 0 + 0 + 0);
ASSERT_EQ(GTestMarkerPayload::sNumDeserialized, 0 + 0 + 0);
ASSERT_EQ(GTestMarkerPayload::sNumStreamed, 0 + 10 + 0);
ASSERT_EQ(GTestMarkerPayload::sNumDestroyed, 0 + 0 + 10);
for (int i = 0; i < 10; i++) {
PROFILER_ADD_MARKER_WITH_PAYLOAD("M5", OTHER, GTestMarkerPayload, (i));
@ -648,10 +692,13 @@ TEST(GeckoProfiler, Markers)
profiler_stop();
// The second set of GTestMarkerPayloads should not have been streamed.
ASSERT_TRUE(GTestMarkerPayload::sNumCreated == 20);
ASSERT_TRUE(GTestMarkerPayload::sNumStreamed == 10);
ASSERT_TRUE(GTestMarkerPayload::sNumDestroyed == 20);
// The second set of GTestMarkerPayloads should not have been serialized or
// streamed.
ASSERT_EQ(GTestMarkerPayload::sNumCreated, 10 + 0 + 0 + 10);
ASSERT_EQ(GTestMarkerPayload::sNumSerialized, 0 + 0 + 0 + 0);
ASSERT_EQ(GTestMarkerPayload::sNumDeserialized, 0 + 0 + 0 + 0);
ASSERT_EQ(GTestMarkerPayload::sNumStreamed, 0 + 10 + 0 + 0);
ASSERT_EQ(GTestMarkerPayload::sNumDestroyed, 0 + 0 + 10 + 10);
}
TEST(GeckoProfiler, DurationLimit)
@ -664,6 +711,8 @@ TEST(GeckoProfiler, DurationLimit)
// Clear up the counters after the last test.
GTestMarkerPayload::sNumCreated = 0;
GTestMarkerPayload::sNumSerialized = 0;
GTestMarkerPayload::sNumDeserialized = 0;
GTestMarkerPayload::sNumStreamed = 0;
GTestMarkerPayload::sNumDestroyed = 0;
@ -675,10 +724,12 @@ TEST(GeckoProfiler, DurationLimit)
SpliceableChunkedJSONWriter w;
ASSERT_TRUE(profiler_stream_json_for_this_process(w));
// The first marker should be destroyed.
ASSERT_TRUE(GTestMarkerPayload::sNumCreated == 2);
ASSERT_TRUE(GTestMarkerPayload::sNumStreamed == 1);
ASSERT_TRUE(GTestMarkerPayload::sNumDestroyed == 1);
// Only the first marker should have been streamed and destroyed.
ASSERT_EQ(GTestMarkerPayload::sNumCreated, 2);
ASSERT_EQ(GTestMarkerPayload::sNumSerialized, 0);
ASSERT_EQ(GTestMarkerPayload::sNumDeserialized, 0);
ASSERT_EQ(GTestMarkerPayload::sNumStreamed, 1);
ASSERT_EQ(GTestMarkerPayload::sNumDestroyed, 1);
}
#define COUNTER_NAME "TestCounter"