From: Stephen Toub Date: Fri, 31 May 2019 22:06:13 +0000 (-0400) Subject: Improve perf of `!threadpool -wi` (#295) X-Git-Tag: submit/tizen/20190813.035844~6^2^2~14 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=5efb1507d6c7dfca022c59750894e55ffaf42f1a;p=platform%2Fcore%2Fdotnet%2Fdiagnostics.git Improve perf of `!threadpool -wi` (#295) The -wi feature added recently walks every item on the heap looking for thread pool queues. It currently does this by comparing object names, but it's much faster to compare module and type def. On my machine on an ~1GB dump, this improved execution time ~20x, from 2:15 to 0:07. --- diff --git a/src/SOS/Strike/strike.cpp b/src/SOS/Strike/strike.cpp index 6c070d618..2c8f1e748 100644 --- a/src/SOS/Strike/strike.cpp +++ b/src/SOS/Strike/strike.cpp @@ -8281,12 +8281,32 @@ DECLARE_API(ThreadPool) DisplayInvalidStructuresMessage(); } + int numModule; + ArrayHolder moduleList = ModuleFromName(const_cast("System.Private.CoreLib.dll"), &numModule); + if (moduleList == NULL || numModule != 1) + { + ExtOut(" Failed to find System.Private.CoreLib.dll\n"); + return Status; + } + DWORD_PTR corelibModule = moduleList[0]; + + mdTypeDef threadPoolWorkQueueMd, threadPoolWorkStealingQueueMd; + GetInfoFromName(corelibModule, "System.Threading.ThreadPoolWorkQueue", &threadPoolWorkQueueMd); + GetInfoFromName(corelibModule, "System.Threading.ThreadPoolWorkQueue+WorkStealingQueue", &threadPoolWorkStealingQueueMd); + // Walk every heap item looking for the global queue and local queues. ExtOut("\nQueued work items:\n%" POINTERSIZE "s %" POINTERSIZE "s %s\n", "Queue", "Address", "Work Item"); HeapStat stats; for (sos::ObjectIterator itr = gcheap.WalkHeap(); !IsInterrupt() && itr != NULL; ++itr) { - if (_wcscmp(itr->GetTypeName(), W("System.Threading.ThreadPoolWorkQueue")) == 0) + DacpMethodTableData mtdata; + if (mtdata.Request(g_sos, TO_TADDR(itr->GetMT())) != S_OK || + mtdata.Module != corelibModule) + { + continue; + } + + if (mtdata.cl == threadPoolWorkQueueMd) { // We found a global queue (there should be only one, given one AppDomain). // Get its workItems ConcurrentQueue. @@ -8371,7 +8391,7 @@ DECLARE_API(ThreadPool) } } } - else if (_wcscmp(itr->GetTypeName(), W("System.Threading.ThreadPoolWorkQueue+WorkStealingQueue")) == 0) + else if (mtdata.cl == threadPoolWorkStealingQueueMd) { // We found a local queue. Get its work items array. int offset = GetObjFieldOffset(itr->GetAddress(), itr->GetMT(), W("m_array"));