michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef mozilla_BackgroundHangTelemetry_h michael@0: #define mozilla_BackgroundHangTelemetry_h michael@0: michael@0: #include "mozilla/Array.h" michael@0: #include "mozilla/Assertions.h" michael@0: #include "mozilla/Move.h" michael@0: #include "mozilla/Mutex.h" michael@0: #include "mozilla/PodOperations.h" michael@0: #include "mozilla/Vector.h" michael@0: michael@0: #include "nsString.h" michael@0: #include "prinrval.h" michael@0: michael@0: namespace mozilla { michael@0: namespace Telemetry { michael@0: michael@0: static const size_t kTimeHistogramBuckets = 8 * sizeof(PRIntervalTime); michael@0: michael@0: /* TimeHistogram is an efficient histogram that puts time durations into michael@0: exponential (base 2) buckets; times are accepted in PRIntervalTime and michael@0: stored in milliseconds. */ michael@0: class TimeHistogram : public mozilla::Array michael@0: { michael@0: public: michael@0: TimeHistogram() michael@0: { michael@0: mozilla::PodArrayZero(*this); michael@0: } michael@0: // Get minimum (inclusive) range of bucket in milliseconds michael@0: uint32_t GetBucketMin(size_t aBucket) const { michael@0: MOZ_ASSERT(aBucket < ArrayLength(*this)); michael@0: return (1u << aBucket) & ~1u; // Bucket 0 starts at 0, not 1 michael@0: } michael@0: // Get maximum (inclusive) range of bucket in milliseconds michael@0: uint32_t GetBucketMax(size_t aBucket) const { michael@0: MOZ_ASSERT(aBucket < ArrayLength(*this)); michael@0: return (1u << (aBucket + 1u)) - 1u; michael@0: } michael@0: void Add(PRIntervalTime aTime); michael@0: }; michael@0: michael@0: /* A hang histogram consists of a stack associated with the michael@0: hang, along with a time histogram of the hang times. */ michael@0: class HangHistogram : public TimeHistogram michael@0: { michael@0: public: michael@0: typedef mozilla::Vector Stack; michael@0: michael@0: private: michael@0: static uint32_t GetHash(const Stack& aStack); michael@0: michael@0: Stack mStack; michael@0: // Use a hash to speed comparisons michael@0: const uint32_t mHash; michael@0: michael@0: public: michael@0: explicit HangHistogram(Stack&& aStack) michael@0: : mStack(mozilla::Move(aStack)) michael@0: , mHash(GetHash(mStack)) michael@0: { michael@0: } michael@0: HangHistogram(HangHistogram&& aOther) michael@0: : TimeHistogram(mozilla::Move(aOther)) michael@0: , mStack(mozilla::Move(aOther.mStack)) michael@0: , mHash(mozilla::Move(aOther.mHash)) michael@0: { michael@0: } michael@0: bool operator==(const HangHistogram& aOther) const; michael@0: bool operator!=(const HangHistogram& aOther) const michael@0: { michael@0: return !operator==(aOther); michael@0: } michael@0: const Stack& GetStack() const { michael@0: return mStack; michael@0: } michael@0: }; michael@0: michael@0: /* Thread hang stats consist of michael@0: - thread name michael@0: - time histogram of all task run times michael@0: - hang histograms of individual hangs. */ michael@0: class ThreadHangStats michael@0: { michael@0: private: michael@0: nsAutoCString mName; michael@0: michael@0: public: michael@0: TimeHistogram mActivity; michael@0: mozilla::Vector mHangs; michael@0: michael@0: explicit ThreadHangStats(const char* aName) michael@0: : mName(aName) michael@0: { michael@0: } michael@0: ThreadHangStats(ThreadHangStats&& aOther) michael@0: : mName(mozilla::Move(aOther.mName)) michael@0: , mActivity(mozilla::Move(aOther.mActivity)) michael@0: , mHangs(mozilla::Move(aOther.mHangs)) michael@0: { michael@0: } michael@0: const char* GetName() const { michael@0: return mName.get(); michael@0: } michael@0: }; michael@0: michael@0: } // namespace Telemetry michael@0: } // namespace mozilla michael@0: #endif // mozilla_BackgroundHangTelemetry_h