summaryrefslogtreecommitdiffstats
path: root/tools/memory-profiler/MemoryProfiler.h
diff options
context:
space:
mode:
Diffstat (limited to 'tools/memory-profiler/MemoryProfiler.h')
-rw-r--r--tools/memory-profiler/MemoryProfiler.h159
1 files changed, 159 insertions, 0 deletions
diff --git a/tools/memory-profiler/MemoryProfiler.h b/tools/memory-profiler/MemoryProfiler.h
new file mode 100644
index 000000000..85a378fb2
--- /dev/null
+++ b/tools/memory-profiler/MemoryProfiler.h
@@ -0,0 +1,159 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=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 tools_profiler_MemoryProfiler_h
+#define tools_profiler_MemoryProfiler_h
+
+#include "nsIMemoryProfiler.h"
+
+#include "mozilla/StaticPtr.h"
+#include "mozilla/TimeStamp.h"
+
+#include "CompactTraceTable.h"
+#include "nsTArray.h"
+#include "prlock.h"
+
+#define MEMORY_PROFILER_CID \
+ { 0xf976eaa2, 0xcc1f, 0x47ee, \
+ { 0x81, 0x29, 0xb8, 0x26, 0x2a, 0x3d, 0xb6, 0xb2 } }
+
+#define MEMORY_PROFILER_CONTRACT_ID "@mozilla.org/tools/memory-profiler;1"
+
+struct PRLock;
+
+namespace mozilla {
+
+class NativeProfilerImpl;
+class GCHeapProfilerImpl;
+
+struct ProfilerForJSContext
+{
+ ProfilerForJSContext()
+ : mProfiler(nullptr)
+ , mEnabled(false)
+ {}
+ GCHeapProfilerImpl* mProfiler;
+ bool mEnabled;
+};
+using JSContextProfilerMap =
+ nsDataHashtable<nsClearingPtrHashKey<JSContext>, ProfilerForJSContext>;
+
+class MemoryProfiler final : public nsIMemoryProfiler
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIMEMORYPROFILER
+
+private:
+ static void InitOnce();
+ ~MemoryProfiler() {}
+
+ // The accesses to other static member are guarded by sLock and
+ // sProfileContextCount.
+ static PRLock* sLock;
+ static uint32_t sProfileContextCount;
+
+ static StaticAutoPtr<NativeProfilerImpl> sNativeProfiler;
+ static StaticAutoPtr<JSContextProfilerMap> sJSContextProfilerMap;
+ static TimeStamp sStartTime;
+};
+
+// Allocation events to be reported.
+struct AllocEvent {
+ TimeStamp mTimestamp;
+ // index to a stacktrace singleton.
+ uint32_t mTraceIdx;
+ // Allocation size
+ int32_t mSize;
+
+ AllocEvent(uint32_t aTraceIdx, int32_t aSize, TimeStamp aTimestamp)
+ : mTimestamp(aTimestamp)
+ , mTraceIdx(aTraceIdx)
+ , mSize(aSize)
+ {}
+};
+
+// Index to allocation events but also a mark bit to be GC-able.
+struct AllocEntry {
+ uint32_t mEventIdx : 31;
+ bool mMarked : 1;
+
+ // Default constructor for uninitialized stack value required by
+ // getter methods.
+ AllocEntry()
+ : mEventIdx(0)
+ , mMarked(false)
+ {}
+ explicit AllocEntry(int aEventIdx)
+ : mEventIdx(aEventIdx)
+ , mMarked(false)
+ {}
+};
+
+using AllocMap = nsDataHashtable<nsClearingVoidPtrHashKey, AllocEntry>;
+
+class ProfilerImpl
+{
+public:
+ static nsTArray<nsCString> GetStacktrace();
+ static double DRandom();
+
+ ProfilerImpl();
+ virtual nsTArray<nsCString> GetNames() const = 0;
+ virtual nsTArray<TrieNode> GetTraces() const = 0;
+ virtual const nsTArray<AllocEvent>& GetEvents() const = 0;
+
+protected:
+ /**
+ * The sampler generates a random variable which conforms to a geometric
+ * distribution of probability p = 1 / mSampleSize to calculate the
+ * next-to-be-sampled byte directly; It avoids rolling a dice on each byte.
+ *
+ * Let Bn denote a Bernoulli process with first success on n-th trial, the
+ * cumulative distribution function of Bn is Cn = 1 - (1 - p) ^ n.
+ * Let U denote a uniformly distributed random variable in [0, 1).
+ * A geometric random variable can be generated by Cn's reverse function:
+ * G = floor(log(1 - U) / log(1 - p)).
+ *
+ * @param aSize the number of bytes seen
+ * @return the number of events sampled
+ */
+ size_t AddBytesSampled(uint32_t aBytes);
+
+ uint32_t mSampleSize;
+
+private:
+ uint32_t mRemainingBytes;
+ double mLog1minusP;
+};
+
+/*
+ * This class is used to make sure the profile data is only accessed
+ * on one thread at a time. Don't use mozilla::Mutex because we don't
+ * want to allocate memory.
+ */
+class AutoMPLock
+{
+public:
+ explicit AutoMPLock(PRLock* aLock)
+ {
+ MOZ_ASSERT(aLock);
+ mLock = aLock;
+ PR_Lock(mLock);
+ }
+
+ ~AutoMPLock()
+ {
+ PR_Unlock(mLock);
+ }
+
+private:
+ PRLock* mLock;
+};
+
+} // namespace mozilla
+
+#endif