Files
RFP_Infinity-Vis/Infinity_Vis_1/infinity_vis_1/benchmark.py

83 lines
3.0 KiB
Python

from __future__ import annotations
import argparse
from pathlib import Path
import time
from .engine import OutputSettings, RealtimeEngine
from .mapping_xml import load_mapping
from .models import PatternParams, SceneState
from .patterns import pattern_ids
from .renderer import FastRenderer
def main() -> None:
parser = argparse.ArgumentParser(description="Benchmark the Infinity_Vis_1 render core.")
parser.add_argument(
"--mapping",
type=Path,
default=Path(__file__).resolve().parents[2] / "sample_data" / "infinity_mirror_mapping_clean.xml",
help="Path to the XML mapping file.",
)
parser.add_argument("--frames", type=int, default=600, help="Frames per pattern.")
parser.add_argument("--pattern", type=str, default="", help="Benchmark a single pattern id.")
parser.add_argument(
"--mode",
type=str,
default="render",
choices=["render", "engine"],
help="Benchmark only the renderer or the new runtime engine loop.",
)
args = parser.parse_args()
mapping = load_mapping(args.mapping)
renderer = FastRenderer(mapping)
stats = renderer.stats()
patterns = [args.pattern] if args.pattern else pattern_ids()
print(f"Mapping: {mapping.name}")
print(f"Tiles: {stats.tile_count} | Controllers: {stats.controller_count} | LEDs: {stats.total_leds}")
for pattern_id in patterns:
scene = SceneState(pattern_id=pattern_id, params=PatternParams(), tempo_bpm=120.0)
if args.mode == "engine":
fps, preview_frames, changed_frames = _benchmark_engine(mapping, scene, max(1, args.frames))
print(
f"{pattern_id:16s} {fps:9.1f} engine fps "
f"| preview {preview_frames:4d} | changed controllers {changed_frames:4d}"
)
else:
fps = _benchmark_renderer(renderer, scene, max(1, args.frames))
print(f"{pattern_id:16s} {fps:9.1f} render fps")
def _benchmark_renderer(renderer: FastRenderer, scene: SceneState, frames: int) -> float:
start = time.perf_counter()
for frame_index in range(frames):
renderer.render(scene, timestamp=start + frame_index / 60.0)
elapsed = time.perf_counter() - start
return frames / elapsed if elapsed > 0 else 0.0
def _benchmark_engine(mapping, scene: SceneState, frames: int) -> tuple[float, int, int]:
engine = RealtimeEngine(
mapping,
scene=scene,
settings=OutputSettings(output_fps=60.0, preview_fps=12.0, delta_sending=True, keepalive_seconds=0.35),
)
start = time.perf_counter()
preview_frames = 0
changed_frames = 0
for frame_index in range(frames):
result = engine.tick(now=start + frame_index / 60.0)
if result.preview_snapshot is not None:
preview_frames += 1
changed_frames += len(result.changed_payloads)
elapsed = time.perf_counter() - start
fps = frames / elapsed if elapsed > 0 else 0.0
return fps, preview_frames, changed_frames
if __name__ == "__main__":
main()