Why favour data structure alignment? - c++

The type of each member of the structure usually has a default alignment i.e.each structure member is aligned on a pre-determined boundary.
For this reason the padding is performed in the following wiki example:
struct MixedData
{
char Data1;
short Data2;
int Data3;
char Data4;
};
struct MixedData /* After compilation in 32-bit x86 machine */
{
char Data1; /* 1 byte */
/* 1 byte for the following 'short' to be aligned on a 2 byte boundary
assuming that the address where structure begins is an even number */
char Padding1[1];
short Data2; /* 2 bytes */
int Data3; /* 4 bytes - largest structure member */
char Data4; /* 1 byte */
char Padding2[3]; /* 3 bytes to make total size of the structure 12 bytes */
};
What is the (practical) reason that alignment should be preserved?

Unaligned reads and writes usually require the CPU to fetch the two adjacent words from memory (instead of just one) and to apply some additional bitwise arithmetic in order to perform the designated operation properly.
Some architectures, like x86 will allow it at a performance cost. Other architectures (most notably ARM), will either raise an exception (usually resulting in a SIGBUS signal for a user process) or even "round" the address to the closest boundary which could result in some very nasty bugs.

On many architectures, aligned reads and writes from and to main memory are much faster than their unaligned counterparts.

Usually, structure are aligned on a processor dependent alignment to make accessing them as quick as possible using the processors 'natural' register size.
For 32-bit processors, it's 4 bytes (or 32-bits), for 64-bit processors it's 8 bytes.
Some (non x86) processors will generate a fault if you try to access (say) an int if it's not aligned on the correct boundary.
Communication between different devices is a practical reason to preserve alignment. With default alignment, this structure would be 24 bytes long, whereas on a 64-bit processor, it would be 48 bytes, and non of the items except the first would be in the same place.
It is normally possible to change the structure padding with a compiler/pragma directive which may negate the need for the manual padding specified in your example, but that's typically different for each compiler.

Related

x86 Memory Alignment of struct vs. cache line?

Rcently I'm working on a "searching system" and something about memory/cache performance confuse me.
assume my machine info : x86 arch(L1-3 cache, 64 bytes cache line), linux OS
CPU reads 64 bytes(cache line) each time, so does CPU read data from memory address(to cache) always 64 multiple? For example 0x00(to 0x3F), 0x40(to 0x7f). If I need data(int32_t) located in 0x20 then system still need to load 0x00--0x3F.
how about this case:
struct Obj{int64_t a[5];char b[2];}; then define
int64_t c[5]; Obj obj; int64_t d;
Will virtual memory (or also physical?) be organized like this?
I think the part you might be missing is the alignment requirement that the compiler imposes for various types.
Integer types are generally aligned to a multiple of their own size (e.g. a 64-bit integer will be aligned to 8 bytes); so-called "natural alignment". This is not a strict architectural requirement of x86; unaligned loads and stores still work, but since they are less efficient, the compiler prefers to avoid them.
An aggregate, like a struct, is aligned according to the highest alignment requirement of its members, and padding will be inserted between members if needed to ensure that each one is properly aligned. Padding will also be added at the end so that the overall size of the struct is a multiple of its required alignment.
So in your example, struct Obj has alignment 8, and its size will be rounded up to 48 (with 6 bytes of padding at the end). So there is no need for 24 bytes of padding to be inserted after c[4] (I think you meant to write the padding at addresses 40-63); your obj can be placed at address 40. d can then be placed at address 88.
Note that none of this has anything to do with the cache line size. Objects are not by default aligned to cache lines, though "natural alignment" will ensure that no integer load or store ever has to cross a cache line.

Why is the size of struct Player is increased by 7 bytes? [duplicate]

The type of each member of the structure usually has a default alignment i.e.each structure member is aligned on a pre-determined boundary.
For this reason the padding is performed in the following wiki example:
struct MixedData
{
char Data1;
short Data2;
int Data3;
char Data4;
};
struct MixedData /* After compilation in 32-bit x86 machine */
{
char Data1; /* 1 byte */
/* 1 byte for the following 'short' to be aligned on a 2 byte boundary
assuming that the address where structure begins is an even number */
char Padding1[1];
short Data2; /* 2 bytes */
int Data3; /* 4 bytes - largest structure member */
char Data4; /* 1 byte */
char Padding2[3]; /* 3 bytes to make total size of the structure 12 bytes */
};
What is the (practical) reason that alignment should be preserved?
Unaligned reads and writes usually require the CPU to fetch the two adjacent words from memory (instead of just one) and to apply some additional bitwise arithmetic in order to perform the designated operation properly.
Some architectures, like x86 will allow it at a performance cost. Other architectures (most notably ARM), will either raise an exception (usually resulting in a SIGBUS signal for a user process) or even "round" the address to the closest boundary which could result in some very nasty bugs.
On many architectures, aligned reads and writes from and to main memory are much faster than their unaligned counterparts.
Usually, structure are aligned on a processor dependent alignment to make accessing them as quick as possible using the processors 'natural' register size.
For 32-bit processors, it's 4 bytes (or 32-bits), for 64-bit processors it's 8 bytes.
Some (non x86) processors will generate a fault if you try to access (say) an int if it's not aligned on the correct boundary.
Communication between different devices is a practical reason to preserve alignment. With default alignment, this structure would be 24 bytes long, whereas on a 64-bit processor, it would be 48 bytes, and non of the items except the first would be in the same place.
It is normally possible to change the structure padding with a compiler/pragma directive which may negate the need for the manual padding specified in your example, but that's typically different for each compiler.

