[*] TODO: (Finish me) Win7 ILoopQueue doesn't seem to like the in process high perf timer io primitive so much. It works fine under Linux and WaitForMultipleObject WinXP-WinRT.

Windows 7 Perf hack
This commit is contained in:
Reece Wilson 2024-09-21 01:45:46 +01:00
parent 36349b4d02
commit ff65193d0f
3 changed files with 76 additions and 58 deletions

View File

@ -16,11 +16,12 @@ namespace Aurora::IO::Loop
void LSTimerIPDispatcher::RunAsync()
{
AU_LOCK_GUARD(this->mutex);
if (this->pParent)
// TODO: not as optimized
// TODO: we now just added a AuSharedFromThis requirement for no good reason
if (auto pThat = AuTryLockMemoryType(this->pParent))
{
AU_LOCK_GUARD(this->pParent->cs);
this->pParent->Set();
this->pParent = nullptr;
pThat->Set();
}
}
@ -29,16 +30,12 @@ namespace Aurora::IO::Loop
reschedStepNsOrZero_(AuMSToNS<AuUInt64>(reschedStepMsOrZero)),
maxIterationsOrZero_(maxIterationsOrZero)
{
this->targetTime_ = AuTime::CurrentClockNS();
this->targetTime_ = AuTime::SteadyClockNS();
}
LSTimerIP::~LSTimerIP()
{
if (this->pDispatcher)
{
AU_LOCK_GUARD(this->pDispatcher->mutex);
this->pDispatcher->pParent = nullptr;
}
}
void LSTimerIP::UpdateTimeWall(AuUInt64 absTimeMs)
@ -82,35 +79,17 @@ namespace Aurora::IO::Loop
AU_DEBUG_MEMCRUNCH;
AU_LOCK_GUARD(this->cs);
AuSPtr<LSTimerIPDispatcher> pNext;
{
AU_LOCK_GUARD(this->dispatcherMutex);
if (this->pDispatcher)
{
AU_LOCK_GUARD(this->pDispatcher->mutex);
if (this->pDispatcher->pParent)
{
// abort
this->pDispatcher->pParent = nullptr;
pNext = this->pDispatcher = AuMakeShared<LSTimerIPDispatcher>();
}
else
{
pNext = this->pDispatcher;
}
}
else
{
pNext = this->pDispatcher = AuMakeShared<LSTimerIPDispatcher>();
}
AuResetMember(this->pDispatcher->pParent);
}
// TODO: optimization was removed. readd it.
auto pNext = this->pDispatcher = AuMakeShared<LSTimerIPDispatcher>();
SysAssert(pNext, "impossible OOM during timer op");
pNext->pParent = this;
pNext->pParent = this->SharedFromThis();;
AuAsync::Schedule(absTimeNs, nullptr, {}, pNext);
this->targetTime_ = absTimeNs;
}
@ -119,11 +98,10 @@ namespace Aurora::IO::Loop
{
AU_LOCK_GUARD(this->cs);
AU_LOCK_GUARD(this->dispatcherMutex);
if (this->pDispatcher)
{
AU_LOCK_GUARD(this->pDispatcher->mutex);
this->pDispatcher->pParent = nullptr;
AuResetMember(this->pDispatcher->pParent);
this->pDispatcher = nullptr;
}
}
@ -168,18 +146,9 @@ namespace Aurora::IO::Loop
bool LSTimerIP::OnTrigger(AuUInt handle)
{
AU_LOCK_GUARD(this->cs);
if (IsSignaledNoSpinIfUserland())
{
return IsSignaledNoSpinIfUserland();
return true;
}
else
{
LSEvent::Reset();
return false;
}
}
bool LSTimerIP::TryTakeWaitNS(AuUInt64 uTimeoutAbs)
{
@ -194,13 +163,19 @@ namespace Aurora::IO::Loop
{
return true;
}
else
{
uNextTime = AuAtomicLoad(&this->targetTime_);
}
auto uNow = AuTime::CurrentClockNS();
auto uNow = AuTime::SteadyClockNS();
if (uNow >= uNextTime)
{
return this->IsSignaledNonblocking();
}
// TODO: this added mess isn't even hit.
// Win32 note: there is quite a bit of hackery behind SleepNs
// Win 7 and lower may spin for a bit
// Various CPUs may enter a user-space montior condition
@ -208,14 +183,42 @@ namespace Aurora::IO::Loop
// Alderlake et al can tpause
if (uTimeoutAbs)
{
AuThreading::SleepNs(AuMin(uNextTime, uTimeoutAbs) - uNow);
if (uTimeoutAbs < uNextTime)
{
AuThreading::SleepNs(uTimeoutAbs - uNow);
return false;
}
AuThreading::SleepNs(uNextTime - uNow);
while (uNextTime < AuTime::SteadyClockNS())
{
if (this->IsSignaledNonblocking())
{
return true;
}
}
return this->IsSignaledNonblocking();
}
else
{
AuThreading::SleepNs(uNextTime - uNow);
return this->IsSignaledNonblocking();
if (this->IsSignaledNonblocking())
{
return true;
}
while (AuAtomicLoad(&this->targetTime_) < AuTime::SteadyClockNS())
{
if (this->IsSignaledNonblocking())
{
return true;
}
}
}
return false;
}
ELoopSource LSTimerIP::GetType()
@ -225,7 +228,7 @@ namespace Aurora::IO::Loop
bool LSTimerIP::TryInit()
{
return LSEvent::TryInit(false, false, true);
return LSEvent::TryInit(false, true, true);
}
bool LSTimerIP::IsSignaled()

