saumwacht-godot/tools/luneraria/lune_benchmark.gd
Martin Stickelbroeck c27a0097c3 M1: spielbarer Drei-Lane-Kern mit Karte, HUD, Menü und Abnahme
Hauptszene scenes/luneraria.tscn, Saumwacht bleibt über --legacy und die
alten QA-Schalter erreichbar. Karte aus Bestandsassets plus neuem Turm,
HUD mit Planung, Lanes und Minimap, Menü umbenannt, Einstellungen werden
aus dem alten Benutzerordner übernommen. Simulation 6,6x schneller
(Raster, Caches, faire Staffelung) und exakt spiegelsymmetrisch.
Regeln 91/91, echte Anwendung 38/38, Legacy unverändert grün.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 21:37:23 +02:00

74 lines
3.6 KiB
GDScript

extends Node
## Frame and simulation cost in a real match scene at representative maximum occupation:
## six armies at the supply cap and a round-13 wave (synthetic fixture, gold granted to the
## fixture only). VSync off; figures apply to this machine only.
## Run: godot --path . --resolution 1920x1080 res://tools/luneraria/lune_benchmark.tscn
const Game = preload("res://scripts/luneraria/lune_game.gd")
func _ready() -> void:
call_deferred("run")
func run() -> void:
Soundscape.enabled = false
DisplayServer.window_set_vsync_mode(DisplayServer.VSYNC_DISABLED)
var t0: int = Time.get_ticks_usec()
var game: Node3D = Game.new()
add_child(game)
game.start({"seed": 5, "human_slot": 0})
var build_ms: float = (Time.get_ticks_usec() - t0) / 1000.0
var state: LuneMatch = game.match_state
state.round_number = 13
for slot: int in range(6):
state.players[slot].draft.gold = 100000
state.players[slot].draft.roster.clear()
LuneBot.plan(state, slot, "ausgewogen")
game._on_ready()
game.camera.look_at_point(Vector3(-10, 0, 10), 34.0, true)
for i in 30: await get_tree().process_frame
RenderingServer.viewport_set_measure_render_time(get_viewport().get_viewport_rid(), true)
var frames: Array[float] = []
var gpu: Array[float] = []
var sim: Array[float] = []
var draws: Array[float] = []
var mobile: Array[int] = []
var last: int = Time.get_ticks_usec()
var end: int = Time.get_ticks_msec() + 8000
game.speed_index = 1
while Time.get_ticks_msec() < end and state.phase == LuneMatch.Phase.COMBAT:
var s0: int = Time.get_ticks_usec()
var before: int = state.combat.steps
await RenderingServer.frame_post_draw
var now: int = Time.get_ticks_usec()
frames.append((now - last) / 1000.0)
last = now
gpu.append(RenderingServer.viewport_get_measured_render_time_gpu(get_viewport().get_viewport_rid()))
draws.append(Performance.get_monitor(Performance.RENDER_TOTAL_DRAW_CALLS_IN_FRAME))
mobile.append(state.combat.mobile_count())
# Pure simulation cost of one fixed step at this occupation, measured separately.
var probe := LuneMatch.new()
probe.setup({"seed": 5, "human_slot": -1})
probe.round_number = 13
for slot: int in range(6):
probe.players[slot].draft.gold = 100000
LuneBot.plan(probe, slot, "ausgewogen")
probe.begin_combat()
var start_units: int = probe.combat.mobile_count()
var s1: int = Time.get_ticks_usec()
for i in 200:
probe.step_combat()
var step_ms: float = (Time.get_ticks_usec() - s1) / 1000.0 / 200.0
frames.sort()
var mean := func(v: Array) -> float:
var t: float = 0.0
for x in v: t += float(x)
return t / maxf(1, v.size())
var report := {"window": get_window().size, "renderer": RenderingServer.get_current_rendering_method(), "gpu": RenderingServer.get_video_adapter_name(),
"cpu": OS.get_processor_name(), "engine": Engine.get_version_info().string, "scene_build_ms": build_ms,
"mobile_units_at_start": start_units, "mobile_units_mean_measured": mean.call(mobile), "buildings": 18,
"frames": frames.size(), "frame_ms_mean": mean.call(frames), "frame_ms_p95": frames[int(frames.size() * .95)] if frames.size() > 0 else -1,
"gpu_ms_mean": mean.call(gpu), "draw_calls_mean": mean.call(draws), "sim_step_ms": step_ms, "sim_speed": "2x (40 steps/s)",
"video_mem_mb": Performance.get_monitor(Performance.RENDER_VIDEO_MEM_USED) / 1048576.0,
"static_mem_mb": Performance.get_monitor(Performance.MEMORY_STATIC) / 1048576.0}
var file := FileAccess.open("res://docs/luneraria/logs/perf-%dx%d.json" % [get_window().size.x, get_window().size.y], FileAccess.WRITE)
file.store_string(JSON.stringify(report, "\t"))
file.close()
print("LUNE_BENCH ", JSON.stringify(report))
get_tree().quit()