Bug 1128768: Part 4 - Update telemetry to serialize BHR hang annotations; r=gfritzsche

This commit is contained in:
Aaron Klotz 2015-03-09 16:34:42 -06:00
parent c68a3139c4
commit 80a1cfae44
2 changed files with 69 additions and 10 deletions

View File

@ -243,7 +243,7 @@ public:
*/
struct AnnotationInfo {
AnnotationInfo(uint32_t aHangIndex,
UniquePtr<HangAnnotations> aAnnotations)
HangAnnotationsPtr aAnnotations)
: mHangIndex(aHangIndex)
, mAnnotations(Move(aAnnotations))
{}
@ -259,7 +259,7 @@ public:
return *this;
}
uint32_t mHangIndex;
UniquePtr<HangAnnotations> mAnnotations;
HangAnnotationsPtr mAnnotations;
private:
// Force move constructor
@ -269,7 +269,7 @@ public:
size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
void AddHang(const Telemetry::ProcessedStack& aStack, uint32_t aDuration,
int32_t aSystemUptime, int32_t aFirefoxUptime,
UniquePtr<HangAnnotations> aAnnotations);
HangAnnotationsPtr aAnnotations);
uint32_t GetDuration(unsigned aIndex) const;
int32_t GetSystemUptime(unsigned aIndex) const;
int32_t GetFirefoxUptime(unsigned aIndex) const;
@ -298,7 +298,7 @@ HangReports::AddHang(const Telemetry::ProcessedStack& aStack,
uint32_t aDuration,
int32_t aSystemUptime,
int32_t aFirefoxUptime,
UniquePtr<HangAnnotations> aAnnotations) {
HangAnnotationsPtr aAnnotations) {
HangInfo info = { aDuration, aSystemUptime, aFirefoxUptime };
mHangInfo.push_back(info);
if (aAnnotations) {
@ -658,7 +658,7 @@ public:
Telemetry::ProcessedStack &aStack,
int32_t aSystemUptime,
int32_t aFirefoxUptime,
UniquePtr<HangAnnotations> aAnnotations);
HangAnnotationsPtr aAnnotations);
#endif
static void RecordThreadHangStats(Telemetry::ThreadHangStats& aStats);
static nsresult GetHistogramEnumId(const char *name, Telemetry::ID *id);
@ -2839,6 +2839,44 @@ CreateJSHangStack(JSContext* cx, const Telemetry::HangStack& stack)
return ret;
}
static JSObject*
CreateJSHangAnnotations(JSContext* cx, const HangAnnotationsVector& annotations)
{
JS::RootedObject annotationsArray(cx, JS_NewArrayObject(cx, 0));
if (!annotationsArray) {
return nullptr;
}
size_t annotationIndex = 0;
for (const HangAnnotationsPtr *i = annotations.begin(), *e = annotations.end();
i != e; ++i) {
JS::RootedObject jsAnnotation(cx, JS_NewPlainObject(cx));
if (!jsAnnotation) {
continue;
}
const HangAnnotationsPtr& curAnnotations = *i;
UniquePtr<HangAnnotations::Enumerator> annotationsEnum =
curAnnotations->GetEnumerator();
if (!annotationsEnum) {
continue;
}
nsAutoString key;
nsAutoString value;
while (annotationsEnum->Next(key, value)) {
JS::RootedValue jsValue(cx);
jsValue.setString(JS_NewUCStringCopyN(cx, value.get(), value.Length()));
if (!JS_DefineUCProperty(cx, jsAnnotation, key.get(), key.Length(),
jsValue, JSPROP_ENUMERATE)) {
return nullptr;
}
}
if (!JS_SetElement(cx, annotationsArray, annotationIndex, jsAnnotation)) {
continue;
}
++annotationIndex;
}
return annotationsArray;
}
static JSObject*
CreateJSHangHistogram(JSContext* cx, const Telemetry::HangHistogram& hang)
{
@ -2849,11 +2887,16 @@ CreateJSHangHistogram(JSContext* cx, const Telemetry::HangHistogram& hang)
JS::RootedObject stack(cx, CreateJSHangStack(cx, hang.GetStack()));
JS::RootedObject time(cx, CreateJSTimeHistogram(cx, hang));
auto& hangAnnotations = hang.GetAnnotations();
JS::RootedObject annotations(cx, CreateJSHangAnnotations(cx, hangAnnotations));
if (!stack ||
!time ||
!annotations ||
!JS_DefineProperty(cx, ret, "stack", stack, JSPROP_ENUMERATE) ||
!JS_DefineProperty(cx, ret, "histogram", time, JSPROP_ENUMERATE)) {
!JS_DefineProperty(cx, ret, "histogram", time, JSPROP_ENUMERATE) ||
(!hangAnnotations.empty() && // <-- Only define annotations when nonempty
!JS_DefineProperty(cx, ret, "annotations", annotations, JSPROP_ENUMERATE))) {
return nullptr;
}
@ -2899,6 +2942,7 @@ CreateJSThreadHangStats(JSContext* cx, const Telemetry::ThreadHangStats& thread)
if (!JS_DefineProperty(cx, ret, "hangs", hangs, JSPROP_ENUMERATE)) {
return nullptr;
}
return ret;
}
@ -3334,12 +3378,12 @@ TelemetryImpl::RecordChromeHang(uint32_t aDuration,
Telemetry::ProcessedStack &aStack,
int32_t aSystemUptime,
int32_t aFirefoxUptime,
UniquePtr<HangAnnotations> aAnnotations)
HangAnnotationsPtr aAnnotations)
{
if (!sTelemetry || !sTelemetry->mCanRecord)
return;
UniquePtr<HangAnnotations> annotations;
HangAnnotationsPtr annotations;
// We only pass aAnnotations if it is not empty.
if (aAnnotations && !aAnnotations->IsEmpty()) {
annotations = Move(aAnnotations);
@ -3608,7 +3652,7 @@ void RecordChromeHang(uint32_t duration,
ProcessedStack &aStack,
int32_t aSystemUptime,
int32_t aFirefoxUptime,
UniquePtr<HangAnnotations> aAnnotations)
HangAnnotationsPtr aAnnotations)
{
TelemetryImpl::RecordChromeHang(duration, aStack,
aSystemUptime, aFirefoxUptime,

View File

@ -8,6 +8,7 @@
#include "mozilla/Array.h"
#include "mozilla/Assertions.h"
#include "mozilla/HangAnnotations.h"
#include "mozilla/Move.h"
#include "mozilla/Mutex.h"
#include "mozilla/PodOperations.h"
@ -119,6 +120,8 @@ private:
HangStack mNativeStack;
// Use a hash to speed comparisons
const uint32_t mHash;
// Annotations attributed to this stack
HangMonitor::HangAnnotationsVector mAnnotations;
public:
explicit HangHistogram(HangStack&& aStack)
@ -131,6 +134,7 @@ public:
, mStack(mozilla::Move(aOther.mStack))
, mNativeStack(mozilla::Move(aOther.mNativeStack))
, mHash(mozilla::Move(aOther.mHash))
, mAnnotations(mozilla::Move(aOther.mAnnotations))
{
}
bool operator==(const HangHistogram& aOther) const;
@ -147,12 +151,23 @@ public:
const HangStack& GetNativeStack() const {
return mNativeStack;
}
const HangMonitor::HangAnnotationsVector& GetAnnotations() const {
return mAnnotations;
}
void Add(PRIntervalTime aTime, HangMonitor::HangAnnotationsPtr aAnnotations) {
TimeHistogram::Add(aTime);
if (aAnnotations) {
mAnnotations.append(Move(aAnnotations));
}
}
};
/* Thread hang stats consist of
- thread name
- time histogram of all task run times
- hang histograms of individual hangs. */
- hang histograms of individual hangs
- annotations for each hang
*/
class ThreadHangStats
{
private: