summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaoni Stephens <Maoni0@users.noreply.github.com>2019-02-27 16:35:03 -0800
committerGitHub <noreply@github.com>2019-02-27 16:35:03 -0800
commitea099fba14da84c3e81eb8d5ad93ecae7c659489 (patch)
tree1bc50d932d45bf72a4680249365557c93159ccc2
parentd0743a467c1df473f511ca0ab73eaf1d119a309b (diff)
downloadcoreclr-ea099fba14da84c3e81eb8d5ad93ecae7c659489.tar.gz
coreclr-ea099fba14da84c3e81eb8d5ad93ecae7c659489.tar.bz2
coreclr-ea099fba14da84c3e81eb8d5ad93ecae7c659489.zip
added a lightweight GC profiling option (#22866)
added a profiling event mask in the high 32-bit, COR_PRF_HIGH_BASIC_GC, for basic GC monitoring. it can be set via `ICorProfilerInfo5::SetEventMask2`. all this gives you is * GC start callback * GC end callback * update generational bounds note that one different behavior between this and the existing COR_PRF_MONITOR_GC is, aside from the obvious that it doesn't give you any info beyond the above, is that the GC end callback + update generational bounds are enabled for _all_ GCs, not just non concurrent GCs. I kept the behavior the same for COR_PRF_MONITOR_GC because I don't want to risk breaking existing profiling tools that do not anticipate these for concurrent GCs.
-rw-r--r--src/inc/corprof.idl6
-rw-r--r--src/inc/profilepriv.inl14
-rw-r--r--src/pal/prebuilt/inc/corprof.h3
-rw-r--r--src/vm/eetoprofinterfaceimpl.cpp4
-rw-r--r--src/vm/gcenv.ee.cpp9
-rw-r--r--src/vm/proftoeeinterfaceimpl.cpp6
6 files changed, 34 insertions, 8 deletions
diff --git a/src/inc/corprof.idl b/src/inc/corprof.idl
index feeac08c51..1062248299 100644
--- a/src/inc/corprof.idl
+++ b/src/inc/corprof.idl
@@ -627,9 +627,13 @@ typedef enum
COR_PRF_HIGH_DISABLE_TIERED_COMPILATION = 0x00000008,
+ COR_PRF_HIGH_BASIC_GC = 0x00000010,
+
COR_PRF_HIGH_REQUIRE_PROFILE_IMAGE = 0,
- COR_PRF_HIGH_ALLOWABLE_AFTER_ATTACH = COR_PRF_HIGH_IN_MEMORY_SYMBOLS_UPDATED | COR_PRF_HIGH_MONITOR_DYNAMIC_FUNCTION_UNLOADS,
+ COR_PRF_HIGH_ALLOWABLE_AFTER_ATTACH = COR_PRF_HIGH_IN_MEMORY_SYMBOLS_UPDATED |
+ COR_PRF_HIGH_MONITOR_DYNAMIC_FUNCTION_UNLOADS |
+ COR_PRF_HIGH_BASIC_GC,
// MONITOR_IMMUTABLE represents all flags that may only be set during initialization.
// Trying to change any of these flags elsewhere will result in a
diff --git a/src/inc/profilepriv.inl b/src/inc/profilepriv.inl
index ac52521b36..095c9f9368 100644
--- a/src/inc/profilepriv.inl
+++ b/src/inc/profilepriv.inl
@@ -727,6 +727,20 @@ inline BOOL CORProfilerDisableTieredCompilation()
((&g_profControlBlock)->dwEventMaskHigh & COR_PRF_HIGH_DISABLE_TIERED_COMPILATION));
}
+inline BOOL CORProfilerTrackBasicGC()
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ CANNOT_TAKE_LOCK;
+ }
+ CONTRACTL_END;
+
+ return (CORProfilerPresent() &&
+ ((&g_profControlBlock)->dwEventMaskHigh & COR_PRF_HIGH_BASIC_GC));
+}
+
#if defined(PROFILING_SUPPORTED) && !defined(CROSSGEN_COMPILE)
#if defined(FEATURE_PROFAPI_ATTACH_DETACH)
diff --git a/src/pal/prebuilt/inc/corprof.h b/src/pal/prebuilt/inc/corprof.h
index 2e18c12283..c7839ddbcf 100644
--- a/src/pal/prebuilt/inc/corprof.h
+++ b/src/pal/prebuilt/inc/corprof.h
@@ -544,8 +544,9 @@ enum __MIDL___MIDL_itf_corprof_0000_0000_0006
COR_PRF_HIGH_IN_MEMORY_SYMBOLS_UPDATED = 0x2,
COR_PRF_HIGH_MONITOR_DYNAMIC_FUNCTION_UNLOADS = 0x4,
COR_PRF_HIGH_DISABLE_TIERED_COMPILATION = 0x8,
+ COR_PRF_HIGH_BASIC_GC = 0x10,
COR_PRF_HIGH_REQUIRE_PROFILE_IMAGE = 0,
- COR_PRF_HIGH_ALLOWABLE_AFTER_ATTACH = ( COR_PRF_HIGH_IN_MEMORY_SYMBOLS_UPDATED | COR_PRF_HIGH_MONITOR_DYNAMIC_FUNCTION_UNLOADS ) ,
+ COR_PRF_HIGH_ALLOWABLE_AFTER_ATTACH = ( COR_PRF_HIGH_IN_MEMORY_SYMBOLS_UPDATED | COR_PRF_HIGH_MONITOR_DYNAMIC_FUNCTION_UNLOADS | COR_PRF_HIGH_BASIC_GC) ,
COR_PRF_HIGH_MONITOR_IMMUTABLE = COR_PRF_HIGH_DISABLE_TIERED_COMPILATION
} COR_PRF_HIGH_MONITOR;
diff --git a/src/vm/eetoprofinterfaceimpl.cpp b/src/vm/eetoprofinterfaceimpl.cpp
index 1b06eaeb94..40b863f93e 100644
--- a/src/vm/eetoprofinterfaceimpl.cpp
+++ b/src/vm/eetoprofinterfaceimpl.cpp
@@ -6196,7 +6196,7 @@ HRESULT EEToProfInterfaceImpl::GarbageCollectionStarted(int cGenerations, BOOL g
LL_INFO10000,
"**PROF: GarbageCollectionStarted.\n"));
- _ASSERTE(!GCHeapUtilities::GetGCHeap()->IsConcurrentGCEnabled());
+ _ASSERTE(!CORProfilerTrackGC() || !GCHeapUtilities::GetGCHeap()->IsConcurrentGCEnabled());
{
// All callbacks are really NOTHROW, but that's enforced partially by the profiler,
@@ -6233,7 +6233,7 @@ HRESULT EEToProfInterfaceImpl::GarbageCollectionFinished()
LL_INFO10000,
"**PROF: GarbageCollectionFinished.\n"));
- _ASSERTE(!GCHeapUtilities::GetGCHeap()->IsConcurrentGCEnabled());
+ _ASSERTE(!CORProfilerTrackGC() || !GCHeapUtilities::GetGCHeap()->IsConcurrentGCEnabled());
{
// All callbacks are really NOTHROW, but that's enforced partially by the profiler,
diff --git a/src/vm/gcenv.ee.cpp b/src/vm/gcenv.ee.cpp
index 6ecd325a08..f27d3f32c8 100644
--- a/src/vm/gcenv.ee.cpp
+++ b/src/vm/gcenv.ee.cpp
@@ -742,7 +742,7 @@ void GCToEEInterface::DiagGCStart(int gen, bool isInduced)
void GCToEEInterface::DiagUpdateGenerationBounds()
{
#ifdef GC_PROFILING
- if (CORProfilerTrackGC())
+ if (CORProfilerTrackGC() || CORProfilerTrackBasicGC())
UpdateGenerationBounds();
#endif // GC_PROFILING
}
@@ -750,9 +750,16 @@ void GCToEEInterface::DiagUpdateGenerationBounds()
void GCToEEInterface::DiagGCEnd(size_t index, int gen, int reason, bool fConcurrent)
{
#ifdef GC_PROFILING
+ // We were only doing generation bounds and GC finish callback for non concurrent GCs so
+ // I am keeping that behavior to not break profilers. But if BasicGC monitoring is enabled
+ // we will do these for all GCs.
if (!fConcurrent)
{
GCProfileWalkHeap();
+ }
+
+ if (CORProfilerTrackBasicGC() || (!fConcurrent && CORProfilerTrackGC()))
+ {
DiagUpdateGenerationBounds();
GarbageCollectionFinishedCallback();
}
diff --git a/src/vm/proftoeeinterfaceimpl.cpp b/src/vm/proftoeeinterfaceimpl.cpp
index c142651496..663b82f403 100644
--- a/src/vm/proftoeeinterfaceimpl.cpp
+++ b/src/vm/proftoeeinterfaceimpl.cpp
@@ -684,7 +684,7 @@ void __stdcall GarbageCollectionStartedCallback(int generation, BOOL induced)
// Notify the profiler of start of the collection
{
- BEGIN_PIN_PROFILER(CORProfilerTrackGC());
+ BEGIN_PIN_PROFILER(CORProfilerTrackGC() || CORProfilerTrackBasicGC());
BOOL generationCollected[COR_PRF_GC_LARGE_OBJECT_HEAP+1];
if (generation == COR_PRF_GC_GEN_2)
generation = COR_PRF_GC_LARGE_OBJECT_HEAP;
@@ -718,7 +718,7 @@ void __stdcall GarbageCollectionFinishedCallback()
#ifdef PROFILING_SUPPORTED
// Notify the profiler of end of the collection
{
- BEGIN_PIN_PROFILER(CORProfilerTrackGC());
+ BEGIN_PIN_PROFILER(CORProfilerTrackGC() || CORProfilerTrackBasicGC());
g_profControlBlock.pProfInterface->GarbageCollectionFinished();
END_PIN_PROFILER();
}
@@ -858,7 +858,7 @@ void __stdcall UpdateGenerationBounds()
#ifdef PROFILING_SUPPORTED
// Notify the profiler of start of the collection
- if (CORProfilerTrackGC())
+ if (CORProfilerTrackGC() || CORProfilerTrackBasicGC())
{
// generate a new generation table
GenerationTable *newGenerationTable = new (nothrow) GenerationTable();