A common optimization mistake is to count only the values a loop reads, not the memory fetched to reach them. Spatial locality is the tendency to access nearby memory locations soon after one another. A CPU typically copies a contiguous block into a cache line rather than fetching one variable at a time. A cache line is usually 64 bytes, enough for eight int64 values. section 12.1.2
func sum(s []int64) int64 {
var total int64
length := len(s)
for i := 0; i < length; i++ {
total += s[i]
}
return total
}
This loop reads a contiguous slice in order. Fetching the line containing s[0] can also make nearby elements available; repeatedly reading total instead illustrates temporal locality. section 12.1.2
Keep the fields you read together
Suppose a loop sums only the a field. With `type Foo struct { a, b int64 }` and `[]Foo`, each a sits beside an unused b. With `type Bar struct { a, b []int64 }`, the a values occupy a contiguous slice. In the comparison, summing Bar.a required two cache lines rather than four and ran about 20% faster on the measured machine. The point is not that a struct of slices is always better: choose a layout around the fields a hot loop actually uses. section 12.1.3
Locality alone does not explain every result. Reading every slice element has a predictable unit stride; reading every second element has a predictable constant stride. Following linked-list pointers has a non-unit stride that the CPU cannot predict from the addresses alone. In the cited comparison, a slice loop was about 70% faster than a linked-list traversal despite similar spatial locality. section 12.1.4
Check padding before blaming the loop
Field order can change how many useful values fit in a line. `struct { b1 byte; i int64; b2 byte }` occupies 24 bytes in the example; moving i first reduces it to 16 bytes. A loop summing i across 10,000 structs ran about 15% faster with the compact layout on the measured machine. Benchmark the relevant workload rather than treating either figure as a universal gain. section 12.4
