Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1351644 > unrolled thread
| Started by | Namhyung Kim <namhyung@kernel.org> |
|---|---|
| First post | 2016-03-07 15:40 +0100 |
| Last post | 2016-03-08 11:40 +0100 |
| Articles | 8 — 3 participants |
Back to article view | Back to linux.kernel
[PATCHSET 0/7] perf tools: Support multiple keys in a single hierarchy level (v3) Namhyung Kim <namhyung@kernel.org> - 2016-03-07 15:40 +0100
[PATCH v3 3/7] perf tools: Support multiple sort keys in a hierarchy level Namhyung Kim <namhyung@kernel.org> - 2016-03-07 15:40 +0100
Re: [PATCH v3 3/7] perf tools: Support multiple sort keys in a hierarchy level Arnaldo Carvalho de Melo <acme@kernel.org> - 2016-03-07 19:00 +0100
[tip:perf/core] perf hists: Support multiple sort keys in a hierarchy level tip-bot for Namhyung Kim <tipbot@zytor.com> - 2016-03-08 11:40 +0100
[PATCH v3 7/7] perf report: Use hierarchy hpp list on gtk Namhyung Kim <namhyung@kernel.org> - 2016-03-07 15:40 +0100
[tip:perf/core] perf report: Use hierarchy hpp list on gtk tip-bot for Namhyung Kim <tipbot@zytor.com> - 2016-03-08 11:40 +0100
[PATCH v3 2/7] perf tools: Use own hpp_list for hierarchy mode Namhyung Kim <namhyung@kernel.org> - 2016-03-07 15:40 +0100
[tip:perf/core] perf hists: Use own hpp_list for hierarchy mode tip-bot for Namhyung Kim <tipbot@zytor.com> - 2016-03-08 11:40 +0100
| From | Namhyung Kim <namhyung@kernel.org> |
|---|---|
| Date | 2016-03-07 15:40 +0100 |
| Subject | [PATCHSET 0/7] perf tools: Support multiple keys in a single hierarchy level (v3) |
| Message-ID | <ra4ud-42s-11@gated-at.bofh.it> |
Hello,
This implements what Arnaldo suggested in previous discussion of
hierarchy patchset [1]. Originally each level in a hierarchy can have
a single sort key in it, but with this patches it's possible to have
more than one sort keys using a syntax similar to event grouping. I
added the struct perf_hpp_list_node and carry it to group output
formats (hpp_fmt) in a single level.
* Changes from v2)
- fix segfault on perf top (Arnaldo)
- add hpp_list_node->skip (Jiri)
* Changes from v1)
- use '{ }' to group sort keys (Arnaldo)
- cleanup hpp_list_node creation (Jiri)
Example below shows how 4 sort keys are used for 2 levels. As you can
see, the first level shows pid and comm of previous (switched) task
and the second level shows pid and comm of next task.
$ perf report --hierarchy -s '{prev_pid,prev_comm},{next_pid,next_comm}' \
--percent-limit 1 -i perf.data.sched
...
# Overhead prev_pid+prev_comm / next_pid+next_comm
# ........... .......................................
#
22.36% 0 swapper/0
9.48% 17773 transmission-gt
5.25% 109 kworker/0:1H
1.53% 6524 Xephyr
21.39% 17773 transmission-gt
9.52% 0 swapper/0
9.04% 0 swapper/2
1.78% 0 swapper/3
It's available on the 'perf/hierarchy-multi-v3' branch in my tree
git://git.kernel.org/pub/scm/linux/kernel/git/namhyung/linux-perf.git
Any feedbacks are welcome
Thanks,
Namhyung
[1] https://lkml.org/lkml/2016/2/24/1041
Namhyung Kim (7):
perf tools: Introduce perf_hpp__setup_hists_formats()
perf tools: Use own hpp_list for hierarchy mode
perf tools: Support multiple sort keys in a hierarchy level
perf tools: Fix indent for multiple hierarchy sort key
perf report: Use hierarchy hpp list on stdio
perf hists browser: Use hierarchy hpp list
perf report: Use hierarchy hpp list on gtk
tools/perf/ui/browsers/hists.c | 147 +++++++++++++++++++----------------
tools/perf/ui/gtk/hists.c | 73 +++++++++++-------
tools/perf/ui/hist.c | 69 +++++++++++++++++
tools/perf/ui/stdio/hist.c | 171 +++++++++++++++++++++--------------------
tools/perf/util/hist.c | 72 +++++++++++------
tools/perf/util/hist.h | 13 ++++
tools/perf/util/sort.c | 74 +++++++++++++++---
tools/perf/util/sort.h | 1 +
8 files changed, 408 insertions(+), 212 deletions(-)
--
2.7.2
[toc] | [next] | [standalone]
| From | Namhyung Kim <namhyung@kernel.org> |
|---|---|
| Date | 2016-03-07 15:40 +0100 |
| Subject | [PATCH v3 3/7] perf tools: Support multiple sort keys in a hierarchy level |
| Message-ID | <ra4uf-42s-55@gated-at.bofh.it> |
| In reply to | #1351644 |
This implements having multiple sort keys in a single hierarchy level.
Originally only single sort key is supported for each level, but now
using the group syntax with '{ }', it can set more than one sort key in
one level. Note that now it needs to quote in order to prevent shell
interpretation.
For example:
$ perf report --hierarchy -s '{comm,dso},sym'
...
# Overhead Command / Shared Object / Symbol
# .............. ..........................................
#
48.67% swapper [kernel.vmlinux]
34.42% [k] intel_idle
1.30% [k] __tick_nohz_idle_enter
1.03% [k] cpuidle_reflect
8.87% firefox libpthread-2.22.so
6.60% [.] __GI___libc_recvmsg
1.18% [.] pthread_cond_signal@@GLIBC_2.3.2
1.09% [.] 0x000000000000ff4b
6.11% Xorg libc-2.22.so
5.27% [.] __memcpy_sse2_unaligned
In the above example, the command name and the shared object name are
shown on the same line but the symbol name is on the different line.
Since the first two are grouped by '{}', they are in the same level.
Suggested-by: Arnaldo Carvalho de Melo <acme@kernel.org>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
tools/perf/util/sort.c | 42 ++++++++++++++++++++++++++++++++----------
1 file changed, 32 insertions(+), 10 deletions(-)
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 71d45d147376..041f236379e0 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -2310,18 +2310,40 @@ static int setup_sort_list(char *str, struct perf_evlist *evlist)
char *tmp, *tok;
int ret = 0;
int level = 0;
+ int next_level = 1;
+ bool in_group = false;
+
+ do {
+ tok = str;
+ tmp = strpbrk(str, "{}, ");
+ if (tmp) {
+ if (in_group)
+ next_level = level;
+ else
+ next_level = level + 1;
+
+ if (*tmp == '{')
+ in_group = true;
+ else if (*tmp == '}')
+ in_group = false;
+
+ *tmp = '\0';
+ str = tmp + 1;
+ }
- for (tok = strtok_r(str, ", ", &tmp);
- tok; tok = strtok_r(NULL, ", ", &tmp)) {
- ret = sort_dimension__add(tok, evlist, level++);
- if (ret == -EINVAL) {
- error("Invalid --sort key: `%s'", tok);
- break;
- } else if (ret == -ESRCH) {
- error("Unknown --sort key: `%s'", tok);
- break;
+ if (*tok) {
+ ret = sort_dimension__add(tok, evlist, level);
+ if (ret == -EINVAL) {
+ error("Invalid --sort key: `%s'", tok);
+ break;
+ } else if (ret == -ESRCH) {
+ error("Unknown --sort key: `%s'", tok);
+ break;
+ }
}
- }
+
+ level = next_level;
+ } while (tmp);
return ret;
}
--
2.7.2
[toc] | [prev] | [next] | [standalone]
| From | Arnaldo Carvalho de Melo <acme@kernel.org> |
|---|---|
| Date | 2016-03-07 19:00 +0100 |
| Subject | Re: [PATCH v3 3/7] perf tools: Support multiple sort keys in a hierarchy level |
| Message-ID | <ra7BL-61Q-3@gated-at.bofh.it> |
| In reply to | #1351647 |
Em Mon, Mar 07, 2016 at 11:35:04PM +0900, Namhyung Kim escreveu:
> This implements having multiple sort keys in a single hierarchy level.
> Originally only single sort key is supported for each level, but now
> using the group syntax with '{ }', it can set more than one sort key in
> one level. Note that now it needs to quote in order to prevent shell
> interpretation.
>
> For example:
>
> $ perf report --hierarchy -s '{comm,dso},sym'
> ...
> # Overhead Command / Shared Object / Symbol
It works, but there is no difference on the one line above, the header,
to help differentiate the above from:
$ perf report --hierarchy -s 'comm,dso,sym'
Also we don't warn the user that such groupings only make sense when
used with --hierarchy.
Anyway, applying the patch, those are things that can be done on top.
- Arnaldo
> # .............. ..........................................
> #
> 48.67% swapper [kernel.vmlinux]
> 34.42% [k] intel_idle
> 1.30% [k] __tick_nohz_idle_enter
> 1.03% [k] cpuidle_reflect
> 8.87% firefox libpthread-2.22.so
> 6.60% [.] __GI___libc_recvmsg
> 1.18% [.] pthread_cond_signal@@GLIBC_2.3.2
> 1.09% [.] 0x000000000000ff4b
> 6.11% Xorg libc-2.22.so
> 5.27% [.] __memcpy_sse2_unaligned
>
> In the above example, the command name and the shared object name are
> shown on the same line but the symbol name is on the different line.
> Since the first two are grouped by '{}', they are in the same level.
>
> Suggested-by: Arnaldo Carvalho de Melo <acme@kernel.org>
> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
> ---
> tools/perf/util/sort.c | 42 ++++++++++++++++++++++++++++++++----------
> 1 file changed, 32 insertions(+), 10 deletions(-)
>
> diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
> index 71d45d147376..041f236379e0 100644
> --- a/tools/perf/util/sort.c
> +++ b/tools/perf/util/sort.c
> @@ -2310,18 +2310,40 @@ static int setup_sort_list(char *str, struct perf_evlist *evlist)
> char *tmp, *tok;
> int ret = 0;
> int level = 0;
> + int next_level = 1;
> + bool in_group = false;
> +
> + do {
> + tok = str;
> + tmp = strpbrk(str, "{}, ");
> + if (tmp) {
> + if (in_group)
> + next_level = level;
> + else
> + next_level = level + 1;
> +
> + if (*tmp == '{')
> + in_group = true;
> + else if (*tmp == '}')
> + in_group = false;
> +
> + *tmp = '\0';
> + str = tmp + 1;
> + }
>
> - for (tok = strtok_r(str, ", ", &tmp);
> - tok; tok = strtok_r(NULL, ", ", &tmp)) {
> - ret = sort_dimension__add(tok, evlist, level++);
> - if (ret == -EINVAL) {
> - error("Invalid --sort key: `%s'", tok);
> - break;
> - } else if (ret == -ESRCH) {
> - error("Unknown --sort key: `%s'", tok);
> - break;
> + if (*tok) {
> + ret = sort_dimension__add(tok, evlist, level);
> + if (ret == -EINVAL) {
> + error("Invalid --sort key: `%s'", tok);
> + break;
> + } else if (ret == -ESRCH) {
> + error("Unknown --sort key: `%s'", tok);
> + break;
> + }
> }
> - }
> +
> + level = next_level;
> + } while (tmp);
>
> return ret;
> }
> --
> 2.7.2
[toc] | [prev] | [next] | [standalone]
| From | tip-bot for Namhyung Kim <tipbot@zytor.com> |
|---|---|
| Date | 2016-03-08 11:40 +0100 |
| Subject | [tip:perf/core] perf hists: Support multiple sort keys in a hierarchy level |
| Message-ID | <randw-84x-33@gated-at.bofh.it> |
| In reply to | #1351647 |
Commit-ID: a23f37e864609f0887c1cb77c4d5b62586484a61
Gitweb: http://git.kernel.org/tip/a23f37e864609f0887c1cb77c4d5b62586484a61
Author: Namhyung Kim <namhyung@kernel.org>
AuthorDate: Mon, 7 Mar 2016 16:44:47 -0300
Committer: Ingo Molnar <mingo@kernel.org>
CommitDate: Tue, 8 Mar 2016 10:11:20 +0100
perf hists: Support multiple sort keys in a hierarchy level
This implements having multiple sort keys in a single hierarchy level.
Originally only single sort key is supported for each level, but now
using the group syntax with '{ }', it can set more than one sort key in
one level. Note that now it needs to quote in order to prevent shell
interpretation.
For example:
$ perf report --hierarchy -s '{comm,dso},sym'
...
# Overhead Command / Shared Object / Symbol
# .............. ..........................................
#
48.67% swapper [kernel.vmlinux]
34.42% [k] intel_idle
1.30% [k] __tick_nohz_idle_enter
1.03% [k] cpuidle_reflect
8.87% firefox libpthread-2.22.so
6.60% [.] __GI___libc_recvmsg
1.18% [.] pthread_cond_signal@@GLIBC_2.3.2
1.09% [.] 0x000000000000ff4b
6.11% Xorg libc-2.22.so
5.27% [.] __memcpy_sse2_unaligned
In the above example, the command name and the shared object name are
shown on the same line but the symbol name is on the different line.
Since the first two are grouped by '{}', they are in the same level.
Suggested-and-Tested=by: Arnaldo Carvalho de Melo <acme@kernel.org>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Wang Nan <wangnan0@huawei.com>
Link: http://lkml.kernel.org/r/1457361308-514-4-git-send-email-namhyung@kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
tools/perf/util/sort.c | 42 ++++++++++++++++++++++++++++++++----------
1 file changed, 32 insertions(+), 10 deletions(-)
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 71d45d1..041f236 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -2310,18 +2310,40 @@ static int setup_sort_list(char *str, struct perf_evlist *evlist)
char *tmp, *tok;
int ret = 0;
int level = 0;
+ int next_level = 1;
+ bool in_group = false;
+
+ do {
+ tok = str;
+ tmp = strpbrk(str, "{}, ");
+ if (tmp) {
+ if (in_group)
+ next_level = level;
+ else
+ next_level = level + 1;
+
+ if (*tmp == '{')
+ in_group = true;
+ else if (*tmp == '}')
+ in_group = false;
+
+ *tmp = '\0';
+ str = tmp + 1;
+ }
- for (tok = strtok_r(str, ", ", &tmp);
- tok; tok = strtok_r(NULL, ", ", &tmp)) {
- ret = sort_dimension__add(tok, evlist, level++);
- if (ret == -EINVAL) {
- error("Invalid --sort key: `%s'", tok);
- break;
- } else if (ret == -ESRCH) {
- error("Unknown --sort key: `%s'", tok);
- break;
+ if (*tok) {
+ ret = sort_dimension__add(tok, evlist, level);
+ if (ret == -EINVAL) {
+ error("Invalid --sort key: `%s'", tok);
+ break;
+ } else if (ret == -ESRCH) {
+ error("Unknown --sort key: `%s'", tok);
+ break;
+ }
}
- }
+
+ level = next_level;
+ } while (tmp);
return ret;
}
[toc] | [prev] | [next] | [standalone]
| From | Namhyung Kim <namhyung@kernel.org> |
|---|---|
| Date | 2016-03-07 15:40 +0100 |
| Subject | [PATCH v3 7/7] perf report: Use hierarchy hpp list on gtk |
| Message-ID | <ra4uf-42s-57@gated-at.bofh.it> |
| In reply to | #1351644 |
Now hpp formats are linked using perf_hpp_list_node when hierarchy is
enabled. Like in stdio, use this info to print entries with multiple
sort keys in a single hierarchy properly.
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
tools/perf/ui/gtk/hists.c | 55 ++++++++++++++++++++++++++++-------------------
1 file changed, 33 insertions(+), 22 deletions(-)
diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c
index 4534e2d7669c..bd9bf7e343b1 100644
--- a/tools/perf/ui/gtk/hists.c
+++ b/tools/perf/ui/gtk/hists.c
@@ -407,7 +407,9 @@ static void perf_gtk__add_hierarchy_entries(struct hists *hists,
struct rb_node *node;
struct hist_entry *he;
struct perf_hpp_fmt *fmt;
+ struct perf_hpp_list_node *fmt_node;
u64 total = hists__total_period(hists);
+ int size;
for (node = rb_first(root); node; node = rb_next(node)) {
GtkTreeIter iter;
@@ -425,11 +427,11 @@ static void perf_gtk__add_hierarchy_entries(struct hists *hists,
gtk_tree_store_append(store, &iter, parent);
col_idx = 0;
- hists__for_each_format(hists, fmt) {
- if (perf_hpp__is_sort_entry(fmt) ||
- perf_hpp__is_dynamic_entry(fmt))
- break;
+ /* the first hpp_list_node is for overhead columns */
+ fmt_node = list_first_entry(&hists->hpp_formats,
+ struct perf_hpp_list_node, list);
+ perf_hpp_list__for_each_format(&fmt_node->hpp, fmt) {
if (fmt->color)
fmt->color(fmt, hpp, he);
else
@@ -439,6 +441,7 @@ static void perf_gtk__add_hierarchy_entries(struct hists *hists,
}
bf = hpp->buf;
+ size = hpp->size;
perf_hpp_list__for_each_format(he->hpp_list, fmt) {
int ret;
@@ -451,9 +454,12 @@ static void perf_gtk__add_hierarchy_entries(struct hists *hists,
advance_hpp(hpp, ret + 2);
}
- gtk_tree_store_set(store, &iter, col_idx, rtrim(bf), -1);
+ gtk_tree_store_set(store, &iter, col_idx, ltrim(rtrim(bf)), -1);
if (!he->leaf) {
+ hpp->buf = bf;
+ hpp->size = size;
+
perf_gtk__add_hierarchy_entries(hists, &he->hroot_out,
store, &iter, hpp,
min_pcnt);
@@ -486,6 +492,7 @@ static void perf_gtk__show_hierarchy(GtkWidget *window, struct hists *hists,
float min_pcnt)
{
struct perf_hpp_fmt *fmt;
+ struct perf_hpp_list_node *fmt_node;
GType col_types[MAX_COLUMNS];
GtkCellRenderer *renderer;
GtkTreeStore *store;
@@ -494,7 +501,7 @@ static void perf_gtk__show_hierarchy(GtkWidget *window, struct hists *hists,
int nr_cols = 0;
char s[512];
char buf[512];
- bool first = true;
+ bool first_node, first_col;
struct perf_hpp hpp = {
.buf = s,
.size = sizeof(s),
@@ -514,11 +521,11 @@ static void perf_gtk__show_hierarchy(GtkWidget *window, struct hists *hists,
renderer = gtk_cell_renderer_text_new();
col_idx = 0;
- hists__for_each_format(hists, fmt) {
- if (perf_hpp__is_sort_entry(fmt) ||
- perf_hpp__is_dynamic_entry(fmt))
- break;
+ /* the first hpp_list_node is for overhead columns */
+ fmt_node = list_first_entry(&hists->hpp_formats,
+ struct perf_hpp_list_node, list);
+ perf_hpp_list__for_each_format(&fmt_node->hpp, fmt) {
gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
-1, fmt->name,
renderer, "markup",
@@ -527,20 +534,24 @@ static void perf_gtk__show_hierarchy(GtkWidget *window, struct hists *hists,
/* construct merged column header since sort keys share single column */
buf[0] = '\0';
- hists__for_each_format(hists ,fmt) {
- if (!perf_hpp__is_sort_entry(fmt) &&
- !perf_hpp__is_dynamic_entry(fmt))
- continue;
- if (perf_hpp__should_skip(fmt, hists))
- continue;
-
- if (first)
- first = false;
- else
+ first_node = true;
+ list_for_each_entry_continue(fmt_node, &hists->hpp_formats, list) {
+ if (!first_node)
strcat(buf, " / ");
+ first_node = false;
- fmt->header(fmt, &hpp, hists_to_evsel(hists));
- strcat(buf, rtrim(hpp.buf));
+ first_col = true;
+ perf_hpp_list__for_each_format(&fmt_node->hpp ,fmt) {
+ if (perf_hpp__should_skip(fmt, hists))
+ continue;
+
+ if (!first_col)
+ strcat(buf, "+");
+ first_col = false;
+
+ fmt->header(fmt, &hpp, hists_to_evsel(hists));
+ strcat(buf, ltrim(rtrim(hpp.buf)));
+ }
}
gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
--
2.7.2
[toc] | [prev] | [next] | [standalone]
| From | tip-bot for Namhyung Kim <tipbot@zytor.com> |
|---|---|
| Date | 2016-03-08 11:40 +0100 |
| Subject | [tip:perf/core] perf report: Use hierarchy hpp list on gtk |
| Message-ID | <randx-84x-63@gated-at.bofh.it> |
| In reply to | #1351648 |
Commit-ID: 58ecd33be90647724a78ce5e0b42f5bc482771fd
Gitweb: http://git.kernel.org/tip/58ecd33be90647724a78ce5e0b42f5bc482771fd
Author: Namhyung Kim <namhyung@kernel.org>
AuthorDate: Mon, 7 Mar 2016 16:44:51 -0300
Committer: Ingo Molnar <mingo@kernel.org>
CommitDate: Tue, 8 Mar 2016 10:11:21 +0100
perf report: Use hierarchy hpp list on gtk
Now hpp formats are linked using perf_hpp_list_node when hierarchy is
enabled. Like in stdio, use this info to print entries with multiple
sort keys in a single hierarchy properly.
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Wang Nan <wangnan0@huawei.com>
Link: http://lkml.kernel.org/r/1457361308-514-8-git-send-email-namhyung@kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
tools/perf/ui/gtk/hists.c | 55 ++++++++++++++++++++++++++++-------------------
1 file changed, 33 insertions(+), 22 deletions(-)
diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c
index 4534e2d..bd9bf7e 100644
--- a/tools/perf/ui/gtk/hists.c
+++ b/tools/perf/ui/gtk/hists.c
@@ -407,7 +407,9 @@ static void perf_gtk__add_hierarchy_entries(struct hists *hists,
struct rb_node *node;
struct hist_entry *he;
struct perf_hpp_fmt *fmt;
+ struct perf_hpp_list_node *fmt_node;
u64 total = hists__total_period(hists);
+ int size;
for (node = rb_first(root); node; node = rb_next(node)) {
GtkTreeIter iter;
@@ -425,11 +427,11 @@ static void perf_gtk__add_hierarchy_entries(struct hists *hists,
gtk_tree_store_append(store, &iter, parent);
col_idx = 0;
- hists__for_each_format(hists, fmt) {
- if (perf_hpp__is_sort_entry(fmt) ||
- perf_hpp__is_dynamic_entry(fmt))
- break;
+ /* the first hpp_list_node is for overhead columns */
+ fmt_node = list_first_entry(&hists->hpp_formats,
+ struct perf_hpp_list_node, list);
+ perf_hpp_list__for_each_format(&fmt_node->hpp, fmt) {
if (fmt->color)
fmt->color(fmt, hpp, he);
else
@@ -439,6 +441,7 @@ static void perf_gtk__add_hierarchy_entries(struct hists *hists,
}
bf = hpp->buf;
+ size = hpp->size;
perf_hpp_list__for_each_format(he->hpp_list, fmt) {
int ret;
@@ -451,9 +454,12 @@ static void perf_gtk__add_hierarchy_entries(struct hists *hists,
advance_hpp(hpp, ret + 2);
}
- gtk_tree_store_set(store, &iter, col_idx, rtrim(bf), -1);
+ gtk_tree_store_set(store, &iter, col_idx, ltrim(rtrim(bf)), -1);
if (!he->leaf) {
+ hpp->buf = bf;
+ hpp->size = size;
+
perf_gtk__add_hierarchy_entries(hists, &he->hroot_out,
store, &iter, hpp,
min_pcnt);
@@ -486,6 +492,7 @@ static void perf_gtk__show_hierarchy(GtkWidget *window, struct hists *hists,
float min_pcnt)
{
struct perf_hpp_fmt *fmt;
+ struct perf_hpp_list_node *fmt_node;
GType col_types[MAX_COLUMNS];
GtkCellRenderer *renderer;
GtkTreeStore *store;
@@ -494,7 +501,7 @@ static void perf_gtk__show_hierarchy(GtkWidget *window, struct hists *hists,
int nr_cols = 0;
char s[512];
char buf[512];
- bool first = true;
+ bool first_node, first_col;
struct perf_hpp hpp = {
.buf = s,
.size = sizeof(s),
@@ -514,11 +521,11 @@ static void perf_gtk__show_hierarchy(GtkWidget *window, struct hists *hists,
renderer = gtk_cell_renderer_text_new();
col_idx = 0;
- hists__for_each_format(hists, fmt) {
- if (perf_hpp__is_sort_entry(fmt) ||
- perf_hpp__is_dynamic_entry(fmt))
- break;
+ /* the first hpp_list_node is for overhead columns */
+ fmt_node = list_first_entry(&hists->hpp_formats,
+ struct perf_hpp_list_node, list);
+ perf_hpp_list__for_each_format(&fmt_node->hpp, fmt) {
gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
-1, fmt->name,
renderer, "markup",
@@ -527,20 +534,24 @@ static void perf_gtk__show_hierarchy(GtkWidget *window, struct hists *hists,
/* construct merged column header since sort keys share single column */
buf[0] = '\0';
- hists__for_each_format(hists ,fmt) {
- if (!perf_hpp__is_sort_entry(fmt) &&
- !perf_hpp__is_dynamic_entry(fmt))
- continue;
- if (perf_hpp__should_skip(fmt, hists))
- continue;
-
- if (first)
- first = false;
- else
+ first_node = true;
+ list_for_each_entry_continue(fmt_node, &hists->hpp_formats, list) {
+ if (!first_node)
strcat(buf, " / ");
+ first_node = false;
- fmt->header(fmt, &hpp, hists_to_evsel(hists));
- strcat(buf, rtrim(hpp.buf));
+ first_col = true;
+ perf_hpp_list__for_each_format(&fmt_node->hpp ,fmt) {
+ if (perf_hpp__should_skip(fmt, hists))
+ continue;
+
+ if (!first_col)
+ strcat(buf, "+");
+ first_col = false;
+
+ fmt->header(fmt, &hpp, hists_to_evsel(hists));
+ strcat(buf, ltrim(rtrim(hpp.buf)));
+ }
}
gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
[toc] | [prev] | [next] | [standalone]
| From | Namhyung Kim <namhyung@kernel.org> |
|---|---|
| Date | 2016-03-07 15:40 +0100 |
| Subject | [PATCH v3 2/7] perf tools: Use own hpp_list for hierarchy mode |
| Message-ID | <ra4ug-42s-75@gated-at.bofh.it> |
| In reply to | #1351644 |
Now each hists has its own hpp lists in hierarchy. So instead of having
a pointer to a single perf_hpp_fmt in a hist entry, make it point the
hpp_list for its level. This will be used to support multiple sort keys
in a single hierarchy level.
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
tools/perf/ui/browsers/hists.c | 45 +++++++++++++++++--------------
tools/perf/ui/gtk/hists.c | 20 +++++++++-----
tools/perf/ui/hist.c | 5 ++++
tools/perf/ui/stdio/hist.c | 44 +++++++++++++++----------------
tools/perf/util/hist.c | 60 ++++++++++++++++++++++++------------------
tools/perf/util/hist.h | 1 +
tools/perf/util/sort.h | 1 +
7 files changed, 103 insertions(+), 73 deletions(-)
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 5ffffcb1e3c5..928b4825b752 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -1388,25 +1388,26 @@ static int hist_browser__show_hierarchy_entry(struct hist_browser *browser,
HE_COLORSET_NORMAL);
}
- ui_browser__write_nstring(&browser->b, "", 2);
- width -= 2;
+ perf_hpp_list__for_each_format(entry->hpp_list, fmt) {
+ ui_browser__write_nstring(&browser->b, "", 2);
+ width -= 2;
- /*
- * No need to call hist_entry__snprintf_alignment()
- * since this fmt is always the last column in the
- * hierarchy mode.
- */
- fmt = entry->fmt;
- if (fmt->color) {
- width -= fmt->color(fmt, &hpp, entry);
- } else {
- int i = 0;
+ /*
+ * No need to call hist_entry__snprintf_alignment()
+ * since this fmt is always the last column in the
+ * hierarchy mode.
+ */
+ if (fmt->color) {
+ width -= fmt->color(fmt, &hpp, entry);
+ } else {
+ int i = 0;
- width -= fmt->entry(fmt, &hpp, entry);
- ui_browser__printf(&browser->b, "%s", ltrim(s));
+ width -= fmt->entry(fmt, &hpp, entry);
+ ui_browser__printf(&browser->b, "%s", ltrim(s));
- while (isspace(s[i++]))
- width++;
+ while (isspace(s[i++]))
+ width++;
+ }
}
}
@@ -1934,7 +1935,7 @@ static int hist_browser__fprintf_hierarchy_entry(struct hist_browser *browser,
struct perf_hpp_fmt *fmt;
bool first = true;
int ret;
- int hierarchy_indent = (nr_sort_keys + 1) * HIERARCHY_INDENT;
+ int hierarchy_indent = nr_sort_keys * HIERARCHY_INDENT;
printed = fprintf(fp, "%*s", level * HIERARCHY_INDENT, "");
@@ -1962,9 +1963,13 @@ static int hist_browser__fprintf_hierarchy_entry(struct hist_browser *browser,
ret = scnprintf(hpp.buf, hpp.size, "%*s", hierarchy_indent, "");
advance_hpp(&hpp, ret);
- fmt = he->fmt;
- ret = fmt->entry(fmt, &hpp, he);
- advance_hpp(&hpp, ret);
+ perf_hpp_list__for_each_format(he->hpp_list, fmt) {
+ ret = scnprintf(hpp.buf, hpp.size, " ");
+ advance_hpp(&hpp, ret);
+
+ ret = fmt->entry(fmt, &hpp, he);
+ advance_hpp(&hpp, ret);
+ }
printed += fprintf(fp, "%s\n", rtrim(s));
diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c
index a5758fdfbe1f..4534e2d7669c 100644
--- a/tools/perf/ui/gtk/hists.c
+++ b/tools/perf/ui/gtk/hists.c
@@ -412,6 +412,7 @@ static void perf_gtk__add_hierarchy_entries(struct hists *hists,
for (node = rb_first(root); node; node = rb_next(node)) {
GtkTreeIter iter;
float percent;
+ char *bf;
he = rb_entry(node, struct hist_entry, rb_node);
if (he->filtered)
@@ -437,13 +438,20 @@ static void perf_gtk__add_hierarchy_entries(struct hists *hists,
gtk_tree_store_set(store, &iter, col_idx++, hpp->buf, -1);
}
- fmt = he->fmt;
- if (fmt->color)
- fmt->color(fmt, hpp, he);
- else
- fmt->entry(fmt, hpp, he);
+ bf = hpp->buf;
+ perf_hpp_list__for_each_format(he->hpp_list, fmt) {
+ int ret;
+
+ if (fmt->color)
+ ret = fmt->color(fmt, hpp, he);
+ else
+ ret = fmt->entry(fmt, hpp, he);
+
+ snprintf(hpp->buf + ret, hpp->size - ret, " ");
+ advance_hpp(hpp, ret + 2);
+ }
- gtk_tree_store_set(store, &iter, col_idx, rtrim(hpp->buf), -1);
+ gtk_tree_store_set(store, &iter, col_idx, rtrim(bf), -1);
if (!he->leaf) {
perf_gtk__add_hierarchy_entries(hists, &he->hroot_out,
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 3a15e844f89a..95795ef4209b 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -722,6 +722,7 @@ static int add_hierarchy_fmt(struct hists *hists, struct perf_hpp_fmt *fmt)
struct perf_hpp_list_node *node = NULL;
struct perf_hpp_fmt *fmt_copy;
bool found = false;
+ bool skip = perf_hpp__should_skip(fmt, hists);
list_for_each_entry(node, &hists->hpp_formats, list) {
if (node->level == fmt->level) {
@@ -735,6 +736,7 @@ static int add_hierarchy_fmt(struct hists *hists, struct perf_hpp_fmt *fmt)
if (node == NULL)
return -1;
+ node->skip = skip;
node->level = fmt->level;
perf_hpp_list__init(&node->hpp);
@@ -745,6 +747,9 @@ static int add_hierarchy_fmt(struct hists *hists, struct perf_hpp_fmt *fmt)
if (fmt_copy == NULL)
return -1;
+ if (!skip)
+ node->skip = false;
+
list_add_tail(&fmt_copy->list, &node->hpp.fields);
list_add_tail(&fmt_copy->sort_list, &node->hpp.sorts);
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index 6d06fbb365b6..073642a63cc9 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -451,33 +451,33 @@ static int hist_entry__hierarchy_fprintf(struct hist_entry *he,
advance_hpp(hpp, ret);
}
- if (sep)
- ret = scnprintf(hpp->buf, hpp->size, "%s", sep);
- else
+ if (!sep)
ret = scnprintf(hpp->buf, hpp->size, "%*s",
- (nr_sort_key - 1) * HIERARCHY_INDENT + 2, "");
+ (nr_sort_key - 1) * HIERARCHY_INDENT, "");
advance_hpp(hpp, ret);
printed += fprintf(fp, "%s", buf);
- hpp->buf = buf;
- hpp->size = size;
-
- /*
- * No need to call hist_entry__snprintf_alignment() since this
- * fmt is always the last column in the hierarchy mode.
- */
- fmt = he->fmt;
- if (perf_hpp__use_color() && fmt->color)
- fmt->color(fmt, hpp, he);
- else
- fmt->entry(fmt, hpp, he);
-
- /*
- * dynamic entries are right-aligned but we want left-aligned
- * in the hierarchy mode
- */
- printed += fprintf(fp, "%s\n", ltrim(buf));
+ perf_hpp_list__for_each_format(he->hpp_list, fmt) {
+ hpp->buf = buf;
+ hpp->size = size;
+
+ /*
+ * No need to call hist_entry__snprintf_alignment() since this
+ * fmt is always the last column in the hierarchy mode.
+ */
+ if (perf_hpp__use_color() && fmt->color)
+ fmt->color(fmt, hpp, he);
+ else
+ fmt->entry(fmt, hpp, he);
+
+ /*
+ * dynamic entries are right-aligned but we want left-aligned
+ * in the hierarchy mode
+ */
+ printed += fprintf(fp, "%s%s", sep ?: " ", ltrim(buf));
+ }
+ printed += putc('\n', fp);
if (symbol_conf.use_callchain && he->leaf) {
u64 total = hists__total_period(hists);
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index fea92fcb6903..29da9e0d8db9 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -1091,18 +1091,25 @@ static void hists__apply_filters(struct hists *hists, struct hist_entry *he);
static struct hist_entry *hierarchy_insert_entry(struct hists *hists,
struct rb_root *root,
struct hist_entry *he,
- struct perf_hpp_fmt *fmt)
+ struct perf_hpp_list *hpp_list)
{
struct rb_node **p = &root->rb_node;
struct rb_node *parent = NULL;
struct hist_entry *iter, *new;
+ struct perf_hpp_fmt *fmt;
int64_t cmp;
while (*p != NULL) {
parent = *p;
iter = rb_entry(parent, struct hist_entry, rb_node_in);
- cmp = fmt->collapse(fmt, iter, he);
+ cmp = 0;
+ perf_hpp_list__for_each_sort_list(hpp_list, fmt) {
+ cmp = fmt->collapse(fmt, iter, he);
+ if (cmp)
+ break;
+ }
+
if (!cmp) {
he_stat__add_stat(&iter->stat, &he->stat);
return iter;
@@ -1121,24 +1128,26 @@ static struct hist_entry *hierarchy_insert_entry(struct hists *hists,
hists__apply_filters(hists, new);
hists->nr_entries++;
- /* save related format for output */
- new->fmt = fmt;
+ /* save related format list for output */
+ new->hpp_list = hpp_list;
/* some fields are now passed to 'new' */
- if (perf_hpp__is_trace_entry(fmt) || perf_hpp__is_dynamic_entry(fmt))
- he->trace_output = NULL;
- else
- new->trace_output = NULL;
+ perf_hpp_list__for_each_sort_list(hpp_list, fmt) {
+ if (perf_hpp__is_trace_entry(fmt) || perf_hpp__is_dynamic_entry(fmt))
+ he->trace_output = NULL;
+ else
+ new->trace_output = NULL;
- if (perf_hpp__is_srcline_entry(fmt))
- he->srcline = NULL;
- else
- new->srcline = NULL;
+ if (perf_hpp__is_srcline_entry(fmt))
+ he->srcline = NULL;
+ else
+ new->srcline = NULL;
- if (perf_hpp__is_srcfile_entry(fmt))
- he->srcfile = NULL;
- else
- new->srcfile = NULL;
+ if (perf_hpp__is_srcfile_entry(fmt))
+ he->srcfile = NULL;
+ else
+ new->srcfile = NULL;
+ }
rb_link_node(&new->rb_node_in, parent, p);
rb_insert_color(&new->rb_node_in, root);
@@ -1149,21 +1158,19 @@ static int hists__hierarchy_insert_entry(struct hists *hists,
struct rb_root *root,
struct hist_entry *he)
{
- struct perf_hpp_fmt *fmt;
+ struct perf_hpp_list_node *node;
struct hist_entry *new_he = NULL;
struct hist_entry *parent = NULL;
int depth = 0;
int ret = 0;
- hists__for_each_sort_list(hists, fmt) {
- if (!perf_hpp__is_sort_entry(fmt) &&
- !perf_hpp__is_dynamic_entry(fmt))
- continue;
- if (perf_hpp__should_skip(fmt, hists))
+ list_for_each_entry(node, &hists->hpp_formats, list) {
+ /* skip period (overhead) and elided columns */
+ if (node->level == 0 || node->skip)
continue;
/* insert copy of 'he' for each fmt into the hierarchy */
- new_he = hierarchy_insert_entry(hists, root, he, fmt);
+ new_he = hierarchy_insert_entry(hists, root, he, &node->hpp);
if (new_he == NULL) {
ret = -1;
break;
@@ -1358,6 +1365,7 @@ static void hierarchy_insert_output_entry(struct rb_root *root,
struct rb_node **p = &root->rb_node;
struct rb_node *parent = NULL;
struct hist_entry *iter;
+ struct perf_hpp_fmt *fmt;
while (*p != NULL) {
parent = *p;
@@ -1373,8 +1381,10 @@ static void hierarchy_insert_output_entry(struct rb_root *root,
rb_insert_color(&he->rb_node, root);
/* update column width of dynamic entry */
- if (perf_hpp__is_dynamic_entry(he->fmt))
- he->fmt->sort(he->fmt, he, NULL);
+ perf_hpp_list__for_each_sort_list(he->hpp_list, fmt) {
+ if (perf_hpp__is_dynamic_entry(fmt))
+ fmt->sort(fmt, he, NULL);
+ }
}
static void hists__hierarchy_output_resort(struct hists *hists,
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 3cab9dc20822..2209188d729c 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -249,6 +249,7 @@ struct perf_hpp_list_node {
struct list_head list;
struct perf_hpp_list hpp;
int level;
+ bool skip;
};
void perf_hpp_list__column_register(struct perf_hpp_list *list,
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 25a5529a94e4..ea1f722cffea 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -130,6 +130,7 @@ struct hist_entry {
u32 raw_size;
void *trace_output;
struct perf_hpp_fmt *fmt;
+ struct perf_hpp_list *hpp_list;
struct hist_entry *parent_he;
union {
/* this is for hierarchical entry structure */
--
2.7.2
[toc] | [prev] | [next] | [standalone]
| From | tip-bot for Namhyung Kim <tipbot@zytor.com> |
|---|---|
| Date | 2016-03-08 11:40 +0100 |
| Subject | [tip:perf/core] perf hists: Use own hpp_list for hierarchy mode |
| Message-ID | <randw-84x-23@gated-at.bofh.it> |
| In reply to | #1351657 |
Commit-ID: 1b2dbbf41a0f4cf7a5662bccb9a18128d16e5ffb
Gitweb: http://git.kernel.org/tip/1b2dbbf41a0f4cf7a5662bccb9a18128d16e5ffb
Author: Namhyung Kim <namhyung@kernel.org>
AuthorDate: Mon, 7 Mar 2016 16:44:46 -0300
Committer: Ingo Molnar <mingo@kernel.org>
CommitDate: Tue, 8 Mar 2016 10:11:19 +0100
perf hists: Use own hpp_list for hierarchy mode
Now each hists has its own hpp lists in hierarchy. So instead of having
a pointer to a single perf_hpp_fmt in a hist entry, make it point the
hpp_list for its level. This will be used to support multiple sort keys
in a single hierarchy level.
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Wang Nan <wangnan0@huawei.com>
Link: http://lkml.kernel.org/r/1457361308-514-3-git-send-email-namhyung@kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
tools/perf/ui/browsers/hists.c | 45 +++++++++++++++++--------------
tools/perf/ui/gtk/hists.c | 20 +++++++++-----
tools/perf/ui/hist.c | 5 ++++
tools/perf/ui/stdio/hist.c | 44 +++++++++++++++----------------
tools/perf/util/hist.c | 60 ++++++++++++++++++++++++------------------
tools/perf/util/hist.h | 1 +
tools/perf/util/sort.h | 1 +
7 files changed, 103 insertions(+), 73 deletions(-)
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 5ffffcb..928b482 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -1388,25 +1388,26 @@ static int hist_browser__show_hierarchy_entry(struct hist_browser *browser,
HE_COLORSET_NORMAL);
}
- ui_browser__write_nstring(&browser->b, "", 2);
- width -= 2;
+ perf_hpp_list__for_each_format(entry->hpp_list, fmt) {
+ ui_browser__write_nstring(&browser->b, "", 2);
+ width -= 2;
- /*
- * No need to call hist_entry__snprintf_alignment()
- * since this fmt is always the last column in the
- * hierarchy mode.
- */
- fmt = entry->fmt;
- if (fmt->color) {
- width -= fmt->color(fmt, &hpp, entry);
- } else {
- int i = 0;
+ /*
+ * No need to call hist_entry__snprintf_alignment()
+ * since this fmt is always the last column in the
+ * hierarchy mode.
+ */
+ if (fmt->color) {
+ width -= fmt->color(fmt, &hpp, entry);
+ } else {
+ int i = 0;
- width -= fmt->entry(fmt, &hpp, entry);
- ui_browser__printf(&browser->b, "%s", ltrim(s));
+ width -= fmt->entry(fmt, &hpp, entry);
+ ui_browser__printf(&browser->b, "%s", ltrim(s));
- while (isspace(s[i++]))
- width++;
+ while (isspace(s[i++]))
+ width++;
+ }
}
}
@@ -1934,7 +1935,7 @@ static int hist_browser__fprintf_hierarchy_entry(struct hist_browser *browser,
struct perf_hpp_fmt *fmt;
bool first = true;
int ret;
- int hierarchy_indent = (nr_sort_keys + 1) * HIERARCHY_INDENT;
+ int hierarchy_indent = nr_sort_keys * HIERARCHY_INDENT;
printed = fprintf(fp, "%*s", level * HIERARCHY_INDENT, "");
@@ -1962,9 +1963,13 @@ static int hist_browser__fprintf_hierarchy_entry(struct hist_browser *browser,
ret = scnprintf(hpp.buf, hpp.size, "%*s", hierarchy_indent, "");
advance_hpp(&hpp, ret);
- fmt = he->fmt;
- ret = fmt->entry(fmt, &hpp, he);
- advance_hpp(&hpp, ret);
+ perf_hpp_list__for_each_format(he->hpp_list, fmt) {
+ ret = scnprintf(hpp.buf, hpp.size, " ");
+ advance_hpp(&hpp, ret);
+
+ ret = fmt->entry(fmt, &hpp, he);
+ advance_hpp(&hpp, ret);
+ }
printed += fprintf(fp, "%s\n", rtrim(s));
diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c
index a5758fd..4534e2d 100644
--- a/tools/perf/ui/gtk/hists.c
+++ b/tools/perf/ui/gtk/hists.c
@@ -412,6 +412,7 @@ static void perf_gtk__add_hierarchy_entries(struct hists *hists,
for (node = rb_first(root); node; node = rb_next(node)) {
GtkTreeIter iter;
float percent;
+ char *bf;
he = rb_entry(node, struct hist_entry, rb_node);
if (he->filtered)
@@ -437,13 +438,20 @@ static void perf_gtk__add_hierarchy_entries(struct hists *hists,
gtk_tree_store_set(store, &iter, col_idx++, hpp->buf, -1);
}
- fmt = he->fmt;
- if (fmt->color)
- fmt->color(fmt, hpp, he);
- else
- fmt->entry(fmt, hpp, he);
+ bf = hpp->buf;
+ perf_hpp_list__for_each_format(he->hpp_list, fmt) {
+ int ret;
+
+ if (fmt->color)
+ ret = fmt->color(fmt, hpp, he);
+ else
+ ret = fmt->entry(fmt, hpp, he);
+
+ snprintf(hpp->buf + ret, hpp->size - ret, " ");
+ advance_hpp(hpp, ret + 2);
+ }
- gtk_tree_store_set(store, &iter, col_idx, rtrim(hpp->buf), -1);
+ gtk_tree_store_set(store, &iter, col_idx, rtrim(bf), -1);
if (!he->leaf) {
perf_gtk__add_hierarchy_entries(hists, &he->hroot_out,
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 3a15e84..95795ef 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -722,6 +722,7 @@ static int add_hierarchy_fmt(struct hists *hists, struct perf_hpp_fmt *fmt)
struct perf_hpp_list_node *node = NULL;
struct perf_hpp_fmt *fmt_copy;
bool found = false;
+ bool skip = perf_hpp__should_skip(fmt, hists);
list_for_each_entry(node, &hists->hpp_formats, list) {
if (node->level == fmt->level) {
@@ -735,6 +736,7 @@ static int add_hierarchy_fmt(struct hists *hists, struct perf_hpp_fmt *fmt)
if (node == NULL)
return -1;
+ node->skip = skip;
node->level = fmt->level;
perf_hpp_list__init(&node->hpp);
@@ -745,6 +747,9 @@ static int add_hierarchy_fmt(struct hists *hists, struct perf_hpp_fmt *fmt)
if (fmt_copy == NULL)
return -1;
+ if (!skip)
+ node->skip = false;
+
list_add_tail(&fmt_copy->list, &node->hpp.fields);
list_add_tail(&fmt_copy->sort_list, &node->hpp.sorts);
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index 6d06fbb..073642a 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -451,33 +451,33 @@ static int hist_entry__hierarchy_fprintf(struct hist_entry *he,
advance_hpp(hpp, ret);
}
- if (sep)
- ret = scnprintf(hpp->buf, hpp->size, "%s", sep);
- else
+ if (!sep)
ret = scnprintf(hpp->buf, hpp->size, "%*s",
- (nr_sort_key - 1) * HIERARCHY_INDENT + 2, "");
+ (nr_sort_key - 1) * HIERARCHY_INDENT, "");
advance_hpp(hpp, ret);
printed += fprintf(fp, "%s", buf);
- hpp->buf = buf;
- hpp->size = size;
-
- /*
- * No need to call hist_entry__snprintf_alignment() since this
- * fmt is always the last column in the hierarchy mode.
- */
- fmt = he->fmt;
- if (perf_hpp__use_color() && fmt->color)
- fmt->color(fmt, hpp, he);
- else
- fmt->entry(fmt, hpp, he);
-
- /*
- * dynamic entries are right-aligned but we want left-aligned
- * in the hierarchy mode
- */
- printed += fprintf(fp, "%s\n", ltrim(buf));
+ perf_hpp_list__for_each_format(he->hpp_list, fmt) {
+ hpp->buf = buf;
+ hpp->size = size;
+
+ /*
+ * No need to call hist_entry__snprintf_alignment() since this
+ * fmt is always the last column in the hierarchy mode.
+ */
+ if (perf_hpp__use_color() && fmt->color)
+ fmt->color(fmt, hpp, he);
+ else
+ fmt->entry(fmt, hpp, he);
+
+ /*
+ * dynamic entries are right-aligned but we want left-aligned
+ * in the hierarchy mode
+ */
+ printed += fprintf(fp, "%s%s", sep ?: " ", ltrim(buf));
+ }
+ printed += putc('\n', fp);
if (symbol_conf.use_callchain && he->leaf) {
u64 total = hists__total_period(hists);
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index fea92fc..29da9e0 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -1091,18 +1091,25 @@ static void hists__apply_filters(struct hists *hists, struct hist_entry *he);
static struct hist_entry *hierarchy_insert_entry(struct hists *hists,
struct rb_root *root,
struct hist_entry *he,
- struct perf_hpp_fmt *fmt)
+ struct perf_hpp_list *hpp_list)
{
struct rb_node **p = &root->rb_node;
struct rb_node *parent = NULL;
struct hist_entry *iter, *new;
+ struct perf_hpp_fmt *fmt;
int64_t cmp;
while (*p != NULL) {
parent = *p;
iter = rb_entry(parent, struct hist_entry, rb_node_in);
- cmp = fmt->collapse(fmt, iter, he);
+ cmp = 0;
+ perf_hpp_list__for_each_sort_list(hpp_list, fmt) {
+ cmp = fmt->collapse(fmt, iter, he);
+ if (cmp)
+ break;
+ }
+
if (!cmp) {
he_stat__add_stat(&iter->stat, &he->stat);
return iter;
@@ -1121,24 +1128,26 @@ static struct hist_entry *hierarchy_insert_entry(struct hists *hists,
hists__apply_filters(hists, new);
hists->nr_entries++;
- /* save related format for output */
- new->fmt = fmt;
+ /* save related format list for output */
+ new->hpp_list = hpp_list;
/* some fields are now passed to 'new' */
- if (perf_hpp__is_trace_entry(fmt) || perf_hpp__is_dynamic_entry(fmt))
- he->trace_output = NULL;
- else
- new->trace_output = NULL;
+ perf_hpp_list__for_each_sort_list(hpp_list, fmt) {
+ if (perf_hpp__is_trace_entry(fmt) || perf_hpp__is_dynamic_entry(fmt))
+ he->trace_output = NULL;
+ else
+ new->trace_output = NULL;
- if (perf_hpp__is_srcline_entry(fmt))
- he->srcline = NULL;
- else
- new->srcline = NULL;
+ if (perf_hpp__is_srcline_entry(fmt))
+ he->srcline = NULL;
+ else
+ new->srcline = NULL;
- if (perf_hpp__is_srcfile_entry(fmt))
- he->srcfile = NULL;
- else
- new->srcfile = NULL;
+ if (perf_hpp__is_srcfile_entry(fmt))
+ he->srcfile = NULL;
+ else
+ new->srcfile = NULL;
+ }
rb_link_node(&new->rb_node_in, parent, p);
rb_insert_color(&new->rb_node_in, root);
@@ -1149,21 +1158,19 @@ static int hists__hierarchy_insert_entry(struct hists *hists,
struct rb_root *root,
struct hist_entry *he)
{
- struct perf_hpp_fmt *fmt;
+ struct perf_hpp_list_node *node;
struct hist_entry *new_he = NULL;
struct hist_entry *parent = NULL;
int depth = 0;
int ret = 0;
- hists__for_each_sort_list(hists, fmt) {
- if (!perf_hpp__is_sort_entry(fmt) &&
- !perf_hpp__is_dynamic_entry(fmt))
- continue;
- if (perf_hpp__should_skip(fmt, hists))
+ list_for_each_entry(node, &hists->hpp_formats, list) {
+ /* skip period (overhead) and elided columns */
+ if (node->level == 0 || node->skip)
continue;
/* insert copy of 'he' for each fmt into the hierarchy */
- new_he = hierarchy_insert_entry(hists, root, he, fmt);
+ new_he = hierarchy_insert_entry(hists, root, he, &node->hpp);
if (new_he == NULL) {
ret = -1;
break;
@@ -1358,6 +1365,7 @@ static void hierarchy_insert_output_entry(struct rb_root *root,
struct rb_node **p = &root->rb_node;
struct rb_node *parent = NULL;
struct hist_entry *iter;
+ struct perf_hpp_fmt *fmt;
while (*p != NULL) {
parent = *p;
@@ -1373,8 +1381,10 @@ static void hierarchy_insert_output_entry(struct rb_root *root,
rb_insert_color(&he->rb_node, root);
/* update column width of dynamic entry */
- if (perf_hpp__is_dynamic_entry(he->fmt))
- he->fmt->sort(he->fmt, he, NULL);
+ perf_hpp_list__for_each_sort_list(he->hpp_list, fmt) {
+ if (perf_hpp__is_dynamic_entry(fmt))
+ fmt->sort(fmt, he, NULL);
+ }
}
static void hists__hierarchy_output_resort(struct hists *hists,
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 3cab9dc..2209188 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -249,6 +249,7 @@ struct perf_hpp_list_node {
struct list_head list;
struct perf_hpp_list hpp;
int level;
+ bool skip;
};
void perf_hpp_list__column_register(struct perf_hpp_list *list,
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 25a5529..ea1f722 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -130,6 +130,7 @@ struct hist_entry {
u32 raw_size;
void *trace_output;
struct perf_hpp_fmt *fmt;
+ struct perf_hpp_list *hpp_list;
struct hist_entry *parent_he;
union {
/* this is for hierarchical entry structure */
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web