From d48002f03f0cb42a7546da76ad05c591e928ca42 Mon Sep 17 00:00:00 2001 From: Andrew Au Date: Mon, 14 Jun 2021 09:52:47 -0700 Subject: [PATCH 1/3] Optionally capture a dump during generational aware analysis --- src/coreclr/inc/clrconfigvalues.h | 1 + src/coreclr/vm/gcenv.ee.cpp | 13 +++++++++++++ src/coreclr/vm/genanalysis.cpp | 6 ++++-- src/coreclr/vm/genanalysis.h | 4 +++- 4 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/coreclr/inc/clrconfigvalues.h b/src/coreclr/inc/clrconfigvalues.h index 3f21e41dfa3693..222ad17dd70043 100644 --- a/src/coreclr/inc/clrconfigvalues.h +++ b/src/coreclr/inc/clrconfigvalues.h @@ -722,6 +722,7 @@ RETAIL_CONFIG_DWORD_INFO(INTERNAL_GCGenAnalysisGen, W("GCGenAnalysisGen"), 0, "T RETAIL_CONFIG_DWORD_INFO(INTERNAL_GCGenAnalysisBytes, W("GCGenAnalysisBytes"), 0, "The number of bytes to trigger generational aware analysis") RETAIL_CONFIG_DWORD_INFO(INTERNAL_GCGenAnalysisIndex, W("GCGenAnalysisIndex"), 0, "The gc index to trigger generational aware analysis") RETAIL_CONFIG_STRING_INFO(INTERNAL_GCGenAnalysisCmd, W("GCGenAnalysisCmd"), "An optional filter to match with the command line used to spawn the process") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_GCGenAnalysisDump, W("GCGenAnalysisDump"), 0, "Enable/Disable capturing a dump as well as the traces") // // Diagnostics Ports diff --git a/src/coreclr/vm/gcenv.ee.cpp b/src/coreclr/vm/gcenv.ee.cpp index 5be5bc2d9ecf96..c3cfb6bff2a5e1 100644 --- a/src/coreclr/vm/gcenv.ee.cpp +++ b/src/coreclr/vm/gcenv.ee.cpp @@ -1651,6 +1651,19 @@ void GCToEEInterface::AnalyzeSurvivorsFinished(size_t gcIndex, int condemnedGene s_forcedGCInProgress = false; reportGenerationBounds(); FireEtwGenAwareEnd((int)gcIndex, GetClrInstanceId()); + if (gcGenAnalysisDump) + { + EX_TRY + { +#ifdef HOST_WIN32 + GenerateCrashDump (GENAWARE_DUMP_FILE_NAME, 2, false); +#else + PAL_GenerateCoreDump (GENAWARE_DUMP_FILE_NAME, 2, false); +#endif + } + EX_CATCH {} + EX_END_CATCH(SwallowAllExceptions); + } EventPipeAdapter::PauseSession(gcGenAnalysisEventPipeSession); gcGenAnalysisState = GcGenAnalysisState::Done; EnableFinalization(true); diff --git a/src/coreclr/vm/genanalysis.cpp b/src/coreclr/vm/genanalysis.cpp index fa2fcdf0a224da..e01ea7c55e39ff 100644 --- a/src/coreclr/vm/genanalysis.cpp +++ b/src/coreclr/vm/genanalysis.cpp @@ -13,6 +13,7 @@ int64_t gcGenAnalysisGen = -1; int64_t gcGenAnalysisBytes = 0; int64_t gcGenAnalysisIndex = 0; uint32_t gcGenAnalysisBufferMB = 0; +bool gcGenAnalysisDump = false; /* static */ void GenAnalysis::Initialize() { @@ -41,6 +42,7 @@ uint32_t gcGenAnalysisBufferMB = 0; gcGenAnalysisGen = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_GCGenAnalysisGen); gcGenAnalysisIndex = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_GCGenAnalysisIndex); gcGenAnalysisBufferMB = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_EventPipeCircularMB); + gcGenAnalysisDump = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_GCGenAnalysisDump); gcGenAnalysisConfigured = GcGenAnalysisState::Enabled; } else @@ -52,13 +54,13 @@ uint32_t gcGenAnalysisBufferMB = 0; #endif { EnableGenerationalAwareSession(); - } + } } /* static */ void GenAnalysis::EnableGenerationalAwareSession() { LPCWSTR outputPath = nullptr; - outputPath = GENAWARE_FILE_NAME; + outputPath = GENAWARE_TRACE_FILE_NAME; NewArrayHolder pProviders; int providerCnt = 1; pProviders = new COR_PRF_EVENTPIPE_PROVIDER_CONFIG[providerCnt]; diff --git a/src/coreclr/vm/genanalysis.h b/src/coreclr/vm/genanalysis.h index 84d9c67d13e8bc..20b344269d1f68 100644 --- a/src/coreclr/vm/genanalysis.h +++ b/src/coreclr/vm/genanalysis.h @@ -18,7 +18,8 @@ enum GcGenAnalysisState Done = 3, }; -#define GENAWARE_FILE_NAME W("gcgenaware.nettrace") +#define GENAWARE_TRACE_FILE_NAME W("gcgenaware.nettrace") +#define GENAWARE_DUMP_FILE_NAME W("gcgenaware.dmp") #define GENAWARE_COMPLETION_FILE_NAME "gcgenaware.nettrace.completed" extern bool s_forcedGCInProgress; @@ -29,6 +30,7 @@ extern GcGenAnalysisState gcGenAnalysisConfigured; extern int64_t gcGenAnalysisGen; extern int64_t gcGenAnalysisBytes; extern int64_t gcGenAnalysisIndex; +extern bool gcGenAnalysisDump; class GenAnalysis { From 242ae8389ae8dfe7a0c271ba5db8e593be2893ba Mon Sep 17 00:00:00 2001 From: Andrew Au Date: Wed, 23 Jun 2021 15:16:05 -0700 Subject: [PATCH 2/3] Fix linux build error --- .../vm/eventing/eventpipe/ds-rt-coreclr.h | 12 +---------- src/coreclr/vm/excep.cpp | 20 +++++++++++++++++++ src/coreclr/vm/excep.h | 2 +- src/coreclr/vm/gcenv.ee.cpp | 6 +----- 4 files changed, 23 insertions(+), 17 deletions(-) diff --git a/src/coreclr/vm/eventing/eventpipe/ds-rt-coreclr.h b/src/coreclr/vm/eventing/eventpipe/ds-rt-coreclr.h index 8094d7b22d9dce..646b8f9bd8f194 100644 --- a/src/coreclr/vm/eventing/eventpipe/ds-rt-coreclr.h +++ b/src/coreclr/vm/eventing/eventpipe/ds-rt-coreclr.h @@ -195,20 +195,10 @@ ds_rt_generate_core_dump (DiagnosticsGenerateCoreDumpCommandPayload *payload) ds_ipc_result_t result = DS_IPC_E_FAIL; EX_TRY { -#ifdef HOST_WIN32 - if (GenerateCrashDump (reinterpret_cast(ds_generate_core_dump_command_payload_get_dump_name (payload)), + if (GenerateDump (reinterpret_cast(ds_generate_core_dump_command_payload_get_dump_name (payload)), static_cast(ds_generate_core_dump_command_payload_get_dump_type (payload)), (ds_generate_core_dump_command_payload_get_diagnostics (payload) != 0) ? true : false)) result = DS_IPC_S_OK; -#else - MAKE_UTF8PTR_FROMWIDE_NOTHROW (dump_name, reinterpret_cast(ds_generate_core_dump_command_payload_get_dump_name (payload))); - if (dump_name != nullptr) { - if (PAL_GenerateCoreDump (dump_name, - static_cast(ds_generate_core_dump_command_payload_get_dump_type (payload)), - (ds_generate_core_dump_command_payload_get_diagnostics (payload) != 0) ? true : false)) - result = DS_IPC_S_OK; - } -#endif } EX_CATCH {} EX_END_CATCH(SwallowAllExceptions); diff --git a/src/coreclr/vm/excep.cpp b/src/coreclr/vm/excep.cpp index 1b192e683695aa..e15d13f2de133b 100644 --- a/src/coreclr/vm/excep.cpp +++ b/src/coreclr/vm/excep.cpp @@ -4176,6 +4176,26 @@ InitializeCrashDump() #endif // HOST_WINDOWS +bool GenerateDump( + LPCWSTR dumpName, + int dumpType, + bool diag) +{ +#ifdef TARGET_UNIX + MAKE_UTF8PTR_FROMWIDE_NOTHROW (dumpNameUtf8, dumpName); + if (dumpNameUtf8 == nullptr) + { + return false; + } + else + { + return PAL_GenerateCoreDump(dumpNameUtf8, dumpType, diag); + } +#else // TARGET_UNIX + return GenerateCrashDump(dumpName, dumpType, diag); +#endif +} + //************************************************************************************ // Create crash dump if enabled and terminate process. Generates crash dumps for both // Windows and Linux if enabled. For Linux, it happens in TerminateProcess in the PAL. diff --git a/src/coreclr/vm/excep.h b/src/coreclr/vm/excep.h index 365c2d148ba2c3..f338dd76f4cb37 100644 --- a/src/coreclr/vm/excep.h +++ b/src/coreclr/vm/excep.h @@ -196,9 +196,9 @@ enum UnhandledExceptionLocation #ifdef HOST_WINDOWS void InitializeCrashDump(); -bool GenerateCrashDump(LPCWSTR dumpName, int dumpType, bool diag); void CreateCrashDumpIfEnabled(bool stackoverflow = false); #endif +bool GenerateDump(LPCWSTR dumpName, int dumpType, bool diag); // Generates crash dumps if enabled for both Windows and Linux void CrashDumpAndTerminateProcess(UINT exitCode); diff --git a/src/coreclr/vm/gcenv.ee.cpp b/src/coreclr/vm/gcenv.ee.cpp index c3cfb6bff2a5e1..d00901b3d0fdb5 100644 --- a/src/coreclr/vm/gcenv.ee.cpp +++ b/src/coreclr/vm/gcenv.ee.cpp @@ -1655,11 +1655,7 @@ void GCToEEInterface::AnalyzeSurvivorsFinished(size_t gcIndex, int condemnedGene { EX_TRY { -#ifdef HOST_WIN32 - GenerateCrashDump (GENAWARE_DUMP_FILE_NAME, 2, false); -#else - PAL_GenerateCoreDump (GENAWARE_DUMP_FILE_NAME, 2, false); -#endif + GenerateDump (GENAWARE_DUMP_FILE_NAME, 2, false); } EX_CATCH {} EX_END_CATCH(SwallowAllExceptions); From b1d5eaa59c3b5db9706c5d73ecfc3e316056973a Mon Sep 17 00:00:00 2001 From: Andrew Au Date: Thu, 24 Jun 2021 11:47:32 -0700 Subject: [PATCH 3/3] Make traces optional --- src/coreclr/inc/clrconfigvalues.h | 3 ++- src/coreclr/vm/excep.cpp | 2 +- src/coreclr/vm/finalizerthread.cpp | 11 ++++++----- src/coreclr/vm/gcenv.ee.cpp | 19 +++++++++++-------- src/coreclr/vm/genanalysis.cpp | 11 ++++++++++- src/coreclr/vm/genanalysis.h | 1 + 6 files changed, 31 insertions(+), 16 deletions(-) diff --git a/src/coreclr/inc/clrconfigvalues.h b/src/coreclr/inc/clrconfigvalues.h index 222ad17dd70043..0d2a1db98e4717 100644 --- a/src/coreclr/inc/clrconfigvalues.h +++ b/src/coreclr/inc/clrconfigvalues.h @@ -722,7 +722,8 @@ RETAIL_CONFIG_DWORD_INFO(INTERNAL_GCGenAnalysisGen, W("GCGenAnalysisGen"), 0, "T RETAIL_CONFIG_DWORD_INFO(INTERNAL_GCGenAnalysisBytes, W("GCGenAnalysisBytes"), 0, "The number of bytes to trigger generational aware analysis") RETAIL_CONFIG_DWORD_INFO(INTERNAL_GCGenAnalysisIndex, W("GCGenAnalysisIndex"), 0, "The gc index to trigger generational aware analysis") RETAIL_CONFIG_STRING_INFO(INTERNAL_GCGenAnalysisCmd, W("GCGenAnalysisCmd"), "An optional filter to match with the command line used to spawn the process") -RETAIL_CONFIG_DWORD_INFO(INTERNAL_GCGenAnalysisDump, W("GCGenAnalysisDump"), 0, "Enable/Disable capturing a dump as well as the traces") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_GCGenAnalysisTrace, W("GCGenAnalysisTrace"), 1, "Enable/Disable capturing a trace") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_GCGenAnalysisDump, W("GCGenAnalysisDump"), 0, "Enable/Disable capturing a dump") // // Diagnostics Ports diff --git a/src/coreclr/vm/excep.cpp b/src/coreclr/vm/excep.cpp index e15d13f2de133b..a1fdf255a5ce01 100644 --- a/src/coreclr/vm/excep.cpp +++ b/src/coreclr/vm/excep.cpp @@ -4193,7 +4193,7 @@ bool GenerateDump( } #else // TARGET_UNIX return GenerateCrashDump(dumpName, dumpType, diag); -#endif +#endif // TARGET_UNIX } //************************************************************************************ diff --git a/src/coreclr/vm/finalizerthread.cpp b/src/coreclr/vm/finalizerthread.cpp index a303400cbd7447..1e4dbf913c898e 100644 --- a/src/coreclr/vm/finalizerthread.cpp +++ b/src/coreclr/vm/finalizerthread.cpp @@ -274,14 +274,15 @@ VOID FinalizerThread::FinalizerThreadWorker(void *args) if (gcGenAnalysisState == GcGenAnalysisState::Done) { gcGenAnalysisState = GcGenAnalysisState::Disabled; - EventPipeAdapter::Disable(gcGenAnalysisEventPipeSessionId); - // Writing an empty file to indicate completion - fclose(fopen(GENAWARE_COMPLETION_FILE_NAME,"w+")); -#ifdef GEN_ANALYSIS_STRESS + if (gcGenAnalysisTrace) { + EventPipeAdapter::Disable(gcGenAnalysisEventPipeSessionId); +#ifdef GEN_ANALYSIS_STRESS GenAnalysis::EnableGenerationalAwareSession(); - } #endif + } + // Writing an empty file to indicate completion + fclose(fopen(GENAWARE_COMPLETION_FILE_NAME,"w+")); } if (!bPriorityBoosted) diff --git a/src/coreclr/vm/gcenv.ee.cpp b/src/coreclr/vm/gcenv.ee.cpp index d00901b3d0fdb5..82d4ccbd308cbb 100644 --- a/src/coreclr/vm/gcenv.ee.cpp +++ b/src/coreclr/vm/gcenv.ee.cpp @@ -1644,13 +1644,17 @@ void GCToEEInterface::AnalyzeSurvivorsFinished(size_t gcIndex, int condemnedGene if ((condemnedGeneration == gcGenAnalysisGen) && (promoted_bytes > (uint64_t)gcGenAnalysisBytes) && (gcIndex > (uint64_t)gcGenAnalysisIndex)) #endif { - EventPipeAdapter::ResumeSession(gcGenAnalysisEventPipeSession); - FireEtwGenAwareBegin((int)gcIndex, GetClrInstanceId()); - s_forcedGCInProgress = true; - GCProfileWalkHeap(true); - s_forcedGCInProgress = false; - reportGenerationBounds(); - FireEtwGenAwareEnd((int)gcIndex, GetClrInstanceId()); + if (gcGenAnalysisTrace) + { + EventPipeAdapter::ResumeSession(gcGenAnalysisEventPipeSession); + FireEtwGenAwareBegin((int)gcIndex, GetClrInstanceId()); + s_forcedGCInProgress = true; + GCProfileWalkHeap(true); + s_forcedGCInProgress = false; + reportGenerationBounds(); + FireEtwGenAwareEnd((int)gcIndex, GetClrInstanceId()); + EventPipeAdapter::PauseSession(gcGenAnalysisEventPipeSession); + } if (gcGenAnalysisDump) { EX_TRY @@ -1660,7 +1664,6 @@ void GCToEEInterface::AnalyzeSurvivorsFinished(size_t gcIndex, int condemnedGene EX_CATCH {} EX_END_CATCH(SwallowAllExceptions); } - EventPipeAdapter::PauseSession(gcGenAnalysisEventPipeSession); gcGenAnalysisState = GcGenAnalysisState::Done; EnableFinalization(true); } diff --git a/src/coreclr/vm/genanalysis.cpp b/src/coreclr/vm/genanalysis.cpp index e01ea7c55e39ff..65f37375c33c34 100644 --- a/src/coreclr/vm/genanalysis.cpp +++ b/src/coreclr/vm/genanalysis.cpp @@ -13,6 +13,7 @@ int64_t gcGenAnalysisGen = -1; int64_t gcGenAnalysisBytes = 0; int64_t gcGenAnalysisIndex = 0; uint32_t gcGenAnalysisBufferMB = 0; +bool gcGenAnalysisTrace = true; bool gcGenAnalysisDump = false; /* static */ void GenAnalysis::Initialize() @@ -42,6 +43,7 @@ bool gcGenAnalysisDump = false; gcGenAnalysisGen = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_GCGenAnalysisGen); gcGenAnalysisIndex = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_GCGenAnalysisIndex); gcGenAnalysisBufferMB = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_EventPipeCircularMB); + gcGenAnalysisTrace = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_GCGenAnalysisTrace); gcGenAnalysisDump = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_GCGenAnalysisDump); gcGenAnalysisConfigured = GcGenAnalysisState::Enabled; } @@ -53,7 +55,14 @@ bool gcGenAnalysisDump = false; if ((gcGenAnalysisConfigured == GcGenAnalysisState::Enabled) && (gcGenAnalysisState == GcGenAnalysisState::Uninitialized)) #endif { - EnableGenerationalAwareSession(); + if (gcGenAnalysisTrace) + { + EnableGenerationalAwareSession(); + } + if (gcGenAnalysisDump) + { + gcGenAnalysisState = GcGenAnalysisState::Enabled; + } } } diff --git a/src/coreclr/vm/genanalysis.h b/src/coreclr/vm/genanalysis.h index 20b344269d1f68..8253aa3eab047d 100644 --- a/src/coreclr/vm/genanalysis.h +++ b/src/coreclr/vm/genanalysis.h @@ -30,6 +30,7 @@ extern GcGenAnalysisState gcGenAnalysisConfigured; extern int64_t gcGenAnalysisGen; extern int64_t gcGenAnalysisBytes; extern int64_t gcGenAnalysisIndex; +extern bool gcGenAnalysisTrace; extern bool gcGenAnalysisDump; class GenAnalysis