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

View File

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

View File

@ -9,6 +9,7 @@
#include "Loop.hpp" #include "Loop.hpp"
#include "ILoopSourceEx.hpp" #include "ILoopSourceEx.hpp"
#include "LSIOHandle.hpp" #include "LSIOHandle.hpp"
#include "LSTimerNoKernelScheduler.hpp"
#include <Source/Threading/Primitives/SMTYield.hpp> #include <Source/Threading/Primitives/SMTYield.hpp>
namespace Aurora::IO::Loop namespace Aurora::IO::Loop
@ -70,6 +71,20 @@ namespace Aurora::IO::Loop
return; 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)) if (auto pMutex = AuDynamicCast<Loop::ILSMutex>(pLoopSource))
{ {
pMutex->Unlock(); pMutex->Unlock();