Show HN: 33% Memory Reduction by Reordering Struct Fields
qvault.io
qvault.io
So I used to do things like this (hopefully the formatting is correct):
~/Desktop$ cat test1.c
#include <stdio.h>
#include <stdint.h>
// Original Ordering
struct stats {
uint8_t NumPosts;
uint16_t Reach;
uint8_t NumLikes;
};
// Packed struct
struct stats_packed {
uint8_t NumPosts;
uint16_t Reach;
uint8_t NumLikes;
} __attribute__((packed));
// Reordered
struct stats_reordered {
uint8_t NumPosts;
uint8_t NumLikes;
uint16_t Reach;
};
int main(){
printf("sizeof(struct stats) = %ld\n", sizeof(struct stats));
printf("sizeof(struct stats_packed) = %ld\n", sizeof(struct stats_packed));
printf("sizeof(struct stats_reordered) = %ld\n", sizeof(struct stats_reordered));
return 0;
}
~/Desktop$ gcc test1.c && ./a.out
sizeof(struct stats) = 6
sizeof(struct stats_packed) = 4
sizeof(struct stats_reordered) = 4But it's the sort of thread that once you pull on it, you just keep pulling. Getting the alignment made the data bigger, then we had to shrink it back, and while you're in there you might as well keep looking around...
This means that a lot of optimizations and assumptions that were made might not longer be valid. For example, in GCC the results of the sizeof operator are evaluated at parse time. One might need to change these values link time. Otherwise statements like:
memset(&astruct, 0, sizeof(astruct));
will overwrite memory that is no longer part of the struct.
Furthermore, constant propagation might have propagated the value of a sizeof operator and it might have been folded into different arithmetic operations. This can be solved in different ways, but if the compiler was not built this way, it might take some time to implement. Also, all pointer arithmetic will need to be changed...
You can at link-time be able to change some structure definitions if you know the structure definition is not escaping your application (i.e. it is not passed to a library). There are possibly other things that might hinder the reordering of the fields, for example casting or placing a structure in a union. If you are casting a structure to another, you might be expecting that the underlying memory to be represented in a specific way in order for the cast to make sense. The same thing happens when you place a struct in a union.