Preserve production code, regression fixtures, audio assets and provenance, test infrastructure, and the original-completion plan and progress ledger. Final game and Windows acceptance remain pending; excluded local artifacts and native experiments are not part of this snapshot.
139 lines
6.8 KiB
GDScript
139 lines
6.8 KiB
GDScript
extends SceneTree
|
|
## Diagnostic measurement, not a replacement for full-load acceptance.
|
|
var phase_samples: Dictionary = {}
|
|
var phase_start := 0
|
|
var current_phase := -1
|
|
|
|
func finish_phase() -> void:
|
|
if current_phase >= 0:
|
|
if not phase_samples.has(current_phase): phase_samples[current_phase] = []
|
|
phase_samples[current_phase].append(Time.get_ticks_usec()-phase_start)
|
|
current_phase = -1
|
|
|
|
func begin_phase(phase: int, _minute: int) -> void:
|
|
finish_phase()
|
|
current_phase = phase
|
|
phase_start = Time.get_ticks_usec()
|
|
|
|
const Demo := preload("res://scripts/ui/pixel_tower_demo.gd")
|
|
func _initialize() -> void: call_deferred("run")
|
|
func stats(samples: Array[int]) -> Dictionary:
|
|
var sorted := samples.duplicate()
|
|
sorted.sort()
|
|
var total := 0
|
|
for value: int in sorted: total += value
|
|
return {"samples":sorted.size(),"average_us":float(total)/sorted.size(),"p95_us":sorted[ceili(sorted.size()*0.95)-1],"max_us":sorted.back()}
|
|
func run() -> void:
|
|
var runtime: Variant = root.get_node("SimulationRuntime")
|
|
var clock: Variant = root.get_node("GameClock")
|
|
var state: Variant = root.get_node("GameState")
|
|
# Disposable Demo fixture funds exact Doran signing_cost 300; DEFAULT5000 and paid hire stay unchanged.
|
|
clock.reset(1,6,0);state.reset();state.resources[&"gold"] += 300;runtime.initialize(clock,state,424242);clock.set_paused(true)
|
|
runtime.configure_save_policy({&"enabled":false,&"daily_checkpoint_enabled":false})
|
|
var demo := Demo.new()
|
|
if not await demo.prepare(runtime,clock,self): quit(1);return
|
|
var main: Control = load("res://scenes/main/main.tscn").instantiate()
|
|
root.add_child(main)
|
|
runtime.configure_save_policy({&"enabled":false,&"daily_checkpoint_enabled":false})
|
|
await process_frame;await process_frame
|
|
clock.tick_phase_started.connect(begin_phase)
|
|
clock.tick_completed.connect(func(_minute: int): finish_phase())
|
|
var checkpoint: Dictionary = runtime.create_snapshot()
|
|
var report := {"fixture":demo.describe(),"headless":DisplayServer.get_name()=="headless","limits":{"x1_average_us":4000,"x3_p95_us":12000},"measurements":{}}
|
|
for speed: int in [1,3]:
|
|
if not runtime.restore_snapshot(checkpoint):quit(2);return
|
|
phase_samples.clear()
|
|
var times: Array[int] = []
|
|
for frame in 40:
|
|
var minute: int = clock.absolute_minute
|
|
var start := Time.get_ticks_usec()
|
|
clock.advance_minutes(speed)
|
|
# Include deferred dashboard cost in the same sample, rather than
|
|
# hiding work outside the synchronous timing interval.
|
|
if main.has_method("_flush_dashboard_refresh"):
|
|
main.call("_flush_dashboard_refresh")
|
|
times.append(Time.get_ticks_usec()-start)
|
|
if clock.absolute_minute != minute+speed:quit(3);return
|
|
await process_frame
|
|
report["measurements"]["x%d" % speed] = stats(times)
|
|
var phases := {}
|
|
for phase: int in phase_samples:
|
|
var values: Array[int] = []
|
|
values.assign(phase_samples[phase])
|
|
phases[SimulationKernel.TickPhase.keys()[phase]] = stats(values)
|
|
report["measurements"]["x%d" % speed]["phases"] = phases
|
|
# Distinguish full update cost from serialization and digest micro-costs.
|
|
var snapshots: Array[int] = []
|
|
var digests: Array[int] = []
|
|
for attempt in 20:
|
|
var start := Time.get_ticks_usec()
|
|
var snapshot: Dictionary = runtime.create_snapshot()
|
|
snapshots.append(Time.get_ticks_usec()-start)
|
|
start=Time.get_ticks_usec()
|
|
SimulationDigest.compute(snapshot)
|
|
digests.append(Time.get_ticks_usec()-start)
|
|
var section_costs := {}
|
|
var final_snapshot: Dictionary = runtime.create_snapshot()
|
|
for section: Variant in final_snapshot[&"systems"][&"runtime"]:
|
|
var values: Array[int] = []
|
|
for attempt in 5:
|
|
var start := Time.get_ticks_usec()
|
|
SimulationDigest.compute(final_snapshot[&"systems"][&"runtime"][section])
|
|
values.append(Time.get_ticks_usec()-start)
|
|
section_costs[String(section)] = stats(values)
|
|
report["runtime_section_digests"] = section_costs
|
|
var ui_costs := {}
|
|
for method: StringName in [&"_refresh_dashboard", &"_refresh_staff_candidates", &"_refresh_selected_entity", &"_operations_dashboard_text"]:
|
|
var values: Array[int] = []
|
|
for attempt in 20:
|
|
var start := Time.get_ticks_usec()
|
|
main.call(method)
|
|
values.append(Time.get_ticks_usec()-start)
|
|
ui_costs[String(method)] = stats(values)
|
|
if main.opening_guide != null:
|
|
for method: StringName in [&"refresh", &"_read_progress", &"_first_lodging_sale"]:
|
|
var values: Array[int] = []
|
|
for attempt in 20:
|
|
var start := Time.get_ticks_usec()
|
|
main.opening_guide.call(method)
|
|
values.append(Time.get_ticks_usec()-start)
|
|
ui_costs["opening_guide."+String(method)] = stats(values)
|
|
report["ui_refresh_costs"] = ui_costs
|
|
var validation_costs := {}
|
|
for service_name: StringName in [&"spatial_subslot_service", &"route_subslot_path_adapter", &"facility_infrastructure_projector", &"excavation_service"]:
|
|
var values: Array[int] = []
|
|
for attempt in 20:
|
|
var start := Time.get_ticks_usec()
|
|
var result: Dictionary = runtime.get(service_name).validate_invariants()
|
|
values.append(Time.get_ticks_usec()-start)
|
|
if not result.get(&"ok", false):quit(5);return
|
|
validation_costs[String(service_name)] = stats(values)
|
|
report["infrastructure_validation_costs"] = validation_costs
|
|
var snapshot_costs := {}
|
|
for service_name: StringName in [&"domain_events", &"command_queue", &"world_service", &"path_service", &"construction_service", &"facility_service", &"guest_service", &"staff_service", &"operations_coordinator", &"facility_infrastructure_projector", &"route_subslot_path_adapter"]:
|
|
var values: Array[int] = []
|
|
for attempt in 20:
|
|
var start := Time.get_ticks_usec()
|
|
runtime.get(service_name).create_snapshot()
|
|
values.append(Time.get_ticks_usec()-start)
|
|
snapshot_costs[String(service_name)] = stats(values)
|
|
var copies: Array[int] = []
|
|
for attempt in 20:
|
|
var start := Time.get_ticks_usec()
|
|
final_snapshot.duplicate(true)
|
|
copies.append(Time.get_ticks_usec()-start)
|
|
snapshot_costs["whole_snapshot_deep_copy"] = stats(copies)
|
|
report["snapshot_component_costs"] = snapshot_costs
|
|
report["snapshot"] = stats(snapshots)
|
|
report["digest"] = stats(digests)
|
|
report["within_budget"] = report["measurements"]["x1"]["average_us"] <= 4000 and report["measurements"]["x3"]["p95_us"] <= 12000
|
|
report["limitations"] = "Small disposable production scenario; auto-save disabled; synchronous tick includes UI subscribers, excludes frame rendering and GPU. Not full-load or Windows acceptance."
|
|
var path := OS.get_environment("THE_TREE_RUNTIME_PROFILE_PATH")
|
|
if path.is_empty():path="res://artifacts/facility-dimensions-2026-09-29/production-scene-profile.json"
|
|
var file := FileAccess.open(path,FileAccess.WRITE)
|
|
if file == null:quit(4);return
|
|
file.store_string(JSON.stringify(report," ")+"\n");file.close()
|
|
print("PRODUCTION_PROFILE ",JSON.stringify(report["measurements"])," snapshot=",report["snapshot"]," digest=",report["digest"]," within_budget=",report["within_budget"])
|
|
main.queue_free();await process_frame
|
|
quit(0)
|