AuroraRuntime/Include/Aurora/Utility/ThroughputCalculator.hpp.buffered
Reece Wilson 7be2d3fbdc [+] AuUtility::ThroughputCalculator
[+] AuNet::ISocketStats
[+] AuNet::ISocketChannel::GetRecvStats()
[+] AuNet::ISocketChannel::GetSendStats()
[+] AuIO::IOProcessor::RunTickEx(AuUInt32 dwTimeout)
[*] Refactor clock APIs
[+] Documentation in headers
[+] AuIO::IIOPipeWork::GetStartTickMS()
[+] AuIO::IIOPipeWork::GetLastTickMS()
[+] AuIO::IIOPipeWork::GetPredictedThroughput()
[+] AuIO::IIOPipeWork::GetBytesProcessed()
2022-12-06 22:58:15 +00:00

137 lines
3.4 KiB
Plaintext

/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: ThroughputCalculator.hpp
Date: 2022-12-06
Author: Reece
***/
#pragma once
namespace Aurora::Utility
{
struct ThroughputCalculator
{
// call me arbitrarily
double inline OnUpdate(AuUInt uUnit)
{
AU_LOCK_GUARD(this->lock);
OnTick(uUnit);
return this->dCurFreq;
}
// then call me arbitrarily:
double inline GetEstimatedHertz()
{
AU_LOCK_GUARD(this->lock);
auto uNow = Aurora::Time::SteadyClockNS();
auto uDelta = uNow - this->uLast;
// we cannot do anything on frame zero
if (!this->dCurFreq)
{
return 0;
}
return this->dCurFreq;
}
AuUInt inline GetTotalStats()
{
return this->uTotalLifetime;
}
AuInt64 inline GetLastFrameTimeWall()
{
return this->uLastWall;
}
private:
void inline OnTick(AuUInt64 uUnit)
{
struct EntryTable
{
AuUInt32 uBits {};
AuUInt32 uTimeDelta {};
};
auto uNow = Aurora::Time::SteadyClockNS();
auto uDelta = uNow - this->uLast;
AuMemmove(uVecTable + 1, uVecTable, sizeof(uVecTable) - sizeof(*uVecTable));
auto pTable = ((EntryTable *)uVecTable);
bool bFirst = !this->uLast;
this->uLast = uNow;
if (bFirst)
{
return;
}
this->uLastWall = Aurora::Time::CurrentClockMS();
static const auto kOneSecond = AuMSToNS<AuUInt64>(AuSToMS<AuUInt64>(1));
pTable[0].uBits = (AuUInt32)uUnit;
pTable[0].uTimeDelta = (AuUInt32)(uDelta / 1000ull);
if (!pTable[0].uTimeDelta)
{
pTable[0].uTimeDelta = 1;
}
if (uVecSize < 10)
{
uVecSize++;
}
AuLogDbg("Added: {} {}", pTable[0].uBits, pTable[0].uTimeDelta * 1000ull);
double dTotal {};
double dTotalBits {};
double dTotalTime {};
double dSamples {};
for (AU_ITR_N(i, uVecSize))
{
if (!pTable[i].uTimeDelta)
{
pTable[i].uTimeDelta = 1;
}
double dDeltaSeconds = ((double)((AuUInt64)pTable[i].uTimeDelta * 1000ull) / (double)kOneSecond);
dTotalBits += pTable[i].uBits;
dTotalTime += dDeltaSeconds;
dTotal += (double)pTable[i].uBits / dDeltaSeconds;
dSamples++;
}
AuLogDbg("{}/{} ({})", dTotal, dSamples, uVecSize);
this->dCurFreq = dTotal / dSamples;
double a = dTotalBits / dTotalTime;
//if (this->dCurFreq > a)
//{
//}
//this->dCurFreq = AuMin(a, this->dCurFreq);
}
AuUInt8 uVecSize {};
AuUInt64 uVecTable[10];
AuThreadPrimitives::SpinLock lock;
AuUInt64 uLast {};
AuUInt uTotalLifetime {};
AuInt64 uLastWall {};
double dCurFreq {};
};
}