Improve perf of `!threadpool -wi` (#295)
authorStephen Toub <stoub@microsoft.com>
Fri, 31 May 2019 22:06:13 +0000 (18:06 -0400)
committerGitHub <noreply@github.com>
Fri, 31 May 2019 22:06:13 +0000 (18:06 -0400)
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.

src/SOS/Strike/strike.cpp

index 6c070d618404737cd9ab883d824ccb9839bffdcf..2c8f1e7486c8cd99f4af8736850fc533577c4f56 100644 (file)
@@ -8281,12 +8281,32 @@ DECLARE_API(ThreadPool)
                 DisplayInvalidStructuresMessage();
             }
 
+            int numModule;
+            ArrayHolder<DWORD_PTR> moduleList = ModuleFromName(const_cast<LPSTR>("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<IThreadPoolWorkItem>.
@@ -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"));