Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Data Layout

This chapter is a work in progress.

Most languages give you no control over how data is arranged in memory. Kāra lets you separate what your data is from how it's stored — without changing the logical API.

Why layout matters

Modern CPUs are memory-bound, not compute-bound. Cache misses dominate performance. How your data is laid out in memory — whether related fields are next to each other, whether you're iterating over dense arrays or chasing pointers — matters more than most algorithmic optimizations.

Layout blocks

A layout block defines physical memory organization separately from the struct definition:

struct Particle {
    position: Vec3,
    velocity: Vec3,
    mass: f64,
    color: Color,
    active: bool,
}

layout Particle {
    group hot { position, velocity }    // fields accessed together in physics loop
    group cold { color, active }        // rarely accessed during simulation
}

The struct's logical API doesn't change — you still write p.position and p.color. But the compiler lays out hot fields contiguously for cache-friendly iteration and keeps cold fields separate.

SoA transforms

For arrays of structs, layout blocks can request Structure-of-Arrays (SoA) layout:

layout Particle {
    soa    // each field becomes its own contiguous array
}

An Array[Particle, 1000] with soa layout stores all positions together, all velocities together, etc. — ideal for SIMD and cache performance. The logical interface (particles[i].position) stays the same.

When to use layout control

Most code doesn't need layout blocks. Use them when:

  • You have hot loops iterating over large arrays of structs.
  • Profiling shows cache misses dominating.
  • You want SoA layout for SIMD-friendly processing.

For everything else, let the compiler pick the layout. It's implementation freedom — the compiler can optimize within the constraints you give it.