aboutsummaryrefslogtreecommitdiff
path: root/zencore
diff options
context:
space:
mode:
authorMartin Ridgers <[email protected]>2021-10-07 08:29:50 +0200
committerMartin Ridgers <[email protected]>2021-10-07 08:29:50 +0200
commit03232621d183f22e12e798a753e4a606763e63d6 (patch)
tree5701d202392dd4ab947139e4046a44ab9bc6cdf7 /zencore
parentMerged main (diff)
parentOnly enable the MSVC debug output sink for sessions when the --debug mode is ... (diff)
downloadzen-03232621d183f22e12e798a753e4a606763e63d6.tar.xz
zen-03232621d183f22e12e798a753e4a606763e63d6.zip
Merged main
Diffstat (limited to 'zencore')
-rw-r--r--zencore/compactbinary.cpp51
-rw-r--r--zencore/filesystem.cpp24
-rw-r--r--zencore/include/zencore/blockingqueue.h75
-rw-r--r--zencore/include/zencore/filesystem.h5
-rw-r--r--zencore/include/zencore/iobuffer.h8
-rw-r--r--zencore/include/zencore/refcount.h10
-rw-r--r--zencore/include/zencore/stats.h64
-rw-r--r--zencore/include/zencore/timer.h15
-rw-r--r--zencore/iobuffer.cpp81
-rw-r--r--zencore/stats.cpp91
-rw-r--r--zencore/timer.cpp16
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...
//