//
// Generational Aware Analysis
//
-RETAIL_CONFIG_DWORD_INFO(INTERNAL_GCGenAnalysisGen, W("GCGenAnalysisGen"), 0, "The generation to trigger generational aware analysis")
-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_GCGenAnalysisTrace, W("GCGenAnalysisTrace"), 1, "Enable/Disable capturing a trace")
-RETAIL_CONFIG_DWORD_INFO(INTERNAL_GCGenAnalysisDump, W("GCGenAnalysisDump"), 0, "Enable/Disable capturing a dump")
+RETAIL_CONFIG_DWORD_INFO(EXTERNAL_GCGenAnalysisGen, W("GCGenAnalysisGen"), 0, "The generation to trigger generational aware analysis")
+RETAIL_CONFIG_DWORD_INFO(EXTERNAL_GCGenAnalysisBytes, W("GCGenAnalysisBytes"), 0, "The number of bytes to trigger generational aware analysis")
+RETAIL_CONFIG_DWORD_INFO(EXTERNAL_GCGenAnalysisTimeUSec, W("GCGenAnalysisTimeUSec"), 0, "The number of microseconds to trigger generational aware analysis")
+RETAIL_CONFIG_DWORD_INFO(EXTERNAL_GCGenAnalysisTimeMSec, W("GCGenAnalysisTimeMSec"), 0, "The number of milliseconds to trigger generational aware analysis")
+RETAIL_CONFIG_DWORD_INFO(EXTERNAL_GCGenAnalysisIndex, W("GCGenAnalysisIndex"), 0, "The gc index to trigger generational aware analysis")
+RETAIL_CONFIG_STRING_INFO(EXTERNAL_GCGenAnalysisCmd, W("GCGenAnalysisCmd"), "An optional filter to match with the command line used to spawn the process")
+RETAIL_CONFIG_DWORD_INFO(EXTERNAL_GCGenAnalysisTrace, W("GCGenAnalysisTrace"), 1, "Enable/Disable capturing a trace")
+RETAIL_CONFIG_DWORD_INFO(EXTERNAL_GCGenAnalysisDump, W("GCGenAnalysisDump"), 0, "Enable/Disable capturing a dump")
//
// Diagnostics Ports
return SystemDomain::System()->GetTotalNumSizedRefHandles();
}
+NormalizedTimer analysisTimer;
+
+bool GenAwareMatchingGeneration(int condemnedGeneration)
+{
+ return (gcGenAnalysisState == GcGenAnalysisState::Enabled) && (condemnedGeneration == gcGenAnalysisGen);
+}
+
+bool GenAwareMatchingCondition(size_t gcIndex, int condemnedGeneration, uint64_t promoted_bytes, uint64_t elapsed)
+{
+ if (!GenAwareMatchingGeneration(condemnedGeneration))
+ {
+ return false;
+ }
+ if (gcIndex < (uint64_t)gcGenAnalysisIndex)
+ {
+ return false;
+ }
+ if ((gcGenAnalysisBytes > 0) && (promoted_bytes <= gcGenAnalysisBytes))
+ {
+ return false;
+ }
+ if ((gcGenAnalysisTime > 0) && (elapsed <= gcGenAnalysisTime))
+ {
+ return false;
+ }
+ return true;
+}
bool GCToEEInterface::AnalyzeSurvivorsRequested(int condemnedGeneration)
{
LIMITED_METHOD_CONTRACT;
+ if (GenAwareMatchingGeneration(condemnedGeneration) && gcGenAnalysisTime > 0)
+ {
+ analysisTimer.Start();
+ }
+
// Is the list active?
GcNotifications gn(g_pGcNotificationTable);
if (gn.IsActive())
{
LIMITED_METHOD_CONTRACT;
+ uint64_t elapsed = 0;
+ if (GenAwareMatchingGeneration(condemnedGeneration) && gcGenAnalysisTime > 0)
+ {
+ analysisTimer.Stop();
+ elapsed = analysisTimer.Elapsed100nsTicks();
+ }
+
// Is the list active?
GcNotifications gn(g_pGcNotificationTable);
if (gn.IsActive())
if (gcGenAnalysisState == GcGenAnalysisState::Enabled)
{
#ifndef GEN_ANALYSIS_STRESS
- if ((condemnedGeneration == gcGenAnalysisGen) && (promoted_bytes > (uint64_t)gcGenAnalysisBytes) && (gcIndex > (uint64_t)gcGenAnalysisIndex))
+ if (GenAwareMatchingCondition(gcIndex, condemnedGeneration, promoted_bytes, elapsed))
#endif
{
if (gcGenAnalysisTrace)
uint64_t gcGenAnalysisEventPipeSessionId = (uint64_t)-1;
GcGenAnalysisState gcGenAnalysisConfigured = GcGenAnalysisState::Uninitialized;
int64_t gcGenAnalysisGen = -1;
-int64_t gcGenAnalysisBytes = 0;
+uint64_t gcGenAnalysisBytes = 0;
+uint64_t gcGenAnalysisTime = 0;
int64_t gcGenAnalysisIndex = 0;
uint32_t gcGenAnalysisBufferMB = 0;
bool gcGenAnalysisTrace = true;
if (gcGenAnalysisConfigured == GcGenAnalysisState::Uninitialized)
{
bool match = true;
- CLRConfigStringHolder gcGenAnalysisCmd(CLRConfig::GetConfigValue(CLRConfig::INTERNAL_GCGenAnalysisCmd));
+ CLRConfigStringHolder gcGenAnalysisCmd(CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_GCGenAnalysisCmd));
if (gcGenAnalysisCmd != nullptr)
{
// Get the managed command line.
{
match = false;
}
- if (match && !CLRConfig::IsConfigOptionSpecified(W("GCGenAnalysisBytes")))
+ if (match && !CLRConfig::IsConfigOptionSpecified(W("GCGenAnalysisBytes")) &&
+ !CLRConfig::IsConfigOptionSpecified(W("GCGenAnalysisTimeUSec")) &&
+ !CLRConfig::IsConfigOptionSpecified(W("GCGenAnalysisTimeMSec")))
{
match = false;
}
if (match)
{
- gcGenAnalysisBytes = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_GCGenAnalysisBytes);
- gcGenAnalysisGen = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_GCGenAnalysisGen);
- gcGenAnalysisIndex = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_GCGenAnalysisIndex);
+ gcGenAnalysisBytes = CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_GCGenAnalysisBytes);
+ gcGenAnalysisTime = CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_GCGenAnalysisTimeUSec) * 10;
+ if (gcGenAnalysisTime == 0)
+ {
+ gcGenAnalysisTime = CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_GCGenAnalysisTimeMSec) * 10000;
+ }
+ gcGenAnalysisGen = CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_GCGenAnalysisGen);
+ gcGenAnalysisIndex = CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_GCGenAnalysisIndex);
gcGenAnalysisBufferMB = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_EventPipeCircularMB);
- gcGenAnalysisTrace = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_GCGenAnalysisTrace);
- gcGenAnalysisDump = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_GCGenAnalysisDump);
+ gcGenAnalysisTrace = CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_GCGenAnalysisTrace);
+ gcGenAnalysisDump = CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_GCGenAnalysisDump);
gcGenAnalysisConfigured = GcGenAnalysisState::Enabled;
}
else
extern uint64_t gcGenAnalysisEventPipeSessionId;
extern GcGenAnalysisState gcGenAnalysisConfigured;
extern int64_t gcGenAnalysisGen;
-extern int64_t gcGenAnalysisBytes;
+extern uint64_t gcGenAnalysisBytes;
+extern uint64_t gcGenAnalysisTime;
extern int64_t gcGenAnalysisIndex;
extern bool gcGenAnalysisTrace;
extern bool gcGenAnalysisDump;