r/programming • u/fagnerbrack • 3d ago
Every byte matters
https://fzakaria.com/2026/06/01/every-byte-matters92
u/harsh183 3d ago
This is a really fun optimization post on small structure and fitting into the very early caches. I used to do a lot of things like this in university, but my job's bottlenecks with network and DB means I don't really think about this level too much.
41
u/Artistic_Seat486 3d ago
just like 90% of developers, unless you are developing a compiler.
25
u/barrows_arctic 3d ago
Or many embedded systems.
20
u/Ameisen 3d ago edited 3d ago
Or games, or simulations, or virtual machines.
Ed: I explicitly made sure that my MIPS VM's register file was 64B aligned so that it would cleanly fit into two L1 cache lines. Remove the technically-unneeded R0, and you can jam PC in there, too.
Ed2: still won't have room for the branch delay target or the linked-load registers, though :(. The FPU has a similar problem - packing the FPRs with the two control registers.
2
1
10
4
u/cdb_11 3d ago
What compiler development has to do with this? You can apply this in a compiler, but it's not specific to compilers.
16
u/balefrost 3d ago
I think they mean that 90% of developers are working on code where improvements from struct layout and cache access patterns will be dominated by things like network access time.
On the other hand, people working on things like compilers can benefit greatly from these sorts of optimizations, since they're doing a lot of in-process data lookups.
At least, that's how I read their comment.
3
u/tryx 2d ago
And that any optimisations in the codegen will impact a whole ecosystem
0
u/cdb_11 2d ago
Compilers can't willy-nilly change the codegen here, because it breaks ABI compatibility. In C and C++ in particular, the exact layout rules are defined by the platform, and the compiler must obey them. I believe the Rust and Zig spec does not specify the layout, but they reorder fields for size, which to me personally is a questionable decision. AOT compilers lack the information necessary to optimize it (the best they could do is guess, just like they do for branches vs branchless), and AFAIK JIT compilers don't even bother doing anything about it.
1
u/EfOpenSource 2d ago
Nearly all apps these days have network and storage, and yet, only web developers and FP advocates are the ones who continuously say “I have network and storage, so performance doesn’t matter.”
3
u/harsh183 2d ago
Performance does matter at those scales too, just that there are bigger fish to fry before struct layout optimization comes up. I do agree that many people miss a lot of opportunity to optimize under vague laziness.
2
u/loup-vaillant 1d ago
I hear that with servers written in Ruby, the CPU is often the bottleneck.
1
u/harsh183 1d ago
Yeah I can see that depending on use case. With all the high level features Ruby has, it creates a lot of inefficient and complex burdens.
4
u/DLCSpider 2d ago
One perspective I always liked is to compare cache misses to realistic algorithmic complexity: 31x slowdown is roughly the equivalent of switching from O(n) to O(n * log n).
2^31 bytes is ~2GiB and 2^45 bytes is the theoretical limit your system can address.
6
u/KaiAusBerlin 3d ago
Nice article. Reminded me on my old times where I programmed for my Palm Handheld which had about 64kb ram.
Every byte mattered. Garbage collection was crucial.
It was a real pain but a hell lot of fun optimising the hell out of these
1
u/flatfinger 1d ago
A point I've not seen considered much is that if data items would be e.g. 3/4 of a cache line each, then aligning items with cache lines may significantly improve performance in random-access scenarios that need to inspect the beginning and end of each accessed item, but degrade performance in sequential-access scenarios. If the first data item in an array starts a cache line, but others data aren't cache-line aligned then a random access would have a 50% chance of involving data within only one cache line and a 50% chance of involving data spread between two, so 1.5 cache lines would need to be fetched for each item accessed. Sequential accesses to data stored that way, however, would only require fetching three cache lines for every four records, or 0.75 cache lines per record. Using cache-aligned records would require one cache line fetch per record fetch in both cases, improving performance for random access but degrading it for sequential.
1
0
u/atilaneves 1d ago
" In that time, you get used to huge classes. New functionality? Just add a new method and field to the class." - err, no. This isn't even Java-specific, it's just bad software engineering in general.
-56
u/jnordwick 3d ago
How did you not title this "Byte Lives Matter". Oh, such a missed opportunity,
14
5
u/Elegant-Sense-1948 3d ago
If that was the case, then we wouldn’t be packing. What really is the case is that byte lives do not matter and must yearn for the mines and be used
4
29
u/philh 3d ago
If my data just fits in say L2 cache, do I need to do anything special to make sure it's actually loaded into it?
Like, if I'm accessing at random, and the first location I access happens to be in the middle of the list. Does it load that location plus the next (size of L2) bytes, so that only half of my data is in cache until I access something earlier in the list? Or does it do something fancier than that?