Mark time trigger (#58261)
authorAndrew Au <andrewau@microsoft.com>
Wed, 22 Sep 2021 20:46:51 +0000 (13:46 -0700)
committerGitHub <noreply@github.com>
Wed, 22 Sep 2021 20:46:51 +0000 (13:46 -0700)
src/coreclr/inc/clrconfigvalues.h
src/coreclr/vm/gcenv.ee.cpp
src/coreclr/vm/genanalysis.cpp
src/coreclr/vm/genanalysis.h

index 60457fd..d7294d2 100644 (file)
@@ -680,12 +680,14 @@ RETAIL_CONFIG_DWORD_INFO(INTERNAL_EventPipeOutputStreaming, W("EventPipeOutputSt
 //
 // 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
index f62a282..d8e2542 100644 (file)
@@ -1601,11 +1601,43 @@ uint32_t GCToEEInterface::GetTotalNumSizedRefHandles()
     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())
@@ -1624,6 +1656,13 @@ void GCToEEInterface::AnalyzeSurvivorsFinished(size_t gcIndex, int condemnedGene
 {
     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())
@@ -1638,7 +1677,7 @@ void GCToEEInterface::AnalyzeSurvivorsFinished(size_t gcIndex, int condemnedGene
     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)
index 65f3737..6bf6d9b 100644 (file)
@@ -10,7 +10,8 @@ EventPipeSession* gcGenAnalysisEventPipeSession = nullptr;
 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;
@@ -22,7 +23,7 @@ bool gcGenAnalysisDump = false;
     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.
@@ -33,18 +34,25 @@ bool gcGenAnalysisDump = false;
         {
             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
index 8253aa3..aca019f 100644 (file)
@@ -28,7 +28,8 @@ extern EventPipeSession* gcGenAnalysisEventPipeSession;
 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;