[PFUNCT]: Do per CU inline statistics
Top five object files (CU, Compilation Unit) per number of inline expansions, vmlinux being dissected is one built for QEMU, most things as modules, that are not being taken into account as we're only looking at vmlinux: [acme@newtoy guinea_pig-2.6]$ pfunct -C ../../acme/OUTPUT/qemu/net-2.6/vmlinux | sort -k2 -nr | head -5 | cut -c40- net/ipv4/tcp_input.c: 274 20655 fs/buffer.c: 272 4597 kernel/sched.c: 214 3549 kernel/signal.c: 196 2730 fs/ext3/inode.c: 191 7961 [acme@newtoy guinea_pig-2.6]$ Top five object files (CU, Compilation Unit) per total size of inline expansions: [acme@newtoy guinea_pig-2.6]$ pfunct -C ../../acme/OUTPUT/qemu/net-2.6/vmlinux | sort -k3 -nr | head -5 | cut -c40- net/ipv4/tcp_input.c: 274 20655 net/xfrm/xfrm_policy.c: 173 11511 kernel/module.c: 95 10826 drivers/char/vt.c: 91 10050 net/xfrm/xfrm_user.c: 150 9682 [acme@newtoy guinea_pig-2.6]$ Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
This commit is contained in:
parent
0330fb5d34
commit
dcfe27a7ef
24
classes.c
24
classes.c
|
@ -34,12 +34,16 @@ static void cus__add(struct cu *cu)
|
|||
list_add_tail(&cu->node, &cus__list);
|
||||
}
|
||||
|
||||
static struct cu *cu__new(unsigned int cu)
|
||||
static struct cu *cu__new(unsigned int cu, const char *name)
|
||||
{
|
||||
struct cu *self = malloc(sizeof(*self));
|
||||
|
||||
if (self != NULL)
|
||||
if (self != NULL) {
|
||||
INIT_LIST_HEAD(&self->classes);
|
||||
self->name = name != NULL ? strdup(name) : NULL;
|
||||
self->nr_inline_expansions = 0;
|
||||
self->size_inline_expansions = 0;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
@ -352,6 +356,17 @@ void class__find_holes(struct class *self, const struct cu *cu)
|
|||
self->padding = self->size - (last->offset + last_size);
|
||||
}
|
||||
|
||||
|
||||
void cu__account_inline_expansions(struct cu *self)
|
||||
{
|
||||
struct class *pos;
|
||||
|
||||
list_for_each_entry(pos, &self->classes, node) {
|
||||
self->nr_inline_expansions += pos->nr_inline_expansions;
|
||||
self->size_inline_expansions += pos->size_inline_expansions;
|
||||
}
|
||||
}
|
||||
|
||||
void class__print_inline_expansions(struct class *self, const struct cu *cu)
|
||||
{
|
||||
char bf[256];
|
||||
|
@ -776,7 +791,10 @@ int classes__load(const char *filename)
|
|||
Dwarf_Die die;
|
||||
|
||||
if (dwarf_offdie(dwarf, last_offset + hdr_size, &die) != NULL) {
|
||||
current_cu = cu__new(current_cu_id);
|
||||
Dwarf_Attribute name;
|
||||
current_cu = cu__new(current_cu_id,
|
||||
attr_string(&die, DW_AT_name,
|
||||
&name));
|
||||
if (current_cu == NULL)
|
||||
oom("cu__new");
|
||||
++current_cu_id;
|
||||
|
|
|
@ -17,7 +17,10 @@
|
|||
struct cu {
|
||||
struct list_head node;
|
||||
struct list_head classes;
|
||||
const char *name;
|
||||
unsigned int id;
|
||||
unsigned long nr_inline_expansions;
|
||||
unsigned long size_inline_expansions;
|
||||
};
|
||||
|
||||
struct class {
|
||||
|
@ -73,6 +76,7 @@ extern void classes__print(const unsigned int tag);
|
|||
extern void class__print_inline_expansions(struct class *self,
|
||||
const struct cu *cu);
|
||||
extern struct class *cus__find_class_by_name(struct cu **cu, const char *name);
|
||||
extern void cu__account_inline_expansions(struct cu *self);
|
||||
extern int cu__for_each_class(struct cu *cu,
|
||||
int (*iterator)(struct cu *cu,
|
||||
struct class *class,
|
||||
|
|
37
pfunct.c
37
pfunct.c
|
@ -20,6 +20,7 @@ static int show_inline_expansions;
|
|||
|
||||
static struct option long_options[] = {
|
||||
{ "class", required_argument, NULL, 'c' },
|
||||
{ "cu_inline_expansions_stats", no_argument, NULL, 'C' },
|
||||
{ "function_name_len", no_argument, NULL, 'N' },
|
||||
{ "goto_labels", no_argument, NULL, 'g' },
|
||||
{ "show_inline_expansions", no_argument, NULL, 'i' },
|
||||
|
@ -36,15 +37,16 @@ static void usage(void)
|
|||
fprintf(stderr,
|
||||
"usage: pfunct [options] <file_name> {<function_name>}\n"
|
||||
" where: \n"
|
||||
" -c, --class=<class> functions that have <class> "
|
||||
"pointer parameters\n"
|
||||
" -g, --goto_labels show number of goto labels\n"
|
||||
" -i, --show_inline_expansions show inline expansions\n"
|
||||
" -s, --sizes show size of functions\n"
|
||||
" -N, --function_name_len show size of functions\n"
|
||||
" -p, --nr_parameters show number or parameters\n"
|
||||
" -S, --variables show number of variables\n"
|
||||
" -V, --verbose be verbose\n");
|
||||
" -c, --class=<class> functions that have <class> "
|
||||
"pointer parameters\n"
|
||||
" -g, --goto_labels show number of goto labels\n"
|
||||
" -i, --show_inline_expansions show inline expansions\n"
|
||||
" -C, --cu_inline_expansions_stats show CU inline expansions stats\n"
|
||||
" -s, --sizes show size of functions\n"
|
||||
" -N, --function_name_len show size of functions\n"
|
||||
" -p, --nr_parameters show number or parameters\n"
|
||||
" -S, --variables show number of variables\n"
|
||||
" -V, --verbose be verbose\n");
|
||||
}
|
||||
|
||||
static int class__has_parameter_of_type(struct cu *cu, struct class *self,
|
||||
|
@ -157,6 +159,15 @@ static int cu_function_iterator(struct cu *cu, void *cookie)
|
|||
return cu__for_each_class(cu, function_iterator, cookie);
|
||||
}
|
||||
|
||||
static int cu_inlines_iterator(struct cu *cu, void *cookie)
|
||||
{
|
||||
cu__account_inline_expansions(cu);
|
||||
if (cu->nr_inline_expansions > 0)
|
||||
printf("%s: %lu %lu\n", cu->name, cu->nr_inline_expansions,
|
||||
cu->size_inline_expansions);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nr_parameters_iterator(struct cu *cu, struct class *class, void *cookie)
|
||||
{
|
||||
if (class->tag != DW_TAG_subprogram || class->inlined)
|
||||
|
@ -199,11 +210,13 @@ int main(int argc, char *argv[])
|
|||
int show_nr_parameters = 0;
|
||||
int show_function_name_len = 0;
|
||||
int show_inline_expansions_stats = 0;
|
||||
int show_inline_stats = 0;
|
||||
|
||||
while ((option = getopt_long(argc, argv, "c:giINpsSV",
|
||||
while ((option = getopt_long(argc, argv, "c:CgiINpsSV",
|
||||
long_options, &option_index)) >= 0)
|
||||
switch (option) {
|
||||
case 'c': class_name = optarg; break;
|
||||
case 'C': show_inline_stats = 1; break;
|
||||
case 's': show_sizes = 1; break;
|
||||
case 'S': show_variables = 1; break;
|
||||
case 'p': show_nr_parameters = 1; break;
|
||||
|
@ -231,7 +244,9 @@ int main(int argc, char *argv[])
|
|||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (show_nr_parameters)
|
||||
if (show_inline_stats)
|
||||
cus__for_each_cu(cu_inlines_iterator, NULL);
|
||||
else if (show_nr_parameters)
|
||||
cus__for_each_cu(cu_nr_parameters_iterator, NULL);
|
||||
else if (show_variables)
|
||||
cus__for_each_cu(cu_variables_iterator, NULL);
|
||||
|
|
Loading…
Reference in New Issue