Skip to content

Commit bf36eb5

Browse files
milianwacmel
authored andcommitted
perf report: Properly handle branch count in match_chain()
Some of the code paths I introduced before returned too early without running the code to handle a node's branch count. By refactoring match_chain to only have one exit point, this can be remedied. Signed-off-by: Milian Wolff <milian.wolff@kdab.com> Acked-by: Namhyung Kim <namhyung@kernel.org> Cc: David Ahern <dsahern@gmail.com> Cc: Jin Yao <yao.jin@linux.intel.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com> Link: http://lkml.kernel.org/r/1707691.qaJ269GSZW@agathebauer Link: http://lkml.kernel.org/r/20171018185350.14893-2-milian.wolff@kdab.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
1 parent aa44189 commit bf36eb5

File tree

1 file changed

+78
-62
lines changed

1 file changed

+78
-62
lines changed

tools/perf/util/callchain.c

Lines changed: 78 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -666,83 +666,99 @@ static enum match_result match_chain_strings(const char *left,
666666
return ret;
667667
}
668668

669-
static enum match_result match_chain(struct callchain_cursor_node *node,
670-
struct callchain_list *cnode)
669+
/*
670+
* We need to always use relative addresses because we're aggregating
671+
* callchains from multiple threads, i.e. different address spaces, so
672+
* comparing absolute addresses make no sense as a symbol in a DSO may end up
673+
* in a different address when used in a different binary or even the same
674+
* binary but with some sort of address randomization technique, thus we need
675+
* to compare just relative addresses. -acme
676+
*/
677+
static enum match_result match_chain_dso_addresses(struct map *left_map, u64 left_ip,
678+
struct map *right_map, u64 right_ip)
671679
{
672-
struct symbol *sym = node->sym;
673-
u64 left, right;
674-
struct dso *left_dso = NULL;
675-
struct dso *right_dso = NULL;
680+
struct dso *left_dso = left_map ? left_map->dso : NULL;
681+
struct dso *right_dso = right_map ? right_map->dso : NULL;
676682

677-
if (callchain_param.key == CCKEY_SRCLINE) {
678-
enum match_result match = match_chain_strings(cnode->srcline,
679-
node->srcline);
683+
if (left_dso != right_dso)
684+
return left_dso < right_dso ? MATCH_LT : MATCH_GT;
680685

681-
/* if no srcline is available, fallback to symbol name */
682-
if (match == MATCH_ERROR && cnode->ms.sym && node->sym)
683-
match = match_chain_strings(cnode->ms.sym->name,
684-
node->sym->name);
686+
if (left_ip != right_ip)
687+
return left_ip < right_ip ? MATCH_LT : MATCH_GT;
685688

686-
if (match != MATCH_ERROR)
687-
return match;
689+
return MATCH_EQ;
690+
}
688691

689-
/* otherwise fall-back to IP-based comparison below */
690-
}
692+
static enum match_result match_chain(struct callchain_cursor_node *node,
693+
struct callchain_list *cnode)
694+
{
695+
enum match_result match = MATCH_ERROR;
691696

692-
if (cnode->ms.sym && sym && callchain_param.key == CCKEY_FUNCTION) {
693-
/*
694-
* Compare inlined frames based on their symbol name because
695-
* different inlined frames will have the same symbol start
696-
*/
697-
if (cnode->ms.sym->inlined || node->sym->inlined)
698-
return match_chain_strings(cnode->ms.sym->name,
699-
node->sym->name);
700-
701-
left = cnode->ms.sym->start;
702-
right = sym->start;
703-
left_dso = cnode->ms.map->dso;
704-
right_dso = node->map->dso;
705-
} else {
706-
left = cnode->ip;
707-
right = node->ip;
697+
switch (callchain_param.key) {
698+
case CCKEY_SRCLINE:
699+
match = match_chain_strings(cnode->srcline, node->srcline);
700+
if (match != MATCH_ERROR)
701+
break;
702+
/* otherwise fall-back to symbol-based comparison below */
703+
__fallthrough;
704+
case CCKEY_FUNCTION:
705+
if (node->sym && cnode->ms.sym) {
706+
/*
707+
* Compare inlined frames based on their symbol name
708+
* because different inlined frames will have the same
709+
* symbol start. Otherwise do a faster comparison based
710+
* on the symbol start address.
711+
*/
712+
if (cnode->ms.sym->inlined || node->sym->inlined) {
713+
match = match_chain_strings(cnode->ms.sym->name,
714+
node->sym->name);
715+
if (match != MATCH_ERROR)
716+
break;
717+
} else {
718+
match = match_chain_dso_addresses(cnode->ms.map, cnode->ms.sym->start,
719+
node->map, node->sym->start);
720+
break;
721+
}
722+
}
723+
/* otherwise fall-back to IP-based comparison below */
724+
__fallthrough;
725+
case CCKEY_ADDRESS:
726+
default:
727+
match = match_chain_dso_addresses(cnode->ms.map, cnode->ip, node->map, node->ip);
728+
break;
708729
}
709730

710-
if (left == right && left_dso == right_dso) {
711-
if (node->branch) {
712-
cnode->branch_count++;
731+
if (match == MATCH_EQ && node->branch) {
732+
cnode->branch_count++;
713733

714-
if (node->branch_from) {
715-
/*
716-
* It's "to" of a branch
717-
*/
718-
cnode->brtype_stat.branch_to = true;
734+
if (node->branch_from) {
735+
/*
736+
* It's "to" of a branch
737+
*/
738+
cnode->brtype_stat.branch_to = true;
719739

720-
if (node->branch_flags.predicted)
721-
cnode->predicted_count++;
740+
if (node->branch_flags.predicted)
741+
cnode->predicted_count++;
722742

723-
if (node->branch_flags.abort)
724-
cnode->abort_count++;
743+
if (node->branch_flags.abort)
744+
cnode->abort_count++;
725745

726-
branch_type_count(&cnode->brtype_stat,
727-
&node->branch_flags,
728-
node->branch_from,
729-
node->ip);
730-
} else {
731-
/*
732-
* It's "from" of a branch
733-
*/
734-
cnode->brtype_stat.branch_to = false;
735-
cnode->cycles_count +=
736-
node->branch_flags.cycles;
737-
cnode->iter_count += node->nr_loop_iter;
738-
cnode->iter_cycles += node->iter_cycles;
739-
}
746+
branch_type_count(&cnode->brtype_stat,
747+
&node->branch_flags,
748+
node->branch_from,
749+
node->ip);
750+
} else {
751+
/*
752+
* It's "from" of a branch
753+
*/
754+
cnode->brtype_stat.branch_to = false;
755+
cnode->cycles_count += node->branch_flags.cycles;
756+
cnode->iter_count += node->nr_loop_iter;
757+
cnode->iter_cycles += node->iter_cycles;
740758
}
741-
742-
return MATCH_EQ;
743759
}
744760

745-
return left > right ? MATCH_GT : MATCH_LT;
761+
return match;
746762
}
747763

748764
/*

0 commit comments

Comments
 (0)