Skip to content

Commit 6ba29fb

Browse files
captain5050namhyung
authored andcommitted
perf callchain: Make brtype_stat in callchain_list optional
struct callchain_list is 352bytes in size, 232 of which are brtype_stat. brtype_stat is only used for certain callchain_list items so make it optional, allocating when necessary. So that printing doesn't need to deal with an optional brtype_stat, pass an empty/zero version. Before: ``` struct callchain_list { u64 ip; /* 0 8 */ struct map_symbol ms; /* 8 24 */ struct { _Bool unfolded; /* 32 1 */ _Bool has_children; /* 33 1 */ }; /* 32 2 */ /* XXX 6 bytes hole, try to pack */ u64 branch_count; /* 40 8 */ u64 from_count; /* 48 8 */ u64 predicted_count; /* 56 8 */ /* --- cacheline 1 boundary (64 bytes) --- */ u64 abort_count; /* 64 8 */ u64 cycles_count; /* 72 8 */ u64 iter_count; /* 80 8 */ u64 iter_cycles; /* 88 8 */ struct branch_type_stat brtype_stat; /* 96 232 */ /* --- cacheline 5 boundary (320 bytes) was 8 bytes ago --- */ const char * srcline; /* 328 8 */ struct list_head list; /* 336 16 */ /* size: 352, cachelines: 6, members: 13 */ /* sum members: 346, holes: 1, sum holes: 6 */ /* last cacheline: 32 bytes */ }; ``` After: ``` struct callchain_list { u64 ip; /* 0 8 */ struct map_symbol ms; /* 8 24 */ struct { _Bool unfolded; /* 32 1 */ _Bool has_children; /* 33 1 */ }; /* 32 2 */ /* XXX 6 bytes hole, try to pack */ u64 branch_count; /* 40 8 */ u64 from_count; /* 48 8 */ u64 predicted_count; /* 56 8 */ /* --- cacheline 1 boundary (64 bytes) --- */ u64 abort_count; /* 64 8 */ u64 cycles_count; /* 72 8 */ u64 iter_count; /* 80 8 */ u64 iter_cycles; /* 88 8 */ struct branch_type_stat * brtype_stat; /* 96 8 */ const char * srcline; /* 104 8 */ struct list_head list; /* 112 16 */ /* size: 128, cachelines: 2, members: 13 */ /* sum members: 122, holes: 1, sum holes: 6 */ }; ``` Signed-off-by: Ian Rogers <irogers@google.com> Cc: K Prateek Nayak <kprateek.nayak@amd.com> Cc: Ravi Bangoria <ravi.bangoria@amd.com> Cc: Sandipan Das <sandipan.das@amd.com> Cc: Anshuman Khandual <anshuman.khandual@arm.com> Cc: German Gomez <german.gomez@arm.com> Cc: James Clark <james.clark@arm.com> Cc: Nick Terrell <terrelln@fb.com> Cc: Sean Christopherson <seanjc@google.com> Cc: Changbin Du <changbin.du@huawei.com> Cc: liuwenyu <liuwenyu7@huawei.com> Cc: Yang Jihong <yangjihong1@huawei.com> Cc: Masami Hiramatsu <mhiramat@kernel.org> Cc: Miguel Ojeda <ojeda@kernel.org> Cc: Song Liu <song@kernel.org> Cc: Leo Yan <leo.yan@linaro.org> Cc: Kajol Jain <kjain@linux.ibm.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: Kan Liang <kan.liang@linux.intel.com> Cc: Athira Rajeev <atrajeev@linux.vnet.ibm.com> Cc: Yanteng Si <siyanteng@loongson.cn> Cc: Liam Howlett <liam.howlett@oracle.com> Cc: Paolo Bonzini <pbonzini@redhat.com> Link: https://lore.kernel.org/r/20231024222353.3024098-10-irogers@google.com Signed-off-by: Namhyung Kim <namhyung@kernel.org>
1 parent d47d876 commit 6ba29fb

2 files changed

Lines changed: 34 additions & 9 deletions

File tree

tools/perf/util/callchain.c

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -586,7 +586,7 @@ fill_node(struct callchain_node *node, struct callchain_cursor *cursor)
586586
call = zalloc(sizeof(*call));
587587
if (!call) {
588588
perror("not enough memory for the code path tree");
589-
return -1;
589+
return -ENOMEM;
590590
}
591591
call->ip = cursor_node->ip;
592592
call->ms = cursor_node->ms;
@@ -602,23 +602,32 @@ fill_node(struct callchain_node *node, struct callchain_cursor *cursor)
602602
* branch_from is set with value somewhere else
603603
* to imply it's "to" of a branch.
604604
*/
605-
call->brtype_stat.branch_to = true;
605+
if (!call->brtype_stat) {
606+
call->brtype_stat = zalloc(sizeof(*call->brtype_stat));
607+
if (!call->brtype_stat) {
608+
perror("not enough memory for the code path branch statisitcs");
609+
free(call->brtype_stat);
610+
return -ENOMEM;
611+
}
612+
}
613+
call->brtype_stat->branch_to = true;
606614

607615
if (cursor_node->branch_flags.predicted)
608616
call->predicted_count = 1;
609617

610618
if (cursor_node->branch_flags.abort)
611619
call->abort_count = 1;
612620

