feat: add STEP-113 Android PBF fast gate diagnostics
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled

This commit is contained in:
tei
2026-10-11 09:11:27 +09:00
parent c6d13e1059
commit 92efa36f4c
14 changed files with 1368 additions and 5 deletions

View File

@@ -1,6 +1,7 @@
#pragma once
#include <mln/renderer/render_segment.hpp>
#include <mln/renderer/particle_fast_path.hpp>
#include <rapidjson/document.h>
#include <rapidjson/stringbuffer.h>
@@ -107,11 +108,141 @@ inline void writeStyleLayerDiagnostics(Writer& writer, const StyleLayerDiagnosti
writer.EndObject();
}
template <typename Writer>
inline void writeFastGatePhase(Writer& w, const FastGatePhaseSample& p, const char* phase,
const char* placementBasis = "previous-completed-render-tree") {
w.StartObject();
w.Key("phase"); w.String(phase);
w.Key("placementBasis"); w.String(!p.hasPlacementSnapshot ? "UNKNOWN/no-completed-snapshot"
: placementBasis);
w.Key("placementChanged"); w.Bool(p.placementChanged);
w.Key("symbolFadeChange"); w.Double(p.symbolFadeChange);
w.Key("placementTransitionActive"); w.Bool(p.placementTransitionActive);
w.Key("contentRevision"); w.Uint64(p.contentRevision);
w.Key("topologyRevision"); w.Uint64(p.topologyRevision);
w.Key("configRevision"); w.Uint64(p.configRevision);
w.Key("fullCpuFrame"); w.Uint64(p.fullCpuFrame);
w.Key("processSimulationAdvance");
if (p.processSimulationAdvance) w.Uint64(*p.processSimulationAdvance); else w.Null();
w.Key("retainedSamplesTruncated"); w.Bool(p.retainedSamplesTruncated);
w.Key("retained"); w.StartArray();
for (const auto& r : p.retained) {
const auto& c = r.cache;
w.StartObject();
w.Key("segmentIndex"); w.Uint(r.segmentIndex);
w.Key("cacheState"); w.String(c.cacheState.c_str());
w.Key("build"); w.Uint64(c.build);
w.Key("reuse"); w.Uint64(c.reuse);
w.Key("invalidation"); w.Uint64(c.invalidation);
w.Key("fallbackCount"); w.Uint64(c.fallbackCount);
w.Key("contentRevision"); w.Uint64(c.contentRevision);
w.Key("sourceRevision"); w.Uint64(c.sourceRevision);
w.Key("sourceReady"); w.Bool(c.sourceReady);
w.Key("sourceStable"); w.Bool(c.sourceStable);
w.Key("supported"); w.Bool(c.supported);
w.Key("finalDecision"); w.String(c.finalDecision.c_str());
w.Key("lastInvalidationReason"); w.String(c.lastInvalidationReason.c_str());
w.Key("lastFallbackReason"); w.String(c.lastFallbackReason.c_str());
w.Key("placementGatePassed"); w.Bool(r.placementGatePassed);
w.Key("actualExecution"); w.String(r.actualExecution.c_str());
w.EndObject();
}
w.EndArray();
w.EndObject();
}
template <typename Writer>
inline void writeFastGateTrace(Writer& w, const FastGateTraceDiagnostics& t) {
w.StartObject();
w.Key("schemaVersion"); w.Uint(t.schemaVersion);
w.Key("capacity"); w.Uint(120);
w.Key("retainedLimitPerPhase"); w.Uint(16);
w.Key("lifecycle"); w.Uint64(t.lifecycle);
w.Key("attempts"); w.Uint64(t.attempts);
w.Key("overwritten"); w.Uint64(t.overwritten);
w.Key("decisionMismatch"); w.Uint64(t.decisionMismatch);
w.Key("fullRendered"); w.Uint64(t.fullRendered);
w.Key("fastRendered"); w.Uint64(t.fastRendered);
w.Key("noRender"); w.Uint64(t.noRender);
w.Key("windowCount"); w.Uint(static_cast<unsigned>(t.frames.size()));
w.Key("windowBeginSequence"); w.Uint64(t.frames.empty() ? 0 : t.frames.front().sequence);
w.Key("windowEndSequence"); w.Uint64(t.frames.empty() ? 0 : t.frames.back().sequence);
uint64_t windowFull = 0, windowFast = 0, windowNoRender = 0;
std::array<uint64_t, 24> windowFailures{};
for (const auto& f : t.frames) {
if (f.completed && f.outcome == "full-rendered") ++windowFull;
else if (f.completed && f.outcome == "fast-rendered") ++windowFast;
else if (f.completed) ++windowNoRender;
for (std::size_t i = 0; i < 24; ++i) if (f.failMask & (uint32_t{1} << i)) ++windowFailures[i];
}
w.Key("windowFullRendered"); w.Uint64(windowFull);
w.Key("windowFastRendered"); w.Uint64(windowFast);
w.Key("windowNoRender"); w.Uint64(windowNoRender);
w.Key("gates"); w.StartArray();
for (std::size_t i = 0; i < particleFastGateReasons.size(); ++i) {
w.StartObject();
w.Key("order"); w.Uint(static_cast<unsigned>(i + 1));
w.Key("reason"); w.String(particleFastPathMissReasonText(particleFastGateReasons[i]));
w.Key("failures"); w.Uint64(t.failureCounts[i]);
w.Key("firstFailures"); w.Uint64(t.firstFailureCounts[i]);
w.Key("windowFailures"); w.Uint64(windowFailures[i]);
w.EndObject();
}
w.EndArray();
w.Key("frames"); w.StartArray();
for (const auto& f : t.frames) {
w.StartObject();
w.Key("sequence"); w.Uint64(f.sequence);
w.Key("frame"); w.Uint64(f.frame);
w.Key("updateTimeNs"); w.Int64(f.updateTimeNs);
w.Key("knownMask"); w.Uint(f.knownMask);
w.Key("failMask"); w.Uint(f.failMask);
w.Key("firstFailure"); w.String(f.firstFailure.c_str());
w.Key("decisionConsistent"); w.Bool(f.decisionConsistent);
w.Key("candidate"); w.Bool(f.candidate);
w.Key("preFastPlacementTransition"); w.Bool(f.preFastPlacementTransition);
w.Key("placementTransitionsEnabled"); w.Bool(f.placementTransitionsEnabled);
w.Key("completed"); w.Bool(f.completed);
w.Key("outcome"); w.String(f.outcome.c_str());
w.Key("gateStatus"); w.StartArray();
for (std::size_t i = 0; i < 24; ++i) {
const auto bit = uint32_t{1} << i;
w.String(!(f.knownMask & bit) ? "UNKNOWN" : (f.failMask & bit) ? "FAIL" : "PASS");
}
w.EndArray();
w.Key("cacheInputsTruncated"); w.Bool(f.cacheInputsTruncated);
w.Key("cacheInputs"); w.StartArray();
for (const auto& c : f.cacheInputs) {
w.StartObject();
w.Key("segmentIndex"); w.Uint(c.segmentIndex);
w.Key("exists"); w.Bool(c.exists);
w.Key("valid"); w.Bool(c.valid);
w.Key("buildRevision"); w.Uint64(c.buildRevision);
w.Key("staticRevision"); w.Uint64(c.staticRevision);
w.EndObject();
}
w.EndArray();
w.Key("pre"); writeFastGatePhase(w, f.pre, "pre-fast");
w.Key("post");
if (f.completed) {
writeFastGatePhase(w, f.post, "post-render", f.outcome == "full-rendered"
? "current-full-render-tree" : f.outcome == "fast-rendered"
? "current-fast-render-tree/no-new-placement" : "previous-completed-render-tree");
} else w.Null();
w.EndObject();
}
w.EndArray();
w.EndObject();
}
inline std::string renderSegmentDiagnosticsToJSON(const RenderSegmentDiagnostics& snapshot) {
rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
writer.StartObject();
writer.Key("schemaVersion"); writer.Uint(snapshot.schemaVersion);
if (snapshot.fastGateTrace) {
writer.Key("fastGateTrace"); writeFastGateTrace(writer, *snapshot.fastGateTrace);
}
writer.Key("enabled"); writer.Bool(snapshot.enabled);
writer.Key("configured"); writer.Bool(snapshot.configured);
writer.Key("valid"); writer.Bool(snapshot.valid);