[CLASSES]: Find bit holes

An example is worth a thousand words, look for "XXX ... bit hole, try to pack"
and the stats at the bottom:

[acme@newtoy net-2.6]$ pahole ../OUTPUT/qemu/net-2.6/fs/inode.o task_struct
/* include2/asm/system.h:11 */
struct task_struct {
        volatile long int          state;                /*     0     4 */
        struct thread_info *       thread_info;          /*     4     4 */
        atomic_t                   usage;                /*     8     4 */
        long unsigned int          flags;                /*    12     4 */
        long unsigned int          ptrace;               /*    16     4 */
        int                        lock_depth;           /*    20     4 */
        int                        load_weight;          /*    24     4 */
        int                        prio;                 /*    28     4 */
        /* --- cacheline 1 boundary (32 bytes) --- */
        int                        static_prio;          /*    32     4 */
        int                        normal_prio;          /*    36     4 */
        struct list_head           run_list;             /*    40     8 */
        struct prio_array *        array;                /*    48     4 */
        short unsigned int         ioprio;               /*    52     2 */

        /* XXX 2 bytes hole, try to pack */

        long unsigned int          sleep_avg;            /*    56     4 */
        long long unsigned int     timestamp;            /*    60     8 */
        /* --- cacheline 2 boundary (64 bytes) was 4 bytes ago --- */
        long long unsigned int     last_ran;             /*    68     8 */
        long long unsigned int     sched_time;           /*    76     8 */
        enum sleep_type            sleep_type;           /*    84     4 */
        long unsigned int          policy;               /*    88     4 */
        cpumask_t                  cpus_allowed;         /*    92     4 */
        /* --- cacheline 3 boundary (96 bytes) --- */
        unsigned int               time_slice;           /*    96     4 */
        unsigned int               first_time_slice;     /*   100     4 */
        struct list_head           tasks;                /*   104     8 */
        struct list_head           ptrace_children;      /*   112     8 */
        struct list_head           ptrace_list;          /*   120     8 */
        /* --- cacheline 4 boundary (128 bytes) --- */
        struct mm_struct *         mm;                   /*   128     4 */
        struct mm_struct *         active_mm;            /*   132     4 */
        struct linux_binfmt *      binfmt;               /*   136     4 */
        long int                   exit_state;           /*   140     4 */
        int                        exit_code;            /*   144     4 */
        int                        exit_signal;          /*   148     4 */
        int                        pdeath_signal;        /*   152     4 */
        long unsigned int          personality;          /*   156     4 */
        /* --- cacheline 5 boundary (160 bytes) --- */
        unsigned int               did_exec:1;           /*   160     4 */

        /* XXX 31 bits hole, try to pack */

        pid_t                      pid;                  /*   164     4 */
        pid_t                      tgid;                 /*   168     4 */
        struct task_struct *       real_parent;          /*   172     4 */
        struct task_struct *       parent;               /*   176     4 */
        struct list_head           children;             /*   180     8 */
        struct list_head           sibling;              /*   188     8 */
        /* --- cacheline 6 boundary (192 bytes) was 4 bytes ago --- */
        struct task_struct *       group_leader;         /*   196     4 */
        struct pid_link            pids[3];              /*   200    36 */
        /* --- cacheline 7 boundary (224 bytes) was 12 bytes ago --- */
        struct list_head           thread_group;         /*   236     8 */
        struct completion *        vfork_done;           /*   244     4 */
        int *                      set_child_tid;        /*   248     4 */
        int *                      clear_child_tid;      /*   252     4 */
        /* --- cacheline 8 boundary (256 bytes) --- */
        long unsigned int          rt_priority;          /*   256     4 */
        cputime_t                  utime;                /*   260     4 */
        cputime_t                  stime;                /*   264     4 */
        long unsigned int          nvcsw;                /*   268     4 */
        long unsigned int          nivcsw;               /*   272     4 */
        struct timespec            start_time;           /*   276     8 */
        long unsigned int          min_flt;              /*   284     4 */
        /* --- cacheline 9 boundary (288 bytes) --- */
        long unsigned int          maj_flt;              /*   288     4 */
        cputime_t                  it_prof_expires;      /*   292     4 */
        cputime_t                  it_virt_expires;      /*   296     4 */
        long long unsigned int     it_sched_expires;     /*   300     8 */
        struct list_head           cpu_timers[3];        /*   308    24 */
        /* --- cacheline 10 boundary (320 bytes) was 12 bytes ago --- */
        uid_t                      uid;                  /*   332     4 */
        uid_t                      euid;                 /*   336     4 */
        uid_t                      suid;                 /*   340     4 */
        uid_t                      fsuid;                /*   344     4 */
        gid_t                      gid;                  /*   348     4 */
        /* --- cacheline 11 boundary (352 bytes) --- */
        gid_t                      egid;                 /*   352     4 */
        gid_t                      sgid;                 /*   356     4 */
        gid_t                      fsgid;                /*   360     4 */
        struct group_info *        group_info;           /*   364     4 */
        kernel_cap_t               cap_effective;        /*   368     4 */
        kernel_cap_t               cap_inheritable;      /*   372     4 */
        kernel_cap_t               cap_permitted;        /*   376     4 */
        unsigned int               keep_capabilities:1;  /*   380     4 */

