Files
gamedev-the-steward/tools/benchmark_loaded_resource_discovery.gd
2026-07-17 00:34:30 +02:00

109 lines
3.2 KiB
GDScript

extends SceneTree
const BenchmarkScript := preload("res://simulation/benchmark/LoadedResourceDiscoveryBenchmark.gd")
const RESOURCE_COUNTS := [18, 180, 1800]
const BENCHMARK_SEED := 17331
const DEFAULT_OUTPUT_PATH := "res://logs/loaded_resource_discovery.json"
func _initialize() -> void:
call_deferred("_run")
func _run() -> void:
var benchmark := BenchmarkScript.new()
var cases: Array[Dictionary] = []
var include_spatial := not _has_argument("--linear-only")
for resource_count in RESOURCE_COUNTS:
var fixture := benchmark.create_fixture(root, resource_count, BENCHMARK_SEED)
var result := benchmark.measure_fixture(
fixture,
_get_integer_argument(
"--queries=", LoadedResourceDiscoveryBenchmark.DEFAULT_QUERY_COUNT
),
_get_integer_argument(
"--samples=", LoadedResourceDiscoveryBenchmark.DEFAULT_SAMPLE_COUNT
),
include_spatial
)
benchmark.free_fixture(fixture)
if result.is_empty():
push_error(
"Loaded-resource discovery benchmark failed at %d resources" % resource_count
)
quit(1)
return
cases.append(result)
_print_case(result)
var report := {
"schema_version": LoadedResourceDiscoveryBenchmark.SCHEMA_VERSION,
"workload_id": String(LoadedResourceDiscoveryBenchmark.WORKLOAD_ID),
"benchmark_seed": BENCHMARK_SEED,
"host_label": _get_argument_value("--host-label=", "unlabelled"),
"godot_version": Engine.get_version_info().get("string", "unknown"),
"resource_counts": RESOURCE_COUNTS,
"resource_spacing": LoadedResourceDiscoveryBenchmark.RESOURCE_SPACING,
"inclusions":
[
"loaded_resource_candidate_discovery",
"authoritative_availability_and_scoring",
"reservation_and_release",
],
"exclusions":
[
"fixture_construction",
"simulation_tick",
"serialization",
"rendering",
"navigation_pathfinding",
],
"cases": cases,
}
var output_path := _get_argument_value("--output=", DEFAULT_OUTPUT_PATH)
var output := FileAccess.open(output_path, FileAccess.WRITE)
if output == null:
push_error("Could not write loaded-resource report to %s" % output_path)
quit(1)
return
output.store_string(JSON.stringify(report, "\t") + "\n")
output.close()
print("[BENCH] Report: %s" % ProjectSettings.globalize_path(output_path))
quit(0)
func _print_case(result: Dictionary) -> void:
var linear: Dictionary = result["linear"]
var message := (
"[BENCH] %4d resources | linear %7.2f us/query"
% [result["resource_count"], linear["usec_per_query_median"]]
)
if result.has("spatial"):
var spatial: Dictionary = result["spatial"]
message += (
" | spatial %7.2f us/query | %.2fx | %.1f inspected"
% [
spatial["usec_per_query_median"],
result["speedup"],
spatial["candidates_inspected_average"],
]
)
print(message)
func _has_argument(argument: String) -> bool:
return argument in OS.get_cmdline_user_args()
func _get_integer_argument(prefix: String, default_value: int) -> int:
return maxi(int(_get_argument_value(prefix, str(default_value))), 1)
func _get_argument_value(prefix: String, default_value: String) -> String:
for argument in OS.get_cmdline_user_args():
if argument.begins_with(prefix):
var value := argument.trim_prefix(prefix)
if not value.is_empty():
return value
return default_value