[+] AuTime::EClock

[+] AuTime::IClock
[+] AuTime::GetWallClock
[+] AuTime::GetProcessClock
[+] AuTime::GetSteadyClock
[+] AuTime::GetClockFromEnum
[*] Rename Timer -> Stopwatch
[*] Refactor a serial AuString to a string view

(*amended year)
This commit is contained in:
Reece Wilson 2023-03-21 10:05:45 +00:00
parent 6974c713f7
commit 82d455c4b1
14 changed files with 367 additions and 241 deletions

View File

@ -432,7 +432,7 @@ namespace Aurora::Memory
// String API
inline bool WriteString(const AuString &string, EStringType type = EStringType::eStringDword, Locale::ECodePage codepage = Locale::ECodePage::eUTF8);
inline bool WriteString(std::string_view string, EStringType type = EStringType::eStringDword, Locale::ECodePage codepage = Locale::ECodePage::eUTF8);
inline bool ReadString(AuString &string, EStringType type = EStringType::eStringDword, Locale::ECodePage codepage = Locale::ECodePage::eUTF8);
// Copy, concat, etc

View File

@ -14,7 +14,7 @@
namespace Aurora::Memory
{
bool ByteBuffer::WriteString(const AuString &string, EStringType type, Locale::ECodePage codepage)
bool ByteBuffer::WriteString(std::string_view string, EStringType type, Locale::ECodePage codepage)
{
ByteBufferPushWriteState a(*this);
AuStreamReadWrittenPair_t len {};
@ -22,7 +22,7 @@ namespace Aurora::Memory
if (codepage != Locale::ECodePage::eUTF8)
{
len = Aurora::Locale::Encoding::EncodeUTF8(string, {}, codepage);
len = Aurora::Locale::Encoding::EncodeUTF8(Memory::MemoryViewRead { string.data(), string.length() }, { }, codepage);
if (len == AuStreamReadWrittenPair_t {0, 0})
{
return false;
@ -41,7 +41,7 @@ namespace Aurora::Memory
return false;
}
len = Aurora::Locale::Encoding::EncodeUTF8(string, writeView, codepage);
len = Aurora::Locale::Encoding::EncodeUTF8(Memory::MemoryViewRead { string.data(), string.length() }, writeView, codepage);
if (len == AuStreamReadWrittenPair_t {0, 0})
{
return false;

View File

@ -1,139 +0,0 @@
/***
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: Clock.hpp
Date: 2021-6-10
Author: Reece
***/
#pragma once
#include "ETimezoneShift.hpp"
#include "TM.hpp"
namespace Aurora::Time
{
/**
Converts milliseconds from the Aurora epoch to a civil timestamp structure
similar to or of std::tm
*/
AUKN_SYM tm ToCivilTime(AuInt64 time, bool UTC = true);
/**
Converts civil time to milliseconds from the Aurora epoch
*/
AUKN_SYM AuInt64 FromCivilTime(const tm &time, bool UTC = true);
/**
Normalizes a civil data structure with respect to UTC, given the two input parameters 'in' civil and 'shiftFrom' timezone hint
*/
AUKN_SYM tm NormalizeCivilTimezone(const tm &in, ETimezoneShift shiftFrom = ETimezoneShift::eUTC);
/**
Translates the Aurora epoch to the standard unix epoch
*/
AUKN_SYM AuInt64 ConvertAuroraToUnixMS(AuInt64 in);
/**
Translates the Aurora epoch to the standard unix epoch
*/
AUKN_SYM AuInt64 ConvertAuroraToUnixNS(AuInt64 in);
/**
Translates a standard unix epoch to the Aurora epoch
*/
AUKN_SYM AuInt64 ConvertUnixToAuroraMS(AuInt64 in);
/**
Translates a standard unix epoch to the Aurora epoch
*/
AUKN_SYM AuInt64 ConvertUnixToAuroraNS(AuInt64 in);
/**
Retrieves wall clock in milliseconds from the Aurora epoch
*/
AUKN_SYM AuInt64 CurrentClockMS();
/**
Retrieves wall clock in nanoseconds from the Aurora epoch
*/
AUKN_SYM AuInt64 CurrentClockNS();
/**
* @brief Steady clock in jiffies
* @return
*/
AUKN_SYM AuUInt64 SteadyClock();
/**
Returns a steady system clock of SteadyClockJiffies() with an undefined epoch.
These values should be used to drive thread primitives, IO time, and tick delta.
On a modern plaform, these should be affected by the users' calendar or NTP.
On stinkier platforms, who cares if we can run mostly bug free with an assumed-sane wall-clock, right?
*/
AUKN_SYM AuUInt64 SteadyClockMS();
/**
* @brief
* @return
*/
AUKN_SYM AuUInt64 SteadyClockNS();
/**
Retrieves the freqency of jiffies per second
*/
AUKN_SYM AuUInt64 SteadyClockJiffies();
/**
Returns a high resolution count of jiffies with an undefined epoch from a
high resolution clock.
These values should be used to drive benchmarks.
These values should not nor can be accurately converted meaningfully
*/
AUKN_SYM AuUInt64 HighResClock();
AUKN_SYM AuUInt64 HighResClockMS();
AUKN_SYM AuUInt64 HighResClockNS();
/**
Retrieves the freqency of jiffies per second
*/
AUKN_SYM AuUInt64 HighResClockJiffies();
/**
Let's say you're fucked and you need a ball park figure.
Enjoy...
*/
AUKN_SYM AuUInt64 ConvertInternalToAuroraEpochMS(AuUInt64 in);
AUKN_SYM AuUInt64 ConvertInternalToAuroraEpochNS(AuUInt64 in);
/**
Converts seconds from the Aurora epoch to time_t
*/
AUKN_SYM time_t SToCTime(AuInt64 time);
/**
Converts nanoseconds from the Aurora epoch to time_t
*/
AUKN_SYM time_t NSToCTime(AuInt64 time);
/**
Converts milliseconds from the Aurora epoch to time_t
*/
AUKN_SYM time_t MSToCTime(AuInt64 time);
AUKN_SYM AuInt64 CTimeToMS(time_t time);
/**
Retrieves the freqency as a fraction of: jiffies per second / 1 * nanoseconds in a second
*/
AUKN_SYM double CPUFrequencyDeltaNS();
/**
Retrieves the freqency as a fraction of: jiffies per second / 1 * milliseconds in a second
*/
AUKN_SYM double CPUFrequencyDeltaMS();
}

View File

@ -11,40 +11,39 @@
namespace Aurora::Time
{
#if ((defined(AU_FORCE_BENCHMARK) || defined(DEBUG) || defined(STAGING)) && (!defined(AU_FORCE_NOBENCHMARK)))
#if ((defined(AU_FORCE_BENCHMARK) || defined(AU_CFG_ID_DEBUG) || defined(AU_CFG_ID_INTERNAL)) && (!defined(AU_FORCE_NOBENCHMARK)))
class DebugBenchmark
struct DebugBenchmark
{
public:
DebugBenchmark(AuString message) : message_(message) {}
inline DebugBenchmark(AuString &&message) : message_(AuMove(message))
{
this->stopwatch_.Start();
}
~DebugBenchmark()
inline ~DebugBenchmark()
{
Finish();
}
void Finish()
inline void Finish()
{
if (AuExchange(finished_, true)) return;
auto time = timer_.End();
Aurora::Logging::LogDbg("[Benchmark] {} took {}", message_, ConvertNSToTimescale(time));
auto uEndNS = this->stopwatch_.EndNS();
Aurora::Logging::LogDbg("[Benchmark] {} took {}", message_, ConvertNSToTimescale(uEndNS));
}
private:
TimerHighRes timer_;
bool finished_ {};
Stopwatch stopwatch_;
AuString message_;
};
#else
class DebugBenchmark
struct DebugBenchmark
{
public:
template<typename ... T>
DebugBenchmark(T... args) {}
void Finish() {}
inline void Finish() {}
};
#endif

View File

@ -0,0 +1,17 @@
/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: EClock.hpp
Date: 2023-3-21
Author: Reece
***/
#pragma once
namespace Aurora::Time
{
AUE_DEFINE(EClock, (
eWall,
eSteady,
eProcessTime
))
}

View File

View File

@ -0,0 +1,19 @@
/***
Copyright (C) 2023 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: IClock.hpp
Date: 2023-3-21
Author: Reece
***/
#pragma once
namespace Aurora::Time
{
struct IClock
{
virtual EClock GetType() = 0;
virtual AuUInt64 GetHertz() = 0;
virtual AuUInt64 NowNS() = 0;
virtual AuUInt64 NowMS() = 0;
};
}

View File

@ -0,0 +1,53 @@
/***
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: Stopwatch.hpp
Date: 2021-6-10
Author: Reece
***/
#pragma once
namespace Aurora::Time
{
AUKN_SYM AuUInt64 SteadyClockNS();
struct Stopwatch
{
inline Stopwatch()
{
Start();
}
inline ~Stopwatch()
{
}
inline void Start()
{
this->start_ = SteadyClockNS();
}
inline void Reset()
{
this->start_ = SteadyClockNS();
this->end_ = 0;
}
inline AuUInt64 EndNS()
{
if (!this->end_) this->end_ = SteadyClockNS();
return this->end_ - this->start_;
}
inline AuUInt64 EndMS()
{
if (!this->end_) this->end_ = SteadyClockNS();
return AuNSToMS<AuUInt64>(this->end_ - this->start_);
}
private:
AuUInt64 start_;
AuUInt64 end_;
};
}

View File

@ -2,28 +2,161 @@
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: Time.hpp
Date: 2021-6-9
Date: 2021-6-10
Author: Reece
***/
#pragma once
#include <Aurora/Time/ETimezoneShift.hpp>
#include <Aurora/Locale/LocaleStrings.hpp>
#include "_Time.hpp"
namespace Aurora::Time
{
static AuString ConvertMSToTimescale(AuUInt32 ms)
{
return Locale::ConvertMSToTimescale(ms);
}
/**
Converts milliseconds from the Aurora epoch to a civil timestamp structure
similar to or of std::tm
*/
AUKN_SYM tm ToCivilTime(AuInt64 time, bool bIsUTC = true);
static AuString ConvertNSToTimescale(AuUInt64 ns)
{
return Locale::ConvertNSToTimescale(ns);
}
/**
Converts civil time to milliseconds from the Aurora epoch
*/
AUKN_SYM AuInt64 FromCivilTime(const tm &time, bool bIsUTC = true);
/**
Normalizes a civil data structure with respect to UTC, given the two input parameters 'in' civil and 'shiftFrom' timezone hint
*/
AUKN_SYM tm NormalizeCivilTimezone(const tm &in, ETimezoneShift shiftFrom = ETimezoneShift::eUTC);
/**
Translates the Aurora epoch to the standard unix epoch
*/
AUKN_SYM AuInt64 ConvertAuroraToUnixMS(AuInt64 in);
/**
Translates the Aurora epoch to the standard unix epoch
*/
AUKN_SYM AuInt64 ConvertAuroraToUnixNS(AuInt64 in);
/**
Translates a standard unix epoch to the Aurora epoch
*/
AUKN_SYM AuInt64 ConvertUnixToAuroraMS(AuInt64 in);
/**
Translates a standard unix epoch to the Aurora epoch
*/
AUKN_SYM AuInt64 ConvertUnixToAuroraNS(AuInt64 in);
/**
Retrieves wall clock in milliseconds from the Aurora epoch
*/
AUKN_SYM AuInt64 CurrentClockMS();
/**
Retrieves wall clock in nanoseconds from the Aurora epoch
*/
AUKN_SYM AuInt64 CurrentClockNS();
/**
* @brief Steady clock in jiffies
* @return
*/
AUKN_SYM AuUInt64 SteadyClock();
/**
Returns a steady system clock of SteadyClockJiffies() with an undefined epoch.
These values should be used to drive thread primitives, IO time, and tick delta.
On a modern plaform, these should be affected by the users' calendar or NTP.
On stinkier platforms, who cares if we can run mostly bug free with an assumed-sane wall-clock, right?
*/
AUKN_SYM AuUInt64 SteadyClockMS();
/**
* @brief
* @return
*/
AUKN_SYM AuUInt64 SteadyClockNS();
/**
Retrieves the freqency of jiffies per second
*/
AUKN_SYM AuUInt64 SteadyClockJiffies();
/**
Returns a high resolution count of jiffies with an undefined epoch from a
high resolution clock.
These values should be used to drive benchmarks.
These values should not nor can be accurately converted meaningfully
*/
AUKN_SYM AuUInt64 HighResClock();
AUKN_SYM AuUInt64 HighResClockMS();
AUKN_SYM AuUInt64 HighResClockNS();
/**
Retrieves the freqency of jiffies per second
*/
AUKN_SYM AuUInt64 HighResClockJiffies();
/**
Let's say you're fucked and you need a ball park figure.
Enjoy...
*/
AUKN_SYM AuUInt64 ConvertInternalToAuroraEpochMS(AuUInt64 in);
AUKN_SYM AuUInt64 ConvertInternalToAuroraEpochNS(AuUInt64 in);
/**
Converts seconds from the Aurora epoch to time_t
*/
AUKN_SYM time_t SToCTime(AuInt64 time);
/**
Converts nanoseconds from the Aurora epoch to time_t
*/
AUKN_SYM time_t NSToCTime(AuInt64 time);
/**
Converts milliseconds from the Aurora epoch to time_t
*/
AUKN_SYM time_t MSToCTime(AuInt64 time);
AUKN_SYM AuInt64 CTimeToMS(time_t time);
/**
Retrieves the freqency as a fraction of: jiffies per second / 1 * nanoseconds in a second
*/
AUKN_SYM double CPUFrequencyDeltaNS();
/**
Retrieves the freqency as a fraction of: jiffies per second / 1 * milliseconds in a second
*/
AUKN_SYM double CPUFrequencyDeltaMS();
/**
* @brief
* @return
*/
AUKN_SYM AuSPtr<IClock> GetWallClock();
/**
* @brief
* @return
*/
AUKN_SYM AuSPtr<IClock> GetSteadyClock();
/**
* @brief
* @return
*/
AUKN_SYM AuSPtr<IClock> GetProcessClock();
/**
* @brief
* @param clock
* @return
*/
AUKN_SYM AuSPtr<IClock> GetClockFromEnum(EClock clock);
}
#include "Clock.hpp"
#include "Timer.hpp"
#include "TimerHighRes.hpp"
#include "DebugBenchmark.hpp"

View File

@ -1,33 +0,0 @@
/***
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: Timer.hpp
Date: 2021-6-10
Author: Reece
***/
#pragma once
namespace Aurora::Time
{
class Timer
{
public:
Timer()
{
Start();
}
void Start()
{
start_ = CurrentClockMS();
}
AuUInt64 End()
{
return CurrentClockMS() - start_;
}
private:
AuUInt64 start_;
};
}

View File

@ -1,35 +0,0 @@
/***
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: TimerHighRes.hpp
Date: 2021-6-10
Author: Reece
***/
#pragma once
namespace Aurora::Time
{
class TimerHighRes
{
public:
TimerHighRes()
{
Start();
}
void Start()
{
start_ = HighResClockNS();
}
AuUInt64 End()
{
auto re = std::clamp<AuInt64>(HighResClockNS() - start_, AuInt64(0), AuNumericLimits<AuInt64>::max());
if (re == AuNumericLimits<AuInt64>::max()) return 0; // ez overflow in subtract. get out of here in 2-3 branches
return re;
}
private:
AuUInt64 start_;
};
}

View File

@ -0,0 +1,31 @@
/***
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: Time.hpp
Date: 2021-6-9
Author: Reece
***/
#pragma once
#include <Aurora/Time/ETimezoneShift.hpp>
#include <Aurora/Time/EClock.hpp>
#include <Aurora/Locale/LocaleStrings.hpp>
#include "IClock.hpp"
namespace Aurora::Time
{
static AuString ConvertMSToTimescale(AuUInt32 ms)
{
return Locale::ConvertMSToTimescale(ms);
}
static AuString ConvertNSToTimescale(AuUInt64 ns)
{
return Locale::ConvertNSToTimescale(ns);
}
}
#include "Stopwatch.hpp"
#include "DebugBenchmark.hpp"
#include "ExtendedTimer.hpp"

68
Source/Time/AuClocks.cpp Normal file
View File

@ -0,0 +1,68 @@
/***
Copyright (C) 2023 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: AuClocks.cpp
Date: 2023-3-21
Author: Reece
***/
#include <RuntimeInternal.hpp>
#include "AuClocks.hpp"
namespace Aurora::Time
{
#define ADD_CLOCK(name, enum, jiffies, getNs, getMs) \
struct name ## Clock_t : IClock \
{ \
EClock GetType() override \
{ \
return EClock::enum; \
} \
\
AuUInt64 GetHertz() override \
{ \
return jiffies(); \
} \
\
AuUInt64 NowNS() override \
{ \
return getNs(); \
} \
\
AuUInt64 NowMS() override \
{ \
return getMs(); \
} \
}; \
\
static name ## Clock_t gClock## name ## Instance; \
\
AUKN_SYM AuSPtr<IClock> Get ## name ## Clock() \
{ \
return AuUnsafeRaiiToShared(&gClock## name ## Instance); \
}
#define FILE_AND_USR_DIR_STEP (AuMSToNS<AuUInt64>(AuSToMS<AuUInt64>(1)) / 100ull)
ADD_CLOCK(Steady, eSteady, SteadyClockJiffies, SteadyClockNS, SteadyClockMS);
ADD_CLOCK(Wall, eWall, FILE_AND_USR_DIR_STEP + AuUInt64, CurrentClockNS, CurrentClockMS);
ADD_CLOCK(ProcTime, eProcessTime, HighResClockJiffies, HighResClockNS, HighResClockMS);
#undef FILE_AND_USR_DIR_STEP
#undef ADD_CLOCK
AUKN_SYM AuSPtr<IClock> GetClockFromEnum(EClock clock)
{
switch (clock)
{
case EClock::eWall:
return GetWallClock();
case EClock::eProcessTime:
return GetProcessClock();
case EClock::eSteady:
return GetSteadyClock();
default:
SysPushErrorArg("Invalid clock");
return {};
}
}
}

13
Source/Time/AuClocks.hpp Normal file
View File

@ -0,0 +1,13 @@
/***
Copyright (C) 2023 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: AuClocks.hpp
Date: 2023-3-21
Author: Reece
***/
#pragma once
namespace Aurora::Time
{
}