A significant majority of the time spent in dumpasync was in getting the type name of each object in order to compare it to "AsyncStateMachineBox". This switches to comparing by module and mdTypeDef. On an ~1GB dump, the time to execute !dumpasync dropped from 43 to 11 seconds on my machine.
}
}
+void FindStateMachineTypes(DWORD_PTR* corelibModule, mdTypeDef* stateMachineBox, mdTypeDef* debugStateMachineBox)
+{
+ int numModule;
+ ArrayHolder<DWORD_PTR> moduleList = ModuleFromName(const_cast<LPSTR>("System.Private.CoreLib.dll"), &numModule);
+ if (moduleList != NULL && numModule == 1)
+ {
+ *corelibModule = moduleList[0];
+ GetInfoFromName(*corelibModule, "System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1", stateMachineBox);
+ GetInfoFromName(*corelibModule, "System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+DebugFinalizableAsyncStateMachineBox`1", debugStateMachineBox);
+ }
+ else
+ {
+ *corelibModule = 0;
+ *stateMachineBox = 0;
+ *debugStateMachineBox = 0;
+ }
+}
+
DECLARE_API(DumpAsync)
{
INIT_API();
DisplayInvalidStructuresMessage();
}
+ // Find the state machine types
+ DWORD_PTR corelibModule;
+ mdTypeDef stateMachineBoxMd, debugStateMachineBoxMd;
+ FindStateMachineTypes(&corelibModule, &stateMachineBoxMd, &debugStateMachineBoxMd);
+
// 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.
std::map<CLRDATA_ADDRESS, AsyncRecord> asyncRecords;
{
// Otherwise, we only care about AsyncStateMachineBox`1 as well as the DebugFinalizableAsyncStateMachineBox`1
// that's used when certain ETW events are set.
- if (_wcsncmp(itr->GetTypeName(), W("System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1"), 79) != 0 &&
- _wcsncmp(itr->GetTypeName(), W("System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+DebugFinalizableAsyncStateMachineBox`1"), 95) != 0)
+ DacpMethodTableData mtdata;
+ if (mtdata.Request(g_sos, TO_TADDR(itr->GetMT())) != S_OK ||
+ mtdata.Module != corelibModule ||
+ (mtdata.cl != stateMachineBoxMd && mtdata.cl != debugStateMachineBoxMd))
{
continue;
}
* Find the EE data given a name. *
* *
\**********************************************************************/
-void GetInfoFromName(DWORD_PTR ModulePtr, const char* name)
+void GetInfoFromName(DWORD_PTR ModulePtr, const char* name, mdTypeDef* retMdTypeDef)
{
+ DWORD_PTR ignoredModuleInfoRet = NULL;
+ if (retMdTypeDef)
+ *retMdTypeDef = 0;
+
ToRelease<IMetaDataImport> pImport = MDImportForModule (ModulePtr);
if (pImport == 0)
return;
BOOL fStatus = FALSE;
while (ModuleDefinition->EnumMethodDefinitionByName(&h, &pMeth) == S_OK)
{
- if (fStatus)
+ if (fStatus && !retMdTypeDef)
ExtOut("-----------------------\n");
mdTypeDef token;
if (pMeth->GetTokenAndScope(&token, NULL) == S_OK)
{
- GetInfoFromModule(ModulePtr, token);
+ GetInfoFromModule(ModulePtr, token, retMdTypeDef ? &ignoredModuleInfoRet : NULL);
fStatus = TRUE;
}
pMeth->Release();
// @todo: Handle Nested classes correctly.
if (SUCCEEDED (pImport->FindTypeDefByName (pName, tkEnclose, &cl)))
{
- GetInfoFromModule(ModulePtr, cl);
+ if (retMdTypeDef)
+ *retMdTypeDef = cl;
+
+ GetInfoFromModule(ModulePtr, cl, retMdTypeDef ? &ignoredModuleInfoRet : NULL);
return;
}
// @todo: Handle Nested classes correctly.
if (SUCCEEDED(pImport->FindTypeDefByName (pName, tkEnclose, &cl)))
{
+ if (retMdTypeDef)
+ *retMdTypeDef = cl;
+
mdMethodDef token;
ULONG cTokens;
HCORENUM henum = NULL;
&token, 1, &cTokens))
&& cTokens == 1)
{
- ExtOut("Member (mdToken token) of\n");
- GetInfoFromModule(ModulePtr, cl);
+ if (!retMdTypeDef) ExtOut("Member (mdToken token) of\n");
+ GetInfoFromModule(ModulePtr, cl, retMdTypeDef ? &ignoredModuleInfoRet : NULL);
return;
}
&token, 1, &cTokens))
&& cTokens == 1)
{
- ExtOut("Field (mdToken token) of\n");
- GetInfoFromModule(ModulePtr, cl);
+ if (!retMdTypeDef) ExtOut("Field (mdToken token) of\n");
+ GetInfoFromModule(ModulePtr, cl, retMdTypeDef ? &ignoredModuleInfoRet : NULL);
return;
}
}
* ArrayHolder class.
*/
DWORD_PTR *ModuleFromName(__in_opt LPSTR name, int *numModules);
-void GetInfoFromName(DWORD_PTR ModuleAddr, const char* name);
+void GetInfoFromName(DWORD_PTR ModuleAddr, const char* name, mdTypeDef* retMdTypeDef=NULL);
void GetInfoFromModule (DWORD_PTR ModuleAddr, ULONG token, DWORD_PTR *ret=NULL);