5 ms·
Sigh... apparently this is now enough of rocket science to be considered for posting on HN... People using packing pragma of GCC should also beware -- an acces
by minipci1321 10y ago
Sigh... apparently this is now enough of rocket science to be considered for posting on HN...
People using packing pragma of GCC should also beware -- an access to a field of a packed structure will be done bytewise, whether a variable happens to be actually aligned or not (I guess the compiler simplified its life by assuming no variable is ever aligned in packet structs), so memory size would go down but CPU use might grow.
At least this used to be true a few years ago, haven't reverified recently.
- looki 10y agoYou mean that it reads the values into single byte registers and assembles those back into the value you want?
- minipci1321 10y agoYes, that is what I meant. It does that even for fields of a structure that are, strictly speaking, not subject to packing -- when, for example, you put a double as the very first field in a struct, and define the entire struct as packed. The double will still be assembled from 8 1-byte reads.
- looki 10y agoThat sounds quite horrible - today was very eye-opening on why people almost never pack structs tightly, thank you.
- vvanders 10y agoYup, same type of thinking helps when working with byte streams, image formats and the like. Working within your native, aligned word size can have wonderful performance benefits.
- jcranmer 10y agoOn x86, most memory can be accessed unaligned (and, unless you cross a cache line boundary, there's effectively no penalty. If you're on Haswell or newer, even if you cross a cache line boundary, there's no latency hit for an L1 cache hit). The code for a struct { char a; double b; } load reference on x86-64 after -O3 is: movsd 1(%rdi), %xmm0 So it looks like gcc is able to condense the load on platforms with unaligned accesses. On ARM, it does look like the double is loaded byte-by-byte.
- minipci1321 10y ago> So it looks like gcc is able to condense the load on platforms with unaligned accesses. It seems there are still some leftovers -- try: struct { int i:31; }; with and without __attribute__((__packed__)).
- bluGill 10y agoTrue (for some processors), but if you are doing packaged structs that should imply you have a reason to tell the compiler you know better than it how to write the struct. That most often (in my experience) means the struct is used for data interchange (ie network or files) and so you have to pay that price for byte access because byte access is a requirement. The other time to do that you might do this is when your are memory constrained and so you are willing to pay a runtime cost just to save a couple bytes of precious memory. I have encountered the first often in the real world: networks are very common. I have only seen the latter one 8 bit CPUs (there they are paying a price to access bits not bytes)
- minipci1321 10y ago> but if you are doing packaged structs that should imply you have a reason to tell the compiler you know better I am pretty sure this could have been implemented better -- for malloc-ed and statically-allocated structs the compiler can know the alignment of the structure, so should be able to emit optimal code according to each case. Admittedly, probably a very minor improvement. It is the feeling of surprise at the time that made me react -- this side-effect wasn't documented in GCC manual at the time, and still isn't. We now have the attribute "aligned", so I am not sure what the code would look like for a struct {} __attribute__((__packed__,__aligned(8))).
- bluGill 10y agoIf the struct is byte, machine word, byte, machine word there is no way to pull that off.
- mikeash 10y agoI would guess that if the struct is packed, the compiler won't assume any particular alignment for the struct itself either, so even if a member is properly aligned relative to the beginning of the struct, it may not be properly aligned in memory.
- Peaker 10y agoOn Intel CPUs there's virtually no cost for misaligned access. Of course, if your misalignment results in your data spanning 2 cache lines instead of 1, that'll be costly, but that's regardless of alignment.