View File

@ -7,6 +7,7 @@
***/
#pragma once
#include <Source/Async/IAsyncRunnable.hpp>
#include "LSHandle.hpp"
#include "LSEvent.hpp"
@ -16,13 +17,13 @@ namespace Aurora::IO::Loop
struct LSTimerIPDispatcher : AuAsync::IAsyncRunnable
{
AuMutex mutex;
LSTimerIP *pParent {};
AuCriticalSection mutex;
AuWPtr<LSTimerIP> pParent {};
void RunAsync() override;
};
struct LSTimerIP : LSEvent, ITimer
struct LSTimerIP : LSEvent, ITimer, AuEnableSharedFromThis<LSTimerIP>
{
LSTimerIP(AuUInt32 reschedStepMsOrZero, AuUInt32 maxIterationsOrZero, bool bSingleshot);
~LSTimerIP();
@ -53,15 +54,14 @@ namespace Aurora::IO::Loop
void UpdateTimeInternal(AuUInt64 absTimeMs);
void UpdateTimeInternalSteady(AuUInt64 absTimeMs);
private:
//private:
friend struct LSTimerIPDispatcher;
AuUInt32 maxIterationsOrZero_ {};
AuUInt64 reschedStepNsOrZero_ {}, targetTime_ {};
AuUInt32 count_ {};
bool bSingleshot {};
AuUInt32 count_ {};
AuCriticalSection cs;
AuMutex dispatcherMutex;
AuSPtr<LSTimerIPDispatcher> pDispatcher;
bool IsSignaledNonblocking();
};

View File

@ -9,6 +9,7 @@
#include "Loop.hpp"
#include "ILoopSourceEx.hpp"
#include "LSIOHandle.hpp"
#include "LSTimerNoKernelScheduler.hpp"
#include <Source/Threading/Primitives/SMTYield.hpp>
namespace Aurora::IO::Loop
@ -70,6 +71,20 @@ namespace Aurora::IO::Loop
return;
}
if (auto pSemaphore = AuDynamicCast<Loop::LSTimerIP>(pLoopSource))
{
// TOOD:Hack:
AU_LOCK_GUARD(pSemaphore->cs);
if (pSemaphore->maxIterationsOrZero_)
{
AuAtomicSub(&pSemaphore->count_, 1u);
}
pSemaphore->UpdateTimeSteadyNs(pSemaphore->targetTime_ - pSemaphore->reschedStepNsOrZero_);
pSemaphore->Set();
return;
}
if (auto pMutex = AuDynamicCast<Loop::ILSMutex>(pLoopSource))
{
pMutex->Unlock();