Files
horizon-airdef/tests/test_perf_bench.py
T
Ludovic Marie 49b6367d2e perf_bench: a load ends when every streaming stage is idle
Builds that report status.streaming are loaded once chunk counts are
stable and no stage (generation, decoration, light, meshing) has held work
for half a second. Meshing going quiet also waited through the remeshing
that follows a load (fluids settling, random ticks: 1500 falling to 60
meshes/s for ~150 s at RD16), which is simulation, not loading. Older
builds keep the meshing-rate rule.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 07:01:03 +02:00

89 lines
4.0 KiB
Python

import json
import unittest
from tools.perf_bench import HISTOGRAM_EDGES_MS, OPTIONS, frames, rnd, summary
class PerfBenchStatsTests(unittest.TestCase):
def test_lows_average_the_slowest_frames(self):
times = [10.0] * 990 + [100.0] * 9 + [1000.0]
s = frames("village", 0, times)
self.assertEqual(s["frames"], 1000)
self.assertEqual(s["avg_fps"], rnd(1000 * 1000 / (9900 + 900 + 1000)))
# Slowest 1%: 9 frames of 100 ms and one of 1000 ms.
self.assertEqual(s["low_1pct_fps"], rnd(1000 * 10 / 1900))
# Slowest 0.1%: the single 1000 ms frame.
self.assertEqual(s["low_01pct_fps"], 1.0)
self.assertEqual((s["p50_ms"], s["p99_ms"], s["p999_ms"], s["max_ms"]), (10.0, 10.0, 100.0, 1000.0))
self.assertEqual(sum(s["histogram"]), 1000)
self.assertEqual(len(s["histogram"]), len(HISTOGRAM_EDGES_MS))
self.assertEqual(s["histogram"][HISTOGRAM_EDGES_MS.index(10)], 990)
self.assertEqual(s["histogram"][HISTOGRAM_EDGES_MS.index(100)], 9)
self.assertEqual(s["histogram"][-1], 1, "1000 ms and over")
def test_same_figures_as_horizon_bench(self):
# crates/horizon-bench's frame_figures_and_histogram test, value for value.
s = frames("flight", 0, [2.0] * 998 + [20.0, 1500.0])
self.assertEqual((s["seconds"], s["low_1pct_fps"], s["low_01pct_fps"]), (3.516, 6.51, 0.667))
self.assertEqual((s["histogram"][2], s["histogram"][13], s["histogram"][23]), (998, 1, 1))
self.assertNotIn("cpu_p50_ms", s)
r = summary([2.0, 4.0, 6.0])
self.assertEqual(r, {"n": 3, "mean": 4.0, "stdev": 2.0, "min": 2.0, "max": 6.0, "ci95": 4.969})
self.assertEqual(summary([5.0])["ci95"], None)
self.assertIsNone(summary([None]))
def test_a_short_flight_still_has_lows(self):
s = frames("x", 0, [5.0, 20.0])
self.assertEqual((s["low_1pct_fps"], s["low_01pct_fps"]), (50.0, 50.0))
self.assertIsNone(frames("x", 0, []))
json.dumps(s)
def test_one_options_file_sets_the_render_distance(self):
self.assertEqual(OPTIONS["renderDistance"].format(distance=16), "16")
self.assertEqual(OPTIONS["graphicsPreset"], '"custom"')
if __name__ == "__main__":
unittest.main()
class WaitLoadedTests(unittest.TestCase):
"""wait_loaded on a scripted game with a fake clock: one status per 50 ms poll."""
def run_script(self, statuses):
import tools.perf_bench as pb
clock = [0.0]
it = iter(statuses)
def control(_command, timeout=None):
return next(it)
real_time, real_sleep = pb.time.time, pb.time.sleep
pb.time.time = lambda: clock[0]
pb.time.sleep = lambda s: clock.__setitem__(0, clock[0] + s)
try:
return pb.wait_loaded(control, lambda p: True, 60)
finally:
pb.time.time, pb.time.sleep = real_time, real_sleep
@staticmethod
def status(chunks, meshed, stages=None):
s = {"player": {"position": [0, 0, 0]}, "pending_chunks": 0, "screen": "game",
"chunks": chunks, "generated_chunks": chunks, "meshed_sections": meshed}
if stages is not None:
s["streaming"] = {"queued": 0, "generating": 0, "protos": 296, "decorating": 0,
"finishing": 0, "lighting": 0, "meshing": stages}
return s
def test_stages_end_the_load_before_the_remesh_tail(self):
# 20 polls (1 s) of meshing work, then idle stages while blocks keep remeshing
# at 400 meshes/s, with a short burst of work every 2 s.
loading = [self.status(900, 1000 * i, stages=500) for i in range(20)]
tail = [self.status(901, 20000 + 20 * i, stages=40 if i % 40 == 0 else 0) for i in range(400)]
self.assertAlmostEqual(self.run_script(loading + tail), 1.0, places=6)
def test_old_builds_wait_for_meshing_to_go_quiet(self):
busy = [self.status(901, 1000 * i) for i in range(20)]
quiet = [self.status(901, 20000 + i) for i in range(40)]
self.assertAlmostEqual(self.run_script(busy + quiet), 1.0, places=6)