Add option to only notify profiler of LOH allocations (#24291)
authorMukul Sabharwal <mjsabby@gmail.com>
Tue, 7 May 2019 03:53:14 +0000 (20:53 -0700)
committerDavid Mason <davmason@microsoft.com>
Tue, 7 May 2019 03:53:13 +0000 (20:53 -0700)
src/inc/corprof.idl
src/inc/profilepriv.inl
src/pal/prebuilt/inc/corprof.h
src/vm/eeprofinterfaces.inl
src/vm/gchelpers.cpp
src/vm/proftoeeinterfaceimpl.cpp
src/vm/proftoeeinterfaceimpl.h

index b34fd31..fa1dfe8 100644 (file)
@@ -634,10 +634,14 @@ typedef enum
 
     COR_PRF_HIGH_REQUIRE_PROFILE_IMAGE              = 0,
 
+    // Enables the large object allocation monitoring according to the LOH threshold.
+    COR_PRF_HIGH_MONITOR_LARGEOBJECT_ALLOCATED      = 0x00000040,
+
     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_GC_MOVED_OBJECTS,
+                                                      COR_PRF_HIGH_MONITOR_GC_MOVED_OBJECTS |
+                                                      COR_PRF_HIGH_MONITOR_LARGEOBJECT_ALLOCATED,
 
     // MONITOR_IMMUTABLE represents all flags that may only be set during initialization.
     // Trying to change any of these flags elsewhere will result in a
@@ -3932,6 +3936,9 @@ interface ICorProfilerInfo10 : ICorProfilerInfo9
 
     // Given an ObjectID, determines whether it is in a read only segment.
     HRESULT IsFrozenObject(ObjectID objectId, BOOL *pbFrozen);
+
+    // Gets the value of the configured LOH Threshold.
+    HRESULT GetLOHObjectSizeThreshold(DWORD *pThreshold);
 }
 
 /*
index 413090f..9126241 100644 (file)
@@ -264,6 +264,21 @@ inline BOOL CORProfilerTrackAllocations()
             ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_OBJECT_ALLOCATED));
 }
 
+inline BOOL CORProfilerTrackLargeAllocations()
+{
+    CONTRACTL
+    {
+        NOTHROW;
+        GC_NOTRIGGER;
+        CANNOT_TAKE_LOCK;
+    }
+    CONTRACTL_END;
+
+    return
+            (CORProfilerPresent() &&
+            ((&g_profControlBlock)->dwEventMaskHigh & COR_PRF_HIGH_MONITOR_LARGEOBJECT_ALLOCATED));
+}
+
 inline BOOL CORProfilerEnableRejit()
 {
     CONTRACTL
index 0963b03..9edfc35 100644 (file)
@@ -547,7 +547,8 @@ enum __MIDL___MIDL_itf_corprof_0000_0000_0006
         COR_PRF_HIGH_BASIC_GC  = 0x10,
         COR_PRF_HIGH_MONITOR_GC_MOVED_OBJECTS  = 0x20,
         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_BASIC_GC )  | COR_PRF_HIGH_MONITOR_GC_MOVED_OBJECTS ) ,
+        COR_PRF_HIGH_MONITOR_LARGEOBJECT_ALLOCATED     = 0x40,
+        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_GC_MOVED_OBJECTS )  | COR_PRF_HIGH_MONITOR_LARGEOBJECT_ALLOCATED ) ,
         COR_PRF_HIGH_MONITOR_IMMUTABLE = COR_PRF_HIGH_DISABLE_TIERED_COMPILATION
     }  COR_PRF_HIGH_MONITOR;
 
@@ -15195,6 +15196,9 @@ EXTERN_C const IID IID_ICorProfilerInfo10;
             ObjectID objectId,
             BOOL *pbFrozen) = 0;
         
+        virtual HRESULT STDMETHODCALLTYPE GetLOHObjectSizeThreshold( 
+            DWORD *pThreshold) = 0;
+        
     };
     
     
@@ -15793,6 +15797,10 @@ EXTERN_C const IID IID_ICorProfilerInfo10;
             ObjectID objectId,
             BOOL *pbFrozen);
         
+        HRESULT ( STDMETHODCALLTYPE *GetLOHObjectSizeThreshold )( 
+            ICorProfilerInfo10 * This,
+            DWORD *pThreshold);
+        
         END_INTERFACE
     } ICorProfilerInfo10Vtbl;
 
@@ -16101,6 +16109,9 @@ EXTERN_C const IID IID_ICorProfilerInfo10;
 #define ICorProfilerInfo10_IsFrozenObject(This,objectId,pbFrozen)      \
     ( (This)->lpVtbl -> IsFrozenObject(This,objectId,pbFrozen) ) 
 
+#define ICorProfilerInfo10_GetLOHObjectSizeThreshold(This,pThreshold)  \
+    ( (This)->lpVtbl -> GetLOHObjectSizeThreshold(This,pThreshold) ) 
+
 #endif /* COBJMACROS */
 
 
