Bug 1384688 - Add thread register and unregister time. r?njn
MozReview-Commit-ID: JDRP8m7QrE1
--- a/tools/profiler/core/ProfilerBacktrace.cpp
+++ b/tools/profiler/core/ProfilerBacktrace.cpp
@@ -30,15 +30,17 @@ ProfilerBacktrace::StreamJSON(Spliceable
{
// This call to StreamSamplesAndMarkers() can safely pass in a non-null
// JSContext. That's because StreamSamplesAndMarkers() only accesses the
// JSContext when streaming JitReturnAddress entries, and such entries
// never appear in synchronous samples.
double firstSampleTimeIgnored;
StreamSamplesAndMarkers(mName.get(), mThreadId,
*mBuffer.get(), aWriter, aProcessStartTime,
+ /* aRegisterTime */ TimeStamp(),
+ /* aUnregisterTime */ TimeStamp(),
/* aSinceTime */ 0, &firstSampleTimeIgnored,
/* aContext */ nullptr,
/* aSavedStreamedSamples */ nullptr,
/* aFirstSavedStreamedSampleTime */ 0.0,
/* aSavedStreamedMarkers */ nullptr,
aUniqueStacks);
}
--- a/tools/profiler/core/ThreadInfo.cpp
+++ b/tools/profiler/core/ThreadInfo.cpp
@@ -17,16 +17,17 @@
#define getpid _getpid
#else
#include <unistd.h> // for getpid()
#endif
ThreadInfo::ThreadInfo(const char* aName, int aThreadId, bool aIsMainThread,
void* aStackTop)
: mName(strdup(aName))
+ , mRegisterTime(TimeStamp::Now())
, mThreadId(aThreadId)
, mIsMainThread(aIsMainThread)
, mRacyInfo(mozilla::WrapNotNull(new RacyThreadInfo()))
, mPlatformData(AllocPlatformData(aThreadId))
, mStackTop(aStackTop)
, mIsBeingProfiled(false)
, mContext(nullptr)
, mJSSampling(INACTIVE)
@@ -79,17 +80,19 @@ ThreadInfo::StreamJSON(const ProfileBuff
mUniqueStacks.emplace(mContext);
}
double firstSampleTime = 0.0;
aWriter.Start(SpliceableJSONWriter::SingleLineStyle);
{
StreamSamplesAndMarkers(Name(), ThreadId(), aBuffer, aWriter,
- aProcessStartTime, aSinceTime, &firstSampleTime,
+ aProcessStartTime,
+ mRegisterTime, mUnregisterTime,
+ aSinceTime, &firstSampleTime,
mContext,
mSavedStreamedSamples.get(),
mFirstSavedStreamedSampleTime,
mSavedStreamedMarkers.get(),
*mUniqueStacks);
mSavedStreamedSamples.reset();
mFirstSavedStreamedSampleTime = 0.0;
mSavedStreamedMarkers.reset();
@@ -143,31 +146,47 @@ ThreadInfo::StreamJSON(const ProfileBuff
}
void
StreamSamplesAndMarkers(const char* aName,
int aThreadId,
const ProfileBuffer& aBuffer,
SpliceableJSONWriter& aWriter,
const TimeStamp& aProcessStartTime,
+ const TimeStamp& aRegisterTime,
+ const TimeStamp& aUnregisterTime,
double aSinceTime,
double* aOutFirstSampleTime,
JSContext* aContext,
char* aSavedStreamedSamples,
double aFirstSavedStreamedSampleTime,
char* aSavedStreamedMarkers,
UniqueStacks& aUniqueStacks)
{
aWriter.StringProperty("processType",
XRE_ChildProcessTypeToString(XRE_GetProcessType()));
aWriter.StringProperty("name", aName);
aWriter.IntProperty("tid", static_cast<int64_t>(aThreadId));
aWriter.IntProperty("pid", static_cast<int64_t>(getpid()));
+ if (aRegisterTime) {
+ aWriter.DoubleProperty("registerTime",
+ (aRegisterTime - aProcessStartTime).ToMilliseconds());
+ } else {
+ aWriter.NullProperty("registerTime");
+ }
+
+ if (aUnregisterTime) {
+ aWriter.DoubleProperty("unregisterTime",
+ (aUnregisterTime - aProcessStartTime).ToMilliseconds());
+ } else {
+ aWriter.NullProperty("unregisterTime");
+ }
+
aWriter.StartObjectProperty("samples");
{
{
JSONSchemaWriter schema(aWriter);
schema.WriteField("stack");
schema.WriteField("time");
schema.WriteField("responsiveness");
schema.WriteField("rss");
--- a/tools/profiler/core/ThreadInfo.h
+++ b/tools/profiler/core/ThreadInfo.h
@@ -3,16 +3,17 @@
/* 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 ThreadInfo_h
#define ThreadInfo_h
#include "mozilla/NotNull.h"
+#include "mozilla/TimeStamp.h"
#include "mozilla/UniquePtrExtensions.h"
#include "platform.h"
#include "ProfileBuffer.h"
#include "js/ProfilingStack.h"
// This class contains the info for a single thread that is accessible without
// protection from gPSMutex in platform.cpp. Because there is no external
@@ -177,25 +178,29 @@ public:
bool IsMainThread() const { return mIsMainThread; }
mozilla::NotNull<RacyThreadInfo*> RacyInfo() const { return mRacyInfo; }
void StartProfiling();
void StopProfiling();
bool IsBeingProfiled() { return mIsBeingProfiled; }
+ void NotifyUnregistered() { mUnregisterTime = TimeStamp::Now(); }
+
PlatformData* GetPlatformData() const { return mPlatformData.get(); }
void* StackTop() const { return mStackTop; }
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
ProfileBuffer::LastSample& LastSample() { return mLastSample; }
private:
mozilla::UniqueFreePtr<char> mName;
+ mozilla::TimeStamp mRegisterTime;
+ mozilla::TimeStamp mUnregisterTime;
int mThreadId;
const bool mIsMainThread;
// The thread's RacyThreadInfo. This is an owning pointer. It could be an
// inline member, but we don't do that because RacyThreadInfo is quite large
// (due to the PseudoStack within it), and we have ThreadInfo vectors and so
// we'd end up wasting a lot of space in those vectors for excess elements.
mozilla::NotNull<RacyThreadInfo*> mRacyInfo;
@@ -370,16 +375,18 @@ private:
ProfileBuffer::LastSample mLastSample;
};
void
StreamSamplesAndMarkers(const char* aName, int aThreadId,
const ProfileBuffer& aBuffer,
SpliceableJSONWriter& aWriter,
const mozilla::TimeStamp& aProcessStartTime,
+ const TimeStamp& aRegisterTime,
+ const TimeStamp& aUnregisterTime,
double aSinceTime,
double* aOutFirstSampleTime,
JSContext* aContext,
char* aSavedStreamedSamples,
double aFirstSavedStreamedSampleTime,
char* aSavedStreamedMarkers,
UniqueStacks& aUniqueStacks);
--- a/tools/profiler/core/platform.cpp
+++ b/tools/profiler/core/platform.cpp
@@ -2957,16 +2957,17 @@ profiler_unregister_thread()
// that for a JS thread that is in the process of disappearing.
int i;
ThreadInfo* info = FindLiveThreadInfo(lock, &i);
MOZ_RELEASE_ASSERT(info == TLSInfo::Info(lock));
if (info) {
DEBUG_LOG("profiler_unregister_thread: %s", info->Name());
if (ActivePS::Exists(lock) && info->IsBeingProfiled()) {
+ info->NotifyUnregistered();
CorePS::DeadThreads(lock).push_back(info);
} else {
delete info;
}
CorePS::ThreadVector& liveThreads = CorePS::LiveThreads(lock);
liveThreads.erase(liveThreads.begin() + i);
// Whether or not we just destroyed the ThreadInfo or transferred it to the