diff options
| author | Martin Ridgers <[email protected]> | 2021-10-07 08:29:50 +0200 |
|---|---|---|
| committer | Martin Ridgers <[email protected]> | 2021-10-07 08:29:50 +0200 |
| commit | 03232621d183f22e12e798a753e4a606763e63d6 (patch) | |
| tree | 5701d202392dd4ab947139e4046a44ab9bc6cdf7 /zencore | |
| parent | Merged main (diff) | |
| parent | Only enable the MSVC debug output sink for sessions when the --debug mode is ... (diff) | |
| download | zen-03232621d183f22e12e798a753e4a606763e63d6.tar.xz zen-03232621d183f22e12e798a753e4a606763e63d6.zip | |
Merged main
Diffstat (limited to 'zencore')
| -rw-r--r-- | zencore/compactbinary.cpp | 51 | ||||
| -rw-r--r-- | zencore/filesystem.cpp | 24 | ||||
| -rw-r--r-- | zencore/include/zencore/blockingqueue.h | 75 | ||||
| -rw-r--r-- | zencore/include/zencore/filesystem.h | 5 | ||||
| -rw-r--r-- | zencore/include/zencore/iobuffer.h | 8 | ||||
| -rw-r--r-- | zencore/include/zencore/refcount.h | 10 | ||||
| -rw-r--r-- | zencore/include/zencore/stats.h | 64 | ||||
| -rw-r--r-- | zencore/include/zencore/timer.h | 15 | ||||
| -rw-r--r-- | zencore/iobuffer.cpp | 81 | ||||
| -rw-r--r-- | zencore/stats.cpp | 91 | ||||
| -rw-r--r-- | zencore/timer.cpp | 16 |
11 files changed, 385 insertions, 55 deletions
diff --git a/zencore/compactbinary.cpp b/zencore/compactbinary.cpp index f3fbf312c..2ce6987d2 100644 --- a/zencore/compactbinary.cpp +++ b/zencore/compactbinary.cpp @@ -1474,10 +1474,30 @@ public: Builder << Accessor.AsIntegerNegative(); break; case CbFieldType::Float32: - Builder.Append("{:.9g}"_format(Accessor.AsFloat32())); + { + const float Value = Accessor.AsFloat32(); + if (std::isfinite(Value)) + { + Builder.Append("{:.9g}"_format(Value)); + } + else + { + Builder << "null"sv; + } + } break; case CbFieldType::Float64: - Builder.Append("{:.17g}"_format(Accessor.AsFloat64())); + { + const double Value = Accessor.AsFloat64(); + if (std::isfinite(Value)) + { + Builder.Append("{:.17g}"_format(Value)); + } + else + { + Builder << "null"sv; + } + } break; case CbFieldType::BoolFalse: Builder << "false"sv; @@ -1834,7 +1854,7 @@ TEST_CASE("uson.json") SUBCASE("number") { - const double ExpectedFloatValue = 21.21f; + const float ExpectedFloatValue = 21.21f; const double ExpectedDoubleValue = 42.42; CbObjectWriter Writer; @@ -1856,6 +1876,31 @@ TEST_CASE("uson.json") CHECK(FloatValue == doctest::Approx(ExpectedFloatValue)); CHECK(DoubleValue == doctest::Approx(ExpectedDoubleValue)); } + + SUBCASE("number.nan") + { + const float FloatNan = std::numeric_limits<float>::quiet_NaN(); + const double DoubleNan = std::numeric_limits<double>::quiet_NaN(); + + CbObjectWriter Writer; + Writer << "FloatNan" << FloatNan; + Writer << "DoubleNan" << DoubleNan; + + CbObject Obj = Writer.Save(); + + StringBuilder<128> Sb; + const std::string_view JsonText = Obj.ToJson(Sb).ToView(); + + std::string JsonError; + json11::Json Json = json11::Json::parse(JsonText.data(), JsonError); + + const double FloatValue = Json["FloatNan"].number_value(); + const double DoubleValue = Json["DoubleNan"].number_value(); + + CHECK(JsonError.empty()); + CHECK(FloatValue == 0); + CHECK(DoubleValue == 0); + } } #endif diff --git a/zencore/filesystem.cpp b/zencore/filesystem.cpp index 2d2603434..9936f30ec 100644 --- a/zencore/filesystem.cpp +++ b/zencore/filesystem.cpp @@ -63,6 +63,13 @@ DeleteReparsePoint(const wchar_t* Path, DWORD dwReparseTag) bool CreateDirectories(const wchar_t* Dir) { + // This may be suboptimal, in that it appears to try and create directories + // from the root on up instead of from some directory which is known to + // be present + // + // We should implement a smarter version at some point since this can be + // pretty expensive in aggregate + return std::filesystem::create_directories(Dir); } @@ -522,6 +529,23 @@ WriteFile(std::filesystem::path Path, IoBuffer Data) WriteFile(Path, &DataPtr, 1); } +IoBuffer +FileContents::Flatten() +{ + if (Data.size() == 1) + { + return Data[0]; + } + else if (Data.empty()) + { + return {}; + } + else + { + ZEN_NOT_IMPLEMENTED(); + } +} + FileContents ReadFile(std::filesystem::path Path) { diff --git a/zencore/include/zencore/blockingqueue.h b/zencore/include/zencore/blockingqueue.h new file mode 100644 index 000000000..277095689 --- /dev/null +++ b/zencore/include/zencore/blockingqueue.h @@ -0,0 +1,75 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include <atomic> +#include <deque> +#include <mutex> + +namespace zen { + +template<typename T> +class BlockingQueue +{ +public: + BlockingQueue() = default; + + ~BlockingQueue() { CompleteAdding(); } + + void Enqueue(T&& Item) + { + { + std::lock_guard Lock(m_Lock); + m_Queue.emplace_back(std::move(Item)); + m_Size++; + } + + m_NewItemSignal.notify_one(); + } + + bool WaitAndDequeue(T& Item) + { + if (m_CompleteAdding.load()) + { + return false; + } + + std::unique_lock Lock(m_Lock); + m_NewItemSignal.wait(Lock, [this]() { return !m_Queue.empty() || m_CompleteAdding.load(); }); + + if (!m_Queue.empty()) + { + Item = std::move(m_Queue.front()); + m_Queue.pop_front(); + m_Size--; + + return true; + } + + return false; + } + + void CompleteAdding() + { + if (!m_CompleteAdding.load()) + { + m_CompleteAdding.store(true); + m_NewItemSignal.notify_all(); + } + } + + std::size_t Size() const + { + std::unique_lock Lock(m_Lock); + return m_Queue.size(); + } + +private: + mutable std::mutex m_Lock; + std::condition_variable m_NewItemSignal; + std::deque<T> m_Queue; + std::atomic_bool m_CompleteAdding{false}; + std::atomic_uint32_t m_Size; +}; + +} // namespace zen diff --git a/zencore/include/zencore/filesystem.h b/zencore/include/zencore/filesystem.h index 6678528f6..c7ac7140d 100644 --- a/zencore/include/zencore/filesystem.h +++ b/zencore/include/zencore/filesystem.h @@ -2,9 +2,10 @@ #pragma once -#include "stream.h" #include "zencore.h" +#include <zencore/iobuffer.h> + #include <filesystem> #include <functional> @@ -36,6 +37,8 @@ struct FileContents { std::vector<IoBuffer> Data; std::error_code ErrorCode; + + IoBuffer Flatten(); }; ZENCORE_API FileContents ReadFile(std::filesystem::path Path); diff --git a/zencore/include/zencore/iobuffer.h b/zencore/include/zencore/iobuffer.h index 36ecbd9a7..110cd7d9d 100644 --- a/zencore/include/zencore/iobuffer.h +++ b/zencore/include/zencore/iobuffer.h @@ -25,6 +25,7 @@ enum class ZenContentType : uint8_t kCbPackageOffer = 6, kCompressedBinary = 7, kUnknownContentType = 8, + kHTML = 9, kCOUNT }; @@ -54,6 +55,8 @@ ToString(ZenContentType ContentType) return "compressed-binary"sv; case ZenContentType::kYAML: return "yaml"sv; + case ZenContentType::kHTML: + return "html"sv; } } @@ -218,6 +221,7 @@ protected: kIsMaterialized = 1 << 3, // Data pointers are valid kLowLevelAlloc = 1 << 4, // Using direct memory allocation kIsWholeFile = 1 << 5, // References an entire file + kIoBufferAlloc = 1 << 6, // Using IoBuffer allocator kIsOwnedByThis = 1 << 7, // Note that we have some extended flags defined below @@ -229,8 +233,8 @@ protected: kContentTypeBit3 = 1 << (24 + 3), // bits are reserved }; - void* AllocateBuffer(size_t InSize, size_t Alignment); - void FreeBuffer(); + void AllocateBuffer(size_t InSize, size_t Alignment); + void FreeBuffer(); }; /** diff --git a/zencore/include/zencore/refcount.h b/zencore/include/zencore/refcount.h index 320718f5b..1873ce48e 100644 --- a/zencore/include/zencore/refcount.h +++ b/zencore/include/zencore/refcount.h @@ -4,6 +4,8 @@ #include "atomic.h" #include "zencore.h" +#include <concepts> + namespace zen { /** @@ -114,6 +116,11 @@ public: inline Ref(T* Ptr) : m_Ref(Ptr) { m_Ref && m_Ref->AddRef(); } inline ~Ref() { m_Ref && m_Ref->Release(); } + template<typename DerivedType> + requires std::derived_from<DerivedType, T> inline Ref(const Ref<DerivedType>& Rhs) : Ref(Rhs.m_Ref) + { + } + [[nodiscard]] inline bool IsNull() const { return m_Ref == nullptr; } inline explicit operator bool() const { return m_Ref != nullptr; } inline T* operator->() const { return m_Ref; } @@ -152,6 +159,9 @@ public: private: T* m_Ref = nullptr; + + template<class T> + friend class Ref; }; void refcount_forcelink(); diff --git a/zencore/include/zencore/stats.h b/zencore/include/zencore/stats.h index dfa8dac34..884bb53f6 100644 --- a/zencore/include/zencore/stats.h +++ b/zencore/include/zencore/stats.h @@ -209,6 +209,8 @@ public: Scope(OperationTiming& Outer); ~Scope(); + void Cancel(); + private: OperationTiming& m_Outer; uint64_t m_StartTick; @@ -219,10 +221,70 @@ private: Histogram m_Histogram; }; +/** Metrics for network requests + + Aggregates tracking of duration, payload sizes into a single + class + + */ +class RequestStats +{ +public: + RequestStats(int32_t SampleCount = 514); + ~RequestStats(); + + void Update(int64_t Duration, int64_t Bytes); + uint64_t Count() const; + + // Timing + + int64_t MaxDuration() const { return m_BytesHistogram.Max(); } + int64_t MinDuration() const { return m_BytesHistogram.Min(); } + double MeanDuration() const { return m_BytesHistogram.Mean(); } + SampleSnapshot DurationSnapshot() const { return m_RequestTimeHistogram.Snapshot(); } + double Rate1() { return m_RequestMeter.Rate1(); } + double Rate5() { return m_RequestMeter.Rate5(); } + double Rate15() { return m_RequestMeter.Rate15(); } + double MeanRate() const { return m_RequestMeter.MeanRate(); } + + // Bytes + + int64_t MaxBytes() const { return m_BytesHistogram.Max(); } + int64_t MinBytes() const { return m_BytesHistogram.Min(); } + double MeanBytes() const { return m_BytesHistogram.Mean(); } + SampleSnapshot BytesSnapshot() const { return m_BytesHistogram.Snapshot(); } + double ByteRate1() { return m_BytesMeter.Rate1(); } + double ByteRate5() { return m_BytesMeter.Rate5(); } + double ByteRate15() { return m_BytesMeter.Rate15(); } + double ByteMeanRate() const { return m_BytesMeter.MeanRate(); } + + struct Scope + { + Scope(OperationTiming& Outer); + ~Scope(); + + void Cancel(); + + private: + OperationTiming& m_Outer; + uint64_t m_StartTick; + }; + + void EmitSnapshot(std::string_view Tag, CbObjectWriter& Cbo); + +private: + Meter m_RequestMeter; + Meter m_BytesMeter; + Histogram m_RequestTimeHistogram; + Histogram m_BytesHistogram; +}; + void EmitSnapshot(std::string_view Tag, OperationTiming& Stat, CbObjectWriter& Cbo); -void EmitSnapshot(std::string_view Tag, const Histogram& Stat, CbObjectWriter& Cbo); +void EmitSnapshot(std::string_view Tag, const Histogram& Stat, CbObjectWriter& Cbo, double ConversionFactor); void EmitSnapshot(std::string_view Tag, Meter& Stat, CbObjectWriter& Cbo); +void EmitSnapshot(const Histogram& Stat, CbObjectWriter& Cbo, double ConversionFactor); + } // namespace zen::metrics namespace zen { diff --git a/zencore/include/zencore/timer.h b/zencore/include/zencore/timer.h index 693b6daaa..e4ddc3505 100644 --- a/zencore/include/zencore/timer.h +++ b/zencore/include/zencore/timer.h @@ -38,6 +38,21 @@ private: uint64_t m_StartValue; }; +// Low frequency timers + +namespace detail { + extern ZENCORE_API uint64_t g_LofreqTimerValue; +} // namespace detail + +inline uint64_t +GetLofreqTimerValue() +{ + return detail::g_LofreqTimerValue; +} + +ZENCORE_API void UpdateLofreqTimerValue(); +ZENCORE_API uint64_t GetLofreqTimerFrequency(); + void timer_forcelink(); // internal } // namespace zen diff --git a/zencore/iobuffer.cpp b/zencore/iobuffer.cpp index 244425761..04685defc 100644 --- a/zencore/iobuffer.cpp +++ b/zencore/iobuffer.cpp @@ -31,26 +31,29 @@ namespace zen { ////////////////////////////////////////////////////////////////////////// -void* +void IoBufferCore::AllocateBuffer(size_t InSize, size_t Alignment) { #if ZEN_PLATFORM_WINDOWS if (((InSize & 0xffFF) == 0) && (Alignment == 0x10000)) { m_Flags |= kLowLevelAlloc; - return VirtualAlloc(nullptr, InSize, MEM_COMMIT, PAGE_READWRITE); + m_DataPtr = VirtualAlloc(nullptr, InSize, MEM_COMMIT, PAGE_READWRITE); + + return; } #endif // ZEN_PLATFORM_WINDOWS -#if ZEN_USE_MIMALLOC && 0 +#if ZEN_USE_MIMALLOC void* Ptr = mi_aligned_alloc(Alignment, RoundUp(InSize, Alignment)); + m_Flags |= kIoBufferAlloc; #else void* Ptr = Memory::Alloc(InSize, Alignment); #endif ZEN_ASSERT(Ptr); - return Ptr; + m_DataPtr = Ptr; } void @@ -70,11 +73,14 @@ IoBufferCore::FreeBuffer() } #endif // ZEN_PLATFORM_WINDOWS -#if ZEN_USE_MIMALLOC && 0 - return mi_free(const_cast<void*>(m_DataPtr)); -#else - return Memory::Free(const_cast<void*>(m_DataPtr)); +#if ZEN_USE_MIMALLOC + if (m_Flags & kIoBufferAlloc) + { + return mi_free(const_cast<void*>(m_DataPtr)); + } #endif + + return Memory::Free(const_cast<void*>(m_DataPtr)); } ////////////////////////////////////////////////////////////////////////// @@ -85,7 +91,7 @@ IoBufferCore::IoBufferCore(size_t InSize) { ZEN_ASSERT(InSize); - m_DataPtr = AllocateBuffer(InSize, sizeof(void*)); + AllocateBuffer(InSize, sizeof(void*)); m_DataBytes = InSize; SetIsOwnedByThis(true); @@ -95,7 +101,7 @@ IoBufferCore::IoBufferCore(size_t InSize, size_t Alignment) { ZEN_ASSERT(InSize); - m_DataPtr = AllocateBuffer(InSize, Alignment); + AllocateBuffer(InSize, Alignment); m_DataBytes = InSize; SetIsOwnedByThis(true); @@ -138,10 +144,9 @@ IoBufferCore::MakeOwned(bool Immutable) { if (!IsOwned()) { - void* OwnedDataPtr = AllocateBuffer(m_DataBytes, sizeof(void*)); - memcpy(OwnedDataPtr, m_DataPtr, m_DataBytes); - - m_DataPtr = OwnedDataPtr; + const void* OldDataPtr = m_DataPtr; + AllocateBuffer(m_DataBytes, sizeof(void*)); + memcpy(const_cast<void*>(m_DataPtr), OldDataPtr, m_DataBytes); SetIsOwnedByThis(true); } @@ -183,29 +188,29 @@ IoBufferExtendedCore::~IoBufferExtendedCore() { if (m_MappedPointer) { -#if ZEN_PLATFORM_WINDOWS +# if ZEN_PLATFORM_WINDOWS UnmapViewOfFile(m_MappedPointer); -#else +# else uint64_t MapSize = ~uint64_t(uintptr_t(m_MmapHandle)); munmap(m_MappedPointer, MapSize); -#endif +# endif } -#if ZEN_PLATFORM_WINDOWS +# if ZEN_PLATFORM_WINDOWS if (m_Flags & kOwnsMmap) { CloseHandle(m_MmapHandle); } -#endif +# endif if (m_Flags & kOwnsFile) { -#if ZEN_PLATFORM_WINDOWS +# if ZEN_PLATFORM_WINDOWS BOOL Success = CloseHandle(m_FileHandle); -#else +# else int Fd = int(uintptr_t(m_FileHandle)); bool Success = (close(Fd) == 0); -#endif +# endif if (!Success) { @@ -239,7 +244,7 @@ IoBufferExtendedCore::Materialize() const const uint64_t MappedOffsetDisplacement = m_FileOffset - MapOffset; const uint64_t MapSize = m_DataBytes + MappedOffsetDisplacement; -#if ZEN_PLATFORM_WINDOWS +# if ZEN_PLATFORM_WINDOWS m_MmapHandle = CreateFileMapping(m_FileHandle, /* lpFileMappingAttributes */ nullptr, /* flProtect */ PAGE_READONLY, @@ -260,7 +265,7 @@ IoBufferExtendedCore::Materialize() const /* FileOffsetHigh */ uint32_t(MapOffset >> 32), /* FileOffsetLow */ uint32_t(MapOffset & 0xffFFffFFu), /* dwNumberOfBytesToMap */ MapSize); -#else +# else m_MmapHandle = (void*)uintptr_t(~MapSize); // ~ so it's never null (assuming MapSize >= 0) m_Flags |= kOwnsMmap; @@ -271,7 +276,7 @@ IoBufferExtendedCore::Materialize() const /* flags */ MAP_SHARED | MAP_NORESERVE, /* fd */ int(uintptr_t(m_FileHandle)), /* offset */ MapOffset); -#endif // ZEN_PLATFORM_WINDOWS +# endif // ZEN_PLATFORM_WINDOWS if (MappedBase == nullptr) { @@ -376,7 +381,7 @@ IoBufferBuilder::MakeFromFile(const path_char_t* FileName, uint64_t Offset, uint { uint64_t FileSize; -#if ZEN_PLATFORM_WINDOWS +# if ZEN_PLATFORM_WINDOWS CAtlFile DataFile; HRESULT hRes = DataFile.Create(FileName, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING); @@ -387,7 +392,7 @@ IoBufferBuilder::MakeFromFile(const path_char_t* FileName, uint64_t Offset, uint } DataFile.GetSize((ULONGLONG&)FileSize); -#else +# else int Fd = open(FileName, O_RDONLY); if (Fd < 0) { @@ -398,7 +403,7 @@ IoBufferBuilder::MakeFromFile(const path_char_t* FileName, uint64_t Offset, uint struct stat Stat; fstat(Fd, &Stat); FileSize = Stat.st_size; -#endif // ZEN_PLATFORM_WINDOWS +# endif // ZEN_PLATFORM_WINDOWS // TODO: should validate that offset is in range @@ -417,15 +422,15 @@ IoBufferBuilder::MakeFromFile(const path_char_t* FileName, uint64_t Offset, uint if (Size) { -#if ZEN_PLATFORM_WINDOWS +# if ZEN_PLATFORM_WINDOWS void* Fd = DataFile.Detach(); -#endif +# endif return IoBuffer(IoBuffer::File, (void*)uintptr_t(Fd), Offset, Size); } -#if !ZEN_PLATFORM_WINDOWS +# if !ZEN_PLATFORM_WINDOWS close(Fd); -#endif +# endif // For an empty file, we may as well just return an empty memory IoBuffer return IoBuffer(IoBuffer::Wrap, "", 0); @@ -437,7 +442,7 @@ IoBufferBuilder::MakeFromTemporaryFile(const path_char_t* FileName) uint64_t FileSize; void* Handle; -#if ZEN_PLATFORM_WINDOWS +# if ZEN_PLATFORM_WINDOWS CAtlFile DataFile; // We need to open with DELETE since this is used for the case @@ -454,8 +459,8 @@ IoBufferBuilder::MakeFromTemporaryFile(const path_char_t* FileName) DataFile.GetSize((ULONGLONG&)FileSize); Handle = DataFile.Detach(); -#else - int Fd = open(FileName, O_RDONLY); +# else + int Fd = open(FileName, O_RDONLY); if (Fd < 0) { return {}; @@ -467,7 +472,7 @@ IoBufferBuilder::MakeFromTemporaryFile(const path_char_t* FileName) FileSize = Stat.st_size; Handle = (void*)uintptr_t(Fd); -#endif // ZEN_PLATFORM_WINDOWS +# endif // ZEN_PLATFORM_WINDOWS IoBuffer Iob(IoBuffer::File, Handle, 0, FileSize); Iob.m_Core->SetIsWholeFile(true); @@ -484,7 +489,7 @@ HashBuffer(IoBuffer& Buffer) ////////////////////////////////////////////////////////////////////////// -#if ZEN_WITH_TESTS +# if ZEN_WITH_TESTS void iobuffer_forcelink() @@ -498,6 +503,6 @@ TEST_CASE("IoBuffer") zen::IoBuffer buffer3(buffer2, 0, buffer2.Size()); } -#endif +# endif } // namespace zen diff --git a/zencore/stats.cpp b/zencore/stats.cpp index 34dc2828f..0c0647999 100644 --- a/zencore/stats.cpp +++ b/zencore/stats.cpp @@ -295,7 +295,14 @@ Histogram::Min() const double Histogram::Mean() const { - return double(m_Sum.load(std::memory_order_relaxed)) / m_Count; + if (m_Count) + { + return double(m_Sum.load(std::memory_order_relaxed)) / m_Count; + } + else + { + return 0.0; + } } uint64_t @@ -398,12 +405,73 @@ OperationTiming::Scope::Scope(OperationTiming& Outer) : m_Outer(Outer), m_StartT OperationTiming::Scope::~Scope() { - m_Outer.Update(GetHifreqTimerValue() - m_StartTick); + if (m_StartTick != 0) + { + m_Outer.Update(GetHifreqTimerValue() - m_StartTick); + } +} + +void +OperationTiming::Scope::Cancel() +{ + m_StartTick = 0; +} + +////////////////////////////////////////////////////////////////////////// + +RequestStats::RequestStats(int32_t SampleCount) : m_RequestTimeHistogram{SampleCount}, m_BytesHistogram{SampleCount} +{ +} + +RequestStats::~RequestStats() +{ +} + +void +RequestStats::Update(int64_t Duration, int64_t Bytes) +{ + m_RequestMeter.Mark(1); + m_RequestTimeHistogram.Update(Duration); + + m_BytesMeter.Mark(Bytes); + m_BytesHistogram.Update(Bytes); +} + +uint64_t +RequestStats::Count() const +{ + return m_RequestMeter.Count(); } ////////////////////////////////////////////////////////////////////////// void +EmitSnapshot(Meter& Stat, CbObjectWriter& Cbo) +{ + Cbo << "count" << Stat.Count(); + Cbo << "rate_mean" << Stat.MeanRate(); + Cbo << "rate_1" << Stat.Rate1() << "rate_5" << Stat.Rate5() << "rate_15" << Stat.Rate15(); +} + +void +RequestStats::EmitSnapshot(std::string_view Tag, CbObjectWriter& Cbo) +{ + Cbo.BeginObject(Tag); + + Cbo.BeginObject("requests"); + metrics::EmitSnapshot(m_RequestMeter, Cbo); + metrics::EmitSnapshot(m_RequestTimeHistogram, Cbo, GetHifreqTimerToSeconds()); + Cbo.EndObject(); + + Cbo.BeginObject("bytes"); + metrics::EmitSnapshot(m_BytesMeter, Cbo); + metrics::EmitSnapshot(m_BytesHistogram, Cbo, 1.0); + Cbo.EndObject(); + + Cbo.EndObject(); +} + +void EmitSnapshot(std::string_view Tag, OperationTiming& Stat, CbObjectWriter& Cbo) { Cbo.BeginObject(Tag); @@ -411,7 +479,6 @@ EmitSnapshot(std::string_view Tag, OperationTiming& Stat, CbObjectWriter& Cbo) SampleSnapshot Snap = Stat.Snapshot(); Cbo << "count" << Stat.Count(); - Cbo << "rate_mean" << Stat.MeanRate(); Cbo << "rate_1" << Stat.Rate1() << "rate_5" << Stat.Rate5() << "rate_15" << Stat.Rate15(); @@ -426,18 +493,22 @@ EmitSnapshot(std::string_view Tag, OperationTiming& Stat, CbObjectWriter& Cbo) } void -EmitSnapshot(std::string_view Tag, const Histogram& Stat, CbObjectWriter& Cbo) +EmitSnapshot(std::string_view Tag, const Histogram& Stat, CbObjectWriter& Cbo, double ConversionFactor) { Cbo.BeginObject(Tag); + EmitSnapshot(Stat, Cbo, ConversionFactor); + Cbo.EndObject(); +} +void +EmitSnapshot(const Histogram& Stat, CbObjectWriter& Cbo, double ConversionFactor) +{ SampleSnapshot Snap = Stat.Snapshot(); - Cbo << "count" << Stat.Count() << "avg" << Stat.Mean(); - Cbo << "min" << Stat.Min() << "max" << Stat.Max(); - Cbo << "p75" << Snap.Get75Percentile() << "p95" << Snap.Get95Percentile() << "p99" << Snap.Get99Percentile() << "p999" - << Snap.Get999Percentile(); - - Cbo.EndObject(); + Cbo << "count" << Stat.Count() * ConversionFactor << "avg" << Stat.Mean() * ConversionFactor; + Cbo << "min" << Stat.Min() * ConversionFactor << "max" << Stat.Max() * ConversionFactor; + Cbo << "p75" << Snap.Get75Percentile() * ConversionFactor << "p95" << Snap.Get95Percentile() * ConversionFactor << "p99" + << Snap.Get99Percentile() * ConversionFactor << "p999" << Snap.Get999Percentile() * ConversionFactor; } void diff --git a/zencore/timer.cpp b/zencore/timer.cpp index 5d30d9b29..9180519bd 100644 --- a/zencore/timer.cpp +++ b/zencore/timer.cpp @@ -69,6 +69,22 @@ GetHifreqTimerFrequencySafe() } ////////////////////////////////////////////////////////////////////////// + +uint64_t detail::g_LofreqTimerValue = GetHifreqTimerValue(); + +void +UpdateLofreqTimerValue() +{ + detail::g_LofreqTimerValue = GetHifreqTimerValue(); +} + +uint64_t +GetLofreqTimerFrequency() +{ + return GetHifreqTimerFrequencySafe(); +} + +////////////////////////////////////////////////////////////////////////// // // Testing related code follows... // |