mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-08 04:08:32 +09:00
[Feat] (Metrics, Config): make the boundary-counter summary cadence a knob, because the device harness never reaches the teardown dump
- MOBILEGL_PIPE_STATS_PERIOD (default 120, clamped to [1, 1000000]) sets the frames per summary line; Init() latches it and a zero falls back to the default - the trace APK's replay never tears MobileGL down, so MOBILEGL_PIPE_STATS_FILE never fires on device and a fixture shorter than the period (create-indirect) reported nothing - PipeStatsTest pins the latch and the zero fallback
This commit is contained in:
@@ -347,6 +347,11 @@ namespace MobileGL::MG_Config {
|
||||
// the server without shipping index bytes per draw. Over budget it degrades to
|
||||
// per-draw staging, counted separately in the stats.
|
||||
Uint32 PipeIndexMirrorMb = 64;
|
||||
// MOBILEGL_PIPE_STATS_PERIOD: frames per boundary-counter summary line. 120 is the
|
||||
// steady-state cadence; the device retrace harness never reaches the teardown dump
|
||||
// and a trimmed fixture (create-indirect) is shorter than 120 frames, so a run that
|
||||
// needs its numbers at all sets this low enough to land at least one window.
|
||||
Uint32 PipeStatsPeriod = 120;
|
||||
// MOBILEGL_PIPE_STATS_FILE: where the boundary counters' teardown JSON dump goes.
|
||||
// Empty (the default) means no dump; the per-120-frame summary line still goes to
|
||||
// the log whenever PipeStats is on, so a device run needs no writable path.
|
||||
|
||||
@@ -252,6 +252,7 @@ namespace MobileGL::MG_ConfigLoader {
|
||||
QueryEnvQuirkOverride("MOBILEGL_PIPE_LEGACY_MEMOS") != MG_Config::QuirkOverride::ForceOff;
|
||||
features.PipeTexelRetainMb = QueryEnvUint32("MOBILEGL_PIPE_TEXEL_RETAIN_MB", 0, 0, 4096);
|
||||
features.PipeIndexMirrorMb = QueryEnvUint32("MOBILEGL_PIPE_INDEX_MIRROR_MB", 64, 0, 4096);
|
||||
features.PipeStatsPeriod = QueryEnvUint32("MOBILEGL_PIPE_STATS_PERIOD", 120, 1, 1000000);
|
||||
QueryEnvVariable("MOBILEGL_PIPE_STATS_FILE", features.PipeStatsFile, "");
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <Config.h>
|
||||
#include <MG_Util/Metrics/PipeStats.h>
|
||||
|
||||
#include <cstdio>
|
||||
@@ -77,6 +78,21 @@ namespace {
|
||||
EXPECT_EQ(PS::FrameCount(), 1u);
|
||||
}
|
||||
|
||||
TEST_F(PipeStatsTest, InitLatchesTheSummaryPeriodFromTheConfigAndNeverKeepsZero) {
|
||||
// The device retrace harness never reaches the teardown dump, so the summary
|
||||
// cadence is the only way a short fixture yields numbers at all: it must follow
|
||||
// MOBILEGL_PIPE_STATS_PERIOD, and a zero must fall back rather than divide.
|
||||
const Uint32 saved = MobileGL::MG_Config::Features.PipeStatsPeriod;
|
||||
MobileGL::MG_Config::Features.PipeStatsPeriod = 7;
|
||||
PS::Init();
|
||||
EXPECT_EQ(PS::SummaryFramePeriod(), 7u);
|
||||
MobileGL::MG_Config::Features.PipeStatsPeriod = 0;
|
||||
PS::Init();
|
||||
EXPECT_EQ(PS::SummaryFramePeriod(), PS::kDefaultSummaryFramePeriod);
|
||||
MobileGL::MG_Config::Features.PipeStatsPeriod = saved;
|
||||
PS::Init();
|
||||
}
|
||||
|
||||
TEST_F(PipeStatsTest, GateHitsAndMissesAreSeparateCounters) {
|
||||
for (Uint32 i = 0; i < 5; ++i) {
|
||||
PS::CountGate(PS::Gate::MagmaPipelineMemo, /*hit=*/true);
|
||||
@@ -262,10 +278,10 @@ namespace {
|
||||
// A summary is emitted every kSummaryFramePeriod presents. The period is a constant the
|
||||
// smoke check depends on, so a change to it has to break a test.
|
||||
TEST_F(PipeStatsTest, SummaryPeriodIsOneHundredAndTwentyFrames) {
|
||||
EXPECT_EQ(PS::kSummaryFramePeriod, 120u);
|
||||
for (Uint64 i = 0; i < PS::kSummaryFramePeriod; ++i) {
|
||||
EXPECT_EQ(PS::SummaryFramePeriod(), 120u);
|
||||
for (Uint64 i = 0; i < PS::SummaryFramePeriod(); ++i) {
|
||||
PS::OnPresent();
|
||||
}
|
||||
EXPECT_EQ(PS::FrameCount(), PS::kSummaryFramePeriod);
|
||||
EXPECT_EQ(PS::FrameCount(), PS::SummaryFramePeriod());
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@@ -130,6 +130,8 @@ namespace MobileGL::MG_Util::PipeStats {
|
||||
Uint64 g_windowBaseFrames = 0;
|
||||
Bool g_shutdownDone = false;
|
||||
|
||||
// Frames per summary line, latched by Init() from MOBILEGL_PIPE_STATS_PERIOD.
|
||||
Uint64 g_summaryPeriod = kDefaultSummaryFramePeriod;
|
||||
inline void Bump(Counter& counter, Uint64 amount) {
|
||||
counter.fetch_add(amount, std::memory_order_relaxed);
|
||||
}
|
||||
@@ -253,14 +255,19 @@ namespace MobileGL::MG_Util::PipeStats {
|
||||
ResetCounters();
|
||||
g_shutdownDone = false;
|
||||
g_pipeStatsEnabled = MG_Config::Features.PipeStats;
|
||||
g_summaryPeriod = MG_Config::Features.PipeStatsPeriod == 0
|
||||
? kDefaultSummaryFramePeriod
|
||||
: static_cast<Uint64>(MG_Config::Features.PipeStatsPeriod);
|
||||
if (g_pipeStatsEnabled) {
|
||||
MGLOG_I("MGPipe stats: counters ON (MOBILEGL_PIPE_STATS), summary every %llu frames%s%s",
|
||||
static_cast<unsigned long long>(kSummaryFramePeriod),
|
||||
static_cast<unsigned long long>(g_summaryPeriod),
|
||||
MG_Config::Features.PipeStatsFile.empty() ? "" : ", JSON dump to ",
|
||||
MG_Config::Features.PipeStatsFile.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
Uint64 SummaryFramePeriod() { return g_summaryPeriod; }
|
||||
|
||||
void Shutdown() {
|
||||
if (!g_pipeStatsEnabled || g_shutdownDone) {
|
||||
return;
|
||||
@@ -336,7 +343,7 @@ namespace MobileGL::MG_Util::PipeStats {
|
||||
#endif
|
||||
}
|
||||
const Uint64 frames = g_frameCount.fetch_add(1, std::memory_order_relaxed) + 1;
|
||||
if (frames % kSummaryFramePeriod == 0) {
|
||||
if (frames % g_summaryPeriod == 0) {
|
||||
EmitSummaryLine();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,7 +129,10 @@ namespace MobileGL::MG_Util::PipeStats {
|
||||
inline constexpr Uint32 kPayloadHistogramBuckets = 24;
|
||||
|
||||
// Frames between two summary lines when MOBILEGL_PIPE_STATS=1.
|
||||
inline constexpr Uint64 kSummaryFramePeriod = 120;
|
||||
inline constexpr Uint64 kDefaultSummaryFramePeriod = 120;
|
||||
// The period Init() latched from MOBILEGL_PIPE_STATS_PERIOD (kDefaultSummaryFramePeriod
|
||||
// when unset); never 0.
|
||||
Uint64 SummaryFramePeriod();
|
||||
|
||||
// The latch. Read directly by Enabled() so the off path is a global load and a
|
||||
// predicted branch - do not turn this into a function call.
|
||||
|
||||
Reference in New Issue
Block a user