Commit 47ef8398 authored by Jin Yao's avatar Jin Yao Committed by Arnaldo Carvalho de Melo

perf streams: Compare two streams

Stream is the branch history which is aggregated by the branch records
from perf samples. Now we support the callchain as stream.

If the callchain entries of one stream are fully matched with the
callchain entries of another stream, we think two streams are matched.

For example,

   cycles: 1, hits: 26.80%                 cycles: 1, hits: 27.30%
   -----------------------                 -----------------------
             main div.c:39                           main div.c:39
             main div.c:44                           main div.c:44

Above two streams are matched (we don't consider the case that source
code is changed).

The matching logic is, compare the chain string first. If it's not
matched, fallback to dso address comparison.
Signed-off-by: default avatarJin Yao <yao.jin@linux.intel.com>
Acked-by: default avatarJiri Olsa <jolsa@kernel.org>
Link: https://lore.kernel.org/r/20201009022845.13141-4-yao.jin@linux.intel.comSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent dd1d8418
...@@ -1613,3 +1613,57 @@ void callchain_param_setup(u64 sample_type) ...@@ -1613,3 +1613,57 @@ void callchain_param_setup(u64 sample_type)
callchain_param.record_mode = CALLCHAIN_FP; callchain_param.record_mode = CALLCHAIN_FP;
} }
} }
static bool chain_match(struct callchain_list *base_chain,
struct callchain_list *pair_chain)
{
enum match_result match;
match = match_chain_strings(base_chain->srcline,
pair_chain->srcline);
if (match != MATCH_ERROR)
return match == MATCH_EQ;
match = match_chain_dso_addresses(base_chain->ms.map,
base_chain->ip,
pair_chain->ms.map,
pair_chain->ip);
return match == MATCH_EQ;
}
bool callchain_cnode_matched(struct callchain_node *base_cnode,
struct callchain_node *pair_cnode)
{
struct callchain_list *base_chain, *pair_chain;
bool match = false;
pair_chain = list_first_entry(&pair_cnode->val,
struct callchain_list,
list);
list_for_each_entry(base_chain, &base_cnode->val, list) {
if (&pair_chain->list == &pair_cnode->val)
return false;
if (!base_chain->srcline || !pair_chain->srcline) {
pair_chain = list_next_entry(pair_chain, list);
continue;
}
match = chain_match(base_chain, pair_chain);
if (!match)
return false;
pair_chain = list_next_entry(pair_chain, list);
}
/*
* Say chain1 is ABC, chain2 is ABCD, we consider they are
* not fully matched.
*/
if (pair_chain && (&pair_chain->list != &pair_cnode->val))
return false;
return match;
}
...@@ -298,4 +298,8 @@ int callchain_branch_counts(struct callchain_root *root, ...@@ -298,4 +298,8 @@ int callchain_branch_counts(struct callchain_root *root,
u64 *abort_count, u64 *cycles_count); u64 *abort_count, u64 *cycles_count);
void callchain_param_setup(u64 sample_type); void callchain_param_setup(u64 sample_type);
bool callchain_cnode_matched(struct callchain_node *base_cnode,
struct callchain_node *pair_cnode);
#endif /* __PERF_CALLCHAIN_H */ #endif /* __PERF_CALLCHAIN_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment