Files
MobileGL/tools/device_bench/disagg/crosshost_report.py
T

74 lines
3.7 KiB
Python

#!/usr/bin/env python3
# MobileGL - tools/device_bench/disagg/crosshost_report.py
# Copyright (c) 2025-2026 MobileGL-Dev
# Licensed under the GNU Lesser General Public License v3.0:
# https://www.gnu.org/licenses/gpl-3.0.txt
# https://www.gnu.org/licenses/lgpl-3.0.txt
# SPDX-License-Identifier: LGPL-3.0-only
# End of Source File Header
"""Reduce crosshost_accept.sh output (.trace-work/perf-compare/crosshost/<run>/) to a table."""
import json, os, re, statistics, sys
root = sys.argv[1] if len(sys.argv) > 1 else os.path.join(
os.path.dirname(__file__), "..", "..", "..", ".trace-work", "perf-compare", "crosshost")
def load(path):
try:
with open(path, encoding="utf-8") as f:
return json.load(f)
except Exception:
return None
def kv(line):
return dict(re.findall(r"(\w+)=([^\s]+)", line))
rows = []
for name in sorted(os.listdir(root)):
d = os.path.join(root, name)
if not os.path.isdir(d):
continue
rc = open(os.path.join(d, "rc.txt")).read().strip() if os.path.exists(os.path.join(d, "rc.txt")) else "?"
res = load(os.path.join(d, "result.json")) or {}
bench = load(os.path.join(d, "benchmark.json")) or {}
summary = {}
frame_bytes = {}
client = os.path.join(d, "mobilegl.client.log")
if os.path.exists(client):
for line in open(client, encoding="utf-8", errors="replace"):
if "P65LinkMetrics kind=summary" in line:
summary = kv(line)
elif "P65LinkMetrics kind=frame " in line:
f = kv(line)
frame_bytes[int(f["frame"])] = int(f["stage_bytes"])
ft = bench.get("frameTimesMs") or []
# Steady state = every frame after the first (the load frame carries the whole texture upload).
steady = [k for k in sorted(frame_bytes) if 2 <= k <= len(ft)]
steady_s = sum(ft[k - 1] for k in steady) / 1000 if steady else 0
steady_mb = sum(frame_bytes[k] for k in steady) / 1e6 if steady else 0
rows.append({
"run": name, "rc": rc,
"ssim": res.get("ssim") if "ssim" in name else None,
"frames": bench.get("totalFrames"),
"fps": bench.get("fps"), "mean_ms": bench.get("meanFrameMs"),
"median_ms": bench.get("medianFrameMs"), "p95_ms": bench.get("p95FrameMs"),
"first_frame_s": round(ft[0] / 1000, 1) if ft else None,
"steady_fps": round(1000 / statistics.median(ft[1:]), 1) if len(ft) > 2 else None,
"steady_MB_per_frame": round(steady_mb / len(steady), 2) if steady else None,
"steady_MBps": round(steady_mb / steady_s, 1) if steady_s else None,
"wait_replies": summary.get("wait_replies"),
"rtt_mean_ms": round(float(summary["rtt_mean_us"]) / 1000, 1) if "rtt_mean_us" in summary else None,
"rtt_p50_ub_ms": round(int(summary["rtt_p50_upper_us"]) / 1000, 1) if "rtt_p50_upper_us" in summary else None,
"rtt_p99_ub_ms": round(int(summary["rtt_p99_upper_us"]) / 1000, 1) if "rtt_p99_upper_us" in summary else None,
"stage_MB": round(int(summary["stage_bytes"]) / 1e6) if "stage_bytes" in summary else None,
"client_cpu_s": round(int(summary["client_thread_cpu_ns"]) / 1e9, 1) if "client_thread_cpu_ns" in summary else None,
"wall_s": round(int(summary["wall_ns"]) / 1e9, 1) if "wall_ns" in summary else None,
})
cols = ["run", "rc", "ssim", "frames", "fps", "steady_fps", "median_ms", "p95_ms", "first_frame_s",
"steady_MB_per_frame", "steady_MBps", "wait_replies", "rtt_mean_ms", "rtt_p50_ub_ms", "rtt_p99_ub_ms", "stage_MB", "client_cpu_s", "wall_s"]
print("| " + " | ".join(cols) + " |")
print("|" + "---|" * len(cols))
for r in rows:
print("| " + " | ".join("" if r[c] is None else str(r[c]) for c in cols) + " |")