Files
gamedev-the-steward/docs/benchmarks/LOADED_RESOURCE_DISCOVERY_01.md
T
2026-07-17 13:57:57 +02:00

3.8 KiB

Loaded Resource Discovery 01

Question

Can villagers resolve finite resource anchors spread across a larger Terrain3D world without scanning every loaded ResourceNode, while selecting exactly the same target as the existing distance/risk/comfort/priority score?

Reviewed workload

  • Godot: 4.7-stable (official);
  • host: Apple M1 Max, 64 GB;
  • benchmark seed: 17331;
  • loaded resources: 18, 180, and 1,800;
  • 400 deterministic target resolutions per sample;
  • seven fresh timing samples per case;
  • 20 m horizontal source spacing with varied terrain-like height, safety risk, comfort distance, discovery priority, and deterministic disabled sources;
  • each query performs the real availability check, score, reservation, and release through ActionTargetResolver and ResourceStateRecord.

The linear reference reproduces the previous ResourceNode.get_all() scan. The spatial path uses the production ActiveWorldAdapter and its 24 m resource-specific horizontal grid. Fixture construction, rendering, navigation pathfinding, simulation ticks, and serialization are excluded.

Results

Loaded anchors Linear µs/query Spatial µs/query Speedup Average inspected Reduction
18 65.04 33.26 1.96x 18 → 3.705 79.42%
180 589.03 38.83 15.17x 180 → 4.375 97.57%
1,800 6,448.00 46.94 137.37x 1,800 → 4.445 99.75%

Every spatial sample produced the same selected-target checksum as its linear reference. The raw samples are in loaded_resource_discovery_01.json.

These are local workload measurements, not portable performance promises. The important shape is that ordinary local queries remain near four inspected anchors while the loaded set grows by 100x.

Exactness contract

ActionTargetResolver queries successively larger grid radii. It may stop only when the best possible score of every farther anchor is strictly worse than the current winner. The lower bound uses the loaded action's authoritative maximum comfort distance, minimum safety risk, and maximum discovery priority. Stable registration order preserves the former first-loaded tie behavior.

Unavailable, depleted, and reserved state remains authoritative in ResourceStateRecord; the grid indexes only loaded IDs, interaction positions, and disposable score bounds. Unloading removes an anchor without deleting its state. Rebinding the same ID or moving a loaded anchor refreshes the index.

One focused regression also gives the farthest test source an extreme priority. The query expands beyond its local cells and selects that source exactly as the linear scan does, proving that the common local fast path is not a hard range cutoff.

Decision

Keep the resource-specific grid inside ActiveWorldAdapter. It has one real consumer, preserves current gameplay, and directly supports larger authored source fields. Do not generalize it into a people/building/event index or a simulation-LOD framework yet.

Terrain3D foliage instances remain decorative unless an intentional stable-ID ResourceNode anchor binds simulation-owned state. A later placement workflow can author those anchors alongside visual instancing without making every tree an authoritative resource. That authored proof is now complete in Jajce Resource Grove 04: two nested finite anchors remain discoverable among three bounded decorative MultiMesh batches, including a real query that expands beyond its first local range.

Capture command

/Applications/Godot.app/Contents/MacOS/Godot \
  --headless --path "$PWD" \
  --script res://tools/benchmark_loaded_resource_discovery.gd -- \
  --queries=400 --samples=7 \
  --host-label=Apple_M1_Max_64_GB \
  --output=res://docs/benchmarks/loaded_resource_discovery_01.json