Question

I was reading about unmanaged code in C#, and came across the following line:-

In a C# program CLR finds the offset using field tokens.
C field names are directly compiled into offsets. For access speed each field is placed at an offset that is a multiple of field's size.
That multiplier is however restricted to a maximum of x bytes, where x is the "pack size".

My question is that what is Pack Size ?

Était-ce utile?

La solution 2

In computer architecture it's a lot faster to have things be byte aligned. When language specs talk about pack size, this is a matter of saying that the compiler will automatically create larger slots for data sizes depending on how things align. This means that sometimes what you think will be a 2 byte field, can actually be at a 4 byte slot in memory. If you want to shave off storage size, in exchange for cpu slowdown, you can adjust the pack size.

Check the msdn on pack for more info.

To quote this tutorial:

Historically memory is byte addressable and arranged sequentially. If the memory is arranged as single bank of one byte width, the processor needs to issue 4 memory read cycles to fetch an integer. It is more economical to read all 4 bytes of integer in one memory cycle. To take such advantage, the memory will be arranged as group of 4 banks as shown in the above figure.

The memory addressing still be sequential. If bank 0 occupies an address X, bank 1, bank 2 and bank 3 will be at (X + 1), (X + 2) and (X + 3) addresses. If an integer of 4 bytes is allocated on X address (X is multiple of 4), the processor needs only one memory cycle to read entire integer.

Where as, if the integer is allocated at an address other than multiple of 4, it spans across two rows of the banks as shown in the below figure. Such an integer requires two memory read cycle to fetch the data.

...

A variable’s data alignment deals with the way the data stored in these banks. For example, the natural alignment of int on 32-bit machine is 4 bytes. When a data type is naturally aligned, the CPU fetches it in minimum read cycles.

Similarly, the natural alignment of short int is 2 bytes. It means, a short int can be stored in bank 0 – bank 1 pair or bank 2 – bank 3 pair. A double requires 8 bytes, and occupies two rows in the memory banks. Any misalignment of double will force more than two read cycles to fetch double data.

Note that a double variable will be allocated on 8 byte boundary on 32 bit machine and requires two memory read cycles. On a 64 bit machine, based on number of banks, double variable will be allocated on 8 byte boundary and requires only one memory read cycle.

While the languages are different, the concept is the same

Autres conseils

I'll take the details of field alignment as a given, covered in devshorts' quote. The pack size setting is where the compiler stops trying to keep a field aligned because it is too big.

It is a compiler setting or a #pragma in native code. A tricky one on Intel processors because they are flexible and allow misaligned data with little to no penalty. A pack size of 8 is a very common default and almost always correct. Sometimes it is 1 or 4. The Pack property in your [StructLayout] declaration must match, if it doesn't then you'll have good odds for reading garbage because you'll read a field at the wrong memory location.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top