        /* XXX 31 bits hole, try to pack */

        /* --- cacheline 12 boundary (384 bytes) --- */
        struct user_struct *       user;                 /*   384     4 */
        struct key *               request_key_auth;     /*   388     4 */
        struct key *               thread_keyring;       /*   392     4 */
        unsigned char              jit_keyring;          /*   396     1 */
        unsigned char              fpu_counter;          /*   397     1 */

        /* XXX 2 bytes hole, try to pack */

        int                        oomkilladj;           /*   400     4 */
        char                       comm[16];             /*   404    16 */
        /* --- cacheline 13 boundary (416 bytes) was 4 bytes ago --- */
        int                        link_count;           /*   420     4 */
        int                        total_link_count;     /*   424     4 */
        struct sysv_sem            sysvsem;              /*   428     4 */
        struct thread_struct       thread;               /*   432   656 */
        /* --- cacheline 34 boundary (1088 bytes) --- */
        struct fs_struct *         fs;                   /*  1088     4 */
        struct files_struct *      files;                /*  1092     4 */
        struct nsproxy *           nsproxy;              /*  1096     4 */
        struct signal_struct *     signal;               /*  1100     4 */
        struct sighand_struct *    sighand;              /*  1104     4 */
        sigset_t                   blocked;              /*  1108     8 */
        sigset_t                   real_blocked;         /*  1116     8 */
        /* --- cacheline 35 boundary (1120 bytes) was 4 bytes ago --- */
        sigset_t                   saved_sigmask;        /*  1124     8 */
        struct sigpending          pending;              /*  1132    16 */
        long unsigned int          sas_ss_sp;            /*  1148     4 */
        /* --- cacheline 36 boundary (1152 bytes) --- */
        size_t                     sas_ss_size;          /*  1152     4 */
        int                        (*notifier)();        /*  1156     4 */
        void *                     notifier_data;        /*  1160     4 */
        sigset_t *                 notifier_mask;        /*  1164     4 */
        void *                     security;             /*  1168     4 */
        struct audit_context *     audit_context;        /*  1172     4 */
        seccomp_t                  seccomp;              /*  1176     0 */
        u32                        parent_exec_id;       /*  1176     4 */
        u32                        self_exec_id;         /*  1180     4 */
        /* --- cacheline 37 boundary (1184 bytes) --- */
        spinlock_t                 alloc_lock;           /*  1184    40 */
        /* --- cacheline 38 boundary (1216 bytes) was 8 bytes ago --- */
        spinlock_t                 pi_lock;              /*  1224    40 */
        /* --- cacheline 39 boundary (1248 bytes) was 16 bytes ago --- */
        struct plist_head          pi_waiters;           /*  1264    20 */
        /* --- cacheline 40 boundary (1280 bytes) was 4 bytes ago --- */
        struct rt_mutex_waiter *   pi_blocked_on;        /*  1284     4 */
        struct mutex_waiter *      blocked_on;           /*  1288     4 */
        unsigned int               irq_events;           /*  1292     4 */
        int                        hardirqs_enabled;     /*  1296     4 */
        long unsigned int          hardirq_enable_ip;    /*  1300     4 */
        unsigned int               hardirq_enable_event; /*  1304     4 */
        long unsigned int          hardirq_disable_ip;   /*  1308     4 */
        /* --- cacheline 41 boundary (1312 bytes) --- */
        unsigned int               hardirq_disable_event; /*  1312     4 */
        int                        softirqs_enabled;     /*  1316     4 */
        long unsigned int          softirq_disable_ip;   /*  1320     4 */
        unsigned int               softirq_disable_event; /*  1324     4 */
        long unsigned int          softirq_enable_ip;    /*  1328     4 */
        unsigned int               softirq_enable_event; /*  1332     4 */
        int                        hardirq_context;      /*  1336     4 */
        int                        softirq_context;      /*  1340     4 */
        /* --- cacheline 42 boundary (1344 bytes) --- */
        u64                        curr_chain_key;       /*  1344     8 */
        int                        lockdep_depth;        /*  1352     4 */
        struct held_lock           held_locks[30];       /*  1356  1200 */
        /* --- cacheline 79 boundary (2528 bytes) was 28 bytes ago --- */
        unsigned int               lockdep_recursion;    /*  2556     4 */
        /* --- cacheline 80 boundary (2560 bytes) --- */
        void *                     journal_info;         /*  2560     4 */
        struct reclaim_state *     reclaim_state;        /*  2564     4 */
        struct backing_dev_info *  backing_dev_info;     /*  2568     4 */
        struct io_context *        io_context;           /*  2572     4 */
        long unsigned int          ptrace_message;       /*  2576     4 */
        siginfo_t *                last_siginfo;         /*  2580     4 */
        wait_queue_t *             io_wait;              /*  2584     4 */
        u64                        rchar;                /*  2588     8 */
        /* --- cacheline 81 boundary (2592 bytes) was 4 bytes ago --- */
        u64                        wchar;                /*  2596     8 */
        u64                        syscr;                /*  2604     8 */
        u64                        syscw;                /*  2612     8 */
        struct robust_list_head *  robust_list;          /*  2620     4 */
        /* --- cacheline 82 boundary (2624 bytes) --- */
        struct list_head           pi_state_list;        /*  2624     8 */
        struct futex_pi_state *    pi_state_cache;       /*  2632     4 */
        atomic_t                   fs_excl;              /*  2636     4 */
        struct rcu_head            rcu;                  /*  2640     8 */
        struct pipe_inode_info *   splice_pipe;          /*  2648     4 */
}; /* size: 2656, cachelines: 83 */
   /* sum members: 2648, holes: 2, sum holes: 4 */
   /* bit holes: 2, sum bit holes: 62 bits */
   /* padding: 4 */

Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
This commit is contained in:
Arnaldo Carvalho de Melo 2006-12-07 12:26:50 -02:00
parent fb4fed3164
commit a373c28ba9
2 changed files with 40 additions and 9 deletions

