aboutsummaryrefslogtreecommitdiff
path: root/src/zen/trace/trace_cache.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/zen/trace/trace_cache.cpp')
-rw-r--r--src/zen/trace/trace_cache.cpp120
1 files changed, 120 insertions, 0 deletions
diff --git a/src/zen/trace/trace_cache.cpp b/src/zen/trace/trace_cache.cpp
index 165c1eecf..954df14e0 100644
--- a/src/zen/trace/trace_cache.cpp
+++ b/src/zen/trace/trace_cache.cpp
@@ -448,6 +448,53 @@ namespace {
return ToSharedBuffer(W);
}
+ // -- Counters section --
+
+ SharedBuffer WriteCountersSection(const TraceModel& Model, StringTableBuilder& Strings)
+ {
+ BinaryWriter W;
+
+ uint32_t DefCount = uint32_t(Model.CounterDefs.size());
+ WritePod(W, DefCount);
+ for (const TraceModel::CounterDef& D : Model.CounterDefs)
+ {
+ CounterDefPod P = {};
+ P.Id = D.Id;
+ P.Type = D.Type;
+ P.DisplayHint = D.DisplayHint;
+ P.Name = Strings.Intern(D.Name);
+ WritePod(W, P);
+ }
+
+ uint32_t SeriesCount = uint32_t(Model.CounterTimeSeries.size());
+ WritePod(W, SeriesCount);
+ // First pass: headers (so the reader can size each series before it
+ // reads samples).
+ for (const TraceModel::CounterSeries& S : Model.CounterTimeSeries)
+ {
+ CounterHeaderPod H = {};
+ H.Id = S.Id;
+ H.Type = S.Type;
+ H.SampleCount = uint32_t(S.Samples.size());
+ H.Min = S.Min;
+ H.Max = S.Max;
+ WritePod(W, H);
+ }
+ // Second pass: contiguous sample blob in the same order as headers.
+ for (const TraceModel::CounterSeries& S : Model.CounterTimeSeries)
+ {
+ for (const TraceModel::CounterSample& Sample : S.Samples)
+ {
+ CounterSamplePod SP = {};
+ SP.TimeUs = Sample.TimeUs;
+ SP.Value = Sample.Value;
+ WritePod(W, SP);
+ }
+ }
+
+ return ToSharedBuffer(W);
+ }
+
// -- Symbols section --
SharedBuffer WriteSymbolsSection(const eastl::hash_map<uint64_t, std::string>& ResolvedSymbols, StringTableBuilder& Strings)
@@ -860,6 +907,67 @@ namespace {
return true;
}
+ bool ReadCountersSection(const SharedBuffer& Data, const StringTableReader& Strings, TraceModel& Model)
+ {
+ BinaryReader R(Data.GetData(), Data.GetSize());
+
+ uint32_t DefCount = 0;
+ if (!ReadUint32(R, DefCount))
+ {
+ return false;
+ }
+ Model.CounterDefs.resize(DefCount);
+ for (uint32_t I = 0; I < DefCount; ++I)
+ {
+ CounterDefPod P;
+ if (!ReadPod(R, P))
+ {
+ return false;
+ }
+ Model.CounterDefs[I].Id = P.Id;
+ Model.CounterDefs[I].Type = P.Type;
+ Model.CounterDefs[I].DisplayHint = P.DisplayHint;
+ Model.CounterDefs[I].Name = std::string(Strings.Get(P.Name));
+ }
+
+ uint32_t SeriesCount = 0;
+ if (!ReadUint32(R, SeriesCount))
+ {
+ return false;
+ }
+ eastl::vector<CounterHeaderPod> Headers(SeriesCount);
+ for (uint32_t I = 0; I < SeriesCount; ++I)
+ {
+ if (!ReadPod(R, Headers[I]))
+ {
+ return false;
+ }
+ }
+ Model.CounterTimeSeries.resize(SeriesCount);
+ for (uint32_t I = 0; I < SeriesCount; ++I)
+ {
+ const CounterHeaderPod& H = Headers[I];
+ TraceModel::CounterSeries& Out = Model.CounterTimeSeries[I];
+ Out.Id = H.Id;
+ Out.Type = H.Type;
+ Out.Count = H.SampleCount;
+ Out.Min = H.Min;
+ Out.Max = H.Max;
+ Out.Samples.resize(H.SampleCount);
+ for (uint32_t J = 0; J < H.SampleCount; ++J)
+ {
+ CounterSamplePod SP;
+ if (!ReadPod(R, SP))
+ {
+ return false;
+ }
+ Out.Samples[J].TimeUs = SP.TimeUs;
+ Out.Samples[J].Value = SP.Value;
+ }
+ }
+ return true;
+ }
+
// ===========================================================================
// File-level helpers
// ===========================================================================
@@ -913,6 +1021,7 @@ WriteAnalyzeCache(const std::filesystem::path& CachePath,
SharedBuffer MemoryRaw = WriteMemorySection(Model, Strings);
SharedBuffer CallstacksRaw = WriteCallstacksSection(Model);
SharedBuffer SymbolsRaw = WriteSymbolsSection(ResolvedSymbols, Strings);
+ SharedBuffer CountersRaw = WriteCountersSection(Model, Strings);
SharedBuffer StringTableRaw = Strings.Serialize();
// Compress each section
@@ -922,6 +1031,7 @@ WriteAnalyzeCache(const std::filesystem::path& CachePath,
Sections[uint32_t(CacheSectionId::Memory)] = CompressSection(MemoryRaw);
Sections[uint32_t(CacheSectionId::Callstacks)] = CompressSection(CallstacksRaw);
Sections[uint32_t(CacheSectionId::Symbols)] = CompressSection(SymbolsRaw);
+ Sections[uint32_t(CacheSectionId::Counters)] = CompressSection(CountersRaw);
// Build file header
CacheFileHeader Header = {};
@@ -1091,6 +1201,16 @@ TryLoadAnalyzeCache(const std::filesystem::path& CachePath, const std::filesyste
}
}
+ SharedBuffer CountersData = DecompressSection(Base, Directory[uint32_t(CacheSectionId::Counters)]);
+ if (!CountersData.IsNull())
+ {
+ if (!ReadCountersSection(CountersData, Strings, Result.Model))
+ {
+ ZEN_DEBUG("Analysis cache: failed to read counters section");
+ // Counters are optional -- continue without them.
+ }
+ }
+
ZEN_INFO("Loaded analysis from cache ({})", zen::NiceBytes(FileData.Size()));
return Result;
}