[*] AuAsync performance improvement: avoiding the kernel

This commit is contained in:
Reece Wilson 2023-09-05 02:36:46 +01:00
parent 876f4439b3
commit 560ca079a4
3 changed files with 39 additions and 24 deletions

View File

@ -151,14 +151,21 @@ namespace Aurora::Async
}
else
{
if (AuAtomicLoad(&pWorker->cvSleepCount))
{
AU_LOCK_GUARD(pWorker->cvWorkMutex);
}
// Barrier:
pWorker->cvWorkMutex->Lock();
pWorker->cvWorkMutex->Unlock();
pWorker->cvVariable->Signal();
}
if (AuAtomicTestAndSet(&pWorker->cvLSActive, 0u) == 0)
{
pWorker->eventLs->Set();
}
}
}
IThreadPool *ThreadPool::ToThreadPool()
{
@ -196,13 +203,13 @@ namespace Aurora::Async
bool ThreadPool::Poll()
{
AuUInt32 uCount {};
return InternalRunOne(false, uCount);
return InternalRunOne(GetThreadStateNoWarn(), false, uCount);
}
bool ThreadPool::RunOnce()
{
AuUInt32 uCount {};
return InternalRunOne(true, uCount);
return InternalRunOne(GetThreadStateNoWarn(), true, uCount);
}
bool ThreadPool::Run()
@ -229,7 +236,7 @@ namespace Aurora::Async
AuUInt32 uCount {};
// Do work (blocking)
if (!InternalRunOne(true, uCount))
if (!InternalRunOne(pJobRunner, true, uCount))
{
if (this->shutdown)
{
@ -242,9 +249,8 @@ namespace Aurora::Async
return ranOnce;
}
bool ThreadPool::InternalRunOne(bool block, AuUInt32 &uCount)
bool ThreadPool::InternalRunOne(AuSPtr<ThreadState> state, bool block, AuUInt32 &uCount)
{
auto state = GetThreadStateNoWarn();
if (!state)
{
SysPushErrorUninitialized("Not an async thread");
@ -278,7 +284,7 @@ namespace Aurora::Async
}
else
{
if (!PollInternal(false, uCount))
if (!PollInternal(state, false, uCount))
{
AuThreading::ContextYield();
}
@ -314,15 +320,17 @@ namespace Aurora::Async
if ((AuBuild::kIsNtDerived && runMode == ERunMode::eEfficient) ||
(!AuBuild::kIsNtDerived))
{
AuAtomicAdd(&state->cvSleepCount, 1u);
asyncLoop->WaitAny(0);
AuAtomicSub(&state->cvSleepCount, 1u);
}
}
success = PollInternal(false, uCount);
success = PollInternal(state, false, uCount);
}
else
{
success = PollInternal(block, uCount);
success = PollInternal(state, block, uCount);
}
} //while (success);
@ -410,10 +418,8 @@ namespace Aurora::Async
}
}
// TODO: rewrite queues
bool ThreadPool::PollInternal(bool block, AuUInt32 &uCount)
bool ThreadPool::PollInternal(AuSPtr<ThreadState> state, bool block, AuUInt32 &uCount)
{
auto state = GetThreadStateNoWarn();
if (!state)
{
SysPushErrorUninitialized("Not an async thread");
@ -425,6 +431,7 @@ namespace Aurora::Async
//state->pendingWorkItems.clear();
{
AuAtomicAdd(&state->cvSleepCount, 1u);
AU_LOCK_GUARD(state->cvWorkMutex);
do
@ -470,15 +477,19 @@ namespace Aurora::Async
(this->GetThreadState()->asyncLoop->GetSourceCount() > 1) ||
this->GetThreadState()->asyncLoop->CommitPending())) //(this->ToKernelWorkQueue()->IsSignaledPeek()))
{
AuAtomicSub(&state->cvSleepCount, 1u);
return false;
}
} while (state->pendingWorkItems.empty() && block);
}
while (state->pendingWorkItems.empty() && block);
if (group->workQueue.IsEmpty(state->id))
{
state->eventLs->Reset();
AuAtomicStore(&state->cvLSActive, 0u);
}
AuAtomicSub(&state->cvSleepCount, 1u);
}
if (state->pendingWorkItems.empty())
@ -776,7 +787,7 @@ namespace Aurora::Async
AuUInt32 ThreadPool::PollAndCount(bool bStrict)
{
AuUInt32 uCount {};
auto bRanAtLeastOne = this->InternalRunOne(false, uCount);
auto bRanAtLeastOne = this->InternalRunOne(this->GetThreadStateNoWarn(), false, uCount);
return uCount ? uCount : (bStrict ? bRanAtLeastOne : 0);
}
@ -788,7 +799,7 @@ namespace Aurora::Async
do
{
uCount = 0;
ranAtLeastOne |= this->InternalRunOne(false, uCount);
ranAtLeastOne |= this->InternalRunOne(this->GetThreadStateNoWarn(), false, uCount);
}
while (uCount);
@ -1091,10 +1102,12 @@ namespace Aurora::Async
// !!!
auto pA = this->GetThreadStateNoWarn();
if (this->shutdown ||
this->shuttingdown_ & 2) // fast
{
if (GetThreadState()->rejecting)
if (pA->rejecting)
{
return false;
}
@ -1107,7 +1120,7 @@ namespace Aurora::Async
do
{
uCount = 0;
ranAtLeastOne |= this->InternalRunOne(false, uCount);
ranAtLeastOne |= this->InternalRunOne(pA, false, uCount);
}
while (uCount);
@ -1350,7 +1363,7 @@ namespace Aurora::Async
do
{
uCount = 0;
this->PollInternal(false, uCount);
this->PollInternal(jobWorker, false, uCount);
}
while (uCount);
}

View File

@ -95,8 +95,8 @@ namespace Aurora::Async
bool Spawn(WorkerId_t workerId, bool create);
bool InternalRunOne(bool block, AuUInt32 &uCount);
bool PollInternal(bool block, AuUInt32 &uCount);
bool InternalRunOne(AuSPtr<ThreadState>, bool block, AuUInt32 &uCount);
bool PollInternal(AuSPtr<ThreadState>, bool block, AuUInt32 &uCount);
size_t GetThreadWorkersCount(ThreadGroup_t group);

View File

@ -68,6 +68,8 @@ namespace Aurora::Async
AuThreadPrimitives::ConditionMutex cvWorkMutex;
AuThreadPrimitives::ConditionVariable cvVariable;
AuAUInt32 cvSleepCount {};
AuAUInt32 cvLSActive {};
AuSPtr<AuLoop::ILSEvent> eventLs;
AuSPtr<AuLoop::ILoopSource> asyncLoopSourceShared;
};