Início › Forums › Street Fighter 6 – Drive System & Frame Data › Unity DOTS / ECS (Entity Component System) Data-Oriented Memory Architecture: Edge Cases, Failure Modes, and Root-Cause Debugging
- This topic has 3 replies, 3 voices, and was last updated 2 days, 21 hours ago by
Owen Hall.
-
AuthorPosts
-
October 16, 2026 at 12:49 pm #118324
Owen HallMemberI’ve been benchmarking a DOTS simulation with a few thousand entities and hitting weird cache behavior that doesn’t match my mental model. I laid out movement data as pure SoA (position, velocity, acceleration as separate NativeArrays) expecting tight cache line utilization on the per-tick update, but profiling shows L2 hit rates tanking around 4k entities even though I’m iterating contiguously. My question: when you’re working with chunk boundaries in a DynamicBuffer-heavy system, how do you actually preserve cache line locality without introducing artificial padding that wastes memory? And at what entity count does the chunk-size tradeoff stop being theoretical and start dominating your frame budget?
On the burst/SIMD side, I’m getting inconsistent speedups across iterations even with identical input data, and I suspect I’m hitting false sharing between jobs writing to adjacent vector types. How are you diagnosing that—GPU-profiler traces, or are you relying mostly on manual reasoning about the IL? Also, when SIMD auto-vectorization fails on a system, do you prefer forcing it with intrinsics, or is there a pattern that usually lets the compiler figure it out on its own? Curious how experienced folks actually root-cause these things versus just guessing at the fix.
🎮 Battlestation & Rig: Ryzen 5 7600X | RTX 4070 Super Dual | 32GB DDR5 6000 CL30 | FormD T1 SFF | ASUS ROG Swift Pro PG248QP 24.1″ 540Hz Esports-TN | Wooting 60HE Hall-Effect + Logitech G Pro X Superlight 2 + Artisan Zero XSoft | Audio-Technica ATH-R70x + Schiit Magni/Modi Stack📍 Seoul (South Korea)"Rapid trigger active, zero deadzone; never miss a counter-strafe."October 18, 2026 at 8:27 pm #118877
Stella PerezMemberGreat topic — the most brutal DOTS footguns tend to hide in the memory layout, not in your logic. The classic failure mode I see is stride/alignment mismatches: if a struct’s largest member exceeds 16 bytes, the Burst compiler and chunk allocator will pad the chunk stride, silently eating memory and wrecking your
Chunk.ByteLengthmath. I always runDebug.Log(chunkInfo.stride)against a hardcoded expected value in a test build — if they diverge, you’ve got hidden padding or a mis-ordered field layout. Another sneaky one isFixedArrayandNativeHashMapinside components: the FixedArray is inline in the chunk (good for cache locality, bad if you underestimate element count and blow the chunk), whileNativeHashMapallocates its backing store on the managed/unsafe heap and breaks all the cache-friendly assumptions you’re building ECS for. Also watch out forNativeArraylifetime confusion across jobs — a struct holding aNativeArrayis fine, but one holding a managedListor a rawIntPtryou forgot to free is how you get heap corruption that only manifests hours into a run.For root-cause debugging, stop treating the profiler as a black box and lean into the Job Debugger and Burst compiler diagnostics together.
October 20, 2026 at 10:18 am #119369
Max WilsonMemberThe biggest footgun I’ve hit with DOTS is assuming chunk data is stable across frames. When a chunk fills up it grows, and when entities are removed adjacent chunks of the same archetype can merge — both operations can relocate the underlying memory and silently invalidate any raw pointer or
NativeArrayyou cached earlier. I’ve spent hours chasing corruption caused by storing a pointer to chunk data in a component or a side buffer and dereferencing it in a later job. The fix is discipline: never hold native pointers across frames or across jobs. Use indices[Rig: Ryzen 7 7800X3D & RTX 4090 24GB] • [Display: ASUS ROG PG27AQDM 240Hz OLED]October 21, 2026 at 7:32 pm #120441
Owen HallMemberFollowed the advice, framedrops stopped after changing that bios setting, thanks guys!
Honestly, we spent like three days going deep on cache-line false sharing and SoA layout in our Burst jobs when the whole time it turned out my XMP profile was unstable and causing random memory controller throttling under load. Wild how you can obsess over entity chunk boundaries while the real culprit was sitting right there in the firmware. Anyway, running rock-solid at 144fps now and the GC spikes are gone too. Appreciate everyone who chimed in—the pointer arithmetic talk was still useful for the next project, but yeah, turn off the fancy RAM profile and everything just works.
"Corsair 5000D Airflow | 10x Noctua NF-A12x25 PWM Fans | Sub-60°C Thermals" -
AuthorPosts
- You must be logged in to reply to this topic.