About struct padding

Suppose we have a packet
struct Foo
{
short size; // 2
short type; // 2
BYTE data; // 1
//1 byte padding not 3?
};
After compilation it's 6 bytes long with 1 byte padding added at the end of the struct.
Isn't the compiler supposed to add 3 bytes padding so that the structs size is 8 bytes long? Because a 32-bit cpu likes to access the data in 4 byte chunks
Btw with #pragma pack(1) it's 5 bytes long, as expected.
Your struct contains shorts which means that those will likely need to be aligned on a two byte boundary. If you were to create arrays of this struct with no padding, every other element would end up with the shorts incorrectly aligned which might crash or be slow.
Padding exists for the purpose of safety and performance. On certain architectures an unaligned read causes a crash. So the compiler pads the struct so that it's members align on addresses dividable by their size. Apart from that the compiler will have little reason to add extra padding just to align the entire struct on the native word boundary. So it will add only one byte in your case.
Try having an int in your struct. This should change the padding to have an additional 3 bytes of padding. Also having the int in between two bytes will make padding between the bytes.
The compiler is free to make whatever choice it wants regarding padding and unless you specify packing explicitly. Different things will happen on different architectures and with different compilers.
You're already accessing memory in one and two byte increments in the struct so you won't hurt performance any further by aligning the struct on 6 bytes vs 8 so the compiler opts to save the space. If you just never make assumptions about struct alignment and let the compiler do the right thing, you won't have to worry about it in practice.
Because a 32-bit cpu likes to access the data in 4 byte chunks
Not exactly. Strictly speaking a memory access is aligned (because here you talk about alignment) when the variable that you access is N bytes long and the variable address is N-bytes aligned.
So it does not mean that it is 4-bytes aligned. Could be 2 bytes aligned as in your case where you declare types short and the data range is 2 bytes.

Structures in C

I got a structure like this:
struct bar {
char x;
char *y;
};
I can assume that on a 32 bit system, that padding for char will make it 4 bytes total, and a pointer in 32 bit is 4, so the total size will be 8 right?
I know it's all implementation specific, but I think if it's within 1-4, it should be padded to 4, within 5-8 to 8 and 9-16 within 16, is this right? it seems to work.
Would I be right to say that the struct will be 12 bytes in a x64 arch, because pointers are 8 bytes? Or what do you think it should be?
I can assume that on a 32 bit system,
that padding for char will make it 4
bytes total, and a pointer in 32 bit
is 4, so the total size will be 8
right?
It's not safe to assume that, but that will often be the case, yes. For x86, fields are usually 32-bit aligned. The reason for this is to increase the system's performance at the cost of memory usage (see here).
Would I be right to say that the
struct will be 12 bytes in a x64 arch,
because pointers are 8 bytes? Or what
do you think it should be?
Similarly, for x64, fields are usually 64-bit/8-byte aligned, so sizeof(bar) would be 16.
As Anders points out, however, all this goes flying out the window once you start playing with alignment via /Zp, the pack directive, or whatever else your compiler supports.
Its a compiler switch, you can't assume anything. If you assume you may get into trouble.
For instance in Visual Studio you can decide using pragma pack(1) that you want it directly on the byte boundary.
You can't assume anything in general. Every platform decides its own padding rules.
That said, any architecture that uses "natural" alignment, where operands are padded to their own size (necessary and sufficient to avoid straddling naturally-aligned pages, cachelines, etc), will make bar twice the pointer size.
So, given natural alignment rules and nothing more, 8 bytes on 32-bit, 16 bytes on 64-bit.
$9.2/12-
Nonstatic data members of a
(non-union) class declared without an
intervening access-specifier are
allocated so that later members have
higher addresses within a class
object. The order of allocation of
nonstatic data members separated by an
access-specifier is unspecified
(11.1). Implementation alignment
requirements might cause two adjacent
members not to be allocated
immediately after each other; so might
requirements for space for managing
virtual functions (10.3) and virtual
base classes (10.1).
So, it is highly implementation specific as you already mentioned.
Not quite.
Padding depends on the alignment requirement of the next member. The natural alignment of built-in data types is their size.
There is no padding before char members since their alignment requirement is 1 (assuming char is 1 byte).
For example, if a char (again assume it is one byte) is followed by a short, which, say, is 2 bytes, there may be up to 1 byte of padding because a short must be 2-byte aligned. If a char is followed by double of the size of 8, there may be up to 7 bytes of padding because a double is 8-byte aligned. On the other hand, if a short is followed by a double, the may be up to 6 bytes of padding.
And the size of a structure is a multiple of the alignment of a member with the largest alignment requirement, so there may be tail padding. In the following structure, for instance,
struct baz {
double d;
char c;
};
the member with the largest alignment requirement is d, it's alignment requirement is 8, Which gives sizeof(baz) == 2 * alignof(double). There is 7 bytes of tail padding after member c.
gcc and other modern compilers support __alignof() operator. There is also a portable version in boost.
As others have mentioned, the behaviour can't be relied upon between platforms. However, if you still need to do this, then one thing you can use is BOOST_STATIC_ASSERT() to ensure that if the assumptions are violated then you find out at compile time, eg
#include <boost/static_assert.hpp>
#if ARCH==x86 // or whatever the platform specific #define is
BOOST_STATIC_ASSERT(sizeof(bar)==8);
#elif ARCH==x64
BOOST_STATIC_ASSERT(sizeof(bar)==16);
#else ...
If alignof() is available you could also use that to test your assumption.

