зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1576555 - Remove unneeded ProfilerMarker - r=gregtatum
Now that what was in ProfilerMarker is stored directly in `BlocksRingBuffer`, there is no need for this class anymore! This also removes all the pointer management around it (when added to a TLS list, moved during sampling, deleted when expired). Differential Revision: https://phabricator.services.mozilla.com/D43431 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
8364b4ebdb
Коммит
79e1b2e357
|
@ -10,8 +10,6 @@
|
|||
|
||||
# include "ProfileBuffer.h"
|
||||
|
||||
# include "ProfilerMarker.h"
|
||||
|
||||
# include "mozilla/MathAlgorithms.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -37,9 +35,6 @@ ProfileBuffer::ProfileBuffer(BlocksRingBuffer& aBuffer) : mEntries(aBuffer) {
|
|||
}
|
||||
|
||||
ProfileBuffer::~ProfileBuffer() {
|
||||
while (mStoredMarkers.peek()) {
|
||||
delete mStoredMarkers.popHead();
|
||||
}
|
||||
// Only ProfileBuffer controls this buffer, and it should be empty when there
|
||||
// is no ProfileBuffer using it.
|
||||
mEntries.Reset();
|
||||
|
@ -80,11 +75,6 @@ uint64_t ProfileBuffer::AddThreadIdEntry(int aThreadId) {
|
|||
return AddThreadIdEntry(mEntries, aThreadId).ConvertToU64();
|
||||
}
|
||||
|
||||
void ProfileBuffer::AddMarker(ProfilerMarker* aMarker) {
|
||||
aMarker->SetPositionInBuffer(AddEntry(ProfileBufferEntry::Marker(aMarker)));
|
||||
mStoredMarkers.insert(aMarker);
|
||||
}
|
||||
|
||||
void ProfileBuffer::CollectCodeLocation(
|
||||
const char* aLabel, const char* aStr, uint32_t aFrameFlags,
|
||||
const Maybe<uint32_t>& aLineNumber, const Maybe<uint32_t>& aColumnNumber,
|
||||
|
@ -122,22 +112,10 @@ void ProfileBuffer::CollectCodeLocation(
|
|||
}
|
||||
}
|
||||
|
||||
void ProfileBuffer::DeleteExpiredStoredMarkers() {
|
||||
AUTO_PROFILER_STATS(base_ProfileBuffer_DeleteExpiredStoredMarkers);
|
||||
|
||||
// Delete markers of samples that have been overwritten due to circular
|
||||
// buffer wraparound.
|
||||
while (mStoredMarkers.peek() &&
|
||||
mStoredMarkers.peek()->HasExpired(BufferRangeStart())) {
|
||||
delete mStoredMarkers.popHead();
|
||||
}
|
||||
}
|
||||
|
||||
size_t ProfileBuffer::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const {
|
||||
// Measurement of the following members may be added later if DMD finds it
|
||||
// is worthwhile:
|
||||
// - memory pointed to by the elements within mEntries
|
||||
// - mStoredMarkers
|
||||
return mEntries.SizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
#define MOZ_PROFILE_BUFFER_H
|
||||
|
||||
#include "ProfileBufferEntry.h"
|
||||
#include "ProfilerMarker.h"
|
||||
|
||||
#include "mozilla/BlocksRingBuffer.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
|
@ -89,11 +88,6 @@ class ProfileBuffer final {
|
|||
|
||||
void DiscardSamplesBeforeTime(double aTime);
|
||||
|
||||
void AddMarker(ProfilerMarker* aMarker);
|
||||
|
||||
// The following method is not signal safe!
|
||||
void DeleteExpiredStoredMarkers();
|
||||
|
||||
size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const;
|
||||
size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const;
|
||||
|
||||
|
@ -141,9 +135,6 @@ class ProfileBuffer final {
|
|||
return mEntries.GetState().mRangeEnd.ConvertToU64();
|
||||
}
|
||||
|
||||
// Markers that marker entries in the buffer might refer to.
|
||||
ProfilerMarkerLinkedList mStoredMarkers;
|
||||
|
||||
private:
|
||||
// Used when duplicating sleeping stacks (to avoid spurious mallocs).
|
||||
const UniquePtr<BlocksRingBuffer::Byte[]> mDuplicationBuffer;
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
# include "ProfileBufferEntry.h"
|
||||
|
||||
# include "BaseProfilerMarkerPayload.h"
|
||||
# include "platform.h"
|
||||
# include "ProfileBuffer.h"
|
||||
|
||||
|
@ -43,11 +44,6 @@ ProfileBufferEntry::ProfileBufferEntry(Kind aKind, void* aPtr) : mKind(aKind) {
|
|||
memcpy(mStorage, &aPtr, sizeof(aPtr));
|
||||
}
|
||||
|
||||
ProfileBufferEntry::ProfileBufferEntry(Kind aKind, ProfilerMarker* aMarker)
|
||||
: mKind(aKind) {
|
||||
memcpy(mStorage, &aMarker, sizeof(aMarker));
|
||||
}
|
||||
|
||||
ProfileBufferEntry::ProfileBufferEntry(Kind aKind, double aDouble)
|
||||
: mKind(aKind) {
|
||||
memcpy(mStorage, &aDouble, sizeof(aDouble));
|
||||
|
@ -79,12 +75,6 @@ void* ProfileBufferEntry::GetPtr() const {
|
|||
return result;
|
||||
}
|
||||
|
||||
ProfilerMarker* ProfileBufferEntry::GetMarker() const {
|
||||
ProfilerMarker* result;
|
||||
memcpy(&result, mStorage, sizeof(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
double ProfileBufferEntry::GetDouble() const {
|
||||
double result;
|
||||
memcpy(&result, mStorage, sizeof(result));
|
||||
|
@ -788,16 +778,6 @@ void ProfileBuffer::StreamSamplesToJSON(SpliceableJSONWriter& aWriter,
|
|||
|
||||
sample.mStack = aUniqueStacks.GetOrAddStackIndex(stack);
|
||||
|
||||
// Skip over the markers. We process them in StreamMarkersToJSON().
|
||||
while (e.Has()) {
|
||||
MOZ_ASSERT(!e.Get().IsMarker());
|
||||
if (e.Get().IsMarker()) {
|
||||
e.Next();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (e.Has() && e.Get().IsResponsiveness()) {
|
||||
sample.mResponsiveness = Some(e.Get().GetDouble());
|
||||
e.Next();
|
||||
|
@ -821,8 +801,6 @@ void ProfileBuffer::StreamMarkersToJSON(SpliceableJSONWriter& aWriter,
|
|||
ProfileBufferEntry::Kind::MODERN_LIMIT));
|
||||
if (type == ProfileBufferEntry::Kind::MarkerData &&
|
||||
aER.ReadObject<int>() == aThreadId) {
|
||||
// Adapted from ProfilerMarker::StreamJSON()
|
||||
|
||||
// Schema:
|
||||
// [name, time, category, data]
|
||||
|
||||
|
@ -1259,7 +1237,6 @@ bool ProfileBuffer::DuplicateLastSample(int aThreadId,
|
|||
(TimeStamp::NowUnfuzzed() - aProcessStartTime)
|
||||
.ToMilliseconds()));
|
||||
break;
|
||||
case ProfileBufferEntry::Kind::Marker:
|
||||
case ProfileBufferEntry::Kind::CounterKey:
|
||||
case ProfileBufferEntry::Kind::Number:
|
||||
case ProfileBufferEntry::Kind::Count:
|
||||
|
|
|
@ -23,8 +23,6 @@
|
|||
namespace mozilla {
|
||||
namespace baseprofiler {
|
||||
|
||||
class ProfilerMarker;
|
||||
|
||||
// NOTE! If you add entries, you need to verify if they need to be added to the
|
||||
// switch statement in DuplicateLastSample!
|
||||
// This will evaluate the MACRO with (KIND, TYPE, SIZE)
|
||||
|
@ -39,7 +37,6 @@ class ProfilerMarker;
|
|||
MACRO(LineNumber, int, sizeof(int)) \
|
||||
MACRO(ColumnNumber, int, sizeof(int)) \
|
||||
MACRO(NativeLeafAddr, void*, sizeof(void*)) \
|
||||
MACRO(Marker, ProfilerMarker*, sizeof(ProfilerMarker*)) \
|
||||
MACRO(Pause, double, sizeof(double)) \
|
||||
MACRO(Responsiveness, double, sizeof(double)) \
|
||||
MACRO(Resume, double, sizeof(double)) \
|
||||
|
@ -95,7 +92,6 @@ class ProfileBufferEntry {
|
|||
ProfileBufferEntry(Kind aKind, const char* aString);
|
||||
ProfileBufferEntry(Kind aKind, char aChars[kNumChars]);
|
||||
ProfileBufferEntry(Kind aKind, void* aPtr);
|
||||
ProfileBufferEntry(Kind aKind, ProfilerMarker* aMarker);
|
||||
ProfileBufferEntry(Kind aKind, double aDouble);
|
||||
ProfileBufferEntry(Kind aKind, int64_t aInt64);
|
||||
ProfileBufferEntry(Kind aKind, uint64_t aUint64);
|
||||
|
@ -129,7 +125,6 @@ class ProfileBufferEntry {
|
|||
|
||||
const char* GetString() const;
|
||||
void* GetPtr() const;
|
||||
ProfilerMarker* GetMarker() const;
|
||||
double GetDouble() const;
|
||||
int GetInt() const;
|
||||
int64_t GetInt64() const;
|
||||
|
|
|
@ -1,175 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef ProfilerMarker_h
|
||||
#define ProfilerMarker_h
|
||||
|
||||
#include "ProfileBufferEntry.h"
|
||||
#include "BaseProfileJSONWriter.h"
|
||||
#include "BaseProfilerMarkerPayload.h"
|
||||
|
||||
#include "mozilla/UniquePtrExtensions.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace baseprofiler {
|
||||
|
||||
template <typename T>
|
||||
class ProfilerLinkedList;
|
||||
|
||||
class ProfilerMarker {
|
||||
friend class ProfilerLinkedList<ProfilerMarker>;
|
||||
|
||||
public:
|
||||
explicit ProfilerMarker(const char* aMarkerName,
|
||||
ProfilingCategoryPair aCategoryPair, int aThreadId,
|
||||
UniquePtr<ProfilerMarkerPayload> aPayload = nullptr,
|
||||
double aTime = 0)
|
||||
: mMarkerName(strdup(aMarkerName)),
|
||||
mPayload(std::move(aPayload)),
|
||||
mNext{nullptr},
|
||||
mTime(aTime),
|
||||
mPositionInBuffer{0},
|
||||
mThreadId{aThreadId},
|
||||
mCategoryPair{aCategoryPair} {}
|
||||
|
||||
void SetPositionInBuffer(uint64_t aPosition) {
|
||||
mPositionInBuffer = aPosition;
|
||||
}
|
||||
|
||||
bool HasExpired(uint64_t aBufferRangeStart) const {
|
||||
return mPositionInBuffer < aBufferRangeStart;
|
||||
}
|
||||
|
||||
double GetTime() const { return mTime; }
|
||||
|
||||
int GetThreadId() const { return mThreadId; }
|
||||
|
||||
void StreamJSON(SpliceableJSONWriter& aWriter,
|
||||
const TimeStamp& aProcessStartTime,
|
||||
UniqueStacks& aUniqueStacks) const {
|
||||
// Schema:
|
||||
// [name, time, category, data]
|
||||
|
||||
aWriter.StartArrayElement();
|
||||
{
|
||||
aUniqueStacks.mUniqueStrings->WriteElement(aWriter, mMarkerName.get());
|
||||
aWriter.DoubleElement(mTime);
|
||||
const ProfilingCategoryPairInfo& info =
|
||||
GetProfilingCategoryPairInfo(mCategoryPair);
|
||||
aWriter.IntElement(unsigned(info.mCategory));
|
||||
// TODO: Store the callsite for this marker if available:
|
||||
// if have location data
|
||||
// b.NameValue(marker, "location", ...);
|
||||
if (mPayload) {
|
||||
aWriter.StartObjectElement(SpliceableJSONWriter::SingleLineStyle);
|
||||
{ mPayload->StreamPayload(aWriter, aProcessStartTime, aUniqueStacks); }
|
||||
aWriter.EndObject();
|
||||
}
|
||||
}
|
||||
aWriter.EndArray();
|
||||
}
|
||||
|
||||
private:
|
||||
UniqueFreePtr<char> mMarkerName;
|
||||
UniquePtr<ProfilerMarkerPayload> mPayload;
|
||||
ProfilerMarker* mNext;
|
||||
double mTime;
|
||||
uint64_t mPositionInBuffer;
|
||||
int mThreadId;
|
||||
ProfilingCategoryPair mCategoryPair;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class ProfilerLinkedList {
|
||||
public:
|
||||
ProfilerLinkedList() : mHead(nullptr), mTail(nullptr) {}
|
||||
|
||||
void insert(T* aElem) {
|
||||
if (!mTail) {
|
||||
mHead = aElem;
|
||||
mTail = aElem;
|
||||
} else {
|
||||
mTail->mNext = aElem;
|
||||
mTail = aElem;
|
||||
}
|
||||
aElem->mNext = nullptr;
|
||||
}
|
||||
|
||||
T* popHead() {
|
||||
if (!mHead) {
|
||||
MOZ_ASSERT(false);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
T* head = mHead;
|
||||
|
||||
mHead = head->mNext;
|
||||
if (!mHead) {
|
||||
mTail = nullptr;
|
||||
}
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
const T* peek() { return mHead; }
|
||||
|
||||
private:
|
||||
T* mHead;
|
||||
T* mTail;
|
||||
};
|
||||
|
||||
typedef ProfilerLinkedList<ProfilerMarker> ProfilerMarkerLinkedList;
|
||||
|
||||
template <typename T>
|
||||
class ProfilerSignalSafeLinkedList {
|
||||
public:
|
||||
ProfilerSignalSafeLinkedList() : mSignalLock(false) {}
|
||||
|
||||
~ProfilerSignalSafeLinkedList() {
|
||||
if (mSignalLock) {
|
||||
// Some thread is modifying the list. We should only be released on that
|
||||
// thread.
|
||||
abort();
|
||||
}
|
||||
|
||||
while (mList.peek()) {
|
||||
delete mList.popHead();
|
||||
}
|
||||
}
|
||||
|
||||
// Insert an item into the list. Must only be called from the owning thread.
|
||||
// Must not be called while the list from accessList() is being accessed.
|
||||
// In the profiler, we ensure that by interrupting the profiled thread
|
||||
// (which is the one that owns this list and calls insert() on it) until
|
||||
// we're done reading the list from the signal handler.
|
||||
void insert(T* aElement) {
|
||||
MOZ_ASSERT(aElement);
|
||||
|
||||
mSignalLock = true;
|
||||
|
||||
mList.insert(aElement);
|
||||
|
||||
mSignalLock = false;
|
||||
}
|
||||
|
||||
// Called within signal, from any thread, possibly while insert() is in the
|
||||
// middle of modifying the list (on the owning thread). Will return null if
|
||||
// that is the case.
|
||||
// Function must be reentrant.
|
||||
ProfilerLinkedList<T>* accessList() { return mSignalLock ? nullptr : &mList; }
|
||||
|
||||
private:
|
||||
ProfilerLinkedList<T> mList;
|
||||
|
||||
// If this is set, then it's not safe to read the list because its contents
|
||||
// are being changed.
|
||||
Atomic<bool> mSignalLock;
|
||||
};
|
||||
|
||||
} // namespace baseprofiler
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // ProfilerMarker_h
|
|
@ -8,8 +8,6 @@
|
|||
#define RegisteredThread_h
|
||||
|
||||
#include "platform.h"
|
||||
#include "ProfilerMarker.h"
|
||||
#include "BaseProfilerMarkerPayload.h"
|
||||
#include "ThreadInfo.h"
|
||||
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
@ -35,25 +33,6 @@ class RacyRegisteredThread final {
|
|||
|
||||
bool IsBeingProfiled() const { return mIsBeingProfiled; }
|
||||
|
||||
void AddPendingMarker(const char* aMarkerName,
|
||||
ProfilingCategoryPair aCategoryPair,
|
||||
UniquePtr<ProfilerMarkerPayload> aPayload,
|
||||
double aTime) {
|
||||
// Note: We don't assert on mIsBeingProfiled, because it could have changed
|
||||
// between the check in the caller and now.
|
||||
ProfilerMarker* marker = new ProfilerMarker(
|
||||
aMarkerName, aCategoryPair, mThreadId, std::move(aPayload), aTime);
|
||||
mPendingMarkers.insert(marker);
|
||||
}
|
||||
|
||||
// Called within signal. Function must be reentrant.
|
||||
ProfilerMarkerLinkedList* GetPendingMarkers() {
|
||||
// The profiled thread is interrupted, so we can access the list safely.
|
||||
// Unless the profiled thread was in the middle of changing the list when
|
||||
// we interrupted it - in that case, accessList() will return null.
|
||||
return mPendingMarkers.accessList();
|
||||
}
|
||||
|
||||
// This is called on every profiler restart. Put things that should happen at
|
||||
// that time here.
|
||||
void ReinitializeOnResume() {
|
||||
|
@ -103,9 +82,6 @@ class RacyRegisteredThread final {
|
|||
private:
|
||||
class ProfilingStack mProfilingStack;
|
||||
|
||||
// A list of pending markers that must be moved to the circular buffer.
|
||||
ProfilerSignalSafeLinkedList<ProfilerMarker> mPendingMarkers;
|
||||
|
||||
// mThreadId contains the thread ID of the current thread. It is safe to read
|
||||
// this from multiple threads concurrently, as it will never be mutated.
|
||||
const int mThreadId;
|
||||
|
|
|
@ -1473,13 +1473,6 @@ static void DoPeriodicSample(PSLockRef aLock,
|
|||
|
||||
DoSharedSample(aLock, /* aIsSynchronous = */ false, aRegisteredThread, aRegs,
|
||||
aSamplePos, aBuffer);
|
||||
|
||||
ProfilerMarkerLinkedList* pendingMarkersList =
|
||||
aRegisteredThread.RacyRegisteredThread().GetPendingMarkers();
|
||||
while (pendingMarkersList && pendingMarkersList->peek()) {
|
||||
ProfilerMarker* marker = pendingMarkersList->popHead();
|
||||
aBuffer.AddMarker(marker);
|
||||
}
|
||||
}
|
||||
|
||||
// END sampling/unwinding code
|
||||
|
@ -1992,7 +1985,6 @@ void SamplerThread::Run() {
|
|||
|
||||
ActivePS::ClearExpiredExitProfiles(lock);
|
||||
|
||||
ActivePS::Buffer(lock).DeleteExpiredStoredMarkers();
|
||||
TimeStamp expiredMarkersCleaned = TimeStamp::NowUnfuzzed();
|
||||
|
||||
if (!ActivePS::IsPaused(lock)) {
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
|
||||
#include "ProfileBuffer.h"
|
||||
|
||||
#include "ProfilerMarker.h"
|
||||
|
||||
#include "BaseProfiler.h"
|
||||
#include "jsfriendapi.h"
|
||||
#include "mozilla/MathAlgorithms.h"
|
||||
|
@ -36,9 +34,6 @@ ProfileBuffer::ProfileBuffer(BlocksRingBuffer& aBuffer) : mEntries(aBuffer) {
|
|||
}
|
||||
|
||||
ProfileBuffer::~ProfileBuffer() {
|
||||
while (mStoredMarkers.peek()) {
|
||||
delete mStoredMarkers.popHead();
|
||||
}
|
||||
// Only ProfileBuffer controls this buffer, and it should be empty when there
|
||||
// is no ProfileBuffer using it.
|
||||
mEntries.Reset();
|
||||
|
@ -79,11 +74,6 @@ uint64_t ProfileBuffer::AddThreadIdEntry(int aThreadId) {
|
|||
return AddThreadIdEntry(mEntries, aThreadId).ConvertToU64();
|
||||
}
|
||||
|
||||
void ProfileBuffer::AddMarker(ProfilerMarker* aMarker) {
|
||||
aMarker->SetPositionInBuffer(AddEntry(ProfileBufferEntry::Marker(aMarker)));
|
||||
mStoredMarkers.insert(aMarker);
|
||||
}
|
||||
|
||||
void ProfileBuffer::CollectCodeLocation(
|
||||
const char* aLabel, const char* aStr, uint32_t aFrameFlags,
|
||||
const Maybe<uint32_t>& aLineNumber, const Maybe<uint32_t>& aColumnNumber,
|
||||
|
@ -121,22 +111,10 @@ void ProfileBuffer::CollectCodeLocation(
|
|||
}
|
||||
}
|
||||
|
||||
void ProfileBuffer::DeleteExpiredStoredMarkers() {
|
||||
AUTO_PROFILER_STATS(gecko_ProfileBuffer_DeleteExpiredStoredMarkers);
|
||||
|
||||
// Delete markers of samples that have been overwritten due to circular
|
||||
// buffer wraparound.
|
||||
while (mStoredMarkers.peek() &&
|
||||
mStoredMarkers.peek()->HasExpired(BufferRangeStart())) {
|
||||
delete mStoredMarkers.popHead();
|
||||
}
|
||||
}
|
||||
|
||||
size_t ProfileBuffer::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const {
|
||||
// Measurement of the following members may be added later if DMD finds it
|
||||
// is worthwhile:
|
||||
// - memory pointed to by the elements within mEntries
|
||||
// - mStoredMarkers
|
||||
return mEntries.SizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
#ifndef MOZ_PROFILE_BUFFER_H
|
||||
#define MOZ_PROFILE_BUFFER_H
|
||||
|
||||
#include "GeckoProfiler.h"
|
||||
#include "ProfileBufferEntry.h"
|
||||
#include "ProfilerMarker.h"
|
||||
|
||||
#include "mozilla/BlocksRingBuffer.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
|
@ -98,11 +98,6 @@ class ProfileBuffer final {
|
|||
|
||||
void DiscardSamplesBeforeTime(double aTime);
|
||||
|
||||
void AddMarker(ProfilerMarker* aMarker);
|
||||
|
||||
// The following method is not signal safe!
|
||||
void DeleteExpiredStoredMarkers();
|
||||
|
||||
// Read an entry in the buffer. Slow!
|
||||
ProfileBufferEntry GetEntry(uint64_t aPosition) const {
|
||||
ProfileBufferEntry entry;
|
||||
|
@ -173,9 +168,6 @@ class ProfileBuffer final {
|
|||
return mEntries.GetState().mRangeEnd.ConvertToU64();
|
||||
}
|
||||
|
||||
// Markers that marker entries in the buffer might refer to.
|
||||
ProfilerMarkerLinkedList mStoredMarkers;
|
||||
|
||||
private:
|
||||
// Used when duplicating sleeping stacks (to avoid spurious mallocs).
|
||||
mozilla::UniquePtr<mozilla::BlocksRingBuffer::Byte[]> mDuplicationBuffer;
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include "platform.h"
|
||||
#include "ProfileBuffer.h"
|
||||
#include "ProfilerMarkerPayload.h"
|
||||
|
||||
#include "js/TrackedOptimizationInfo.h"
|
||||
#include "jsapi.h"
|
||||
|
@ -46,11 +47,6 @@ ProfileBufferEntry::ProfileBufferEntry(Kind aKind, void* aPtr) : mKind(aKind) {
|
|||
memcpy(mStorage, &aPtr, sizeof(aPtr));
|
||||
}
|
||||
|
||||
ProfileBufferEntry::ProfileBufferEntry(Kind aKind, ProfilerMarker* aMarker)
|
||||
: mKind(aKind) {
|
||||
memcpy(mStorage, &aMarker, sizeof(aMarker));
|
||||
}
|
||||
|
||||
ProfileBufferEntry::ProfileBufferEntry(Kind aKind, double aDouble)
|
||||
: mKind(aKind) {
|
||||
memcpy(mStorage, &aDouble, sizeof(aDouble));
|
||||
|
@ -82,12 +78,6 @@ void* ProfileBufferEntry::GetPtr() const {
|
|||
return result;
|
||||
}
|
||||
|
||||
ProfilerMarker* ProfileBufferEntry::GetMarker() const {
|
||||
ProfilerMarker* result;
|
||||
memcpy(&result, mStorage, sizeof(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
double ProfileBufferEntry::GetDouble() const {
|
||||
double result;
|
||||
memcpy(&result, mStorage, sizeof(result));
|
||||
|
@ -1124,16 +1114,6 @@ void ProfileBuffer::StreamSamplesToJSON(SpliceableJSONWriter& aWriter,
|
|||
|
||||
sample.mStack = aUniqueStacks.GetOrAddStackIndex(stack);
|
||||
|
||||
// Skip over the markers. We process them in StreamMarkersToJSON().
|
||||
while (e.Has()) {
|
||||
MOZ_ASSERT(!e.Get().IsMarker());
|
||||
if (e.Get().IsMarker()) {
|
||||
e.Next();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (e.Has() && e.Get().IsResponsiveness()) {
|
||||
sample.mResponsiveness = Some(e.Get().GetDouble());
|
||||
e.Next();
|
||||
|
@ -1206,8 +1186,6 @@ void ProfileBuffer::StreamMarkersToJSON(SpliceableJSONWriter& aWriter,
|
|||
ProfileBufferEntry::Kind::MODERN_LIMIT));
|
||||
if (type == ProfileBufferEntry::Kind::MarkerData &&
|
||||
aER.ReadObject<int>() == aThreadId) {
|
||||
// Adapted from ProfilerMarker::StreamJSON()
|
||||
|
||||
// Schema:
|
||||
// [name, time, category, data]
|
||||
|
||||
|
@ -1652,7 +1630,6 @@ bool ProfileBuffer::DuplicateLastSample(int aThreadId,
|
|||
(TimeStamp::NowUnfuzzed() - aProcessStartTime)
|
||||
.ToMilliseconds()));
|
||||
break;
|
||||
case ProfileBufferEntry::Kind::Marker:
|
||||
case ProfileBufferEntry::Kind::CounterKey:
|
||||
case ProfileBufferEntry::Kind::Number:
|
||||
case ProfileBufferEntry::Kind::Count:
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#include "nsString.h"
|
||||
|
||||
class ProfilerCodeAddressService;
|
||||
class ProfilerMarker;
|
||||
|
||||
// NOTE! If you add entries, you need to verify if they need to be added to the
|
||||
// switch statement in DuplicateLastSample!
|
||||
|
@ -38,7 +37,6 @@ class ProfilerMarker;
|
|||
MACRO(LineNumber, int, sizeof(int)) \
|
||||
MACRO(ColumnNumber, int, sizeof(int)) \
|
||||
MACRO(NativeLeafAddr, void*, sizeof(void*)) \
|
||||
MACRO(Marker, ProfilerMarker*, sizeof(ProfilerMarker*)) \
|
||||
MACRO(Pause, double, sizeof(double)) \
|
||||
MACRO(Responsiveness, double, sizeof(double)) \
|
||||
MACRO(Resume, double, sizeof(double)) \
|
||||
|
@ -94,7 +92,6 @@ class ProfileBufferEntry {
|
|||
ProfileBufferEntry(Kind aKind, const char* aString);
|
||||
ProfileBufferEntry(Kind aKind, char aChars[kNumChars]);
|
||||
ProfileBufferEntry(Kind aKind, void* aPtr);
|
||||
ProfileBufferEntry(Kind aKind, ProfilerMarker* aMarker);
|
||||
ProfileBufferEntry(Kind aKind, double aDouble);
|
||||
ProfileBufferEntry(Kind aKind, int64_t aInt64);
|
||||
ProfileBufferEntry(Kind aKind, uint64_t aUint64);
|
||||
|
@ -128,7 +125,6 @@ class ProfileBufferEntry {
|
|||
|
||||
const char* GetString() const;
|
||||
void* GetPtr() const;
|
||||
ProfilerMarker* GetMarker() const;
|
||||
double GetDouble() const;
|
||||
int GetInt() const;
|
||||
int64_t GetInt64() const;
|
||||
|
|
|
@ -1,180 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef ProfilerMarker_h
|
||||
#define ProfilerMarker_h
|
||||
|
||||
#include "ProfileBufferEntry.h"
|
||||
#include "ProfileJSONWriter.h"
|
||||
#include "ProfilerMarkerPayload.h"
|
||||
|
||||
#include "mozilla/UniquePtrExtensions.h"
|
||||
|
||||
template <typename T>
|
||||
class ProfilerLinkedList;
|
||||
|
||||
class ProfilerMarker {
|
||||
friend class ProfilerLinkedList<ProfilerMarker>;
|
||||
|
||||
public:
|
||||
explicit ProfilerMarker(
|
||||
const char* aMarkerName, JS::ProfilingCategoryPair aCategoryPair,
|
||||
int aThreadId,
|
||||
mozilla::UniquePtr<ProfilerMarkerPayload> aPayload = nullptr,
|
||||
double aTime = 0)
|
||||
: mMarkerName(strdup(aMarkerName)),
|
||||
mPayload(std::move(aPayload)),
|
||||
mNext{nullptr},
|
||||
mTime(aTime),
|
||||
mPositionInBuffer{0},
|
||||
mThreadId{aThreadId},
|
||||
mCategoryPair{aCategoryPair} {}
|
||||
|
||||
void SetPositionInBuffer(uint64_t aPosition) {
|
||||
mPositionInBuffer = aPosition;
|
||||
}
|
||||
|
||||
bool HasExpired(uint64_t aBufferRangeStart) const {
|
||||
return mPositionInBuffer < aBufferRangeStart;
|
||||
}
|
||||
|
||||
double GetTime() const { return mTime; }
|
||||
|
||||
int GetThreadId() const { return mThreadId; }
|
||||
|
||||
void StreamJSON(SpliceableJSONWriter& aWriter,
|
||||
const mozilla::TimeStamp& aProcessStartTime,
|
||||
UniqueStacks& aUniqueStacks) const {
|
||||
// Schema:
|
||||
// [name, time, category, data]
|
||||
|
||||
aWriter.StartArrayElement();
|
||||
{
|
||||
aUniqueStacks.mUniqueStrings->WriteElement(aWriter, mMarkerName.get());
|
||||
aWriter.DoubleElement(mTime);
|
||||
const JS::ProfilingCategoryPairInfo& info =
|
||||
JS::GetProfilingCategoryPairInfo(mCategoryPair);
|
||||
aWriter.IntElement(unsigned(info.mCategory));
|
||||
// TODO: Store the callsite for this marker if available:
|
||||
// if have location data
|
||||
// b.NameValue(marker, "location", ...);
|
||||
if (mPayload) {
|
||||
aWriter.StartObjectElement(SpliceableJSONWriter::SingleLineStyle);
|
||||
{ mPayload->StreamPayload(aWriter, aProcessStartTime, aUniqueStacks); }
|
||||
aWriter.EndObject();
|
||||
}
|
||||
}
|
||||
aWriter.EndArray();
|
||||
}
|
||||
|
||||
private:
|
||||
mozilla::UniqueFreePtr<char> mMarkerName;
|
||||
mozilla::UniquePtr<ProfilerMarkerPayload> mPayload;
|
||||
ProfilerMarker* mNext;
|
||||
double mTime;
|
||||
uint64_t mPositionInBuffer;
|
||||
int mThreadId;
|
||||
JS::ProfilingCategoryPair mCategoryPair;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class ProfilerLinkedList {
|
||||
public:
|
||||
ProfilerLinkedList() : mHead(nullptr), mTail(nullptr) {}
|
||||
|
||||
void insert(T* aElem) {
|
||||
if (!mTail) {
|
||||
mHead = aElem;
|
||||
mTail = aElem;
|
||||
} else {
|
||||
mTail->mNext = aElem;
|
||||
mTail = aElem;
|
||||
}
|
||||
aElem->mNext = nullptr;
|
||||
}
|
||||
|
||||
T* popHead() {
|
||||
if (!mHead) {
|
||||
MOZ_ASSERT(false);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
T* head = mHead;
|
||||
|
||||
mHead = head->mNext;
|
||||
if (!mHead) {
|
||||
mTail = nullptr;
|
||||
}
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
const T* peek() { return mHead; }
|
||||
|
||||
private:
|
||||
T* mHead;
|
||||
T* mTail;
|
||||
};
|
||||
|
||||
typedef ProfilerLinkedList<ProfilerMarker> ProfilerMarkerLinkedList;
|
||||
|
||||
template <typename T>
|
||||
class ProfilerSignalSafeLinkedList {
|
||||
public:
|
||||
ProfilerSignalSafeLinkedList() : mSignalLock(false) {}
|
||||
|
||||
~ProfilerSignalSafeLinkedList() {
|
||||
if (mSignalLock) {
|
||||
// Some thread is modifying the list. We should only be released on that
|
||||
// thread.
|
||||
abort();
|
||||
}
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
// Reset the list of pending signals in this list.
|
||||
// We assume that this is called at a time when it is
|
||||
// guaranteed that no more than a single user (the caller)
|
||||
// is accessing the list. In particular, it is only
|
||||
// called from within the RacyRegisteredThread::ReinitializeOnResume
|
||||
// method.
|
||||
void reset() {
|
||||
while (mList.peek()) {
|
||||
delete mList.popHead();
|
||||
}
|
||||
}
|
||||
|
||||
// Insert an item into the list. Must only be called from the owning thread.
|
||||
// Must not be called while the list from accessList() is being accessed.
|
||||
// In the profiler, we ensure that by interrupting the profiled thread
|
||||
// (which is the one that owns this list and calls insert() on it) until
|
||||
// we're done reading the list from the signal handler.
|
||||
void insert(T* aElement) {
|
||||
MOZ_ASSERT(aElement);
|
||||
|
||||
mSignalLock = true;
|
||||
|
||||
mList.insert(aElement);
|
||||
|
||||
mSignalLock = false;
|
||||
}
|
||||
|
||||
// Called within signal, from any thread, possibly while insert() is in the
|
||||
// middle of modifying the list (on the owning thread). Will return null if
|
||||
// that is the case.
|
||||
// Function must be reentrant.
|
||||
ProfilerLinkedList<T>* accessList() { return mSignalLock ? nullptr : &mList; }
|
||||
|
||||
private:
|
||||
ProfilerLinkedList<T> mList;
|
||||
|
||||
// If this is set, then it's not safe to read the list because its contents
|
||||
// are being changed.
|
||||
mozilla::Atomic<bool> mSignalLock;
|
||||
};
|
||||
|
||||
#endif // ProfilerMarker_h
|
|
@ -8,8 +8,6 @@
|
|||
#define RegisteredThread_h
|
||||
|
||||
#include "platform.h"
|
||||
#include "ProfilerMarker.h"
|
||||
#include "ProfilerMarkerPayload.h"
|
||||
#include "ThreadInfo.h"
|
||||
|
||||
#include "js/TraceLoggerAPI.h"
|
||||
|
@ -37,30 +35,9 @@ class RacyRegisteredThread final {
|
|||
|
||||
bool IsBeingProfiled() const { return mIsBeingProfiled; }
|
||||
|
||||
void AddPendingMarker(const char* aMarkerName,
|
||||
JS::ProfilingCategoryPair aCategoryPair,
|
||||
mozilla::UniquePtr<ProfilerMarkerPayload> aPayload,
|
||||
double aTime) {
|
||||
// Note: We don't assert on mIsBeingProfiled, because it could have changed
|
||||
// between the check in the caller and now.
|
||||
ProfilerMarker* marker = new ProfilerMarker(
|
||||
aMarkerName, aCategoryPair, mThreadId, std::move(aPayload), aTime);
|
||||
mPendingMarkers.insert(marker);
|
||||
}
|
||||
|
||||
// Called within signal. Function must be reentrant.
|
||||
ProfilerMarkerLinkedList* GetPendingMarkers() {
|
||||
// The profiled thread is interrupted, so we can access the list safely.
|
||||
// Unless the profiled thread was in the middle of changing the list when
|
||||
// we interrupted it - in that case, accessList() will return null.
|
||||
return mPendingMarkers.accessList();
|
||||
}
|
||||
|
||||
// This is called on every profiler restart. Put things that should happen at
|
||||
// that time here.
|
||||
void ReinitializeOnResume() {
|
||||
mPendingMarkers.reset();
|
||||
|
||||
// This is needed to cause an initial sample to be taken from sleeping
|
||||
// threads that had been observed prior to the profiler stopping and
|
||||
// restarting. Otherwise sleeping threads would not have any samples to
|
||||
|
@ -107,9 +84,6 @@ class RacyRegisteredThread final {
|
|||
private:
|
||||
class ProfilingStack mProfilingStack;
|
||||
|
||||
// A list of pending markers that must be moved to the circular buffer.
|
||||
ProfilerSignalSafeLinkedList<ProfilerMarker> mPendingMarkers;
|
||||
|
||||
// mThreadId contains the thread ID of the current thread. It is safe to read
|
||||
// this from multiple threads concurrently, as it will never be mutated.
|
||||
const int mThreadId;
|
||||
|
|
|
@ -1756,13 +1756,6 @@ static void DoPeriodicSample(PSLockRef aLock,
|
|||
DoSharedSample(aLock, /* aIsSynchronous = */ false, aRegisteredThread, aRegs,
|
||||
aSamplePos, aBuffer);
|
||||
|
||||
ProfilerMarkerLinkedList* pendingMarkersList =
|
||||
aRegisteredThread.RacyRegisteredThread().GetPendingMarkers();
|
||||
while (pendingMarkersList && pendingMarkersList->peek()) {
|
||||
ProfilerMarker* marker = pendingMarkersList->popHead();
|
||||
aBuffer.AddMarker(marker);
|
||||
}
|
||||
|
||||
ThreadResponsiveness* resp = aProfiledThreadData.GetThreadResponsiveness();
|
||||
if (resp && resp->HasData()) {
|
||||
double delta = resp->GetUnresponsiveDuration(
|
||||
|
@ -2550,7 +2543,6 @@ void SamplerThread::Run() {
|
|||
|
||||
ActivePS::ClearExpiredExitProfiles(lock);
|
||||
|
||||
ActivePS::Buffer(lock).DeleteExpiredStoredMarkers();
|
||||
TimeStamp expiredMarkersCleaned = TimeStamp::NowUnfuzzed();
|
||||
|
||||
if (!ActivePS::IsPaused(lock)) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче