aboutsummaryrefslogtreecommitdiffstats
path: root/vespamalloc
diff options
context:
space:
mode:
authorHenning Baldersheim <balder@yahoo-inc.com>2020-12-17 13:10:18 +0000
committerHenning Baldersheim <balder@yahoo-inc.com>2020-12-17 13:10:18 +0000
commitb208f3ba04c121d03517c1f0ddc3af92934ac264 (patch)
tree54440448071aefedeb045bfaf9a4bbeed94f64f8 /vespamalloc
parent2eea2ff7cb37c926222f023e6e587d0c5a6fbbc1 (diff)
Build a histogram of currently live allocations.
Diffstat (limited to 'vespamalloc')
-rw-r--r--vespamalloc/src/vespamalloc/malloc/common.h3
-rw-r--r--vespamalloc/src/vespamalloc/malloc/datasegment.h2
-rw-r--r--vespamalloc/src/vespamalloc/malloc/datasegment.hpp30
-rw-r--r--vespamalloc/src/vespamalloc/malloc/threadlist.hpp5
4 files changed, 31 insertions, 9 deletions
diff --git a/vespamalloc/src/vespamalloc/malloc/common.h b/vespamalloc/src/vespamalloc/malloc/common.h
index 36f1bd0521d..b1b26f6b350 100644
--- a/vespamalloc/src/vespamalloc/malloc/common.h
+++ b/vespamalloc/src/vespamalloc/malloc/common.h
@@ -15,7 +15,8 @@ namespace vespamalloc {
#define NUM_SIZE_CLASSES 32 // Max 64G
-#define NUM_THREADS 16384
+static constexpr uint32_t NUM_THREADS = 16384;
+
#define UNUSED(a)
#ifdef ENABLE_DEBUG
#define DEBUG(a) a
diff --git a/vespamalloc/src/vespamalloc/malloc/datasegment.h b/vespamalloc/src/vespamalloc/malloc/datasegment.h
index 1ad4887c033..5c1c1f06088 100644
--- a/vespamalloc/src/vespamalloc/malloc/datasegment.h
+++ b/vespamalloc/src/vespamalloc/malloc/datasegment.h
@@ -28,7 +28,7 @@ public:
static size_t adjustedClassSize(SizeClassT sc) { return (sc > 0x400) ? (sc - 0x400) << 16 : sc; }
size_t dataSize() const { return (const char*)end() - (const char*)start(); }
size_t textSize() const { return size_t(start()); }
- size_t infoThread(FILE * os, int level, uint32_t thread, SizeClassT sct) const __attribute__((noinline));
+ size_t infoThread(FILE * os, int level, uint32_t thread, SizeClassT sct, uint32_t maxThreadId=0) const __attribute__((noinline));
void info(FILE * os, size_t level) __attribute__((noinline));
void setupLog(size_t noMemLogLevel, size_t bigMemLogLevel,
size_t bigLimit, size_t bigIncrement,
diff --git a/vespamalloc/src/vespamalloc/malloc/datasegment.hpp b/vespamalloc/src/vespamalloc/malloc/datasegment.hpp
index 6c9c1287ff8..09c47ec8ae7 100644
--- a/vespamalloc/src/vespamalloc/malloc/datasegment.hpp
+++ b/vespamalloc/src/vespamalloc/malloc/datasegment.hpp
@@ -6,9 +6,7 @@
namespace vespamalloc {
template<typename MemBlockPtrT>
-DataSegment<MemBlockPtrT>::~DataSegment()
-{
-}
+DataSegment<MemBlockPtrT>::~DataSegment() = default;
#define INIT_LOG_LIMIT 0x400000000ul // 16G
@@ -161,8 +159,19 @@ void DataSegment<MemBlockPtrT>::returnBlock(void *ptr)
}
}
+namespace {
+
+std::vector<uint32_t>
+createHistogram(bool allThreads, uint32_t maxThreads) {
+ if (allThreads) {
+ return std::vector<uint32_t>(maxThreads, 0);
+ }
+ return std::vector<uint32_t>();
+}
+
+}
template<typename MemBlockPtrT>
-size_t DataSegment<MemBlockPtrT>::infoThread(FILE * os, int level, uint32_t thread, SizeClassT sct) const
+size_t DataSegment<MemBlockPtrT>::infoThread(FILE * os, int level, uint32_t thread, SizeClassT sct, uint32_t maxThreadId) const
{
using CallGraphLT = CallGraph<typename MemBlockPtrT::Stack, 0x10000, Index>;
bool allThreads(thread == 0);
@@ -172,6 +181,7 @@ size_t DataSegment<MemBlockPtrT>::infoThread(FILE * os, int level, uint32_t thre
size_t notAccounted(0);
size_t invalidCallStacks(0);
std::unique_ptr<CallGraphLT> callGraph = std::make_unique<CallGraphLT>();
+ std::vector<uint32_t> threadHistogram = createHistogram(allThreads, maxThreadId);
for (size_t i=0; i < NELEMS(_blockList); ) {
const BlockT & b = _blockList[i];
SizeClassT sc = b.sizeClass();
@@ -185,6 +195,9 @@ size_t DataSegment<MemBlockPtrT>::infoThread(FILE * os, int level, uint32_t thre
allocatedCount++;
if (allThreads || (mem.threadId() == thread)) {
usedCount++;
+ if (mem.threadId() < threadHistogram.size()) {
+ threadHistogram[mem.threadId()]++;
+ }
if (usedCount < _allocs2Show) {
mem.info(os, level);
}
@@ -223,7 +236,14 @@ size_t DataSegment<MemBlockPtrT>::infoThread(FILE * os, int level, uint32_t thre
ost << agg;
fprintf(os, "%s\n", ost.c_str());
}
- fprintf(os, " count(%ld)", usedCount);
+ if ( !threadHistogram.empty()) {
+ fprintf(os, "Histogram");
+ for (uint32_t i(0); i < threadHistogram.size(); i++) {
+ if (threadHistogram[i] > 0) {
+ fprintf(os, "\nThread %u: %u", i, threadHistogram[i]);
+ }
+ }
+ }
return usedCount;
}
diff --git a/vespamalloc/src/vespamalloc/malloc/threadlist.hpp b/vespamalloc/src/vespamalloc/malloc/threadlist.hpp
index aa514643265..12afc8107b3 100644
--- a/vespamalloc/src/vespamalloc/malloc/threadlist.hpp
+++ b/vespamalloc/src/vespamalloc/malloc/threadlist.hpp
@@ -32,10 +32,11 @@ void ThreadListT<MemBlockPtrT, ThreadStatT>::info(FILE * os, size_t level)
peakThreads = i;
}
}
- fprintf(os, "#%ld active threads. Peak threads #%ld\n", activeThreads, peakThreads);
+ fprintf(os, "#%ld active threads. Peak threads #%ld. %u threads created in total.\n",
+ activeThreads, peakThreads, _threadCountAccum.load());
if ((level > 1) && ! ThreadStatT::isDummy()) {
for (SizeClassT sc(0); sc < NUM_SIZE_CLASSES; sc++) {
- _allocPool.dataSegment().infoThread(os, level, 0, sc);
+ _allocPool.dataSegment().infoThread(os, level, 0, sc, _threadCountAccum.load() + 1);
}
}
for (size_t i(0); i < getMaxNumThreads(); i++) {