Files
gamedev-the-steward/docs/benchmarks/SIMULATION_SCALING_BASELINE_02.md
T
2026-07-17 00:34:30 +02:00

3.3 KiB

Simulation scaling baseline 02

This is the reviewed comparison after introducing one reusable per-tick SimulationPopulationView. The view indexes all, living, and starving NPCs by stable ID, is refreshed as each NPC advances, and is shared by relationship and action-selection queries. It is transient derived state and is not serialized.

The machine-readable samples are in simulation_scaling_baseline_02.json. The workload, seed, host, exclusions, warmup, and three-sample median contract match baseline 01.

Results

Case NPCs Seeded history Median us/tick Ticks/s Simulated realtime Arrival share End JSON
Population 6 6 0 63.85 15,662.93 18,795.5x 4.5% 0.06 MiB
Population 60 60 0 662.62 1,509.17 1,811.0x 5.7% 0.56 MiB
Population 600 600 0 11,654.10 85.81 103.0x 18.0% 5.67 MiB
History 600 60 600 722.60 1,383.90 1,660.7x 5.2% 0.71 MiB
History 6,000 60 6,000 1,430.65 698.98 838.8x 2.6% 2.04 MiB

All samples within each case were deterministic. More importantly, every final checksum exactly matches the corresponding baseline-01 checksum, so the optimization preserves selection, interleaved NPC updates, event growth, and serialized continuation state.

Comparison

Case Baseline 01 us/tick Baseline 02 us/tick Change
Population 6 55.74 63.85 14.6% slower
Population 60 621.87 662.62 6.6% slower
Population 600 15,187.74 11,654.10 23.3% faster
History 600 677.12 722.60 6.7% slower
History 6,000 1,421.19 1,430.65 0.7% slower

The shared dictionaries add a small fixed per-tick cost, visible in tiny fixtures and normal local timing noise. At the measured population knee they remove repeated all-NPC lookup construction and improve the 600-NPC case from 65.84 to 85.81 ticks per second. The local 50-ticks-per-second reference target remains comfortably met without introducing simulation LOD.

Decision and next measurement

Keep the population view. It has a real relationship/action consumer, improves the measured pressure point, and preserves exact state. Do not add batching or active/abstract NPC modes merely to improve this data-only number.

That next bounded scale slice is now complete. The measured workload justified a resource-specific horizontal grid owned by ActiveWorldAdapter; exact expanding queries preserve every linear selected-target checksum and reduce the 1,800-anchor case from 6,448.00 to 46.94 microseconds. See Loaded Resource Discovery 01.

Terrain3D-instanced visual trees and grass are not automatically authoritative resources. Intentional harvest anchors must continue to bind simulation-owned ResourceStateRecord data by stable ID; large decorative populations can stay presentation-only until a gameplay rule needs them.

Capture command

/Applications/Godot.app/Contents/MacOS/Godot \
  --headless --path "$PWD" \
  --script res://tools/benchmark_simulation_scaling.gd -- \
  --host-label=Apple_M1_Max_64_GB \
  --output=res://docs/benchmarks/simulation_scaling_baseline_02.json