1---2name: data-oriented-design-guide3description: Use when designing or refactoring performance-critical data layouts for cache efficiency, in any language. Triggers on prompts about SoA/AoS/AoSoA, cache misses, hot/cold field splitting, data-oriented design, component-storage layout, batch/bulk processing, handles vs pointers, avoiding pointer chasing, even when the user doesn't say 'data-oriented' or 'cache'.4---56# Data-Oriented Design Guidelines78## Essentials910- **The problem is data movement** - Optimize cache traffic, not instruction count, see [references/cache-behavior.md](references/cache-behavior.md)11- **Design from the data** - Model bulk input→output transforms, not idealized objects, see [references/data-as-transforms.md](references/data-as-transforms.md)12- **Measure first** - Profile cache misses before changing layout, see [references/measurement-and-profiling.md](references/measurement-and-profiling.md)13- **Record cheaply, always on** - Per-frame accumulating counters recorded via a cached accumulator pointer (one store, no lookup/branch/lock), history allocated only for viewed counters, see [references/statistics-recording.md](references/statistics-recording.md)1415## Layout1617- **SoA / AoS / AoSoA** - Split structs into per-field arrays for hot loops, see [references/soa-aos-aosoa.md](references/soa-aos-aosoa.md)18- **SIMD-friendly layout** - Contiguous columns, padding, alignment for vectorization, see [references/simd-friendly-layout.md](references/simd-friendly-layout.md)19- **Nested / variable-length arrays** - Hold child lists in bulk arrays + cache-line chunks, not per-object heap pointers, see [references/nested-arrays.md](references/nested-arrays.md)2021## Processing2223- **Sequential access** - Stream linearly, never chase pointers, see [references/access-patterns.md](references/access-patterns.md)24- **Existence-based processing** - Bucket by state so branches become loops, see [references/existence-based-processing.md](references/existence-based-processing.md)25- **Batch over one-at-a-time** - Transform N items per call, amortize overhead, see [references/data-as-transforms.md](references/data-as-transforms.md)26- **Default to zero** - Make all-zero a valid default; reserve 0 for none/neutral, not magic sentinels, see [references/zero-as-default.md](references/zero-as-default.md)2728## Memory2930- **Handles, not pointers** - Reference by index/handle into relocatable, stable arrays (swap-remove, free lists, indirection tables), see [references/handles-and-indices.md](references/handles-and-indices.md)31- **Allocation** - Contiguous storage matters for cache, but the allocators themselves (arenas/pools/lifetimes) are general, see **memory-management-guide**3233## Gotchas3435- SoA only wins when loops touch a subset of fields; full-record access can favor AoS: measure both.36- The hardware prefetcher tracks linear strides; randomizing your index order silently disables it.37- Padding for alignment trades memory for throughput, on cache-bound loads, the smaller packed layout can still win.38- A counter you cache as a raw pointer dangles if its backing array reallocates: hand out indices into a stable block, or pointers into a non-relocating pool.3940## Progressive Disclosure4142- Read [references/cache-behavior.md](references/cache-behavior.md) - Load when reasoning about cache lines, latency, or miss types43- Read [references/data-as-transforms.md](references/data-as-transforms.md) - Load when modeling a system as bulk streams instead of objects44- Read [references/soa-aos-aosoa.md](references/soa-aos-aosoa.md) - Load when choosing or converting between AoS, SoA, and AoSoA layouts45- Read [references/access-patterns.md](references/access-patterns.md) - Load when iterating collections or replacing pointer-chasing structures46- Read [references/handles-and-indices.md](references/handles-and-indices.md) - Load when designing entity references, stable arrays, or free lists47- Read [references/existence-based-processing.md](references/existence-based-processing.md) - Load when removing per-item branches by sorting or bucketing48- Read [references/simd-friendly-layout.md](references/simd-friendly-layout.md) - Load when laying out data for vectorization or alignment49- Read [references/nested-arrays.md](references/nested-arrays.md) - Load when objects own variable-length child lists, or you're reaching for a per-object growable container50- Read [references/zero-as-default.md](references/zero-as-default.md) - Load when choosing sentinels, nil values, or default-initialized state51- Read [references/measurement-and-profiling.md](references/measurement-and-profiling.md) - Load when measuring before/after or reading hardware counters52- Read [references/statistics-recording.md](references/statistics-recording.md) - Load when building always-on counters/telemetry that must add near-zero overhead on hot paths