perf callchain: Abstract callchain print function
authorNamhyung Kim <namhyung@kernel.org>
Mon, 9 Nov 2015 05:45:39 +0000 (14:45 +0900)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Thu, 19 Nov 2015 16:19:22 +0000 (13:19 -0300)
This is a preparation to support for printing other type of callchain
value like count or period.

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Tested-by: Brendan 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: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/ui/browsers/hists.c
tools/perf/ui/gtk/hists.c
tools/perf/ui/stdio/hist.c
tools/perf/util/callchain.c
tools/perf/util/callchain.h

index fa9eb92c9e24a477e45623c1017a2791fc68dd07..0b18857a36e80fbaed5c6c17e7eebda1f54c654e 100644 (file)
@@ -592,7 +592,6 @@ static int hist_browser__show_callchain(struct hist_browser *browser,
        while (node) {
                struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node);
                struct rb_node *next = rb_next(node);
-               u64 cumul = callchain_cumul_hits(child);
                struct callchain_list *chain;
                char folded_sign = ' ';
                int first = true;
@@ -619,9 +618,12 @@ static int hist_browser__show_callchain(struct hist_browser *browser,
                                                       browser->show_dso);
 
                        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!";
                                else
                                        str = alloc_str;
index 4b3585eed1e84be6feb0243f4f9f0cbd7e1ef592..cff7bb9d9632b579bec481cb6b7a73486dccbc47 100644 (file)
@@ -100,14 +100,10 @@ static void perf_gtk__add_callchain(struct rb_root *root, GtkTreeStore *store,
                struct callchain_list *chain;
                GtkTreeIter iter, new_parent;
                bool need_new_parent;
-               double percent;
-               u64 hits, child_total;
+               u64 child_total;
 
                node = rb_entry(nd, struct callchain_node, rb_node);
 
-               hits = callchain_cumul_hits(node);
-               percent = 100.0 * hits / total;
-
                new_parent = *parent;
                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,
 
                        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);
 
                        callchain_list__sym_name(chain, buf, sizeof(buf), false);
index ea7984932d9a74daf21f8a6db77bc7add34082cc..f4de055cab9bf74a0838fb660af6f57f6573174e 100644 (file)
@@ -34,10 +34,10 @@ static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask,
        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,
-                                    u64 total_samples, u64 hits,
-                                    int left_margin)
+                                    u64 total_samples, int left_margin)
 {
        int i;
        size_t ret = 0;
@@ -50,10 +50,9 @@ static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain,
                else
                        ret += fprintf(fp, " ");
                if (!period && i == depth - 1) {
-                       double percent;
-
-                       percent = hits * 100.0 / total_samples;
-                       ret += percent_color_fprintf(fp, "--%2.2f%%-- ", percent);
+                       ret += fprintf(fp, "--");
+                       ret += callchain_node__fprintf_value(node, fp, total_samples);
+                       ret += fprintf(fp, "--");
                } else
                        ret += fprintf(fp, "%s", "          ");
        }
@@ -120,10 +119,9 @@ static size_t __callchain__fprintf_graph(FILE *fp, struct rb_root *root,
                                                   left_margin);
                i = 0;
                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++,
                                                      total_samples,
-                                                     cumul,
                                                      left_margin);
                }
 
@@ -143,14 +141,17 @@ static size_t __callchain__fprintf_graph(FILE *fp, struct rb_root *root,
 
        if (callchain_param.mode == CHAIN_GRAPH_REL &&
                remaining && remaining != total_samples) {
+               struct callchain_node rem_node = {
+                       .hit = remaining,
+               };
 
                if (!rem_sq_bracket)
                        return ret;
 
                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,
-                                             remaining, left_margin);
+                                             left_margin);
        }
 
        return ret;
@@ -243,12 +244,11 @@ static size_t callchain__fprintf_flat(FILE *fp, struct rb_root *tree,
        struct rb_node *rb_node = rb_first(tree);
 
        while (rb_node) {
-               double percent;
-
                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 += fprintf(fp, "\n");
                if (++entries_printed == callchain_param.print_limit)
@@ -295,12 +295,11 @@ static size_t callchain__fprintf_folded(FILE *fp, struct rb_root *tree,
        struct rb_node *rb_node = rb_first(tree);
 
        while (rb_node) {
-               double percent;
 
                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 += fprintf(fp, "\n");
                if (++entries_printed == callchain_param.print_limit)
index 08cb220ba5ea2f5610f5e192a0faa59a9c9947ae..b948bd068966e122322b0da777be6f6679065b0f 100644 (file)
@@ -805,6 +805,35 @@ char *callchain_list__sym_name(struct callchain_list *cl,
        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)
 {
        struct callchain_list *list, *tmp;
index 544d99ac169c710bc74819418be1d297553b4b55..060e636e33ab1af3dc28c34cd703e5d7d925d715 100644 (file)
@@ -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 *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);