8 lessons

Data Layout in Memory

Where the bytes actually sit: alignment and padding, endianness, address arithmetic, why an array beats a linked list at equal complexity, and array-of-structs versus struct-of-arrays.

SourceCompilerInstructionsFront EndExecutionRegistersCachesMemoryI/OBehavior
Alignment: Why Addresses Are Not Arbitrary
▶ lab

Hardware prefers a four-byte value at an address divisible by four. Break that and the penalty ranges from literally nothing, through a silent extra memory access, to a fault that kills the process — and which one you get depends entirely on the architecture.

Q · Why does the address a value sits at matter, when memory is supposedly just bytes?
Padding: Why Your Struct Is Bigger Than Its Fields
▶ lab

A struct with a char and an int is not five bytes. The compiler inserts padding to keep every field naturally aligned, and in a large array of those structs the padding is memory you pay to move but never read.

Q · Why does `sizeof` a struct exceed the sum of its fields, and when is that worth caring about?
Endianness: Which Byte Comes First

The value `0x12345678` is unambiguous. The four bytes it occupies in memory are not — their order depends on the machine. It matters exactly when bytes leave the machine, which is why it is a networking and file-format problem more than a CPU one.

Q · In what order does a multi-byte value actually sit in memory, and when does that order become my problem?
What `arr[i]` Actually Compiles To

Indexing an array is not a lookup. It is arithmetic: base plus index times element size, computed in a single addressing mode on most architectures. That is why arrays are the cheapest random-access structure hardware supports.

Q · What does the machine actually do to turn `arr[i]` into a value?
Both Are O(n). One Is Far Slower.
▶ lab

Traversing an array and traversing a linked list are both linear. On real hardware the array can be an order of magnitude faster, because complexity counts operations and hardware charges for data movement and dependencies.

Q · If traversal is O(n) either way, why is the array so much faster in practice?
Pointer Chasing: The Address You Do Not Have Yet
▶ lab

Any traversal where the next address comes out of the current load runs at one memory round trip per step. It is the mechanism behind slow lists, slow trees, slow graphs and hash lookups that underperform their O(1) label.

Q · Why can the CPU not overlap the memory accesses in a tree or graph traversal?
Array of Structs, or Struct of Arrays?
▶ lab

The same particles can be one array of records or several parallel arrays of fields. Which is faster depends entirely on whether your loop reads most fields of a few records, or one field of many — and the difference is how much of each cache line you actually use.

Q · Should related fields live together in a record, or should each field get its own array?
Data-Oriented Design, Without the Dogma

Organise data around how it is processed rather than around how the domain is modelled. It is a real technique with real wins in hot loops — and a genuinely bad default for code where clarity matters more than cache lines.

Q · When is it worth organising code around the data's memory layout instead of around the problem domain?