C++ struct size: 2+4+2+2+4 = 16 [duplicate]

This question already has answers here:
Closed 13 years ago.
Possible Duplicate:
Why isn’t sizeof for a struct equal to the sum of sizeof of each member?
Why is the sizeof(); of this structure 16 bytes? I'm compiling in g++.
struct bitmapfileheader {
unsigned short bfType;
unsigned int bfSize;
unsigned short bfReserved1;
unsigned short bfReserved2;
unsigned int bfOffBits;
};
It's because the 4 byte ints are aligned to a 4 byte boundry, so there are 2 bytes of padding after bfType.
Alignment.
Likely on your platform ints have to be 4byte aligned and shorts are 2byte aligned.
+0 -1 : bfType
+2 -3 : <padding>
+4 -7: bfSize
+8 -9: bfReserve1
+10 -11: bfReserve2
+12 -15: bfOffBits
-------------
16 bytes
Alignment is good because unaligned structures require extra work for many architectures.
The individual fields in a structure need to be aligned appropriately. The compiler will pad additional space in the structure in order to satisfy alignment requirements.
If you don't want this, you can use the UNALIGNED macro.
I think your compiler uses 4-byte allignment for the fields.
This issue comes because of a concept known as alignment. In many cases, it is desirable to have a number placed at an address that is a multiple of the size of the number in bytes (up to some maximum, often the pointer size of the platform). A variable so placed is said to be aligned to a n-byte boundary, where n is the number. The exact effects of this depend on the processor. Many processors perform math faster if the data is properly aligned. Some are even incapable of performing operations (sometimes even load operations) on unsuitably-aligned data - in order to work on such data, it has to be loaded into two registers and then a series of bit shifts and masks need to be performed to get a usable value, and then it needs to be put back. Think of it like storing half of the int in each of two buckets and needing to put them together to use it, rather than simply storing the whole int in one bucket.
In your case, the initial bfType likely needs to be aligned to a 2-byte boundary, while bfSize likely needs to be aligned to a 4-byte boundary. The compiler has to accomodate this by aligning the entire struct to 4 bytes, and leaving 2 unused bytes between bfType and bfSize.
When compiling on the same system, however, the padding is probably going to be consistent, possibly depending on compiler options and the specific ABI used (generally, you're safe on the same platform unless you are trying to make things incompatible). You can freely make another struct with the same first 5 members, and they will take up 16 bytes of the other struct, in the exact same positions.
If you really need to avoid this behavior, you will have to check your compiler documentation. Most compilers offer an attribute or keyword to declare a variable as having no alignment, and another one to indicate that a struct should have no padding. But these are rarely necessary in the general course of things.
U can pragma pack the structure to avoid padding
ISO C++03, 9.2[class.mem]/12:
Nonstatic data members of a (non-union) class declared without an intervening access-specifier are allocated so that later members have higher addresses within a class object. The order of allocation of nonstatic data members separated by an access-specifier is unspecified (11.1). Implementation alignment requirements might cause two adjacent members not to be allocated immediately after each other; so might requirements for space for managing virtual functions (10.3) and virtual base classes (10.1).
because of the way memory is allocated, there will be padding after a short
This is due to alignment - the compiler has to do some padding.