Skip to content

Commit

Permalink
Add initialization for yield normalization
Browse files Browse the repository at this point in the history
  • Loading branch information
eduardo-vp committed Mar 22, 2024
1 parent 78b5f40 commit 6cfd3b3
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 13 deletions.
4 changes: 4 additions & 0 deletions src/coreclr/vm/ceemain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -779,6 +779,10 @@ void EEStartupHelper()
StubPrecode::StaticInitialize();
FixupPrecode::StaticInitialize();

// Perform some measurements before garbage collector is initialized
// so GC initialization and the first few GCs can use the normalized yield
YieldProcessorNormalization::PerformMeasurement();

InitializeGarbageCollector();

if (!GCHandleUtilities::GetGCHandleManager()->Initialize())
Expand Down
48 changes: 35 additions & 13 deletions src/coreclr/vm/yieldprocessornormalized.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@
enum class NormalizationState : UINT8
{
Uninitialized,
PartiallyInitialized,
Initialized,
Failed
};

static const int NsPerYieldMeasurementCount = 8;
static const unsigned int MeasurementPeriodMs = 4000;
static const int s_partialInitializationMeasurementCount = 2; // number of measurements to be done during partial initialization

static const unsigned int NsPerS = 1000 * 1000 * 1000;

Expand Down Expand Up @@ -118,9 +120,9 @@ void YieldProcessorNormalization::PerformMeasurement()
}
CONTRACTL_END;

_ASSERTE(s_isMeasurementScheduled);
_ASSERTE(s_isMeasurementScheduled ^ (s_normalizationState == NormalizationState::Uninitialized));

double latestNsPerYield;
double latestNsPerYield = 0; // initialize to supress error C4701
if (s_normalizationState == NormalizationState::Initialized)
{
if (GetTickCount() - s_previousNormalizationTimeMs < MeasurementPeriodMs)
Expand All @@ -137,19 +139,31 @@ void YieldProcessorNormalization::PerformMeasurement()
}
s_nextMeasurementIndex = nextMeasurementIndex;
}
else if (s_normalizationState == NormalizationState::Uninitialized)
else if (s_normalizationState == NormalizationState::Uninitialized || s_normalizationState == NormalizationState::PartiallyInitialized)
{
LARGE_INTEGER li;
if (!QueryPerformanceFrequency(&li) || li.QuadPart < 1000 * 1000)
int startIndex, endIndex;
if (s_normalizationState == NormalizationState::Uninitialized)
{
// High precision clock not available or clock resolution is too low, resort to defaults
s_normalizationState = NormalizationState::Failed;
return;
LARGE_INTEGER li;
if (!QueryPerformanceFrequency(&li) || li.QuadPart < 1000 * 1000)
{
// High precision clock not available or clock resolution is too low, resort to defaults
s_normalizationState = NormalizationState::Failed;
return;
}
s_performanceCounterTicksPerS = li.QuadPart;

startIndex = 0;
endIndex = s_partialInitializationMeasurementCount;
}
else
{
startIndex = s_partialInitializationMeasurementCount;
endIndex = NsPerYieldMeasurementCount;
}
s_performanceCounterTicksPerS = li.QuadPart;

unsigned int measureDurationUs = DetermineMeasureDurationUs();
for (int i = 0; i < NsPerYieldMeasurementCount; ++i)
for (int i = startIndex; i < endIndex; ++i)
{
latestNsPerYield = MeasureNsPerYield(measureDurationUs);
AtomicStore(&s_nsPerYieldMeasurements[i], latestNsPerYield);
Expand All @@ -163,6 +177,11 @@ void YieldProcessorNormalization::PerformMeasurement()
FireEtwYieldProcessorMeasurement(GetClrInstanceId(), latestNsPerYield, s_establishedNsPerYield);
}
}

s_normalizationState =
(s_normalizationState == NormalizationState::Uninitialized) ?
NormalizationState::PartiallyInitialized :
NormalizationState::Initialized;
}
else
{
Expand All @@ -171,7 +190,11 @@ void YieldProcessorNormalization::PerformMeasurement()
}

double establishedNsPerYield = s_nsPerYieldMeasurements[0];
for (int i = 1; i < NsPerYieldMeasurementCount; ++i)
int endIndex =
(s_normalizationState == NormalizationState::PartiallyInitialized) ?
s_partialInitializationMeasurementCount :
NsPerYieldMeasurementCount;
for (int i = 1; i < endIndex; ++i)
{
double nsPerYield = s_nsPerYieldMeasurements[i];
if (nsPerYield < establishedNsPerYield)
Expand Down Expand Up @@ -201,7 +224,6 @@ void YieldProcessorNormalization::PerformMeasurement()
GCHeapUtilities::GetGCHeap()->SetYieldProcessorScalingFactor((float)yieldsPerNormalizedYield);

s_previousNormalizationTimeMs = GetTickCount();
s_normalizationState = NormalizationState::Initialized;
s_isMeasurementScheduled = false;
}

Expand All @@ -217,7 +239,7 @@ void YieldProcessorNormalization::ScheduleMeasurementIfNecessary()
CONTRACTL_END;

NormalizationState normalizationState = VolatileLoadWithoutBarrier(&s_normalizationState);
if (normalizationState == NormalizationState::Initialized)
if (normalizationState == NormalizationState::Initialized || normalizationState == NormalizationState::PartiallyInitialized)
{
if (GetTickCount() - s_previousNormalizationTimeMs < MeasurementPeriodMs)
{
Expand Down

0 comments on commit 6cfd3b3

Please sign in to comment.