From: Stephen Toub Date: Fri, 31 May 2019 22:11:23 +0000 (-0400) Subject: Improve perf of `!dumpasync -tasks` (#294) X-Git-Tag: submit/tizen/20190813.035844~6^2^2~13 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=dfc2d13c5b2a374d1cc2971d0893a671a2f8ba08;p=platform%2Fcore%2Fdotnet%2Fdiagnostics.git Improve perf of `!dumpasync -tasks` (#294) When the `-tasks` flag is set, we look at every object on the heap and walk its hierarchy to decide if it's a task or a task-derived type. But we currently do that by comparing the name of every object against "System.Threading.Tasks.Task", which is very expensive. This switches to comparing by module and type def. On my machine, a `!dumpasync -tasks` command that previously took ~1 minute now takes ~30 seconds. --- diff --git a/src/SOS/Strike/strike.cpp b/src/SOS/Strike/strike.cpp index 2c8f1e748..6738487df 100644 --- a/src/SOS/Strike/strike.cpp +++ b/src/SOS/Strike/strike.cpp @@ -4428,7 +4428,7 @@ void ExtOutStateMachineFields(AsyncRecord& ar) } } -void FindStateMachineTypes(DWORD_PTR* corelibModule, mdTypeDef* stateMachineBox, mdTypeDef* debugStateMachineBox) +void FindStateMachineTypes(DWORD_PTR* corelibModule, mdTypeDef* stateMachineBox, mdTypeDef* debugStateMachineBox, mdTypeDef* task) { int numModule; ArrayHolder moduleList = ModuleFromName(const_cast("System.Private.CoreLib.dll"), &numModule); @@ -4437,6 +4437,7 @@ void FindStateMachineTypes(DWORD_PTR* corelibModule, mdTypeDef* stateMachineBox, *corelibModule = moduleList[0]; GetInfoFromName(*corelibModule, "System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1", stateMachineBox); GetInfoFromName(*corelibModule, "System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+DebugFinalizableAsyncStateMachineBox`1", debugStateMachineBox); + GetInfoFromName(*corelibModule, "System.Threading.Tasks.Task", task); } else { @@ -4511,8 +4512,8 @@ DECLARE_API(DumpAsync) // Find the state machine types DWORD_PTR corelibModule; - mdTypeDef stateMachineBoxMd, debugStateMachineBoxMd; - FindStateMachineTypes(&corelibModule, &stateMachineBoxMd, &debugStateMachineBoxMd); + mdTypeDef stateMachineBoxMd, debugStateMachineBoxMd, taskMd; + FindStateMachineTypes(&corelibModule, &stateMachineBoxMd, &debugStateMachineBoxMd, &taskMd); // Walk each heap object looking for async state machine objects. As we're targeting .NET Core 2.1+, all such objects // will be Task or Task-derived types. @@ -4530,7 +4531,7 @@ DECLARE_API(DumpAsync) { // If the user has selected to include all tasks and not just async state machine boxes, we simply need to validate // that this is Task or Task-derived, and if it's not, skip it. - if (!IsDerivedFrom(itr->GetMT(), W("System.Threading.Tasks.Task"))) + if (!IsDerivedFrom(itr->GetMT(), corelibModule, taskMd)) { continue; } diff --git a/src/SOS/Strike/util.cpp b/src/SOS/Strike/util.cpp index 03f618d78..f45ecc080 100644 --- a/src/SOS/Strike/util.cpp +++ b/src/SOS/Strike/util.cpp @@ -2152,6 +2152,23 @@ BOOL IsDerivedFrom(CLRDATA_ADDRESS mtObj, __in_z LPCWSTR baseString) return FALSE; } +BOOL IsDerivedFrom(CLRDATA_ADDRESS mtObj, DWORD_PTR modulePtr, mdTypeDef typeDef) +{ + DacpMethodTableData dmtd; + + for (CLRDATA_ADDRESS walkMT = mtObj; + walkMT != NULL && dmtd.Request(g_sos, walkMT) == S_OK; + walkMT = dmtd.ParentMethodTable) + { + if (dmtd.Module == modulePtr && dmtd.cl == typeDef) + { + return TRUE; + } + } + + return FALSE; +} + BOOL TryGetMethodDescriptorForDelegate(CLRDATA_ADDRESS delegateAddr, CLRDATA_ADDRESS* pMD) { if (!sos::IsObject(delegateAddr, false)) diff --git a/src/SOS/Strike/util.h b/src/SOS/Strike/util.h index f32e4cefc..944dfcb78 100644 --- a/src/SOS/Strike/util.h +++ b/src/SOS/Strike/util.h @@ -1850,6 +1850,7 @@ BOOL IsStringObject (size_t obj); BOOL IsObjectArray (DWORD_PTR objPointer); BOOL IsObjectArray (DacpObjectData *pData); BOOL IsDerivedFrom(CLRDATA_ADDRESS mtObj, __in_z LPCWSTR baseString); +BOOL IsDerivedFrom(CLRDATA_ADDRESS mtObj, DWORD_PTR modulePtr, mdTypeDef typeDef); BOOL TryGetMethodDescriptorForDelegate(CLRDATA_ADDRESS delegateAddr, CLRDATA_ADDRESS* pMD); #ifdef FEATURE_PAL