Commit 5ab250ca authored by Namhyung Kim's avatar Namhyung Kim Committed by Arnaldo Carvalho de Melo

perf callchain: Abstract callchain print function

This is a preparation to support for printing other type of callchain
value like count or period.
Signed-off-by: default avatarNamhyung Kim <namhyung@kernel.org>
Tested-by: default avatarBrendan Gregg <brendan.d.gregg@gmail.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Kan Liang <kan.liang@intel.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1447047946-1691-4-git-send-email-namhyung@kernel.org
[ renamed new _sprintf_ operation to _scnprintf_ ]
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 26e77924
...@@ -592,7 +592,6 @@ static int hist_browser__show_callchain(struct hist_browser *browser, ...@@ -592,7 +592,6 @@ static int hist_browser__show_callchain(struct hist_browser *browser,
while (node) { while (node) {
struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node); struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node);
struct rb_node *next = rb_next(node); struct rb_node *next = rb_next(node);
u64 cumul = callchain_cumul_hits(child);
struct callchain_list *chain; struct callchain_list *chain;
char folded_sign = ' '; char folded_sign = ' ';
int first = true; int first = true;
...@@ -619,9 +618,12 @@ static int hist_browser__show_callchain(struct hist_browser *browser, ...@@ -619,9 +618,12 @@ static int hist_browser__show_callchain(struct hist_browser *browser,
browser->show_dso); browser->show_dso);
if (was_first && need_percent) { if (was_first && need_percent) {
double percent = cumul * 100.0 / total; char buf[64];
if (asprintf(&alloc_str, "%2.2f%% %s", percent, str) < 0) callchain_node__scnprintf_value(child, buf, sizeof(buf),
total);
if (asprintf(&alloc_str, "%s %s", buf, str) < 0)
str = "Not enough memory!"; str = "Not enough memory!";
else else
str = alloc_str; str = alloc_str;
......
...@@ -100,14 +100,10 @@ static void perf_gtk__add_callchain(struct rb_root *root, GtkTreeStore *store, ...@@ -100,14 +100,10 @@ static void perf_gtk__add_callchain(struct rb_root *root, GtkTreeStore *store,
struct callchain_list *chain; struct callchain_list *chain;
GtkTreeIter iter, new_parent; GtkTreeIter iter, new_parent;
bool need_new_parent; bool need_new_parent;
double percent; u64 child_total;
u64 hits, child_total;
node = rb_entry(nd, struct callchain_node, rb_node); node = rb_entry(nd, struct callchain_node, rb_node);
hits = callchain_cumul_hits(node);
percent = 100.0 * hits / total;
new_parent = *parent; new_parent = *parent;
need_new_parent = !has_single_node && (node->val_nr > 1); need_new_parent = !has_single_node && (node->val_nr > 1);
...@@ -116,7 +112,7 @@ static void perf_gtk__add_callchain(struct rb_root *root, GtkTreeStore *store, ...@@ -116,7 +112,7 @@ static void perf_gtk__add_callchain(struct rb_root *root, GtkTreeStore *store,
gtk_tree_store_append(store, &iter, &new_parent); gtk_tree_store_append(store, &iter, &new_parent);
scnprintf(buf, sizeof(buf), "%5.2f%%", percent); callchain_node__scnprintf_value(node, buf, sizeof(buf), total);
gtk_tree_store_set(store, &iter, 0, buf, -1); gtk_tree_store_set(store, &iter, 0, buf, -1);
callchain_list__sym_name(chain, buf, sizeof(buf), false); callchain_list__sym_name(chain, buf, sizeof(buf), false);
......
...@@ -34,10 +34,10 @@ static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask, ...@@ -34,10 +34,10 @@ static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask,
return ret; return ret;
} }
static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_node *node,
struct callchain_list *chain,
int depth, int depth_mask, int period, int depth, int depth_mask, int period,
u64 total_samples, u64 hits, u64 total_samples, int left_margin)
int left_margin)
{ {
int i; int i;
size_t ret = 0; size_t ret = 0;
...@@ -50,10 +50,9 @@ static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, ...@@ -50,10 +50,9 @@ static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain,
else else
ret += fprintf(fp, " "); ret += fprintf(fp, " ");
if (!period && i == depth - 1) { if (!period && i == depth - 1) {
double percent; ret += fprintf(fp, "--");
ret += callchain_node__fprintf_value(node, fp, total_samples);
percent = hits * 100.0 / total_samples; ret += fprintf(fp, "--");
ret += percent_color_fprintf(fp, "--%2.2f%%-- ", percent);
} else } else
ret += fprintf(fp, "%s", " "); ret += fprintf(fp, "%s", " ");
} }
...@@ -120,10 +119,9 @@ static size_t __callchain__fprintf_graph(FILE *fp, struct rb_root *root, ...@@ -120,10 +119,9 @@ static size_t __callchain__fprintf_graph(FILE *fp, struct rb_root *root,
left_margin); left_margin);
i = 0; i = 0;
list_for_each_entry(chain, &child->val, list) { list_for_each_entry(chain, &child->val, list) {
ret += ipchain__fprintf_graph(fp, chain, depth, ret += ipchain__fprintf_graph(fp, child, chain, depth,
new_depth_mask, i++, new_depth_mask, i++,
total_samples, total_samples,
cumul,
left_margin); left_margin);
} }
...@@ -143,14 +141,17 @@ static size_t __callchain__fprintf_graph(FILE *fp, struct rb_root *root, ...@@ -143,14 +141,17 @@ static size_t __callchain__fprintf_graph(FILE *fp, struct rb_root *root,
if (callchain_param.mode == CHAIN_GRAPH_REL && if (callchain_param.mode == CHAIN_GRAPH_REL &&
remaining && remaining != total_samples) { remaining && remaining != total_samples) {
struct callchain_node rem_node = {
.hit = remaining,
};
if (!rem_sq_bracket) if (!rem_sq_bracket)
return ret; return ret;
new_depth_mask &= ~(1 << (depth - 1)); new_depth_mask &= ~(1 << (depth - 1));
ret += ipchain__fprintf_graph(fp, &rem_hits, depth, ret += ipchain__fprintf_graph(fp, &rem_node, &rem_hits, depth,
new_depth_mask, 0, total_samples, new_depth_mask, 0, total_samples,
remaining, left_margin); left_margin);
} }
return ret; return ret;
...@@ -243,12 +244,11 @@ static size_t callchain__fprintf_flat(FILE *fp, struct rb_root *tree, ...@@ -243,12 +244,11 @@ static size_t callchain__fprintf_flat(FILE *fp, struct rb_root *tree,
struct rb_node *rb_node = rb_first(tree); struct rb_node *rb_node = rb_first(tree);
while (rb_node) { while (rb_node) {
double percent;
chain = rb_entry(rb_node, struct callchain_node, rb_node); chain = rb_entry(rb_node, struct callchain_node, rb_node);
percent = chain->hit * 100.0 / total_samples;
ret = percent_color_fprintf(fp, " %6.2f%%\n", percent); ret += fprintf(fp, " ");
ret += callchain_node__fprintf_value(chain, fp, total_samples);
ret += fprintf(fp, "\n");
ret += __callchain__fprintf_flat(fp, chain, total_samples); ret += __callchain__fprintf_flat(fp, chain, total_samples);
ret += fprintf(fp, "\n"); ret += fprintf(fp, "\n");
if (++entries_printed == callchain_param.print_limit) if (++entries_printed == callchain_param.print_limit)
...@@ -295,12 +295,11 @@ static size_t callchain__fprintf_folded(FILE *fp, struct rb_root *tree, ...@@ -295,12 +295,11 @@ static size_t callchain__fprintf_folded(FILE *fp, struct rb_root *tree,
struct rb_node *rb_node = rb_first(tree); struct rb_node *rb_node = rb_first(tree);
while (rb_node) { while (rb_node) {
double percent;
chain = rb_entry(rb_node, struct callchain_node, rb_node); chain = rb_entry(rb_node, struct callchain_node, rb_node);
percent = chain->hit * 100.0 / total_samples;
ret += fprintf(fp, "%.2f%% ", percent); ret += callchain_node__fprintf_value(chain, fp, total_samples);
ret += fprintf(fp, " ");
ret += __callchain__fprintf_folded(fp, chain); ret += __callchain__fprintf_folded(fp, chain);
ret += fprintf(fp, "\n"); ret += fprintf(fp, "\n");
if (++entries_printed == callchain_param.print_limit) if (++entries_printed == callchain_param.print_limit)
......
...@@ -805,6 +805,35 @@ char *callchain_list__sym_name(struct callchain_list *cl, ...@@ -805,6 +805,35 @@ char *callchain_list__sym_name(struct callchain_list *cl,
return bf; return bf;
} }
char *callchain_node__scnprintf_value(struct callchain_node *node,
char *bf, size_t bfsize, u64 total)
{
double percent = 0.0;
u64 period = callchain_cumul_hits(node);
if (callchain_param.mode == CHAIN_FOLDED)
period = node->hit;
if (total)
percent = period * 100.0 / total;
scnprintf(bf, bfsize, "%.2f%%", percent);
return bf;
}
int callchain_node__fprintf_value(struct callchain_node *node,
FILE *fp, u64 total)
{
double percent = 0.0;
u64 period = callchain_cumul_hits(node);
if (callchain_param.mode == CHAIN_FOLDED)
period = node->hit;
if (total)
percent = period * 100.0 / total;
return percent_color_fprintf(fp, "%.2f%%", percent);
}
static void free_callchain_node(struct callchain_node *node) static void free_callchain_node(struct callchain_node *node)
{ {
struct callchain_list *list, *tmp; struct callchain_list *list, *tmp;
......
...@@ -230,6 +230,10 @@ static inline int arch_skip_callchain_idx(struct thread *thread __maybe_unused, ...@@ -230,6 +230,10 @@ static inline int arch_skip_callchain_idx(struct thread *thread __maybe_unused,
char *callchain_list__sym_name(struct callchain_list *cl, char *callchain_list__sym_name(struct callchain_list *cl,
char *bf, size_t bfsize, bool show_dso); char *bf, size_t bfsize, bool show_dso);
char *callchain_node__scnprintf_value(struct callchain_node *node,
char *bf, size_t bfsize, u64 total);
int callchain_node__fprintf_value(struct callchain_node *node,
FILE *fp, u64 total);
void free_callchain(struct callchain_root *root); void free_callchain(struct callchain_root *root);
......
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