diff --git a/Include/Aurora/HWInfo/CpuLoadSampler.hpp b/Include/Aurora/HWInfo/CpuLoadSampler.hpp new file mode 100644 index 00000000..e7f88937 --- /dev/null +++ b/Include/Aurora/HWInfo/CpuLoadSampler.hpp @@ -0,0 +1,28 @@ +/*** + Copyright (C) 2023 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: CpuLoadSampler.hpp + Date: 2023-10-28 + Author: Reece + + Note: This API does not query system-wide CPU utilization + This belongs alongside AuProcess just about as much as our memory stat APIs do. I think it's fine to keep hardware perf query apis under AuHwInfo. +***/ +#pragma once + +namespace Aurora::HWInfo +{ + struct ICpuLoadSampler + { + /** + * @brief + * @return a percentage (0 - 100; as a decimal) of the local process or thread CPU usage between ::GetLoad() calls, with respect to a uMinSamplePeriod averaging period. + */ + virtual double GetLoad() = 0; + }; + + AUKN_SHARED_SOO2_NCM(CpuLoadSampler, ICpuLoadSampler, 64, + ((AuUInt32, bTriggered), (bool, bThreadMode)), + AuUInt32 uMinSamplePeriodMS = AuSToMS(1), // May be zero + bool bThreadMode = false); // False = Sample Process Usage | True = Sample Thread Usage +} \ No newline at end of file diff --git a/Include/Aurora/HWInfo/HWInfo.hpp b/Include/Aurora/HWInfo/HWInfo.hpp index 3f97e872..d9259ccd 100644 --- a/Include/Aurora/HWInfo/HWInfo.hpp +++ b/Include/Aurora/HWInfo/HWInfo.hpp @@ -8,4 +8,5 @@ #pragma once #include "CpuInfo.hpp" -#include "RamInfo.hpp" \ No newline at end of file +#include "RamInfo.hpp" +#include "CpuLoadSampler.hpp" \ No newline at end of file diff --git a/Source/HWInfo/AuCpuLoadSampler.cpp b/Source/HWInfo/AuCpuLoadSampler.cpp new file mode 100644 index 00000000..f63325f4 --- /dev/null +++ b/Source/HWInfo/AuCpuLoadSampler.cpp @@ -0,0 +1,117 @@ +/*** + Copyright (C) 2023 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: CpuLoadSampler.cpp + Date: 2023-10-28 + Author: Reece +***/ +#include +#include "AuCpuLoadSampler.hpp" + +namespace Aurora::HWInfo +{ + CpuLoadSamplerImpl::CpuLoadSamplerImpl(AuUInt32 uMinSamplePeriodMS, + bool bThreadMode) : + uMinSamplePeriod(uMinSamplePeriodMS), + bThreadMode(bThreadMode) + { + + } + + CpuLoadSamplerImpl::~CpuLoadSamplerImpl() + + { + + } + + double CpuLoadSamplerImpl::GetLoad() + { + if (!this->bThreadMode) + { + return this->processState.GetLoad(this->uMinSamplePeriod, false); + } + else + { + return this->threadState->GetLoad(this->uMinSamplePeriod, true); + } + } + + double CpuLoadSamplerState::GetLoad(AuUInt32 uMinSamplePeriod, bool bThread) + { + AuUInt64 now[2] = { + AuTime::SteadyClockNS(), + bThread ? AuTime::ThreadClockNS() : AuTime::ProcessClockNS() + }; + + double dDeltaSteady = now[0] - this->uPrevTimes[0]; + double dDeltaProcess = now[1] - this->uPrevTimes[1]; + double dUsage = 0; + double dMinSamplePeriod = double(AuMSToNS(uMinSamplePeriod)); + + if (!uMinSamplePeriod || + dDeltaSteady >= dMinSamplePeriod) + { + dUsage = dDeltaProcess / dDeltaSteady; + this->uPrevTimes[1] = now[1]; + this->uPrevTimes[0] = now[0]; + this->dPrevLoad = dUsage; + } + else + { + dUsage = dDeltaProcess / dDeltaSteady; + #if 0 + dUsage *= dDeltaSteady / double(dMinSamplePeriod); + if (this->dPrevLoad) dUsage = dUsage + this->dPrevLoad / 2.0; + #else + if (this->dPrevLoad) + { + double dFrameDelta = dDeltaSteady / double(dMinSamplePeriod); + double dFrameDeltaInverse = 1.0 - dFrameDelta; + dUsage *= dFrameDelta; + dUsage += this->dPrevLoad * dFrameDeltaInverse; + } + else + { + dUsage *= dDeltaSteady / double(dMinSamplePeriod); + } + #endif + } + + if (!bool(this->uPrevTimes[0])) + { + this->uPrevTimes[1] = now[1]; + this->uPrevTimes[0] = now[0]; + return 0; + } + else + { + dUsage = dUsage * 100.0; + + if (dUsage > 100.0) + { + return 100.0; + } + else if (dUsage < 0.0) + { + return 0.0; + } + else + { + return dUsage; + } + } + } + + AUKN_SYM ICpuLoadSampler *CpuLoadSamplerNew(AuUInt32 uMinSamplePeriodMS, + bool bThreadMode) + { + return _new CpuLoadSamplerImpl(uMinSamplePeriodMS, bThreadMode); + } + + AUKN_SYM void CpuLoadSamplerRelease(ICpuLoadSampler *pEvent) + { + AuSafeDelete(pEvent); + } + + AUROXTL_INTERFACE_SOO_SRC_EX(AURORA_SYMBOL_EXPORT, CpuLoadSampler, CpuLoadSamplerImpl, (AuUInt32, uMinSamplePeriod), (bool, bThreadMode)) +} \ No newline at end of file diff --git a/Source/HWInfo/AuCpuLoadSampler.hpp b/Source/HWInfo/AuCpuLoadSampler.hpp new file mode 100644 index 00000000..6e012e0b --- /dev/null +++ b/Source/HWInfo/AuCpuLoadSampler.hpp @@ -0,0 +1,34 @@ +/*** + Copyright (C) 2023 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: CpuLoadSampler.hpp + Date: 2023-10-28 + Author: Reece +***/ +#pragma once + +namespace Aurora::HWInfo +{ + struct CpuLoadSamplerState + { + double GetLoad(AuUInt32 uMinSamplePeriod, bool bThread); + + AuUInt64 uPrevTimes[2] {}; + double dPrevLoad {}; + }; + + struct CpuLoadSamplerImpl : ICpuLoadSampler + { + CpuLoadSamplerImpl(AuUInt32 uMinSamplePeriodMS, + bool bThreadMode); + + ~CpuLoadSamplerImpl(); + + double GetLoad() override; + + AuUInt32 uMinSamplePeriod {}; + bool bThreadMode {}; + CpuLoadSamplerState processState; + AuTLSVariable threadState; + }; +} \ No newline at end of file