How do cache misses shape the way you lay out data?
A miss to main memory costs on the order of a couple of hundred cycles, so a structure that is theoretically better can lose badly to a contiguous array. That leads to laying data out the way it will be traversed — structure-of-arrays when you touch one field over many objects, packing hot fields together, and avoiding pointer chasing in the inner loop. False sharing is the same problem inverted: two threads writing to different variables in one cache line serialise on it, and the fix is padding to a cache line.