445 lines
14 KiB
C++
445 lines
14 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "UbaStats.h"
|
|
#include "UbaLogger.h"
|
|
|
|
namespace uba
|
|
{
|
|
inline void Write(BinaryWriter& writer, u64 v) { writer.Write7BitEncoded(v); }
|
|
inline void Write(BinaryWriter& writer, u32 v) { writer.Write7BitEncoded(v); }
|
|
|
|
inline void Read(BinaryReader& reader, u64& v, u32 version) { v = reader.Read7BitEncoded(); }
|
|
inline void Read(BinaryReader& reader, u32& v, u32 version) { v = u32(reader.Read7BitEncoded()); }
|
|
inline void Read(BinaryReader& reader, Timer& timer, u32 version) { timer.time = reader.Read7BitEncoded(); timer.count = (u32)reader.Read7BitEncoded(); }
|
|
inline void Read(BinaryReader& reader, AtomicU64& v, u32 version) { v = reader.Read7BitEncoded(); }
|
|
inline void Read(BinaryReader& reader, TimeAndBytes& timer, u32 version) { timer.time = reader.Read7BitEncoded(); timer.count = (u32)reader.Read7BitEncoded(); if (version >= 30) timer.bytes = reader.Read7BitEncoded(); }
|
|
|
|
inline bool IsEmpty(u64 v) { return v == 0; }
|
|
inline bool IsEmpty(u32 v) { return v == 0; }
|
|
|
|
const tchar EmptyCharArray[] = TC(" ");
|
|
|
|
void ProcessStats::Print(Logger& logger, u64 frequency)
|
|
{
|
|
if (hostTotalTime)
|
|
{
|
|
logger.Info(TC(" Total %8u %9s"), GetTotalCount(), TimeToText(GetTotalTime(), false, frequency).str);
|
|
logger.Info(TC(" WaitOnResponse %8u %9s"), waitOnResponse.count.load(), TimeToText(waitOnResponse.time, false, frequency).str);
|
|
logger.Info(TC(" Host %17s"), TimeToText(hostTotalTime, false, frequency).str);
|
|
logger.Info(TC(""));
|
|
|
|
struct Stat { const char* name; u64 nameLen; const Timer& timer; };
|
|
Stat stats[] =
|
|
{
|
|
#define UBA_PROCESS_STAT(T, ver) { #T, sizeof(#T), T },
|
|
UBA_PROCESS_STATS
|
|
#undef UBA_PROCESS_STAT
|
|
};
|
|
|
|
for (Stat& s : stats)
|
|
if (s.timer.count)
|
|
logger.Info(TC(" %c") PERCENT_HS TC("%s %8u %9s"), ToUpper(s.name[0]), s.name + 1, EmptyCharArray + s.nameLen, s.timer.count.load(), TimeToText(s.timer.time, false, frequency).str);
|
|
|
|
logger.Info(TC(""));
|
|
|
|
logger.Info(TC(" Startup Time %9s"), TimeToText(startupTime, false, frequency).str);
|
|
logger.Info(TC(" Exit Time %9s"), TimeToText(exitTime, false, frequency).str);
|
|
if (detoursMemory)
|
|
logger.Info(TC(" DetoursMem %9s"), BytesToText(detoursMemory).str);
|
|
}
|
|
if (iopsRead)
|
|
logger.Info(TC(" IopsRead %9llu"), iopsRead.load());
|
|
if (iopsWrite)
|
|
logger.Info(TC(" IopsWrite %9llu"), iopsWrite.load());
|
|
if (iopsOther)
|
|
logger.Info(TC(" IopsOther %9llu"), iopsOther.load());
|
|
|
|
if (peakMemory)
|
|
logger.Info(TC(" PeakMem %9s"), BytesToText(peakMemory).str);
|
|
if (cpuTime)
|
|
logger.Info(TC(" CPU Time %9s"), TimeToText(cpuTime, false, frequency).str);
|
|
logger.Info(TC(" Wall Time %9s"), TimeToText(wallTime, false, frequency).str);
|
|
}
|
|
|
|
u64 ProcessStats::GetTotalTime()
|
|
{
|
|
return
|
|
#define UBA_PROCESS_STAT(T, ver) + T.time
|
|
UBA_PROCESS_STATS
|
|
#undef UBA_PROCESS_STAT
|
|
;
|
|
}
|
|
|
|
u32 ProcessStats::GetTotalCount()
|
|
{
|
|
return
|
|
#define UBA_PROCESS_STAT(T, ver) + T.count
|
|
UBA_PROCESS_STATS
|
|
#undef UBA_PROCESS_STAT
|
|
;
|
|
}
|
|
|
|
void ProcessStats::Read(BinaryReader& reader, u32 version)
|
|
{
|
|
uba::Read(reader, waitOnResponse, version);
|
|
|
|
if (version < 30)
|
|
{
|
|
#define UBA_PROCESS_STAT(T, ver) if (ver <= version) uba::Read(reader, T, version);
|
|
UBA_PROCESS_STATS
|
|
#undef UBA_PROCESS_STAT
|
|
}
|
|
else
|
|
{
|
|
u64 bits = reader.Read7BitEncoded();
|
|
#define UBA_PROCESS_STAT(var, ver) if (bits & (1 << Bit_##var)) uba::Read(reader, var, version);
|
|
UBA_PROCESS_STATS
|
|
#undef UBA_PROCESS_STAT
|
|
}
|
|
|
|
if (version >= 37)
|
|
{
|
|
startupTime = reader.Read7BitEncoded();
|
|
exitTime = reader.Read7BitEncoded();
|
|
wallTime = reader.Read7BitEncoded();
|
|
cpuTime = reader.Read7BitEncoded();
|
|
detoursMemory = reader.Read7BitEncoded();
|
|
peakMemory = reader.Read7BitEncoded();
|
|
if (version >= 39)
|
|
{
|
|
iopsRead = reader.Read7BitEncoded();
|
|
iopsWrite = reader.Read7BitEncoded();
|
|
iopsOther = reader.Read7BitEncoded();
|
|
}
|
|
hostTotalTime = reader.Read7BitEncoded();
|
|
}
|
|
else
|
|
{
|
|
startupTime = reader.ReadU64();
|
|
exitTime = reader.ReadU64();
|
|
wallTime = reader.ReadU64();
|
|
cpuTime = reader.ReadU64();
|
|
detoursMemory = reader.ReadU32();
|
|
hostTotalTime = reader.ReadU64();
|
|
}
|
|
}
|
|
|
|
void ProcessStats::Add(const ProcessStats& other)
|
|
{
|
|
waitOnResponse += other.waitOnResponse;
|
|
|
|
#define UBA_PROCESS_STAT(T, ver) T += other.T;
|
|
UBA_PROCESS_STATS
|
|
#undef UBA_PROCESS_STAT
|
|
|
|
startupTime += other.startupTime;
|
|
exitTime += other.exitTime;
|
|
wallTime += other.wallTime;
|
|
cpuTime += other.cpuTime;
|
|
detoursMemory = Max(detoursMemory, other.detoursMemory);
|
|
peakMemory = Max(peakMemory, other.peakMemory);
|
|
iopsRead += other.iopsRead;
|
|
iopsWrite += other.iopsWrite;
|
|
iopsOther += other.iopsOther;
|
|
hostTotalTime += other.hostTotalTime;
|
|
}
|
|
|
|
template<typename T>
|
|
void LogStat(Logger& logger, const char* name, const T&, u64 frequency) {}
|
|
|
|
void LogStat(Logger& logger, const char* name, const Timer& timer, u64 frequency)
|
|
{
|
|
if (!timer.count)
|
|
return;
|
|
logger.Info(TC(" %c") PERCENT_HS TC("%s %8u %9s"), ToUpper(name[0]), name+1, EmptyCharArray + strlen(name)+1, timer.count.load(), TimeToText(timer.time, false, frequency).str);
|
|
}
|
|
|
|
void LogStat(Logger& logger, const char* name, const ExtendedTimer& timer, u64 frequency)
|
|
{
|
|
LogStat(logger, name, (const Timer&)timer, frequency);
|
|
}
|
|
|
|
void LogStat(Logger& logger, const char* name, const TimeAndBytes& timer, u64 frequency)
|
|
{
|
|
if (!timer.count)
|
|
return;
|
|
logger.Info(TC(" %c") PERCENT_HS TC("%s %8u %9s"), ToUpper(name[0]), name+1, EmptyCharArray + strlen(name)+1, timer.count.load(), TimeToText(timer.time, false, frequency).str);
|
|
if (timer.bytes)
|
|
logger.Info(TC(" Bytes %9s"), BytesToText(timer.bytes).str);
|
|
}
|
|
|
|
void KernelStats::Print(Logger& logger, bool writeHeader, u64 frequency)
|
|
{
|
|
if (writeHeader)
|
|
logger.Info(TC(" ------- Kernel stats summary --------"));
|
|
|
|
#define UBA_KERNEL_STAT(type, var, ver) LogStat(logger, #var, var, frequency);
|
|
UBA_KERNEL_STATS
|
|
#undef UBA_KERNEL_STAT
|
|
|
|
if (writeHeader)
|
|
logger.Info(TC(""));
|
|
}
|
|
|
|
bool KernelStats::IsEmpty()
|
|
{
|
|
#define UBA_KERNEL_STAT(type, var, ver) if (var.count) return false;
|
|
UBA_KERNEL_STATS
|
|
#undef UBA_KERNEL_STAT
|
|
return true;
|
|
}
|
|
|
|
void KernelStats::Add(const KernelStats& other)
|
|
{
|
|
#define UBA_KERNEL_STAT(type, var, ver) var += other.var;
|
|
UBA_KERNEL_STATS
|
|
#undef UBA_KERNEL_STAT
|
|
}
|
|
|
|
void KernelStats::Read(BinaryReader& reader, u32 version)
|
|
{
|
|
if (version < 30)
|
|
{
|
|
#define UBA_KERNEL_STAT(type, var, ver) if (ver <= version) uba::Read(reader, var, version);
|
|
UBA_KERNEL_STATS
|
|
#undef UBA_KERNEL_STAT
|
|
return;
|
|
}
|
|
|
|
u16 bits = reader.ReadU16();
|
|
#define UBA_KERNEL_STAT(type, var, ver) if (bits & (1 << Bit_##var)) uba::Read(reader, var, version);
|
|
UBA_KERNEL_STATS
|
|
#undef UBA_KERNEL_STAT
|
|
}
|
|
|
|
void StorageStats::Write(BinaryWriter& writer)
|
|
{
|
|
u64 bits = 0;
|
|
#define UBA_STORAGE_STAT(type, var, ver) if (!uba::IsEmpty(var)) bits |= (1 << Bit_##var);
|
|
UBA_STORAGE_STATS
|
|
#undef UBA_STORAGE_STAT
|
|
|
|
writer.Write7BitEncoded(bits);
|
|
|
|
#define UBA_STORAGE_STAT(type, var, ver) if (!uba::IsEmpty(var)) uba::Write(writer, var);
|
|
UBA_STORAGE_STATS
|
|
#undef UBA_STORAGE_STAT
|
|
}
|
|
|
|
void StorageStats::Read(BinaryReader& reader, u32 version)
|
|
{
|
|
if (version < 30)
|
|
{
|
|
#define UBA_STORAGE_STAT(type, var, ver) if (ver <= version) uba::Read(reader, var, version);
|
|
UBA_STORAGE_STATS
|
|
#undef UBA_STORAGE_STAT
|
|
return;
|
|
}
|
|
|
|
u64 bits = reader.Read7BitEncoded();
|
|
#define UBA_STORAGE_STAT(type, var, ver) if (bits & (1 << Bit_##var)) uba::Read(reader, var, version);
|
|
UBA_STORAGE_STATS
|
|
#undef UBA_STORAGE_STAT
|
|
}
|
|
|
|
void StorageStats::Add(const StorageStats& other)
|
|
{
|
|
#define UBA_STORAGE_STAT(type, var, ver) var += other.var;
|
|
UBA_STORAGE_STATS
|
|
#undef UBA_STORAGE_STAT
|
|
}
|
|
|
|
void StorageStats::Print(Logger& logger, u64 frequency)
|
|
{
|
|
if (calculateCasKey.count)
|
|
logger.Info(TC(" CalculateCasKeys %6u %9s"), calculateCasKey.count.load(), TimeToText(calculateCasKey.time, false, frequency).str);
|
|
if (ensureCas.count)
|
|
logger.Info(TC(" EnsureCas %6u %9s"), ensureCas.count.load(), TimeToText(ensureCas.time, false, frequency).str);
|
|
if (recvCas.count)
|
|
{
|
|
logger.Info(TC(" ReceiveCas %6u %9s"), recvCas.count.load(), TimeToText(recvCas.time, false, frequency).str);
|
|
logger.Info(TC(" Bytes Raw/Comp %9s %9s"), BytesToText(recvCasBytesRaw).str, BytesToText(recvCasBytesComp).str);
|
|
if (decompressRecv.count)
|
|
logger.Info(TC(" Decompress %6u %9s"), decompressRecv.count.load(), TimeToText(decompressRecv.time, false, frequency).str);
|
|
}
|
|
if (sendCas.count)
|
|
{
|
|
logger.Info(TC(" SendCas %6u %9s"), sendCas.count.load(), TimeToText(sendCas.time, false, frequency).str);
|
|
logger.Info(TC(" Bytes Raw/Comp %9s %9s"), BytesToText(sendCasBytesRaw).str, BytesToText(sendCasBytesComp).str);
|
|
logger.Info(TC(" Compress %6u %9s"), compressSend.count.load(), TimeToText(compressSend.time, false, frequency).str);
|
|
}
|
|
if (createCas.count)
|
|
{
|
|
logger.Info(TC(" CreateCas %6u %9s"), createCas.count.load(), TimeToText(createCas.time, false, frequency).str);
|
|
logger.Info(TC(" Bytes Raw/Comp %9s %9s"), BytesToText(createCasBytesRaw).str, BytesToText(createCasBytesComp).str);
|
|
logger.Info(TC(" Compress %6u %9s"), compressWrite.count.load(), TimeToText(compressWrite.time, false, frequency).str);
|
|
}
|
|
if (copyOrLink.count)
|
|
logger.Info(TC(" CopyOrLink %6u %9s"), copyOrLink.count.load(), TimeToText(copyOrLink.time, false, frequency).str);
|
|
if (copyOrLinkWait.count)
|
|
logger.Info(TC(" CopyOrLinkWait %6u %9s"), copyOrLinkWait.count.load(), TimeToText(copyOrLinkWait.time, false, frequency).str);
|
|
if (compressWrite.count)
|
|
logger.Info(TC(" CompressToMem %6u %9s"), compressWrite.count.load(), TimeToText(compressWrite.time, false, frequency).str);
|
|
if (decompressToMem.count)
|
|
logger.Info(TC(" DecompressToMem %6u %9s"), decompressToMem.count.load(), TimeToText(decompressToMem.time, false, frequency).str);
|
|
|
|
if (memoryCopy.count)
|
|
logger.Info(TC(" MemoryCopy %6u %9s"), memoryCopy.count.load(), TimeToText(memoryCopy.time, false, frequency).str);
|
|
}
|
|
|
|
bool StorageStats::IsEmpty()
|
|
{
|
|
#define UBA_STORAGE_STAT(type, var, ver) if (var != type()) return false;
|
|
UBA_STORAGE_STATS
|
|
#undef UBA_STORAGE_STAT
|
|
return true;
|
|
}
|
|
|
|
thread_local StorageStats* t_storageStats;
|
|
|
|
StorageStats* StorageStats::GetCurrent()
|
|
{
|
|
return t_storageStats;
|
|
}
|
|
|
|
|
|
StorageStatsScope::StorageStatsScope(StorageStats& s) : stats(s)
|
|
{
|
|
t_storageStats = &stats;
|
|
}
|
|
|
|
StorageStatsScope::~StorageStatsScope()
|
|
{
|
|
t_storageStats = nullptr;
|
|
}
|
|
|
|
|
|
void SessionStats::Write(BinaryWriter& writer)
|
|
{
|
|
u16 bits = 0;
|
|
#define UBA_SESSION_STAT(type, var, ver) if (var.count) bits |= (1 << Bit_##var);
|
|
UBA_SESSION_STATS
|
|
#undef UBA_SESSION_STAT
|
|
|
|
writer.WriteU16(bits);
|
|
|
|
#define UBA_SESSION_STAT(type, var, ver) if (var.count) uba::Write(writer, var);
|
|
UBA_SESSION_STATS
|
|
#undef UBA_SESSION_STAT
|
|
}
|
|
|
|
void SessionStats::Read(BinaryReader& reader, u32 version)
|
|
{
|
|
if (version < 30)
|
|
{
|
|
#define UBA_SESSION_STAT(type, var, ver) if (ver <= version) uba::Read(reader, var, version);
|
|
UBA_SESSION_STATS
|
|
#undef UBA_SESSION_STAT
|
|
return;
|
|
}
|
|
|
|
u16 bits = reader.ReadU16();
|
|
#define UBA_SESSION_STAT(type, var, ver) if (bits & (1 << Bit_##var)) uba::Read(reader, var, version);
|
|
UBA_SESSION_STATS
|
|
#undef UBA_SESSION_STAT
|
|
}
|
|
|
|
void SessionStats::Add(const SessionStats& other)
|
|
{
|
|
#define UBA_SESSION_STAT(type, var, ver) var += other.var;
|
|
UBA_SESSION_STATS
|
|
#undef UBA_SESSION_STAT
|
|
}
|
|
|
|
void SessionStats::Print(Logger& logger, u64 frequency)
|
|
{
|
|
#define UBA_SESSION_STAT(type, var, ver) LogStat(logger, #var, var, frequency);
|
|
UBA_SESSION_STATS
|
|
#undef UBA_SESSION_STAT
|
|
}
|
|
|
|
bool SessionStats::IsEmpty()
|
|
{
|
|
#define UBA_SESSION_STAT(type, var, ver) if (var.count) return false;
|
|
UBA_SESSION_STATS
|
|
#undef UBA_SESSION_STAT
|
|
return true;
|
|
}
|
|
|
|
thread_local SessionStats* t_sessionStats;
|
|
|
|
SessionStats* SessionStats::GetCurrent()
|
|
{
|
|
return t_sessionStats;
|
|
}
|
|
|
|
|
|
SessionStatsScope::SessionStatsScope(SessionStats& s) : stats(s)
|
|
{
|
|
t_sessionStats = &stats;
|
|
}
|
|
|
|
SessionStatsScope::~SessionStatsScope()
|
|
{
|
|
t_sessionStats = nullptr;
|
|
}
|
|
|
|
void SessionSummaryStats::Write(BinaryWriter& writer)
|
|
{
|
|
stats.Write(writer);
|
|
#define UBA_SESSION_SUMMARY_STAT(type, var) uba::Write(writer, var);
|
|
UBA_SESSION_SUMMARY_STATS
|
|
#undef UBA_SESSION_SUMMARY_STAT
|
|
}
|
|
|
|
void SessionSummaryStats::Read(BinaryReader& reader, u32 version)
|
|
{
|
|
stats.Read(reader, version);
|
|
#define UBA_SESSION_SUMMARY_STAT(type, var) uba::Read(reader, var, version);
|
|
UBA_SESSION_SUMMARY_STATS
|
|
#undef UBA_SESSION_SUMMARY_STAT
|
|
}
|
|
|
|
void SessionSummaryStats::Print(Logger& logger, u64 frequency)
|
|
{
|
|
#define UBA_SESSION_SUMMARY_STAT(T, V) LogStat(logger, #V, V, frequency);
|
|
UBA_SESSION_SUMMARY_STATS
|
|
#undef UBA_SESSION_SUMMARY_STAT
|
|
stats.Print(logger, frequency);
|
|
logger.Info(TC(" MemoryPressureWait %9s"), TimeToText(waitMemPressure, false, frequency).str);
|
|
logger.Info(TC(" ProcessesKilled %9llu"), killCount);
|
|
logger.Info(TC(""));
|
|
}
|
|
|
|
void CacheStats::Write(BinaryWriter& writer)
|
|
{
|
|
#define UBA_CACHE_STAT(type, var, ver) uba::Write(writer, var);
|
|
UBA_CACHE_STATS
|
|
#undef UBA_CACHE_STAT
|
|
}
|
|
|
|
void CacheStats::Read(BinaryReader& reader, u32 version)
|
|
{
|
|
#define UBA_CACHE_STAT(type, var, ver) if (ver <= version) uba::Read(reader, var, version);
|
|
UBA_CACHE_STATS
|
|
#undef UBA_CACHE_STAT
|
|
}
|
|
|
|
void CacheStats::Print(Logger& logger, u64 frequency)
|
|
{
|
|
#define UBA_CACHE_STAT(type, var, ver) LogStat(logger, #var, var, frequency);
|
|
UBA_CACHE_STATS
|
|
#undef UBA_CACHE_STAT
|
|
if (fetchBytesComp)
|
|
logger.Info(TC(" Bytes Raw/Comp %9s %9s"), BytesToText(fetchBytesRaw).str, BytesToText(fetchBytesComp).str);
|
|
}
|
|
|
|
bool CacheStats::IsEmpty()
|
|
{
|
|
#define UBA_CACHE_STAT(type, var, ver) if (var != type()) return false;
|
|
UBA_CACHE_STATS
|
|
#undef UBA_CACHE_STAT
|
|
return true;
|
|
}
|
|
}
|