View File

@ -658,6 +658,7 @@ void class__find_holes(struct class *self)
{
struct class_member *pos, *last = NULL;
uint64_t last_size = 0, size;
unsigned int bit_sum = 0;
self->nr_holes = 0;
@ -676,8 +677,21 @@ void class__find_holes(struct class *self)
if (last->hole > 0)
++self->nr_holes;
}
}
if (pos->bit_size == 0) {
if (bit_sum != 0) {
last->bit_hole = (last_size * 8) - bit_sum;
if (last->bit_hole != 0)
++self->nr_bit_holes;
bit_sum = 0;
}
} else
bit_sum += pos->bit_size;
size = class_member__size(pos);
/*
* check for bitfields, accounting for only the biggest
@ -692,8 +706,12 @@ void class__find_holes(struct class *self)
last = pos;
}
if (last != NULL && last->offset + last_size != self->size)
self->padding = self->size - (last->offset + last_size);
if (last != NULL) {
if (last->offset + last_size != self->size)
self->padding = self->size - (last->offset + last_size);
if (last->bit_size != 0)
self->bit_padding = (last_size * 8) - bit_sum;
}
}
struct class_member *class__find_member_by_name(const struct class *self,
@ -913,6 +931,7 @@ static void class__print_struct(struct class *self)
unsigned int last_cacheline = 0;
int last_bit_size = 0;
int last_offset = -1;
unsigned int sum_bit_holes = 0;
printf("%s {\n", class__name(self, name, sizeof(name)));
list_for_each_entry(pos, &self->members, tag.node) {
@ -942,6 +961,11 @@ static void class__print_struct(struct class *self)
"try to pack */\n\n", pos->hole);
sum_holes += pos->hole;
}
if (pos->bit_hole != 0) {
printf("\n /* XXX %d bits hole, "
"try to pack */\n\n", pos->bit_hole);
sum_bit_holes += pos->bit_hole;
}
/*
* check for bitfields, accounting for only the biggest
* of the byte_size in the fields in each bitfield set.
@ -959,18 +983,21 @@ static void class__print_struct(struct class *self)
last_bit_size = pos->bit_size;
}
printf("}; /* size: %llu", self->size);
printf("}; /* size: %llu, cachelines: %llu */\n", self->size,
(self->size + cacheline_size - 1) / cacheline_size);
if (sum_holes > 0)
printf(", sum members: %lu, holes: %d, sum holes: %lu",
printf(" /* sum members: %lu, holes: %d, sum holes: %lu */\n",
sum, self->nr_holes, sum_holes);
if (sum_bit_holes > 0)
printf(" /* bit holes: %d, sum bit holes: %lu bits */\n",
self->nr_bit_holes, sum_bit_holes);
if (self->padding > 0)
printf(", padding: %u", self->padding);
printf(", cachelines: %llu", (self->size + cacheline_size - 1) /
cacheline_size);
printf(" /* padding: %u */\n", self->padding);
if (self->bit_padding > 0)
printf(" /* bit_padding: %u bits */\n", self->bit_padding);
last_cacheline = self->size % cacheline_size;
if (last_cacheline != 0)
printf(",\n last cacheline: %u bytes", last_cacheline);
puts(" */");
printf(" /* last cacheline: %u bytes */\n", last_cacheline);
if (sum + sum_holes != self->size - self->padding)
printf("\n/* BRAIN FART ALERT! %llu != "

View File

@ -54,7 +54,9 @@ struct class {
uint64_t nr_entries; /* For arrays */
unsigned short nr_members;
unsigned short nr_holes;
unsigned short nr_bit_holes;
unsigned short padding;
unsigned short bit_padding;
unsigned int refcnt;
signed int diff;
struct class *class_to_diff;
@ -70,6 +72,8 @@ struct class_member {
unsigned char visited:1;
unsigned short hole; /* If there is a hole before the next
one (or the end of the struct) */
unsigned short bit_hole; /* If there is a bit hole before the next
one (or the end of the struct) */
};
struct lexblock {