[*] Clean up grug and auasync scheduler / improved idle cpu usage
This commit is contained in:
parent
8a9c45c213
commit
30fa15b726
@ -111,11 +111,11 @@ namespace Aurora
|
||||
|
||||
struct AsyncConfig
|
||||
{
|
||||
bool bStartSchedularOnStartup { true }; // turn this off to make your application lighter-weight; turn this on for higher performance (+expensive) scheduling
|
||||
bool bEnableLegacyTicks { false }; // turn this on to enable an async apps singleton threadpool to SysPump on worker id zero. Alternatively, use SetMainThreadForSysPumpScheduling once you have a thread pool and worker id.
|
||||
bool bStartSchedularOnStartup { true }; // spawns the sched thread during the runtime initialization process, otherwise delegate it until the last min
|
||||
bool bEnableLegacyTicks { false }; // turn this on to enable an async apps singleton threadpool to SysPump on worker id zero. Alternatively, use SetMainThreadForSysPumpScheduling once you have a thread pool and worker id.
|
||||
AuUInt32 threadPoolDefaultStackSize { };
|
||||
AuUInt32 dwSchedulerRateLimitMS { 2 }; //
|
||||
AuUInt32 dwLegacyMainThreadSystemTickMS { 25 }; // nowadays this is primarily used to dispatch main-thread posted (AuConsole) commands
|
||||
AuUInt32 dwSchedulerRateLimitNS { AuMSToNS<AuUInt64>(2) }; //
|
||||
AuUInt32 dwLegacyMainThreadSystemTickMS { 60 }; // nowadays this is primarily used to dispatch main-thread posted (AuConsole) commands
|
||||
};
|
||||
|
||||
struct FIOConfig
|
||||
|
@ -81,32 +81,35 @@ namespace Aurora::Async
|
||||
|
||||
static void SchedNextTime(AuUInt64 uNSAbs)
|
||||
{
|
||||
if (uNextSysTickGuessed > uNSAbs ||
|
||||
!uNextSysTickGuessed)
|
||||
while (true)
|
||||
{
|
||||
while (true)
|
||||
auto uCurrent = AuAtomicLoad(&uNextSysTickGuessed);
|
||||
|
||||
if (uCurrent &&
|
||||
uCurrent <= uNSAbs)
|
||||
{
|
||||
auto uCurrent = uNextSysTickGuessed;
|
||||
return;
|
||||
}
|
||||
|
||||
if (uCurrent &&
|
||||
uCurrent <= uNSAbs)
|
||||
{
|
||||
break;
|
||||
}
|
||||
auto uRateLimit = AuAtomicLoad(&uNextWakeuptimeRateLimit);
|
||||
if (uRateLimit &&
|
||||
uRateLimit > uNSAbs)
|
||||
{
|
||||
uNSAbs = uRateLimit;
|
||||
|
||||
if (uNextWakeuptimeRateLimit > uNSAbs)
|
||||
if (uRateLimit == uCurrent)
|
||||
{
|
||||
uNSAbs = uNextWakeuptimeRateLimit;
|
||||
}
|
||||
|
||||
if (AuAtomicCompareExchange(&uNextSysTickGuessed, uNSAbs, uCurrent) == uCurrent)
|
||||
{
|
||||
break;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
gSchedCondvar->Signal();
|
||||
if (AuAtomicCompareExchange(&uNextSysTickGuessed, uNSAbs, uCurrent) == uCurrent)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
gSchedCondvar->Signal();
|
||||
}
|
||||
|
||||
static void SchedThread()
|
||||
@ -123,7 +126,7 @@ namespace Aurora::Async
|
||||
{
|
||||
AU_LOCK_GUARD(gSchedLock);
|
||||
|
||||
auto uNextTick = uNextSysTickGuessed;
|
||||
auto uNextTick = AuAtomicLoad(&uNextSysTickGuessed);
|
||||
auto uNow = AuTime::SteadyClockNS();
|
||||
|
||||
if (uNow < uNextTick)
|
||||
@ -142,9 +145,13 @@ namespace Aurora::Async
|
||||
0);
|
||||
}
|
||||
|
||||
GetDispatchableTasks(pending);
|
||||
if (gRuntimeConfig.async.dwSchedulerRateLimitNS)
|
||||
{
|
||||
uNextWakeuptimeRateLimit =
|
||||
AuTime::SteadyClockNS() + gRuntimeConfig.async.dwSchedulerRateLimitNS;
|
||||
}
|
||||
|
||||
uNextWakeuptimeRateLimit = AuTime::SteadyClockNS() + AuMSToNS<AuUInt64>(gRuntimeConfig.async.dwSchedulerRateLimitMS);
|
||||
GetDispatchableTasks(pending);
|
||||
}
|
||||
|
||||
for (auto &entry : pending)
|
||||
@ -155,7 +162,7 @@ namespace Aurora::Async
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
Debug::PrintError();
|
||||
SysPushErrorCatch();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,24 @@ namespace Aurora::Async
|
||||
{
|
||||
}
|
||||
|
||||
ThreadStateBase::ThreadStateBase()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ThreadStateBase::~ThreadStateBase()
|
||||
{
|
||||
if (this->asyncLoop)
|
||||
{
|
||||
this->asyncLoop->pParent = nullptr;
|
||||
|
||||
if (this->asyncLoop)
|
||||
{
|
||||
(void)this->asyncLoop->SourceRemove(this->sync.eventLs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ThreadStateSync::Init()
|
||||
{
|
||||
this->eventLs = AuLoop::NewLSAsync();
|
||||
|
@ -62,6 +62,9 @@ namespace Aurora::Async
|
||||
|
||||
struct ThreadStateBase
|
||||
{
|
||||
ThreadStateBase();
|
||||
~ThreadStateBase();
|
||||
|
||||
AuWPtr<GroupState> parent;
|
||||
/////////////////////////////////
|
||||
ThreadStateShutdown shutdown;
|
||||
|
@ -54,6 +54,10 @@ namespace Aurora::Async
|
||||
|
||||
void AsyncLoop::Schedule()
|
||||
{
|
||||
if (!this->pParent)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (AuThreads::GetThread() != this->pParent->thread.pThread.get())
|
||||
{
|
||||
AuAtomicAdd(&this->commitPending_, 1u);
|
||||
|
@ -27,13 +27,12 @@
|
||||
|
||||
namespace Aurora::Grug
|
||||
{
|
||||
static const auto kGrugSleepMs = 100;
|
||||
static const auto kGrugFlushMs = 500;
|
||||
static const auto kGrugSleepMs = 300;
|
||||
static const auto kGrugFlushMs = 600;
|
||||
|
||||
static AuThreads::ThreadUnique_t gGrugsBigWorld;
|
||||
static AuCondMutex gMutex; // ^ that
|
||||
static AuConditionVariable gCondVar(AuUnsafeRaiiToShared(gMutex.AsPointer())); // slow logger work queue
|
||||
static AuSemaphore gArrows;
|
||||
static AuBinarySemaphore gArrowsRetarded(false, true, true);
|
||||
static AuMutex gOtherMutex;
|
||||
static AuList<AuPair<AuUInt, bool>> gHandlesToClose;
|
||||
static AuList<AuThreadPrimitives::IEvent *> gEventsToTrigger;
|
||||
@ -46,16 +45,16 @@ namespace Aurora::Grug
|
||||
// grug require only 1 strand
|
||||
static void GrugWorld()
|
||||
{
|
||||
// ignorerino
|
||||
#if defined(AURORA_IS_LINUX_DERIVED)
|
||||
LinuxSuperSecretFuckGlibc();
|
||||
::LinuxSuperSecretFuckGlibc();
|
||||
#endif
|
||||
|
||||
// grug surive first night
|
||||
SlowStartupTasks();
|
||||
|
||||
AU_LOCK_GUARD(gMutex);
|
||||
|
||||
AuDebug::AddMemoryCrunch(); // this thread must never encounter an out of memory condition. begin out of memory mitigations.
|
||||
// this thread must never encounter an out of memory condition. begin out of memory mitigations.
|
||||
AuDebug::AddMemoryCrunch();
|
||||
|
||||
Utility::RateLimiter limiter;
|
||||
limiter.SetNextStep(AuMSToNS<AuUInt64>(kGrugFlushMs));
|
||||
@ -63,16 +62,7 @@ namespace Aurora::Grug
|
||||
// grug has cave
|
||||
while (AuIsThreadRunning())
|
||||
{
|
||||
// * -> grug wake up from 100ms (kGrugSleepMs)
|
||||
// grug smashy alarm
|
||||
gCondVar->WaitForSignal(kGrugFlushMs);
|
||||
|
||||
// grug anoy
|
||||
if (gArrows && gArrows->TryLock())
|
||||
{
|
||||
// grug yeet
|
||||
DequeueOneArrow();
|
||||
}
|
||||
// grug anoyd
|
||||
|
||||
// grug pump all async log messages
|
||||
GrugFlushWrites();
|
||||
@ -80,29 +70,24 @@ namespace Aurora::Grug
|
||||
// adhd grug wonder around the log pool every 500ms (rate limited to 100ms sleeps)
|
||||
if (limiter.CheckExchangePass())
|
||||
{
|
||||
// poo2loo
|
||||
GrugFlushFlushs();
|
||||
}
|
||||
|
||||
// grug give up
|
||||
// grug yield for at least 100ms -> *
|
||||
if (gArrows)
|
||||
// grug sleep for 100ms or until poked
|
||||
if (gArrowsRetarded->TryLock() ||
|
||||
gArrows->LockMS(kGrugSleepMs))
|
||||
{
|
||||
// grug sleep for 100ms or until poked
|
||||
if (gArrows->LockMS(kGrugSleepMs))
|
||||
{
|
||||
DequeueOneArrow();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// grug sleep 100ms
|
||||
AuThreading::Sleep(kGrugSleepMs);
|
||||
DequeueOneArrow();
|
||||
}
|
||||
|
||||
// grug has to carry stupid platforms
|
||||
#if defined(AURORA_IS_LINUX_DERIVED)
|
||||
::LinuxSuperSecretIOTick();
|
||||
#endif
|
||||
|
||||
// grug done
|
||||
GrugDoIoWork();
|
||||
}
|
||||
}
|
||||
@ -114,11 +99,16 @@ namespace Aurora::Grug
|
||||
|
||||
static void InitFlushThread()
|
||||
{
|
||||
if (gGrugsBigWorld)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Startup a runner thread that will take care of all the stress of triggering IO every so often on a remote thread
|
||||
gGrugsBigWorld = AuThreads::ThreadUnique(AuThreads::ThreadInfo(
|
||||
AuMakeShared<AuThreads::IThreadVectorsFunctional>(AuThreads::IThreadVectorsFunctional::OnEntry_t(std::bind(GrugWorld)),
|
||||
AuThreads::IThreadVectorsFunctional::OnExit_t{}),
|
||||
"Cave Grug"
|
||||
gGrugsBigWorld = AuMove(AuThreads::Spawn(std::bind(GrugWorld),
|
||||
false,
|
||||
{},
|
||||
"Cave Grug"
|
||||
));
|
||||
|
||||
if (!gGrugsBigWorld)
|
||||
@ -129,7 +119,6 @@ namespace Aurora::Grug
|
||||
// he's a lazy bastard
|
||||
gGrugsBigWorld->SetThrottle(AuThreads::EThreadThrottle::eEfficient);
|
||||
gGrugsBigWorld->SetPriority(AuThreads::EThreadPriority::ePrioLow);
|
||||
gGrugsBigWorld->Run();
|
||||
}
|
||||
|
||||
void InitGrug()
|
||||
@ -152,22 +141,12 @@ namespace Aurora::Grug
|
||||
|
||||
void NotifyGrugOfTelemetry()
|
||||
{
|
||||
if (gArrows)
|
||||
{
|
||||
gArrows->Unlock(1);
|
||||
}
|
||||
|
||||
DrachenlordScreech();
|
||||
gArrows->Unlock(1);
|
||||
}
|
||||
|
||||
void DrachenlordScreech()
|
||||
{
|
||||
if (!gCondVar)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
gCondVar->Signal();
|
||||
gArrowsRetarded->Set();
|
||||
}
|
||||
|
||||
bool IsGrug()
|
||||
|
Loading…
Reference in New Issue
Block a user