Stop incrementing class profile counter once the reservoir table is full (#82723)
authorAndy Ayers <andya@microsoft.com>
Tue, 28 Feb 2023 07:53:18 +0000 (23:53 -0800)
committerGitHub <noreply@github.com>
Tue, 28 Feb 2023 07:53:18 +0000 (23:53 -0800)
The counter in the class profile counter is used to determine when to
switch to probabilistic updates of the reservior table, but it is currently
not used to detemine the probability of an update. So there's no need to keep
incrementing it once the table is full.

Since the count is mutable shared state, bypassing updates should reduce cache
contention somewhat.

Contributes to #72387.

src/coreclr/vm/jithelpers.cpp

index 3d27ff8..c6b2033 100644 (file)
@@ -5423,22 +5423,27 @@ static unsigned HandleHistogramProfileRand()
 }
 
 template<typename T>
-FORCEINLINE static bool CheckSample(T index, size_t* sampleIndex)
+FORCEINLINE static bool CheckSample(T* pIndex, size_t* sampleIndex)
 {
     const unsigned S = ICorJitInfo::HandleHistogram32::SIZE;
     const unsigned N = ICorJitInfo::HandleHistogram32::SAMPLE_INTERVAL;
     static_assert_no_msg(N >= S);
     static_assert_no_msg((std::is_same<T, uint32_t>::value || std::is_same<T, uint64_t>::value));
 
-    // If table is not yet full, just add entries in.
+    // If table is not yet full, just add entries in
+    // and increment the table index.
     //
+    T const index = *pIndex;
+
     if (index < S)
     {
         *sampleIndex = static_cast<size_t>(index);
+        *pIndex = index + 1;
         return true;
     }
 
-    unsigned x = HandleHistogramProfileRand();
+    unsigned const x = HandleHistogramProfileRand();
+
     // N is the sampling window size,
     // it should be larger than the table size.
     //
@@ -5469,7 +5474,7 @@ HCIMPL2(void, JIT_ClassProfile32, Object *obj, ICorJitInfo::HandleHistogram32* c
     VALIDATEOBJECTREF(objRef);
 
     size_t sampleIndex;
-    if (!CheckSample(classProfile->Count++, &sampleIndex) || objRef == NULL)
+    if (!CheckSample(&classProfile->Count, &sampleIndex) || objRef == NULL)
     {
         return;
     }
@@ -5504,7 +5509,7 @@ HCIMPL2(void, JIT_ClassProfile64, Object *obj, ICorJitInfo::HandleHistogram64* c
     VALIDATEOBJECTREF(objRef);
 
     size_t sampleIndex;
-    if (!CheckSample(classProfile->Count++, &sampleIndex) || objRef == NULL)
+    if (!CheckSample(&classProfile->Count, &sampleIndex) || objRef == NULL)
     {
         return;
     }
@@ -5534,7 +5539,7 @@ HCIMPL2(void, JIT_DelegateProfile32, Object *obj, ICorJitInfo::HandleHistogram32
     VALIDATEOBJECTREF(objRef);
 
     size_t methodSampleIndex;
-    if (!CheckSample(methodProfile->Count++, &methodSampleIndex) || objRef == NULL)
+    if (!CheckSample(&methodProfile->Count, &methodSampleIndex) || objRef == NULL)
     {
         return;
     }
@@ -5581,7 +5586,7 @@ HCIMPL2(void, JIT_DelegateProfile64, Object *obj, ICorJitInfo::HandleHistogram64
     VALIDATEOBJECTREF(objRef);
 
     size_t methodSampleIndex;
-    if (!CheckSample(methodProfile->Count++, &methodSampleIndex) || objRef == NULL)
+    if (!CheckSample(&methodProfile->Count, &methodSampleIndex) || objRef == NULL)
     {
         return;
     }
@@ -5627,7 +5632,7 @@ HCIMPL3(void, JIT_VTableProfile32, Object* obj, CORINFO_METHOD_HANDLE baseMethod
     VALIDATEOBJECTREF(objRef);
 
     size_t methodSampleIndex;
-    if (!CheckSample(methodProfile->Count++, &methodSampleIndex) || objRef == NULL)
+    if (!CheckSample(&methodProfile->Count, &methodSampleIndex) || objRef == NULL)
     {
         return;
     }
@@ -5676,7 +5681,7 @@ HCIMPL3(void, JIT_VTableProfile64, Object* obj, CORINFO_METHOD_HANDLE baseMethod
     VALIDATEOBJECTREF(objRef);
 
     size_t methodSampleIndex;
-    if (!CheckSample(methodProfile->Count++, &methodSampleIndex) || objRef == NULL)
+    if (!CheckSample(&methodProfile->Count, &methodSampleIndex) || objRef == NULL)
     {
         return;
     }