From f04619047cc7da4aa022da9d4de08c2f202aa0bc Mon Sep 17 00:00:00 2001 From: Henning Baldersheim Date: Thu, 17 Dec 2020 14:47:45 +0000 Subject: - Dump histogram on single line and order with most active thread first. - Skip thread and size classes with no allocations. - Use the unique thread id, instead of index among active threads. --- vespamalloc/src/vespamalloc/malloc/datasegment.hpp | 32 +++++++++++++++++++--- vespamalloc/src/vespamalloc/malloc/threadlist.hpp | 2 +- vespamalloc/src/vespamalloc/malloc/threadpool.h | 2 +- 3 files changed, 30 insertions(+), 6 deletions(-) (limited to 'vespamalloc') diff --git a/vespamalloc/src/vespamalloc/malloc/datasegment.hpp b/vespamalloc/src/vespamalloc/malloc/datasegment.hpp index 09c47ec8ae7..355c9e9daad 100644 --- a/vespamalloc/src/vespamalloc/malloc/datasegment.hpp +++ b/vespamalloc/src/vespamalloc/malloc/datasegment.hpp @@ -224,8 +224,12 @@ size_t DataSegment::infoThread(FILE * os, int level, uint32_t thre i++; } } - fprintf(os, "\nCallTree(Checked=%ld, GlobalAlloc=%ld(%ld%%)," "By%sAlloc=%ld(%2.2f%%) NotAccountedDue2FullGraph=%ld InvalidCallStacks=%ld:\n", - checkedCount, allocatedCount, checkedCount ? allocatedCount*100/checkedCount : 0, + if (checkedCount == 0) { + return 0; + } + + fprintf(os, "\nCallTree SC %d(Checked=%ld, GlobalAlloc=%ld(%ld%%)," "By%sAlloc=%ld(%2.2f%%) NotAccountedDue2FullGraph=%ld InvalidCallStacks=%ld:\n", + sct, checkedCount, allocatedCount, checkedCount ? allocatedCount*100/checkedCount : 0, allThreads ? "Us" : "Me", usedCount, checkedCount ? static_cast(usedCount*100)/checkedCount : 0.0, notAccounted, invalidCallStacks); if ( ! callGraph->empty()) { @@ -237,12 +241,32 @@ size_t DataSegment::infoThread(FILE * os, int level, uint32_t thre fprintf(os, "%s\n", ost.c_str()); } if ( !threadHistogram.empty()) { - fprintf(os, "Histogram"); + uint32_t nonZeroCount(0); for (uint32_t i(0); i < threadHistogram.size(); i++) { if (threadHistogram[i] > 0) { - fprintf(os, "\nThread %u: %u", i, threadHistogram[i]); + nonZeroCount++; + } + } + using Pair = std::pair; + std::vector orderedHisto; + orderedHisto.reserve(nonZeroCount); + for (uint32_t i(0); i < threadHistogram.size(); i++) { + if (threadHistogram[i] > 0) { + orderedHisto.emplace_back(i, threadHistogram[i]); + } + } + std::sort(orderedHisto.begin(), orderedHisto.end(), [](const Pair & a, const Pair & b) { return a.second > b.second;}); + fprintf(os, "ThreadHistogram SC %d: [", sct); + + bool first(true); + for (const Pair & entry : orderedHisto) { + if ( !first) { + fprintf(os, ", "); } + fprintf(os, "{%u, %u}", entry.first, entry.second); + first = false; } + fprintf(os, " ]"); } return usedCount; } diff --git a/vespamalloc/src/vespamalloc/malloc/threadlist.hpp b/vespamalloc/src/vespamalloc/malloc/threadlist.hpp index 12afc8107b3..24f9fc4388c 100644 --- a/vespamalloc/src/vespamalloc/malloc/threadlist.hpp +++ b/vespamalloc/src/vespamalloc/malloc/threadlist.hpp @@ -43,8 +43,8 @@ void ThreadListT::info(FILE * os, size_t level) const ThreadPool & thread = _threadVector[i]; if (thread.isActive()) { if ( ! ThreadStatT::isDummy()) { - fprintf(os, "Thread #%ld = pid # %d\n", i, thread.osThreadId()); if (thread.isUsed()) { + fprintf(os, "Thread #%u = pid # %d\n", thread.threadId(), thread.osThreadId()); thread.info(os, level, _allocPool.dataSegment()); } } diff --git a/vespamalloc/src/vespamalloc/malloc/threadpool.h b/vespamalloc/src/vespamalloc/malloc/threadpool.h index 792cf2c8108..f719df026fe 100644 --- a/vespamalloc/src/vespamalloc/malloc/threadpool.h +++ b/vespamalloc/src/vespamalloc/malloc/threadpool.h @@ -34,6 +34,7 @@ public: */ bool isUsed() const; int osThreadId() const { return _osThreadId; } + uint32_t threadId() const { return _threadId; } void quit() { _osThreadId = 0; } // Implicit memory barrier void init(int thrId); static void setParams(size_t alwayReuseLimit, size_t threadCacheLimit); @@ -42,7 +43,6 @@ private: bool hasActuallyBeenUsed() const; ThreadPoolT(const ThreadPoolT & rhs); ThreadPoolT & operator =(const ThreadPoolT & rhs); - uint32_t threadId() const { return _threadId; } void setThreadId(uint32_t th) { _threadId = th; } class AllocFree { public: -- cgit v1.2.3