[PATCH 1/7] perf hists: Separate out hist print functions
From: Namhyung Kim Separate out those functions into ui/stdio/hist.c. This is required for upcoming changes. Signed-off-by: Namhyung Kim --- tools/perf/Makefile| 3 +- tools/perf/ui/stdio/hist.c | 648 +++ tools/perf/util/hist.c | 677 ++--- tools/perf/util/hist.h | 2 + 4 files changed, 669 insertions(+), 661 deletions(-) create mode 100644 tools/perf/ui/stdio/hist.c diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 75af93dc52ad..cb18b047c9c9 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -404,11 +404,10 @@ LIB_OBJS += $(OUTPUT)util/target.o LIB_OBJS += $(OUTPUT)util/rblist.o LIB_OBJS += $(OUTPUT)util/intlist.o LIB_OBJS += $(OUTPUT)ui/helpline.o +LIB_OBJS += $(OUTPUT)ui/stdio/hist.o BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o - BUILTIN_OBJS += $(OUTPUT)builtin-bench.o - # Benchmark modules BUILTIN_OBJS += $(OUTPUT)bench/sched-messaging.o BUILTIN_OBJS += $(OUTPUT)bench/sched-pipe.o diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c new file mode 100644 index ..7881d625e17a --- /dev/null +++ b/tools/perf/ui/stdio/hist.c @@ -0,0 +1,648 @@ +#include +#include + +#include "../../util/util.h" +#include "../../util/hist.h" +#include "../../util/sort.h" + + +static size_t callchain__fprintf_left_margin(FILE *fp, int left_margin) +{ + int i; + int ret = fprintf(fp, ""); + + for (i = 0; i < left_margin; i++) + ret += fprintf(fp, " "); + + return ret; +} + +static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask, + int left_margin) +{ + int i; + size_t ret = callchain__fprintf_left_margin(fp, left_margin); + + for (i = 0; i < depth; i++) + if (depth_mask & (1 << i)) + ret += fprintf(fp, "| "); + else + ret += fprintf(fp, " "); + + ret += fprintf(fp, "\n"); + + return ret; +} + +static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, +int depth, int depth_mask, int period, +u64 total_samples, u64 hits, +int left_margin) +{ + int i; + size_t ret = 0; + + ret += callchain__fprintf_left_margin(fp, left_margin); + for (i = 0; i < depth; i++) { + if (depth_mask & (1 << i)) + ret += fprintf(fp, "|"); + 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); + } else + ret += fprintf(fp, "%s", " "); + } + if (chain->ms.sym) + ret += fprintf(fp, "%s\n", chain->ms.sym->name); + else + ret += fprintf(fp, "0x%0" PRIx64 "\n", chain->ip); + + return ret; +} + +static struct symbol *rem_sq_bracket; +static struct callchain_list rem_hits; + +static void init_rem_hits(void) +{ + rem_sq_bracket = malloc(sizeof(*rem_sq_bracket) + 6); + if (!rem_sq_bracket) { + fprintf(stderr, "Not enough memory to display remaining hits\n"); + return; + } + + strcpy(rem_sq_bracket->name, "[...]"); + rem_hits.ms.sym = rem_sq_bracket; +} + +static size_t __callchain__fprintf_graph(FILE *fp, struct rb_root *root, +u64 total_samples, int depth, +int depth_mask, int left_margin) +{ + struct rb_node *node, *next; + struct callchain_node *child; + struct callchain_list *chain; + int new_depth_mask = depth_mask; + u64 remaining; + size_t ret = 0; + int i; + uint entries_printed = 0; + + remaining = total_samples; + + node = rb_first(root); + while (node) { + u64 new_total; + u64 cumul; + + child = rb_entry(node, struct callchain_node, rb_node); + cumul = callchain_cumul_hits(child); + remaining -= cumul; + + /* +* The depth mask manages the output of pipes that show +* the depth. We don't want to keep the pipes of the current +* level for the last child of this depth. +* Except if we have remaining filtered hits. They will +* supersede the last child +*/ + next = rb_next(node); + if (!next && (callchain_param.mode != CHAIN_GRAPH_REL || !remaining)) + new_depth_mask &= ~(1 << (depth - 1)); + +
[PATCH 1/7] perf hists: Separate out hist print functions
From: Namhyung Kim namhyung@lge.com Separate out those functions into ui/stdio/hist.c. This is required for upcoming changes. Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/Makefile| 3 +- tools/perf/ui/stdio/hist.c | 648 +++ tools/perf/util/hist.c | 677 ++--- tools/perf/util/hist.h | 2 + 4 files changed, 669 insertions(+), 661 deletions(-) create mode 100644 tools/perf/ui/stdio/hist.c diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 75af93dc52ad..cb18b047c9c9 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -404,11 +404,10 @@ LIB_OBJS += $(OUTPUT)util/target.o LIB_OBJS += $(OUTPUT)util/rblist.o LIB_OBJS += $(OUTPUT)util/intlist.o LIB_OBJS += $(OUTPUT)ui/helpline.o +LIB_OBJS += $(OUTPUT)ui/stdio/hist.o BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o - BUILTIN_OBJS += $(OUTPUT)builtin-bench.o - # Benchmark modules BUILTIN_OBJS += $(OUTPUT)bench/sched-messaging.o BUILTIN_OBJS += $(OUTPUT)bench/sched-pipe.o diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c new file mode 100644 index ..7881d625e17a --- /dev/null +++ b/tools/perf/ui/stdio/hist.c @@ -0,0 +1,648 @@ +#include stdio.h +#include math.h + +#include ../../util/util.h +#include ../../util/hist.h +#include ../../util/sort.h + + +static size_t callchain__fprintf_left_margin(FILE *fp, int left_margin) +{ + int i; + int ret = fprintf(fp, ); + + for (i = 0; i left_margin; i++) + ret += fprintf(fp, ); + + return ret; +} + +static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask, + int left_margin) +{ + int i; + size_t ret = callchain__fprintf_left_margin(fp, left_margin); + + for (i = 0; i depth; i++) + if (depth_mask (1 i)) + ret += fprintf(fp, | ); + else + ret += fprintf(fp,); + + ret += fprintf(fp, \n); + + return ret; +} + +static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, +int depth, int depth_mask, int period, +u64 total_samples, u64 hits, +int left_margin) +{ + int i; + size_t ret = 0; + + ret += callchain__fprintf_left_margin(fp, left_margin); + for (i = 0; i depth; i++) { + if (depth_mask (1 i)) + ret += fprintf(fp, |); + 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); + } else + ret += fprintf(fp, %s, ); + } + if (chain-ms.sym) + ret += fprintf(fp, %s\n, chain-ms.sym-name); + else + ret += fprintf(fp, 0x%0 PRIx64 \n, chain-ip); + + return ret; +} + +static struct symbol *rem_sq_bracket; +static struct callchain_list rem_hits; + +static void init_rem_hits(void) +{ + rem_sq_bracket = malloc(sizeof(*rem_sq_bracket) + 6); + if (!rem_sq_bracket) { + fprintf(stderr, Not enough memory to display remaining hits\n); + return; + } + + strcpy(rem_sq_bracket-name, [...]); + rem_hits.ms.sym = rem_sq_bracket; +} + +static size_t __callchain__fprintf_graph(FILE *fp, struct rb_root *root, +u64 total_samples, int depth, +int depth_mask, int left_margin) +{ + struct rb_node *node, *next; + struct callchain_node *child; + struct callchain_list *chain; + int new_depth_mask = depth_mask; + u64 remaining; + size_t ret = 0; + int i; + uint entries_printed = 0; + + remaining = total_samples; + + node = rb_first(root); + while (node) { + u64 new_total; + u64 cumul; + + child = rb_entry(node, struct callchain_node, rb_node); + cumul = callchain_cumul_hits(child); + remaining -= cumul; + + /* +* The depth mask manages the output of pipes that show +* the depth. We don't want to keep the pipes of the current +* level for the last child of this depth. +* Except if we have remaining filtered hits. They will +* supersede the last child +*/ + next = rb_next(node); + if (!next (callchain_param.mode != CHAIN_GRAPH_REL || !remaining)) + new_depth_mask = ~(1 (depth - 1)); + + /*
Re: [PATCH 1/7] perf hists: Separate out hist print functions
Hi, Arnaldo On Thu, 9 Aug 2012 16:18:27 -0300, Arnaldo Carvalho de Melo wrote: > Em Mon, Aug 06, 2012 at 05:57:36PM +0900, Namhyung Kim escreveu: >> From: Namhyung Kim >> >> Separate out those functions into ui/hist.c. This is required for >> upcoming changes. > > Isn't it better to further separate it by introducing the ui/stdio/ > directory since these functions use fprintf? > Maybe. I agree that general ui code reside on ui/ and front-end specifics should go to their subdirectories. But not sure for the stdio case since they'll have very simple code only. For this case, most of functions would be converted to manipulate a string buffer like scnprintf and shared by all front-end's as long as possible - callchain print code needs some more working. But if you want, I'll separate out actual fprintf's to ui/stdio/. Thanks, Namhyung -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 1/7] perf hists: Separate out hist print functions
Em Mon, Aug 06, 2012 at 05:57:36PM +0900, Namhyung Kim escreveu: > From: Namhyung Kim > > Separate out those functions into ui/hist.c. This is required for > upcoming changes. Isn't it better to further separate it by introducing the ui/stdio/ directory since these functions use fprintf? - Arnaldo > Signed-off-by: Namhyung Kim > --- > tools/perf/Makefile| 4 +- > tools/perf/ui/hist.c | 648 ++ > tools/perf/util/hist.c | 677 > ++--- > tools/perf/util/hist.h | 2 + > 4 files changed, 670 insertions(+), 661 deletions(-) > create mode 100644 tools/perf/ui/hist.c > > diff --git a/tools/perf/Makefile b/tools/perf/Makefile > index 35655c3a7b7a..49cff288ac24 100644 > --- a/tools/perf/Makefile > +++ b/tools/perf/Makefile > @@ -388,10 +388,10 @@ LIB_OBJS += $(OUTPUT)util/target.o > LIB_OBJS += $(OUTPUT)util/rblist.o > LIB_OBJS += $(OUTPUT)util/intlist.o > > -BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o > +LIB_OBJS += $(OUTPUT)ui/hist.o > > +BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o > BUILTIN_OBJS += $(OUTPUT)builtin-bench.o > - > # Benchmark modules > BUILTIN_OBJS += $(OUTPUT)bench/sched-messaging.o > BUILTIN_OBJS += $(OUTPUT)bench/sched-pipe.o > diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c > new file mode 100644 > index ..b7936dc6271f > --- /dev/null > +++ b/tools/perf/ui/hist.c > @@ -0,0 +1,648 @@ > +#include > +#include > + > +#include "../util/util.h" > +#include "../util/hist.h" > +#include "../util/sort.h" > + > + > +static size_t callchain__fprintf_left_margin(FILE *fp, int left_margin) > +{ > + int i; > + int ret = fprintf(fp, ""); > + > + for (i = 0; i < left_margin; i++) > + ret += fprintf(fp, " "); > + > + return ret; > +} > + > +static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int > depth_mask, > + int left_margin) > +{ > + int i; > + size_t ret = callchain__fprintf_left_margin(fp, left_margin); > + > + for (i = 0; i < depth; i++) > + if (depth_mask & (1 << i)) > + ret += fprintf(fp, "| "); > + else > + ret += fprintf(fp, " "); > + > + ret += fprintf(fp, "\n"); > + > + return ret; > +} > + > +static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, > + int depth, int depth_mask, int period, > + u64 total_samples, u64 hits, > + int left_margin) > +{ > + int i; > + size_t ret = 0; > + > + ret += callchain__fprintf_left_margin(fp, left_margin); > + for (i = 0; i < depth; i++) { > + if (depth_mask & (1 << i)) > + ret += fprintf(fp, "|"); > + 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); > + } else > + ret += fprintf(fp, "%s", " "); > + } > + if (chain->ms.sym) > + ret += fprintf(fp, "%s\n", chain->ms.sym->name); > + else > + ret += fprintf(fp, "0x%0" PRIx64 "\n", chain->ip); > + > + return ret; > +} > + > +static struct symbol *rem_sq_bracket; > +static struct callchain_list rem_hits; > + > +static void init_rem_hits(void) > +{ > + rem_sq_bracket = malloc(sizeof(*rem_sq_bracket) + 6); > + if (!rem_sq_bracket) { > + fprintf(stderr, "Not enough memory to display remaining > hits\n"); > + return; > + } > + > + strcpy(rem_sq_bracket->name, "[...]"); > + rem_hits.ms.sym = rem_sq_bracket; > +} > + > +static size_t __callchain__fprintf_graph(FILE *fp, struct rb_root *root, > + u64 total_samples, int depth, > + int depth_mask, int left_margin) > +{ > + struct rb_node *node, *next; > + struct callchain_node *child; > + struct callchain_list *chain; > + int new_depth_mask = depth_mask; > + u64 remaining; > + size_t ret = 0; > + int i; > + uint entries_printed = 0; > + > + remaining = total_samples; > + > + node = rb_first(root); > + while (node) { > + u64 new_total; > + u64 cumul; > + > + child = rb_entry(node, struct callchain_node, rb_node); > + cumul = callchain_cumul_hits(child); > + remaining -= cumul; > + > + /* > + * The depth mask manages the output of pipes that show > + * the depth. We don't want to keep the pipes of the current > + * level for the last child of this depth. > + * Except
Re: [PATCH 1/7] perf hists: Separate out hist print functions
Em Mon, Aug 06, 2012 at 05:57:36PM +0900, Namhyung Kim escreveu: From: Namhyung Kim namhyung@lge.com Separate out those functions into ui/hist.c. This is required for upcoming changes. Isn't it better to further separate it by introducing the ui/stdio/ directory since these functions use fprintf? - Arnaldo Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/Makefile| 4 +- tools/perf/ui/hist.c | 648 ++ tools/perf/util/hist.c | 677 ++--- tools/perf/util/hist.h | 2 + 4 files changed, 670 insertions(+), 661 deletions(-) create mode 100644 tools/perf/ui/hist.c diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 35655c3a7b7a..49cff288ac24 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -388,10 +388,10 @@ LIB_OBJS += $(OUTPUT)util/target.o LIB_OBJS += $(OUTPUT)util/rblist.o LIB_OBJS += $(OUTPUT)util/intlist.o -BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o +LIB_OBJS += $(OUTPUT)ui/hist.o +BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o BUILTIN_OBJS += $(OUTPUT)builtin-bench.o - # Benchmark modules BUILTIN_OBJS += $(OUTPUT)bench/sched-messaging.o BUILTIN_OBJS += $(OUTPUT)bench/sched-pipe.o diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c new file mode 100644 index ..b7936dc6271f --- /dev/null +++ b/tools/perf/ui/hist.c @@ -0,0 +1,648 @@ +#include stdio.h +#include math.h + +#include ../util/util.h +#include ../util/hist.h +#include ../util/sort.h + + +static size_t callchain__fprintf_left_margin(FILE *fp, int left_margin) +{ + int i; + int ret = fprintf(fp, ); + + for (i = 0; i left_margin; i++) + ret += fprintf(fp, ); + + return ret; +} + +static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask, + int left_margin) +{ + int i; + size_t ret = callchain__fprintf_left_margin(fp, left_margin); + + for (i = 0; i depth; i++) + if (depth_mask (1 i)) + ret += fprintf(fp, | ); + else + ret += fprintf(fp,); + + ret += fprintf(fp, \n); + + return ret; +} + +static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, + int depth, int depth_mask, int period, + u64 total_samples, u64 hits, + int left_margin) +{ + int i; + size_t ret = 0; + + ret += callchain__fprintf_left_margin(fp, left_margin); + for (i = 0; i depth; i++) { + if (depth_mask (1 i)) + ret += fprintf(fp, |); + 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); + } else + ret += fprintf(fp, %s, ); + } + if (chain-ms.sym) + ret += fprintf(fp, %s\n, chain-ms.sym-name); + else + ret += fprintf(fp, 0x%0 PRIx64 \n, chain-ip); + + return ret; +} + +static struct symbol *rem_sq_bracket; +static struct callchain_list rem_hits; + +static void init_rem_hits(void) +{ + rem_sq_bracket = malloc(sizeof(*rem_sq_bracket) + 6); + if (!rem_sq_bracket) { + fprintf(stderr, Not enough memory to display remaining hits\n); + return; + } + + strcpy(rem_sq_bracket-name, [...]); + rem_hits.ms.sym = rem_sq_bracket; +} + +static size_t __callchain__fprintf_graph(FILE *fp, struct rb_root *root, + u64 total_samples, int depth, + int depth_mask, int left_margin) +{ + struct rb_node *node, *next; + struct callchain_node *child; + struct callchain_list *chain; + int new_depth_mask = depth_mask; + u64 remaining; + size_t ret = 0; + int i; + uint entries_printed = 0; + + remaining = total_samples; + + node = rb_first(root); + while (node) { + u64 new_total; + u64 cumul; + + child = rb_entry(node, struct callchain_node, rb_node); + cumul = callchain_cumul_hits(child); + remaining -= cumul; + + /* + * The depth mask manages the output of pipes that show + * the depth. We don't want to keep the pipes of the current + * level for the last child of this depth. + * Except if we have remaining filtered hits. They will + * supersede the last child + */ + next = rb_next(node); +
Re: [PATCH 1/7] perf hists: Separate out hist print functions
Hi, Arnaldo On Thu, 9 Aug 2012 16:18:27 -0300, Arnaldo Carvalho de Melo wrote: Em Mon, Aug 06, 2012 at 05:57:36PM +0900, Namhyung Kim escreveu: From: Namhyung Kim namhyung@lge.com Separate out those functions into ui/hist.c. This is required for upcoming changes. Isn't it better to further separate it by introducing the ui/stdio/ directory since these functions use fprintf? Maybe. I agree that general ui code reside on ui/ and front-end specifics should go to their subdirectories. But not sure for the stdio case since they'll have very simple code only. For this case, most of functions would be converted to manipulate a string buffer like scnprintf and shared by all front-end's as long as possible - callchain print code needs some more working. But if you want, I'll separate out actual fprintf's to ui/stdio/. Thanks, Namhyung -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 1/7] perf hists: Separate out hist print functions
From: Namhyung Kim Separate out those functions into ui/hist.c. This is required for upcoming changes. Signed-off-by: Namhyung Kim --- tools/perf/Makefile| 4 +- tools/perf/ui/hist.c | 648 ++ tools/perf/util/hist.c | 677 ++--- tools/perf/util/hist.h | 2 + 4 files changed, 670 insertions(+), 661 deletions(-) create mode 100644 tools/perf/ui/hist.c diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 35655c3a7b7a..49cff288ac24 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -388,10 +388,10 @@ LIB_OBJS += $(OUTPUT)util/target.o LIB_OBJS += $(OUTPUT)util/rblist.o LIB_OBJS += $(OUTPUT)util/intlist.o -BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o +LIB_OBJS += $(OUTPUT)ui/hist.o +BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o BUILTIN_OBJS += $(OUTPUT)builtin-bench.o - # Benchmark modules BUILTIN_OBJS += $(OUTPUT)bench/sched-messaging.o BUILTIN_OBJS += $(OUTPUT)bench/sched-pipe.o diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c new file mode 100644 index ..b7936dc6271f --- /dev/null +++ b/tools/perf/ui/hist.c @@ -0,0 +1,648 @@ +#include +#include + +#include "../util/util.h" +#include "../util/hist.h" +#include "../util/sort.h" + + +static size_t callchain__fprintf_left_margin(FILE *fp, int left_margin) +{ + int i; + int ret = fprintf(fp, ""); + + for (i = 0; i < left_margin; i++) + ret += fprintf(fp, " "); + + return ret; +} + +static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask, + int left_margin) +{ + int i; + size_t ret = callchain__fprintf_left_margin(fp, left_margin); + + for (i = 0; i < depth; i++) + if (depth_mask & (1 << i)) + ret += fprintf(fp, "| "); + else + ret += fprintf(fp, " "); + + ret += fprintf(fp, "\n"); + + return ret; +} + +static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, +int depth, int depth_mask, int period, +u64 total_samples, u64 hits, +int left_margin) +{ + int i; + size_t ret = 0; + + ret += callchain__fprintf_left_margin(fp, left_margin); + for (i = 0; i < depth; i++) { + if (depth_mask & (1 << i)) + ret += fprintf(fp, "|"); + 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); + } else + ret += fprintf(fp, "%s", " "); + } + if (chain->ms.sym) + ret += fprintf(fp, "%s\n", chain->ms.sym->name); + else + ret += fprintf(fp, "0x%0" PRIx64 "\n", chain->ip); + + return ret; +} + +static struct symbol *rem_sq_bracket; +static struct callchain_list rem_hits; + +static void init_rem_hits(void) +{ + rem_sq_bracket = malloc(sizeof(*rem_sq_bracket) + 6); + if (!rem_sq_bracket) { + fprintf(stderr, "Not enough memory to display remaining hits\n"); + return; + } + + strcpy(rem_sq_bracket->name, "[...]"); + rem_hits.ms.sym = rem_sq_bracket; +} + +static size_t __callchain__fprintf_graph(FILE *fp, struct rb_root *root, +u64 total_samples, int depth, +int depth_mask, int left_margin) +{ + struct rb_node *node, *next; + struct callchain_node *child; + struct callchain_list *chain; + int new_depth_mask = depth_mask; + u64 remaining; + size_t ret = 0; + int i; + uint entries_printed = 0; + + remaining = total_samples; + + node = rb_first(root); + while (node) { + u64 new_total; + u64 cumul; + + child = rb_entry(node, struct callchain_node, rb_node); + cumul = callchain_cumul_hits(child); + remaining -= cumul; + + /* +* The depth mask manages the output of pipes that show +* the depth. We don't want to keep the pipes of the current +* level for the last child of this depth. +* Except if we have remaining filtered hits. They will +* supersede the last child +*/ + next = rb_next(node); + if (!next && (callchain_param.mode != CHAIN_GRAPH_REL || !remaining)) + new_depth_mask &= ~(1 << (depth - 1)); + + /* +* But we keep the
[PATCH 1/7] perf hists: Separate out hist print functions
From: Namhyung Kim namhyung@lge.com Separate out those functions into ui/hist.c. This is required for upcoming changes. Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/Makefile| 4 +- tools/perf/ui/hist.c | 648 ++ tools/perf/util/hist.c | 677 ++--- tools/perf/util/hist.h | 2 + 4 files changed, 670 insertions(+), 661 deletions(-) create mode 100644 tools/perf/ui/hist.c diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 35655c3a7b7a..49cff288ac24 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -388,10 +388,10 @@ LIB_OBJS += $(OUTPUT)util/target.o LIB_OBJS += $(OUTPUT)util/rblist.o LIB_OBJS += $(OUTPUT)util/intlist.o -BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o +LIB_OBJS += $(OUTPUT)ui/hist.o +BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o BUILTIN_OBJS += $(OUTPUT)builtin-bench.o - # Benchmark modules BUILTIN_OBJS += $(OUTPUT)bench/sched-messaging.o BUILTIN_OBJS += $(OUTPUT)bench/sched-pipe.o diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c new file mode 100644 index ..b7936dc6271f --- /dev/null +++ b/tools/perf/ui/hist.c @@ -0,0 +1,648 @@ +#include stdio.h +#include math.h + +#include ../util/util.h +#include ../util/hist.h +#include ../util/sort.h + + +static size_t callchain__fprintf_left_margin(FILE *fp, int left_margin) +{ + int i; + int ret = fprintf(fp, ); + + for (i = 0; i left_margin; i++) + ret += fprintf(fp, ); + + return ret; +} + +static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask, + int left_margin) +{ + int i; + size_t ret = callchain__fprintf_left_margin(fp, left_margin); + + for (i = 0; i depth; i++) + if (depth_mask (1 i)) + ret += fprintf(fp, | ); + else + ret += fprintf(fp,); + + ret += fprintf(fp, \n); + + return ret; +} + +static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, +int depth, int depth_mask, int period, +u64 total_samples, u64 hits, +int left_margin) +{ + int i; + size_t ret = 0; + + ret += callchain__fprintf_left_margin(fp, left_margin); + for (i = 0; i depth; i++) { + if (depth_mask (1 i)) + ret += fprintf(fp, |); + 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); + } else + ret += fprintf(fp, %s, ); + } + if (chain-ms.sym) + ret += fprintf(fp, %s\n, chain-ms.sym-name); + else + ret += fprintf(fp, 0x%0 PRIx64 \n, chain-ip); + + return ret; +} + +static struct symbol *rem_sq_bracket; +static struct callchain_list rem_hits; + +static void init_rem_hits(void) +{ + rem_sq_bracket = malloc(sizeof(*rem_sq_bracket) + 6); + if (!rem_sq_bracket) { + fprintf(stderr, Not enough memory to display remaining hits\n); + return; + } + + strcpy(rem_sq_bracket-name, [...]); + rem_hits.ms.sym = rem_sq_bracket; +} + +static size_t __callchain__fprintf_graph(FILE *fp, struct rb_root *root, +u64 total_samples, int depth, +int depth_mask, int left_margin) +{ + struct rb_node *node, *next; + struct callchain_node *child; + struct callchain_list *chain; + int new_depth_mask = depth_mask; + u64 remaining; + size_t ret = 0; + int i; + uint entries_printed = 0; + + remaining = total_samples; + + node = rb_first(root); + while (node) { + u64 new_total; + u64 cumul; + + child = rb_entry(node, struct callchain_node, rb_node); + cumul = callchain_cumul_hits(child); + remaining -= cumul; + + /* +* The depth mask manages the output of pipes that show +* the depth. We don't want to keep the pipes of the current +* level for the last child of this depth. +* Except if we have remaining filtered hits. They will +* supersede the last child +*/ + next = rb_next(node); + if (!next (callchain_param.mode != CHAIN_GRAPH_REL || !remaining)) + new_depth_mask = ~(1 (depth - 1)); + + /* +* But we keep the older