diff options
author | Henning Baldersheim <balder@yahoo-inc.com> | 2020-12-17 13:10:18 +0000 |
---|---|---|
committer | Henning Baldersheim <balder@yahoo-inc.com> | 2020-12-17 13:10:18 +0000 |
commit | b208f3ba04c121d03517c1f0ddc3af92934ac264 (patch) | |
tree | 54440448071aefedeb045bfaf9a4bbeed94f64f8 /vespamalloc/src | |
parent | 2eea2ff7cb37c926222f023e6e587d0c5a6fbbc1 (diff) |
Build a histogram of currently live allocations.
Diffstat (limited to 'vespamalloc/src')
-rw-r--r-- | vespamalloc/src/vespamalloc/malloc/common.h | 3 | ||||
-rw-r--r-- | vespamalloc/src/vespamalloc/malloc/datasegment.h | 2 | ||||
-rw-r--r-- | vespamalloc/src/vespamalloc/malloc/datasegment.hpp | 30 | ||||
-rw-r--r-- | vespamalloc/src/vespamalloc/malloc/threadlist.hpp | 5 |
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++) { |