1
0
Fork 0
mirror of https://github.com/VSadov/Satori.git synced 2025-06-09 09:34:49 +09:00

Suspend SpinWait tweak

This commit is contained in:
vsadov 2024-08-22 15:11:18 -07:00
parent 9bcf08d5e9
commit 1dad554930
2 changed files with 38 additions and 21 deletions

View file

@ -222,27 +222,39 @@ void ThreadStore::UnlockThreadStore()
m_Lock.Leave();
}
// exponential spinwait with an approximate time limit for waiting in microsecond range.
// when iteration == -1, only usecLimit is used
void SpinWait(int iteration, int usecLimit)
// spinwait with an approximate time limit for waiting in microsecond range.
void SpinWait(int usecLimit)
{
int64_t startTicks = PalQueryPerformanceCounter();
int64_t ticksPerSecond = PalQueryPerformanceFrequency();
int64_t endTicks = startTicks + (usecLimit * ticksPerSecond) / 1000000;
int l = min((unsigned)iteration, 30);
for (int i = 0; i < l; i++)
#ifdef TARGET_UNIX
if (usecLimit > 10)
{
for (int j = 0; j < (1 << i); j++)
{
System_YieldProcessor();
}
struct timespec requested;
struct timespec remaining;
requested.tv_sec = 0;
requested.tv_nsec = usecLimit * 1000;
while (nanosleep(&requested, &remaining) == EINTR)
{
requested = remaining;
}
}
#endif // TARGET_UNIX
for (int i = 0; i < 30; i++)
{
int64_t currentTicks = PalQueryPerformanceCounter();
if (currentTicks > endTicks)
{
break;
}
for (int j = 0; j < (1 << i); j++)
{
System_YieldProcessor();
}
}
}
@ -297,12 +309,12 @@ void ThreadStore::SuspendAllThreads(bool waitForGCEvent)
if (remaining < prevRemaining || !observeOnly)
{
// 5 usec delay, then check for more progress
SpinWait(-1, 5);
SpinWait(5);
observeOnly = true;
}
else
{
SpinWait(retries++, 100);
SpinWait(min(1 << retries++, 100));
observeOnly = false;
// make sure our spining is not starving other threads, but not too often,

View file

@ -3206,8 +3206,7 @@ COR_PRF_SUSPEND_REASON GCSuspendReasonToProfSuspendReason(ThreadSuspend::SUSPEND
#endif // PROFILING_SUPPORTED
// exponential spinwait with an approximate time limit for waiting in microsecond range.
// when iteration == -1, only usecLimit is used
void SpinWait(int iteration, int usecLimit)
void SpinWait(int usecLimit)
{
LARGE_INTEGER li;
QueryPerformanceCounter(&li);
@ -3217,20 +3216,26 @@ void SpinWait(int iteration, int usecLimit)
int64_t ticksPerSecond = li.QuadPart;
int64_t endTicks = startTicks + (usecLimit * ticksPerSecond) / 1000000;
int l = min((unsigned)iteration, 30);
for (int i = 0; i < l; i++)
#ifdef TARGET_UNIX
if (usecLimit > 10)
{
for (int j = 0; j < (1 << i); j++)
{
System_YieldProcessor();
}
PAL_nanosleep(usecLimit * 1000);
}
#endif // TARGET_UNIX
for (int i = 0; i < 30; i++)
{
QueryPerformanceCounter(&li);
int64_t currentTicks = li.QuadPart;
if (currentTicks > endTicks)
{
break;
}
for (int j = 0; j < (1 << i); j++)
{
System_YieldProcessor();
}
}
}
@ -3587,7 +3592,7 @@ void ThreadSuspend::SuspendRuntime(ThreadSuspend::SUSPEND_REASON reason)
if (g_SystemInfo.dwNumberOfProcessors > 1 && (hasProgress || !observeOnly))
{
// small pause
SpinWait(-1, 5);
SpinWait(5);
STRESS_LOG1(LF_SYNC, LL_INFO1000, "Spinning, %d threads remaining\n", countThreads);
observeOnly = true;
@ -3610,7 +3615,7 @@ void ThreadSuspend::SuspendRuntime(ThreadSuspend::SUSPEND_REASON reason)
STRESS_LOG1(LF_SYNC, LL_INFO1000, "Waiting for suspend event %d threads remaining\n", countThreads);
// DWORD res = g_pGCSuspendEvent->Wait(PING_JIT_TIMEOUT, FALSE);
SpinWait(retries++, 100);
SpinWait(min(1 << retries++, 100));
// make sure our spining is not starving other threads, but not too often,
// this can cause a 1-15 msec delay, depending on OS, and that is a lot while