index a080002..ea29ede 100644 (file)
@@ -23,5 +23,14 @@ FORCEINLINE BOOL TrackAllocations()
 #endif // PROFILING_SUPPORTED
 }
 
+FORCEINLINE BOOL TrackLargeAllocations()
+{
+#ifdef PROFILING_SUPPORTED
+    return CORProfilerTrackLargeAllocations();
+#else
+    return FALSE;
+#endif // PROFILING_SUPPORTED
+}
+
 
 #endif
index 8cb4fee..22a1a5d 100644 (file)
@@ -542,10 +542,13 @@ OBJECTREF AllocateSzArray(MethodTable* pArrayMT, INT32 cElements, GC_ALLOC_FLAGS
     // Initialize Object
     orArray->m_NumComponents = cElements;
 
+    bool bProfilerNotifyLargeAllocation = false;
+
     if (bAllocateInLargeHeap || 
         (totalSize >= g_pConfig->GetGCLOHThreshold()))
     {
         GCHeapUtilities::GetGCHeap()->PublishObject((BYTE*)orArray);
+        bProfilerNotifyLargeAllocation = TrackLargeAllocations();
     }
 
 #ifdef  _LOGALLOC
@@ -566,7 +569,7 @@ OBJECTREF AllocateSzArray(MethodTable* pArrayMT, INT32 cElements, GC_ALLOC_FLAGS
 
     // Notify the profiler of the allocation
     // do this after initializing bounds so callback has size information
-    if (TrackAllocations())
+    if (TrackAllocations() || bProfilerNotifyLargeAllocation)
     {
         ProfileTrackArrayAlloc(orArray);
     }
@@ -768,10 +771,13 @@ OBJECTREF AllocateArrayEx(MethodTable *pArrayMT, INT32 *pArgs, DWORD dwNumArgs,
     // Initialize Object
     orArray->m_NumComponents = cElements;
 
+    bool bProfilerNotifyLargeAllocation = false;
+
     if (bAllocateInLargeHeap || 
         (totalSize >= g_pConfig->GetGCLOHThreshold()))
     {
         GCHeapUtilities::GetGCHeap()->PublishObject((BYTE*)orArray);
+        bProfilerNotifyLargeAllocation = TrackLargeAllocations();
     }
 
 #ifdef  _LOGALLOC
@@ -804,7 +810,7 @@ OBJECTREF AllocateArrayEx(MethodTable *pArrayMT, INT32 *pArgs, DWORD dwNumArgs,
 
     // Notify the profiler of the allocation
     // do this after initializing bounds so callback has size information
-    if (TrackAllocations())
+    if (TrackAllocations() || bProfilerNotifyLargeAllocation)
     {
         ProfileTrackArrayAlloc(orArray);
     }
@@ -988,13 +994,15 @@ STRINGREF AllocateString( DWORD cchStringLength )
     orObject->SetMethodTable( g_pStringClass );
     orObject->SetStringLength( cchStringLength );
 
+    bool bProfilerNotifyLargeAllocation = false;
     if (ObjectSize >= g_pConfig->GetGCLOHThreshold())
     {
+        bProfilerNotifyLargeAllocation = TrackLargeAllocations();
         GCHeapUtilities::GetGCHeap()->PublishObject((BYTE*)orObject);
     }
 
     // Notify the profiler of the allocation
-    if (TrackAllocations())
+    if (TrackAllocations() || bProfilerNotifyLargeAllocation)
     {
         OBJECTREF objref = ObjectToOBJECTREF((Object*)orObject);
         GCPROTECT_BEGIN(objref);
@@ -1062,13 +1070,16 @@ UTF8STRINGREF AllocateUtf8String(DWORD cchStringLength)
     orObject->SetMethodTable(g_pUtf8StringClass);
     orObject->SetLength(cchStringLength);
 
-    if (ObjectSize >= LARGE_OBJECT_SIZE)
+    bool bProfilerNotifyLargeAllocation = false;
+
+    if (ObjectSize >= g_pConfig->GetGCLOHThreshold())
     {
         GCHeapUtilities::GetGCHeap()->PublishObject((BYTE*)orObject);
+        bProfilerNotifyLargeAllocation = TrackLargeAllocations();
     }
 
     // Notify the profiler of the allocation
-    if (TrackAllocations())
+    if (TrackAllocations() || bProfilerNotifyLargeAllocation)
     {
         OBJECTREF objref = ObjectToOBJECTREF((Object*)orObject);
         GCPROTECT_BEGIN(objref);
@@ -1192,9 +1203,11 @@ OBJECTREF AllocateObject(MethodTable *pMT
         // verify zero'd memory (at least for sync block)
         _ASSERTE( orObject->HasEmptySyncBlockInfo() );
 
+        bool bProfilerNotifyLargeAllocation = false;
         if ((baseSize >= g_pConfig->GetGCLOHThreshold()))
         {
             orObject->SetMethodTableForLargeObject(pMT);
+            bProfilerNotifyLargeAllocation = TrackLargeAllocations();
             GCHeapUtilities::GetGCHeap()->PublishObject((BYTE*)orObject);
         }
         else
@@ -1203,7 +1216,7 @@ OBJECTREF AllocateObject(MethodTable *pMT
         }
 
         // Notify the profiler of the allocation
-        if (TrackAllocations())
+        if (TrackAllocations() || bProfilerNotifyLargeAllocation)
         {
             OBJECTREF objref = ObjectToOBJECTREF((Object*)orObject);
             GCPROTECT_BEGIN(objref);
index 467ab29..b5ade59 100644 (file)
@@ -649,7 +649,7 @@ void __stdcall ProfilerObjectAllocatedCallback(OBJECTREF objref, ClassID classId
     // Notify the profiler of the allocation
 
     {
-        BEGIN_PIN_PROFILER(CORProfilerTrackAllocations());
+        BEGIN_PIN_PROFILER(CORProfilerTrackAllocations() || CORProfilerTrackLargeAllocations());
         // Note that for generic code we always return uninstantiated ClassIDs and FunctionIDs.
         // Thus we strip any instantiations of the ClassID (which is really a type handle) here.
         g_profControlBlock.pProfInterface->ObjectAllocated(
@@ -6893,6 +6893,46 @@ HRESULT ProfToEEInterfaceImpl::IsFrozenObject(ObjectID objectId, BOOL *pbFrozen)
 }
 
 /*
+ * GetLOHObjectSizeThreshold
+ * 
+ * Gets the value of the configured LOH Threshold.
+ * 
+ * Parameters:
+ *      pThreshold        - value of the threshold in bytes
+ *
+ * Returns:
+ *   S_OK if successful
+ *
+ */
+HRESULT ProfToEEInterfaceImpl::GetLOHObjectSizeThreshold(DWORD *pThreshold)
+{
+    CONTRACTL
+    {
+        NOTHROW;
+        GC_NOTRIGGER;
+        MODE_ANY;
+        EE_THREAD_NOT_REQUIRED;
+        CANNOT_TAKE_LOCK;
+    }
+    CONTRACTL_END;
+
+    PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(
+        kP2EEAllowableAfterAttach,
+        (LF_CORPROF,
+        LL_INFO1000,
+        "**PROF: GetLOHObjectSizeThreshold\n"));
+
+    if (pThreshold == nullptr)
+    {
+        return E_INVALIDARG;
+    }
+
+    *pThreshold = g_pConfig->GetGCLOHThreshold();
+
+    return S_OK;
+}
+
+/*
  * GetStringLayout
  *
  * This function describes to a profiler the internal layout of a string.
index d41eec9..ff5e463 100644 (file)
@@ -611,6 +611,8 @@ public:
 
     COM_METHOD IsFrozenObject(ObjectID objectId, BOOL *pbFrozen);
 
+    COM_METHOD GetLOHObjectSizeThreshold(DWORD *pThreshold);
+
     // end ICorProfilerInfo10
 
 protected: