Say a project has this struct:
struct cheese {
char name[52];
char a;
int b;
char c;
int d;
short e;
};
And we want to see how the layout looks like more precisely:
[acme@filo examples]$ pahole swiss_cheese cheese
/* <11b> /home/acme/git/pahole/examples/swiss_cheese.c:3 */
struct cheese {
char name[52]; /* 0 52 */
char a; /* 52 1 *//* XXX 3 bytes hole, try to pack */
int b; /* 56 4 */
char c; /* 60 1 *//* XXX 3 bytes hole, try to pack */
/* — cacheline 1 boundary (64 bytes) — */
int d; /* 64 4 */
short int e; /* 68 2 */
}; /* size: 72, cachelines: 2 */
/* sum members: 64, holes: 2, sum holes: 6 */
/* padding: 2 */
/* last cacheline: 8 bytes */
[acme@filo examples]$
Heck, what a swiss cheese! Surely we can do better, huh? Lets ask pahole for a little help:
[acme@filo examples]$ pahole -kV swiss_cheese cheese
/* moving c(size=1) to after a(offset=52, size=1, hole=3) */
/* moving e(size=2) to after c(offset=53, size=1, hole=2) *//* <11b> /home/acme/git/pahole/examples/swiss_cheese.c:3 */
struct cheese {
char name[52]; /* 0 52 */
char a; /* 52 1 */
char c; /* 53 1 */
short int e; /* 54 2 */
int b; /* 56 4 */
int d; /* 60 4 */
/* — cacheline 1 boundary (64 bytes) — */
}; /* size: 64, cachelines: 1 */
/* saved 8 bytes and 1 cacheline! */
[acme@filo examples]$
Much better now, no?
Ok, lets try something more interesting, like some Linux kernel structs, the output is big, so here are some links for some structs that spent some jiffies on pahole’s spa:
- struct hwif_t – saved 4 bytes and 1 cacheline
- struct task_struct – saved 4 bytes
- struct jsm_channel – saved 8 bytes
Type demotion of bigger than needed bitfields will help getting more saved 🙂