613-
branch_type_count(&call->brtype_stat,
621+
branch_type_count(call->brtype_stat,
614622
&cursor_node->branch_flags,
615623
cursor_node->branch_from,
616624
cursor_node->ip);
617625
} else {
618626
/*
619627
* It's "from" of a branch
620628
*/
621-
call->brtype_stat.branch_to = false;
629+
if (call->brtype_stat && call->brtype_stat->branch_to)
630+
call->brtype_stat->branch_to = false;
622631
call->cycles_count =
623632
cursor_node->branch_flags.cycles;
624633
call->iter_count = cursor_node->nr_loop_iter;
@@ -652,6 +661,7 @@ add_child(struct callchain_node *parent,
652661
list_del_init(&call->list);
653662
map__zput(call->ms.map);
654663
maps__zput(call->ms.maps);
664+
zfree(&call->brtype_stat);
655665
free(call);
656666
}
657667
free(new);
@@ -762,23 +772,31 @@ static enum match_result match_chain(struct callchain_cursor_node *node,
762772
/*
763773
* It's "to" of a branch
764774
*/
765-
cnode->brtype_stat.branch_to = true;
775+
if (!cnode->brtype_stat) {
776+
cnode->brtype_stat = zalloc(sizeof(*cnode->brtype_stat));
777+
if (!cnode->brtype_stat) {
778+
perror("not enough memory for the code path branch statisitcs");
779+
return MATCH_ERROR;
780+
}
781+
}
782+
cnode->brtype_stat->branch_to = true;
766783

767784
if (node->branch_flags.predicted)
768785
cnode->predicted_count++;
769786

770787
if (node->branch_flags.abort)
771788
cnode->abort_count++;
772789

773-
branch_type_count(&cnode->brtype_stat,
790+
branch_type_count(cnode->brtype_stat,
774791
&node->branch_flags,
775792
node->branch_from,
776793
node->ip);
777794
} else {
778795
/*
779796
* It's "from" of a branch
780797
*/
781-
cnode->brtype_stat.branch_to = false;
798+
if (cnode->brtype_stat && cnode->brtype_stat->branch_to)
799+
cnode->brtype_stat->branch_to = false;
782800
cnode->cycles_count += node->branch_flags.cycles;
783801
cnode->iter_count += node->nr_loop_iter;
784802
cnode->iter_cycles += node->iter_cycles;
@@ -1026,6 +1044,7 @@ merge_chain_branch(struct callchain_cursor *cursor,
10261044
maps__zput(ms.maps);
10271045
map__zput(list->ms.map);
10281046
maps__zput(list->ms.maps);
1047+
zfree(&list->brtype_stat);
10291048
free(list);
10301049
}
10311050

@@ -1447,11 +1466,14 @@ static int callchain_counts_printf(FILE *fp, char *bf, int bfsize,
14471466
int callchain_list_counts__printf_value(struct callchain_list *clist,
14481467
FILE *fp, char *bf, int bfsize)
14491468
{
1469+
static const struct branch_type_stat empty_brtype_stat = {};
1470+
const struct branch_type_stat *brtype_stat;
14501471
u64 branch_count, predicted_count;
14511472
u64 abort_count, cycles_count;
14521473
u64 iter_count, iter_cycles;
14531474
u64 from_count;
14541475

1476+
brtype_stat = clist->brtype_stat ?: &empty_brtype_stat;
14551477
branch_count = clist->branch_count;
14561478
predicted_count = clist->predicted_count;
14571479
abort_count = clist->abort_count;
@@ -1463,7 +1485,7 @@ int callchain_list_counts__printf_value(struct callchain_list *clist,
14631485
return callchain_counts_printf(fp, bf, bfsize, branch_count,
14641486
predicted_count, abort_count,
14651487
cycles_count, iter_count, iter_cycles,
1466-
from_count, &clist->brtype_stat);
1488+
from_count, brtype_stat);
14671489
}
14681490

14691491
static void free_callchain_node(struct callchain_node *node)
@@ -1476,13 +1498,15 @@ static void free_callchain_node(struct callchain_node *node)
14761498
list_del_init(&list->list);
14771499
map__zput(list->ms.map);
14781500
maps__zput(list->ms.maps);
1501+
zfree(&list->brtype_stat);
14791502
free(list);
14801503
}
14811504

14821505
list_for_each_entry_safe(list, tmp, &node->val, list) {
14831506
list_del_init(&list->list);
14841507
map__zput(list->ms.map);
14851508
maps__zput(list->ms.maps);
1509+
zfree(&list->brtype_stat);
14861510
free(list);
14871511
}
14881512

@@ -1569,6 +1593,7 @@ int callchain_node__make_parent_list(struct callchain_node *node)
15691593
list_del_init(&chain->list);
15701594
map__zput(chain->ms.map);
15711595
maps__zput(chain->ms.maps);
1596+
zfree(&chain->brtype_stat);
15721597
free(chain);
15731598
}
15741599
return -ENOMEM;

tools/perf/util/callchain.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ struct callchain_list {
129129
u64 cycles_count;
130130
u64 iter_count;
131131
u64 iter_cycles;
132-
struct branch_type_stat brtype_stat;
132+
struct branch_type_stat *brtype_stat;
133133
const char *srcline;
134134
struct list_head list;
135135
};

0 commit comments

Comments
 (0)