KeyValuePair<int, int>: 8 bytes
KeyValuePair<long, long>: 16 bytes
KeyValuePair<long, int>: 16 bytes (!!)
KeyValuePair<int, long>: 16 bytes (!!)
I would expect the latter two pairs to require only 8 (long) + 4 (int)
= 12 bytes. Why do they take up 16?
Sizes were determined using dynamic SizeOf emitted through the ILGenerator, as discussed here: Size of generic structure
It's due to data structure Alignment. To quote the Wikipedia article:
Data alignment means putting the data at a memory address equal to some multiple of the word size, which increases the system's performance due to the way the CPU handles memory. To align the data, it may be necessary to insert some meaningless bytes between the end of the last data structure and the start of the next, which is data structure padding.
As an int is 4 bytes having a KeyValuePair of a long and an int would result in misaligned data structures. This would result in a significant drop in performance. It's therefore better to "waste" 4 bytes on each record to get the data aligned and therefore able to be written and read efficiently.
As to why single ints aren't padded - don't forget with a structure/class it's relatively easy to add padding variable - but for a plain value type you haven't got that structure/class there. I'd guess that the extra work required (adding a dummy structure around the int to insert the padding into) isn't worth the performance gain.
There's real no difference between 32 bit and 64 bit operating systems here, they'll still need padding and aligning, but the amount of padding might vary.
In the "old days" you often had to manually add padding to data structures to get the correct alignment, these days it tends to be handled automatically by the compiler.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With