This repository has been archived on 2026-05-24. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
AgrarianGameArchive/Scripts/verify_performance_profiling_markers.py
T

110 lines
4.3 KiB
Python

#!/usr/bin/env python3
"""Validate Agrarian Unreal stat and Insights profiling markers."""
from pathlib import Path
import sys
REPO_ROOT = Path(__file__).resolve().parents[1]
STATS = [
"STAT_AgrarianGameStateTick",
"STAT_AgrarianSurvivalTick",
"STAT_AgrarianSkyLightingRefresh",
"STAT_AgrarianWeatherAudioRefresh",
"STAT_AgrarianFoliageInstanceMutation",
"STAT_AgrarianWeatherProviderRequest",
"STAT_AgrarianWeatherProviderParse",
]
SOURCE_MARKERS = {
"Source/AgrarianGame/AgrarianGameState.cpp": [
"TRACE_CPUPROFILER_EVENT_SCOPE(AgrarianGameStateTick)",
"SCOPE_CYCLE_COUNTER(STAT_AgrarianGameStateTick)",
],
"Source/AgrarianGame/AgrarianSurvivalComponent.cpp": [
"TRACE_CPUPROFILER_EVENT_SCOPE(AgrarianSurvivalTick)",
"SCOPE_CYCLE_COUNTER(STAT_AgrarianSurvivalTick)",
],
"Source/AgrarianGame/AgrarianSkyLightingController.cpp": [
"TRACE_CPUPROFILER_EVENT_SCOPE(AgrarianSkyLightingRefresh)",
"SCOPE_CYCLE_COUNTER(STAT_AgrarianSkyLightingRefresh)",
],
"Source/AgrarianGame/AgrarianWeatherAudioController.cpp": [
"TRACE_CPUPROFILER_EVENT_SCOPE(AgrarianWeatherAudioRefresh)",
"SCOPE_CYCLE_COUNTER(STAT_AgrarianWeatherAudioRefresh)",
],
"Source/AgrarianGame/AgrarianFoliagePatch.cpp": [
"TRACE_CPUPROFILER_EVENT_SCOPE(AgrarianFoliageClear)",
"TRACE_CPUPROFILER_EVENT_SCOPE(AgrarianFoliageAddTreeInstance)",
"TRACE_CPUPROFILER_EVENT_SCOPE(AgrarianFoliageAddShrubInstance)",
"TRACE_CPUPROFILER_EVENT_SCOPE(AgrarianFoliageAddGrassInstance)",
"SCOPE_CYCLE_COUNTER(STAT_AgrarianFoliageInstanceMutation)",
],
"Source/AgrarianGame/AgrarianWeatherProviderSubsystem.cpp": [
"TRACE_CPUPROFILER_EVENT_SCOPE(AgrarianWeatherProviderRequest)",
"TRACE_CPUPROFILER_EVENT_SCOPE(AgrarianWeatherProviderFallback)",
"TRACE_CPUPROFILER_EVENT_SCOPE(AgrarianWeatherProviderParseOpenMeteo)",
"TRACE_CPUPROFILER_EVENT_SCOPE(AgrarianWeatherProviderParseNoaaNws)",
"SCOPE_CYCLE_COUNTER(STAT_AgrarianWeatherProviderRequest)",
"SCOPE_CYCLE_COUNTER(STAT_AgrarianWeatherProviderParse)",
],
}
def read_text(relative_path: str) -> str:
path = REPO_ROOT / relative_path
if not path.exists():
raise AssertionError(f"Missing required file: {relative_path}")
return path.read_text(encoding="utf-8")
def require(needle: str, haystack: str, context: str) -> None:
if needle not in haystack:
raise AssertionError(f"Missing {needle!r} in {context}")
def main() -> int:
errors: list[str] = []
try:
header = read_text("Source/AgrarianGame/AgrarianPerformanceStats.h")
source = read_text("Source/AgrarianGame/AgrarianPerformanceStats.cpp")
require("DECLARE_STATS_GROUP(TEXT(\"Agrarian\"), STATGROUP_Agrarian", header, "AgrarianPerformanceStats.h")
for stat in STATS:
require(f"DECLARE_CYCLE_STAT_EXTERN(", header, "AgrarianPerformanceStats.h")
require(stat, header, "AgrarianPerformanceStats.h")
require(f"DEFINE_STAT({stat});", source, "AgrarianPerformanceStats.cpp")
except AssertionError as exc:
errors.append(str(exc))
for relative_path, markers in SOURCE_MARKERS.items():
try:
contents = read_text(relative_path)
require("#include \"AgrarianPerformanceStats.h\"", contents, relative_path)
require("#include \"ProfilingDebugging/CpuProfilerTrace.h\"", contents, relative_path)
for marker in markers:
require(marker, contents, relative_path)
except AssertionError as exc:
errors.append(str(exc))
try:
roadmap = read_text("AGRARIAN_DEVELOPMENT_ROADMAP.md")
require("[x] Add performance profiling markers.", roadmap, "AGRARIAN_DEVELOPMENT_ROADMAP.md")
docs = read_text("Docs/TechnicalDesignDocument.md")
require("stat Agrarian", docs, "Docs/TechnicalDesignDocument.md")
require("Unreal Insights", docs, "Docs/TechnicalDesignDocument.md")
except AssertionError as exc:
errors.append(str(exc))
if errors:
for error in errors:
print(f"ERROR: {error}", file=sys.stderr)
return 1
print("Performance profiling markers are wired.")
return 0
if __name__ == "__main__":
raise SystemExit(main())