12 comments

[ 3.2 ms ] story [ 48.3 ms ] thread
Seeing the very large amounts of alignment padding really makes me wonder if aligning data structures (and CPUs that require it) is an increasingly obolescent practice; it wastes space, making less useful data fit in the caches, and as far as I can tell was only necessary because some CPU designers wanted to save the - comparatively tiny relative to the cache - bit of logic to extract the right set of bytes from the cache line and bring in another one if the access spans two of them.

http://lemire.me/blog/archives/2012/05/31/data-alignment-for...

I know that you can arrange structures in an attempt to minimise any padding, like what's been done here, but that doesn't always work out so perhaps it would've been better to pack everything together.

x86 CPUs have always been forgiving of unaligned access. So while modern x86 CPUs might have resolved this performance issue, if you ever want to run your software on ARM, for example, you're still going to have to align everything.
FWIW, since ARMv6 unaligned access has been supported on ARM.
Depends on the OS you target. IIRC Windows will handle misalignment for you.
There's a second performance reason (although I can't comment on whether it's relevant in this case); it's cache banking.

Sandy Bridge and Ivy Bridge processors load data into L1 cache in 64 byte chunks. This is split across 8 banks, the first 8 bytes go in the first bank, and so on.

Each bank can service one request at a time. If you have aligned structs, then you will only be accessing one cache bank for each request. If you have unaligned structs, you might access two cache banks, or three for a 16 byte read.

This increases contention and reduces the opportunities for instruction level parallelism, because it increases the number of conflicting instructions.

This is unfortunately tricky to benchmark synthetically (your link displayed it well; his benchmark doesn't show it but the linked benchmark is 50% slower - who's is the realistic case? (probably a bit of both)), but it's entirely possible that you'd see a difference over a large test case set.

I think with Haswell there's less of a problem.

Also it's probably easier for them to align and guarantee their code works on all architectures; PHP memory usage is not huge in general (I know Wordpress is doing badly if it uses 64MB) so it's not really a problem.

PHP actually has a default request memory limit of 128MB.
Which when discussing typical memory usage is about as useful as saying "X86-32 has a per-process limit of 4GB!"
Not quite: that figure was chosen because most applications won't exceed it. It's not an arbitrary number.
Unaligned access isn't cache—optimal; if you go over the line boundary you need to fetch two.
There is another reason for moving type tags outside of allocated blocks, albeit possibly not very relevant to PHP; for some local variables, type tags can be removed by constant propagation altogether.
Unboxed variables is a possibility some people have thought about, and I think HHVM does it. Given PHP 7'a parameter type hints it might be practical to do. Though a problem would be that if you strip off the type tag, you have to add it back again whenever you pass the value anywhere.