perf/core improvements and fixes
Subsystems (2)
Arnaldo Carvalho de Melo
maintainerHi Ingo,
Please consider pulling,
- Arnaldo
The following changes since commit 009668520ae00d52026ccdb3884864e3473c6b65:
Merge tag 'perf-core-for-mingo-20160303' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core (2016-03-04 12:19:21 +0100)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git tags/perf-core-for-mingo-20160307
for you to fetch changes up to b03ae342d9bec460a6c9c327c3f5f758263b0932:
perf report: Use hierarchy hpp list on gtk (2016-03-07 15:10:41 -0300)
----------------------------------------------------------------
perf/core improvements and fixes:
User visible:
- Allow grouping multiple sort keys per 'perf report/top --hierarchy' level (Namhyung Kim)
- Document 'perf stat --detailed' option (Borislav Petkov)
Infrastructure:
- jitdump prep work for supporting it with Intel PT (Adrian Hunter)
- Use 64-bit shifts with (TSC) time conversion (Adrian Hunter)
Trivial:
- Explicitly declare inc_group_count as a void function (Colin Ian King)
----------------------------------------------------------------
Adrian Hunter (5):
perf inject: Hit all DSOs for AUX data in JIT and other cases perf session: Simplify tool stubs
perf jit: Let jit_process() return errors
perf jit: Move clockid validation
perf tools: Use 64-bit shifts with (TSC) time conversion
Borislav Petkov (1):
perf stat: Document --detailed option
Colin Ian King (1):
perf tools: Explicitly declare inc_group_count as a void function
Namhyung Kim (8):
perf hists: Add level field to struct perf_hpp_fmt perf hists: Introduce perf_hpp__setup_hists_formats() perf hists: Use own hpp_list for hierarchy mode perf hists: Support multiple sort keys in a hierarchy level perf hists: 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/Documentation/perf-stat.txt | 8 ++ tools/perf/arch/x86/tests/rdpmc.c | 2 +- tools/perf/builtin-inject.c | 52 ++++------ 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 | 14 +++ tools/perf/util/jitdump.c | 29 +++++- tools/perf/util/parse-events.y | 2 +- tools/perf/util/session.c | 40 ++------ tools/perf/util/sort.c | 146 ++++++++++++++++++++-------- tools/perf/util/sort.h | 1 + tools/perf/util/tsc.c | 2 +- 15 files changed, 514 insertions(+), 314 deletions(-)
Arnaldo Carvalho de Melo
maintainerPATCH 1/15 perf tools: Explicitly declare inc_group_count as a void function
From: Colin Ian King <[email protected]>
The return type is not defined, so it defaults to int, however, the function is not returning anything, so this is clearly not correct. Make it a void function.
--- tools/perf/util/parse-events.y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/perf/util/parse-events.y +1 -1
@@ -28,7 +28,7 @@ do { \ INIT_LIST_HEAD(list); \ } while (0) -static inc_group_count(struct list_head *list, +static void inc_group_count(struct list_head *list, struct parse_events_evlist *data) { /* Count groups only have more than 1 members */
Signature · 1 line
2.5.0
Arnaldo Carvalho de Melo
maintainerPATCH 2/15 perf inject: Hit all DSOs for AUX data in JIT and other cases
In reply to Arnaldo Carvalho de MeloFrom: Adrian Hunter <[email protected]>
Currently, when injecting build ids, if there is AUX data then 'perf inject' hits all DSOs because it is not known which DSOs the trace data would hit.
That needs to be done for JIT injection also, and in fact there is no reason to distinguish what kind of injection is being done. That is, any time there is AUX data and the HEADER_BUID_ID feature flag is set, and the AUX data is not being processed, then hit all DSOs. This patch does that.
--- tools/perf/builtin-inject.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)
tools/perf/builtin-inject.c +8 -4
@@ -679,12 +679,16 @@ static int __cmd_inject(struct perf_inject *inject) ret =perf_session__process_events (session);if (!file_out->is_pipe) { -if (inject->build_ids) { +if (inject->build_ids)perf_header__set_feat (&session->header,HEADER_BUILD_ID ); -if (inject->have_auxtrace) -dsos__hit_all (session); - } +/* +* Keep all buildids when there is unprocessed AUX data because +* it is not known which ones the AUX trace hits. +*/ +if (perf_header__has_feat (&session->header,HEADER_BUILD_ID ) && + inject->have_auxtrace && !inject->itrace_synth_opts.set) +dsos__hit_all (session);/* * The AUX areas have been removed and replaced with * synthesized hardware events, so clear the feature flag and
Signature · 1 line
2.5.0
Arnaldo Carvalho de Melo
maintainerPATCH 3/15 perf session: Simplify tool stubs
In reply to Arnaldo Carvalho de MeloFrom: Adrian Hunter <[email protected]>
Some of the stubs are identical so just have one function for them.
--- tools/perf/util/session.c | 40 +++++++--------------------------------- 1 file changed, 7 insertions(+), 33 deletions(-)
tools/perf/util/session.c +7 -33
@@ -240,14 +240,6 @@ static int process_event_stub(struct perf_tool *tool __maybe_unused,return 0 ; } -static int process_build_id_stub (struct perf_tool *tool__maybe_unused , -union perf_event *event__maybe_unused , -struct perf_session *session__maybe_unused ) -{ -dump_printf (": unhandled!\n" ); -return 0 ; -} -static int process_finished_round_stub (struct perf_tool *tool__maybe_unused ,union perf_event *event__maybe_unused ,struct ordered_events *oe__maybe_unused )
@@ -260,23 +252,6 @@ static int process_finished_round(struct perf_tool *tool,union perf_event *event, struct ordered_events *oe); -static int process_id_index_stub (struct perf_tool *tool__maybe_unused , -union perf_event *event__maybe_unused , -struct perf_session *perf_session -__maybe_unused ) -{ -dump_printf (": unhandled!\n" ); -return 0 ; -} - -static int process_event_auxtrace_info_stub (struct perf_tool *tool__maybe_unused , -union perf_event *event__maybe_unused , -struct perf_session *session__maybe_unused ) -{ -dump_printf (": unhandled!\n" ); -return 0 ; -} -static int skipn (int fd,off_t n) {char buf[4096 ];
@@ -303,10 +278,9 @@ static s64 process_event_auxtrace_stub(struct perf_tool *tool __maybe_unused,return event->auxtrace.size; } -static -int process_event_auxtrace_error_stub (struct perf_tool *tool__maybe_unused , -union perf_event *event__maybe_unused , -struct perf_session *session__maybe_unused ) +static int process_event_op2_stub (struct perf_tool *tool__maybe_unused , +union perf_event *event__maybe_unused , +struct perf_session *session__maybe_unused ) {dump_printf (": unhandled!\n" );return 0 ;
@@ -410,7 +384,7 @@ void perf_tool__fill_defaults(struct perf_tool *tool)if (tool->tracing_data ==NULL ) tool->tracing_data = process_event_synth_tracing_data_stub;if (tool->build_id ==NULL ) - tool->build_id = process_build_id_stub; + tool->build_id = process_event_op2_stub;if (tool->finished_round ==NULL ) {if (tool->ordered_events) tool->finished_round = process_finished_round;
@@ -418,13 +392,13 @@ void perf_tool__fill_defaults(struct perf_tool *tool) tool->finished_round = process_finished_round_stub; }if (tool->id_index ==NULL ) - tool->id_index = process_id_index_stub; + tool->id_index = process_event_op2_stub;if (tool->auxtrace_info ==NULL ) - tool->auxtrace_info = process_event_auxtrace_info_stub; + tool->auxtrace_info = process_event_op2_stub;if (tool->auxtrace ==NULL ) tool->auxtrace = process_event_auxtrace_stub;if (tool->auxtrace_error ==NULL ) - tool->auxtrace_error = process_event_auxtrace_error_stub; + tool->auxtrace_error = process_event_op2_stub;if (tool->thread_map ==NULL ) tool->thread_map = process_event_thread_map_stub;if (tool->cpu_map ==NULL )
Signature · 1 line
2.5.0
Adrian Hunter
reviewerRe: [PATCH 03/15] perf session: Simplify tool stubs
Quoted 1 line · Arnaldo Carvalho de Melo
From: Adrian Hunter <[email protected]>
Very sorry, but I just noticed that this and patch 5 (perf jit: Move clockid validation) have the wrong email address for the "From" and "Signed-off-by".
It should be [email protected]. Please consider changing it or
dropping these patches for now.
Quoted 8 lines
Some of the stubs are identical so just have one function for them.
Signed-off-by Adrian Hunter <[email protected]>Cc Jiri Olsa <[email protected]>Cc Stephane Eranian <[email protected]>Signed-off-by Arnaldo Carvalho de Melo <[email protected]>
Re: [PATCH 03/15] perf session: Simplify tool stubs
Quoted 7 lines · Adrian Hunter
Quoted 1 line · Arnaldo Carvalho de Melo
From: Adrian Hunter <[email protected]>
Very sorry, but I just noticed that this and patch 5 (perf jit: Move clockid validation) have the wrong email address for the "From" and "Signed-off-by".
It should be [email protected]. Please consider changing it or
dropping these patches for now.
Ok, I've changed these two patches and have applied the whole series from email. (we are getting close to the merge window)
Thanks,
Ingo
Arnaldo Carvalho de Melo
maintainerPATCH 4/15 perf jit: Let jit_process() return errors
In reply to Arnaldo Carvalho de MeloFrom: Adrian Hunter <[email protected]>
In preparation for moving clockid validation into jit_process().
Previously a return value of zero meant the processing had been done and non-zero meant either the processing was not done (i.e. not the jitdump file mmap event) or an error occurred.
Change it so that zero means the processing was not done, one means the processing was done and successful, and negative values are an error.
--- tools/perf/builtin-inject.c | 16 ++++++++++++---- tools/perf/util/jitdump.c | 6 ++++-- 2 files changed, 16 insertions(+), 6 deletions(-)
tools/perf/builtin-inject.c +12 -4
@@ -253,12 +253,16 @@ static int perf_event__jit_repipe_mmap(struct perf_tool *tool, { struct perf_inject *inject = container_of(tool, struct perf_inject, tool);u64 n =0 ; +int ret;/* * if jit marker, then inject jit mmaps and generate ELF images */ -if (!jit_process (inject->session, &inject->output, machine, - event->mmap.filename, sample->pid, &n)) { + ret =jit_process (inject->session, &inject->output, machine, + event->mmap.filename, sample->pid, &n); +if (ret <0 ) +return ret; +if (ret) { inject->bytes_written += n;return 0 ; }
@@ -287,12 +291,16 @@ static int perf_event__jit_repipe_mmap2(struct perf_tool *tool, { struct perf_inject *inject = container_of(tool, struct perf_inject, tool);u64 n =0 ; +int ret;/* * if jit marker, then inject jit mmaps and generate ELF images */ -if (!jit_process (inject->session, &inject->output, machine, - event->mmap2.filename, sample->pid, &n)) { + ret =jit_process (inject->session, &inject->output, machine, + event->mmap2.filename, sample->pid, &n); +if (ret <0 ) +return ret; +if (ret) { inject->bytes_written += n;return 0 ; }
tools/perf/util/jitdump.c +4 -2
@@ -647,7 +647,7 @@ jit_process(struct perf_session *session,* first, detect marker mmap (i.e., the jitdump mmap) */ if (jit_detect (filename, pid)) -return -1 ; +return 0 ;memset (&jd,0 ,sizeof (jd));
@@ -665,8 +665,10 @@ jit_process(struct perf_session *session, *nbytes =0 ; ret =jit_inject (&jd, filename); -if (!ret) +if (!ret) { *nbytes = jd.bytes_written; + ret =1 ; + }return ret; }
Signature · 1 line
2.5.0
Arnaldo Carvalho de Melo
maintainerPATCH 5/15 perf jit: Move clockid validation
In reply to Arnaldo Carvalho de MeloFrom: Adrian Hunter <[email protected]>
Move clockid validation into jit_process() so it can later be made conditional.
--- tools/perf/builtin-inject.c | 24 ------------------------ tools/perf/util/jitdump.c | 23 +++++++++++++++++++++++ 2 files changed, 23 insertions(+), 24 deletions(-)
tools/perf/builtin-inject.c +0 -24
@@ -729,23 +729,6 @@ static int __cmd_inject(struct perf_inject *inject)return ret; } -#ifdef HAVE_LIBELF_SUPPORT -static int -jit_validate_events (struct perf_session *session) -{ -struct perf_evsel *evsel; - -/* -* check that all events use CLOCK_MONOTONIC -*/ -evlist__for_each (session->evlist, evsel) { -if (evsel->attr.use_clockid ==0 || evsel->attr.clockid !=CLOCK_MONOTONIC ) -return -1 ; - } -return 0 ; -} -#endif -int cmd_inject (int argc,const char **argv,const char *prefix__maybe_unused ) {struct perf_inject inject = {
@@ -852,13 +835,6 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) }#ifdef HAVE_LIBELF_SUPPORT if (inject.jit_mode) { -/* -* validate event is using the correct clockid -*/ -if (jit_validate_events (inject.session)) { -fprintf (stderr,"error, jitted code must be sampled with perf record -k 1\n" ); -return -1 ; - } inject.tool.mmap2 = perf_event__jit_repipe_mmap2; inject.tool.mmap = perf_event__jit_repipe_mmap; inject.tool.ordered_events = true;
tools/perf/util/jitdump.c +23 -0
@@ -99,6 +99,21 @@ jit_close(struct jit_buf_desc *jd) }static int +jit_validate_events (struct perf_session *session) +{ +struct perf_evsel *evsel; + +/* +* check that all events use CLOCK_MONOTONIC +*/ +evlist__for_each (session->evlist, evsel) { +if (evsel->attr.use_clockid ==0 || evsel->attr.clockid !=CLOCK_MONOTONIC ) +return -1 ; + } +return 0 ; +} + +static int jit_open (struct jit_buf_desc *jd,const char *name) {struct jitheader header;
@@ -157,6 +172,14 @@ jit_open(struct jit_buf_desc *jd, const char *name) goto error; } +/* +* validate event is using the correct clockid +*/ +if (jit_validate_events (jd->session)) { +pr_err ("error, jitted code must be sampled with perf record -k 1\n" ); + goto error; + } + bs = header.total_size -sizeof (header);if (bs > bsz) {
Signature · 1 line
2.5.0
Arnaldo Carvalho de Melo
maintainerPATCH 6/15 perf tools: Use 64-bit shifts with (TSC) time conversion
In reply to Arnaldo Carvalho de MeloFrom: Adrian Hunter <[email protected]>
Commit b9511cd761fa ("perf/x86: Fix time_shift in perf_event_mmap_page") altered the time conversion algorithms documented in the perf_event.h header file, to use 64-bit shifts. That was done to make the code more future-proof (i.e. some time in the future a 32-bit shift could be allowed). Reflect those changes in perf tools.
--- tools/perf/arch/x86/tests/rdpmc.c | 2 +- tools/perf/util/tsc.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
tools/perf/arch/x86/tests/rdpmc.c +1 -1
@@ -59,7 +59,7 @@ static u64 mmap_read_self(void *addr)u64 quot, rem; quot = (cyc >> time_shift); - rem = cyc & ((1 << time_shift) -1 ); + rem = cyc & (((u64 )1 << time_shift) -1 ); delta = time_offset + quot * time_mult + ((rem * time_mult) >> time_shift);
tools/perf/util/tsc.c +1 -1
@@ -19,7 +19,7 @@ u64 tsc_to_perf_time(u64 cyc, struct perf_tsc_conversion *tc)u64 quot, rem; quot = cyc >> tc->time_shift; - rem = cyc & ((1 << tc->time_shift) -1 ); + rem = cyc & (((u64 )1 << tc->time_shift) -1 );return tc->time_zero + quot * tc->time_mult + ((rem * tc->time_mult) >> tc->time_shift); }
Signature · 1 line
2.5.0
Arnaldo Carvalho de Melo
maintainerPATCH 7/15 perf hists: Add level field to struct perf_hpp_fmt
In reply to Arnaldo Carvalho de MeloFrom: Namhyung Kim <[email protected]>
The level field is to distinguish levels in the hierarchy mode. Currently each column (perf_hpp_fmt) has a different level.
--- tools/perf/util/hist.h | 1 + tools/perf/util/sort.c | 74 ++++++++++++++++++++++++++++---------------------- 2 files changed, 42 insertions(+), 33 deletions(-)
tools/perf/util/hist.h +1 -0
@@ -233,6 +233,7 @@ struct perf_hpp_fmt {int len;int user_len;int idx; +int level; };struct perf_hpp_list {
tools/perf/util/sort.c +41 -33
272 lines not on this page · raw message
Signature · 1 line
2.5.0
Arnaldo Carvalho de Melo
maintainerPATCH 8/15 perf stat: Document --detailed option
In reply to Arnaldo Carvalho de MeloFrom: Borislav Petkov <[email protected]>
I'm surprised this remained undocumented since at least 2011. And it is actually a very useful switch, as Steve and I came to realize recently.
Add the text from
2cba3ffb9a9d ("perf stat: Add -d -d and -d -d -d options to show more CPU events")
which added the incrementing aspect to -d.
--- tools/perf/Documentation/perf-stat.txt | 8 ++++++++ 1 file changed, 8 insertions(+)
tools/perf/Documentation/perf-stat.txt +8 -0
@@ -69,6 +69,14 @@ report:: --scale:: scale/normalize counter values +-d:: +--detailed:: + print more detailed statistics, can be specified up to 3 times + + -d: detailed events, L1 and LLC data cache + -d -d: more detailed events, dTLB and iTLB events + -d -d -d: very detailed events, adding prefetch events + -r:: --repeat=<n>:: repeat command and print average + stddev (max: 100). 0 means forever.
Signature · 1 line
2.5.0
Re: [PATCH 08/15] perf stat: Document --detailed option
Quoted 10 lines · Arnaldo Carvalho de Melo
From: Borislav Petkov <[email protected]>
I'm surprised this remained undocumented since at least 2011. And it is actually a very useful switch, as Steve and I came to realize recently.
Add the text from
2cba3ffb9a9d("perf stat: Add -d -d and -d -d -d options to show more CPU events")which added the incrementing aspect to -d.
Ah yes, my fault ...
Quoted 19 lines
Signed-off-by Borislav Petkov <[email protected]>Cc Davidlohr Bueso <[email protected]>Cc Jiri Olsa <[email protected]>Cc Mel Gorman <[email protected]>Cc Peter Zijlstra <[email protected]>Cc Steven Rostedt <[email protected]>Fixes 2cba3ffb9a9d ("perf stat: Add -d -d and -d -d -d options to show more CPU events")Signed-off-by Arnaldo Carvalho de Melo <[email protected]>--- tools/perf/Documentation/perf-stat.txt | 8 ++++++++ 1 file changed, 8 insertions(+)tools/perf/Documentation/perf-stat.txt +0
-0
tools/perf/Documentation/perf-stat.txt report:: · line 78
Quoted 10 lines
tools/perf/Documentation/perf-stat.txt +7
-0@@ -69,6 +69,14 @@ report:: --scale:: scale/normalize counter values +-d:: +--detailed:: + print more detailed statistics, can be specified up to 3 times + + -d: detailed events, L1 and LLC data cache + -d -d: more detailed events, dTLB and iTLB events + -d -d -d: very detailed events, adding prefetch events
Btw., something I noticed: it would be really nice if 'perf stat -h -d' printed the most detailed documentation available for the option. Right now it prints:
triton:~/tip/tools/perf> perf stat -h -d
Usage: perf stat [<options>] [<command>]
-d, --detailed detailed run - start a lot of events
The only way to get to the most detailed documentation is the not very obvious path of:
perf help stat
and then searching for '-d'.
Ideally there should only be a single place to document options - but I guess unifying the in-code option descriptions and more verbose description in the man pages is very non-trivial ...
Thanks,
Ingo
Arnaldo Carvalho de Melo
maintainerPATCH 9/15 perf hists: Introduce perf_hpp__setup_hists_formats()
In reply to Arnaldo Carvalho de MeloFrom: Namhyung Kim <[email protected]>
The perf_hpp__setup_hists_formats() is to build hists-specific output formats (and sort keys). Currently it's only used in order to build the output format in a hierarchy with same sort keys, but it could be used with different sort keys in non-hierarchy mode later.
--- tools/perf/ui/hist.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/hist.c | 12 ++++++++++ tools/perf/util/hist.h | 11 +++++++++ tools/perf/util/sort.c | 32 +++++++++++++++++++++++++ 4 files changed, 118 insertions(+)
tools/perf/ui/hist.c +63 -0
@@ -5,6 +5,7 @@#include "../util/util.h" #include "../util/sort.h" #include "../util/evsel.h" +#include "../util/evlist.h" /* hist period print (hpp) functions */
@@ -715,3 +716,65 @@ void perf_hpp__set_user_width(const char *width_list_str)break ; } } + +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; + +list_for_each_entry (node, &hists->hpp_formats, list) { +if (node->level == fmt->level) { + found = true; +break ; + } + } + +if (!found) { + node =malloc (sizeof (*node)); +if (node ==NULL ) +return -1 ; + + node->level = fmt->level; +perf_hpp_list__init (&node->hpp); + +list_add_tail (&node->list, &hists->hpp_formats); + } + + fmt_copy =perf_hpp_fmt__dup (fmt); +if (fmt_copy ==NULL ) +return -1 ; + +list_add_tail (&fmt_copy->list, &node->hpp.fields); +list_add_tail (&fmt_copy->sort_list, &node->hpp.sorts); + +return 0 ; +} + +int perf_hpp__setup_hists_formats (struct perf_hpp_list *list, +struct perf_evlist *evlist) +{ +struct perf_evsel *evsel; +struct perf_hpp_fmt *fmt; +struct hists *hists; +int ret; + +if (!symbol_conf.report_hierarchy) +return 0 ; + +evlist__for_each (evlist, evsel) { + hists =evsel__hists (evsel); + +perf_hpp_list__for_each_sort_list (list, fmt) { +if (perf_hpp__is_dynamic_entry (fmt) && + !perf_hpp__defined_dynamic_entry (fmt, hists)) +continue ; + + ret =add_hierarchy_fmt (hists, fmt); +if (ret <0 ) +return ret; + } + } + +return 0 ; +}
tools/perf/util/hist.c +12 -0
@@ -2105,6 +2105,7 @@ int __hists__init(struct hists *hists, struct perf_hpp_list *hpp_list)pthread_mutex_init (&hists->lock,NULL ); hists->socket_filter =-1 ; hists->hpp_list = hpp_list; +INIT_LIST_HEAD (&hists->hpp_formats);return 0 ; }
@@ -2133,8 +2134,19 @@ static void hists__delete_all_entries(struct hists *hists)static void hists_evsel__exit (struct perf_evsel *evsel) {struct hists *hists =evsel__hists (evsel); +struct perf_hpp_fmt *fmt, *pos; +struct perf_hpp_list_node *node, *tmp;hists__delete_all_entries (hists); + +list_for_each_entry_safe (node, tmp, &hists->hpp_formats, list) { +perf_hpp_list__for_each_format_safe (&node->hpp, fmt, pos) { +list_del (&fmt->list); +free (fmt); + } +list_del (&node->list); +free (node); + } }static int hists_evsel__init (struct perf_evsel *evsel)
tools/perf/util/hist.h +11 -0
@@ -78,6 +78,7 @@ struct hists {u16 col_len[HISTC_NR_COLS ];int socket_filter;struct perf_hpp_list *hpp_list; +struct list_head hpp_formats;int nr_sort_keys; };
@@ -244,6 +245,12 @@ struct perf_hpp_list {extern struct perf_hpp_list perf_hpp_list; +struct perf_hpp_list_node { +struct list_head list; +struct perf_hpp_list hpp; +int level; +}; +void perf_hpp_list__column_register (struct perf_hpp_list *list,struct perf_hpp_fmt *format); void perf_hpp_list__register_sort_field(struct perf_hpp_list *list,
@@ -299,6 +306,8 @@ void perf_hpp__cancel_cumulate(void);void perf_hpp__setup_output_field (struct perf_hpp_list *list);void perf_hpp__reset_output_field (struct perf_hpp_list *list);void perf_hpp__append_sort_keys (struct perf_hpp_list *list); +int perf_hpp__setup_hists_formats (struct perf_hpp_list *list, +struct perf_evlist *evlist);bool perf_hpp__is_sort_entry (struct perf_hpp_fmt *format);
@@ -308,6 +317,8 @@ bool perf_hpp__is_trace_entry(struct perf_hpp_fmt *fmt);bool perf_hpp__is_srcline_entry (struct perf_hpp_fmt *fmt);bool perf_hpp__is_srcfile_entry (struct perf_hpp_fmt *fmt); +struct perf_hpp_fmt *perf_hpp_fmt__dup (struct perf_hpp_fmt *fmt); +int hist_entry__filter (struct hist_entry *he,int type,const void *arg); static inline bool perf_hpp__should_skip(struct perf_hpp_fmt *format,
tools/perf/util/sort.c +32 -0
@@ -1908,6 +1908,34 @@ __alloc_dynamic_entry(struct perf_evsel *evsel, struct format_field *field,return hde; } +struct perf_hpp_fmt *perf_hpp_fmt__dup (struct perf_hpp_fmt *fmt) +{ +struct perf_hpp_fmt *new_fmt =NULL ; + +if (perf_hpp__is_sort_entry (fmt)) { +struct hpp_sort_entry *hse, *new_hse; + + hse = container_of(fmt, struct hpp_sort_entry, hpp); + new_hse =memdup (hse,sizeof (*hse)); +if (new_hse) + new_fmt = &new_hse->hpp; + }else if (perf_hpp__is_dynamic_entry (fmt)) { +struct hpp_dynamic_entry *hde, *new_hde; + + hde = container_of(fmt, struct hpp_dynamic_entry, hpp); + new_hde =memdup (hde,sizeof (*hde)); +if (new_hde) + new_fmt = &new_hde->hpp; + }else { + new_fmt =memdup (fmt,sizeof (*fmt)); + } + +INIT_LIST_HEAD (&new_fmt->list); +INIT_LIST_HEAD (&new_fmt->sort_list); + +return new_fmt; +} +static int parse_field_name (char *str,char **event,char **field,char **opt) {char *event_name, *field_name, *opt_name;
@@ -2700,6 +2728,10 @@ int setup_sorting(struct perf_evlist *evlist)/* and then copy output fields to sort keys */ perf_hpp__append_sort_keys (&perf_hpp_list); +/* setup hists-specific output fields */ +if (perf_hpp__setup_hists_formats (&perf_hpp_list, evlist) <0 ) +return -1 ; +return 0 ; }
Signature · 1 line
2.5.0
Arnaldo Carvalho de Melo
maintainerPATCH 10/15 perf hists: Use own hpp_list for hierarchy mode
In reply to Arnaldo Carvalho de MeloFrom: Namhyung Kim <[email protected]>
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.
--- 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(-)
tools/perf/ui/browsers/hists.c +25 -20
@@ -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));
tools/perf/ui/gtk/hists.c +14 -6
@@ -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,
tools/perf/ui/hist.c +5 -0
@@ -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);
tools/perf/ui/stdio/hist.c +22 -22
55 lines not on this page · raw message
tools/perf/util/hist.c +35 -25
112 lines not on this page · raw message
tools/perf/util/hist.h +1 -0
@@ -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,
tools/perf/util/sort.h +1 -0
@@ -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 */
Signature · 1 line
2.5.0
Arnaldo Carvalho de Melo
maintainerPATCH 11/15 perf hists: Support multiple sort keys in a hierarchy level
In reply to Arnaldo Carvalho de MeloFrom: Namhyung Kim <[email protected]>
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_unalignedIn 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 <[email protected]>
--- tools/perf/util/sort.c | 42 ++++++++++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 10 deletions(-)
tools/perf/util/sort.c +32 -10
@@ -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; }
Signature · 1 line
2.5.0
Arnaldo Carvalho de Melo
maintainerPATCH 12/15 perf hists: Fix indent for multiple hierarchy sort key
In reply to Arnaldo Carvalho de MeloFrom: Namhyung Kim <[email protected]>
When multiple sort keys are used in a single hierarchy, it should indent using number of hierarchy levels instead of number of sort keys.
--- tools/perf/ui/browsers/hists.c | 23 ++++++++++------------- tools/perf/ui/hist.c | 1 + tools/perf/ui/stdio/hist.c | 26 +++++++++++--------------- tools/perf/util/hist.h | 1 + 4 files changed, 23 insertions(+), 28 deletions(-)
tools/perf/ui/browsers/hists.c +10 -13
@@ -1280,7 +1280,7 @@ static int hist_browser__show_entry(struct hist_browser *browser,static int hist_browser__show_hierarchy_entry (struct hist_browser *browser,struct hist_entry *entry,unsigned short row, -int level,int nr_sort_keys) +int level) {int printed =0 ;int width = browser->b.width;
@@ -1294,7 +1294,7 @@ static int hist_browser__show_hierarchy_entry(struct hist_browser *browser, .current_entry = current_entry, };int column =0 ; -int hierarchy_indent = (nr_sort_keys -1 ) *HIERARCHY_INDENT ; +int hierarchy_indent = (entry->hists->nr_hpp_node -2 ) *HIERARCHY_INDENT ;if (current_entry) { browser->he_selection = entry;
@@ -1436,8 +1436,7 @@ show_callchain: }static int hist_browser__show_no_entry (struct hist_browser *browser, -unsigned short row, -int level,int nr_sort_keys) +unsigned short row,int level) {int width = browser->b.width;bool current_entry =ui_browser__is_current_entry (&browser->b, row);
@@ -1445,6 +1444,7 @@ static int hist_browser__show_no_entry(struct hist_browser *browser,int column =0 ;int ret;struct perf_hpp_fmt *fmt; +int indent = browser->hists->nr_hpp_node -2 ;if (current_entry) { browser->he_selection =NULL ;
@@ -1485,8 +1485,8 @@ static int hist_browser__show_no_entry(struct hist_browser *browser, width -= ret; } -ui_browser__write_nstring (&browser->b,"" , nr_sort_keys *HIERARCHY_INDENT ); - width -= nr_sort_keys *HIERARCHY_INDENT ; +ui_browser__write_nstring (&browser->b,"" , indent *HIERARCHY_INDENT ); + width -= indent *HIERARCHY_INDENT ;if (column >= browser->b.horiz_scroll) {char buf[32 ];
@@ -1553,7 +1553,7 @@ static int hists_browser__scnprintf_hierarchy_headers(struct hist_browser *browsstruct perf_hpp_fmt *fmt;size_t ret =0 ;int column =0 ; -int nr_sort_keys = hists->nr_sort_keys; +int indent = hists->nr_hpp_node -2 ;bool first = true; ret =scnprintf (buf, size," " );
@@ -1577,7 +1577,7 @@ static int hists_browser__scnprintf_hierarchy_headers(struct hist_browser *brows } ret =scnprintf (dummy_hpp.buf, dummy_hpp.size,"%*s" , - (nr_sort_keys -1 ) *HIERARCHY_INDENT ,"" ); + indent *HIERARCHY_INDENT ,"" );if (advance_hpp_check (&dummy_hpp, ret))return ret;
@@ -1645,7 +1645,6 @@ static unsigned int hist_browser__refresh(struct ui_browser *browser)u16 header_offset =0 ;struct rb_node *nd; struct hist_browser *hb = container_of(browser, struct hist_browser, b); -int nr_sort = hb->hists->nr_sort_keys;if (hb->show_headers) {hist_browser__show_headers (hb);
@@ -1672,14 +1671,12 @@ static unsigned int hist_browser__refresh(struct ui_browser *browser)if (symbol_conf.report_hierarchy) { row +=hist_browser__show_hierarchy_entry (hb, h, row, - h->depth, - nr_sort); + h->depth);if (row == browser->rows)break ;if (h->has_no_entry) { -hist_browser__show_no_entry (hb, row, h->depth, - nr_sort); +hist_browser__show_no_entry (hb, row, h->depth); row++; } }else {
tools/perf/ui/hist.c +1 -0
@@ -740,6 +740,7 @@ static int add_hierarchy_fmt(struct hists *hists, struct perf_hpp_fmt *fmt) node->level = fmt->level;perf_hpp_list__init (&node->hpp); + hists->nr_hpp_node++;list_add_tail (&node->list, &hists->hpp_formats); }
tools/perf/ui/stdio/hist.c +11 -15
@@ -412,7 +412,7 @@ static int hist_entry__snprintf(struct hist_entry *he, struct perf_hpp *hpp)static int hist_entry__hierarchy_fprintf (struct hist_entry *he,struct perf_hpp *hpp, -int nr_sort_key,struct hists *hists, +struct hists *hists,FILE *fp) {const char *sep = symbol_conf.field_sep;
@@ -453,7 +453,7 @@ static int hist_entry__hierarchy_fprintf(struct hist_entry *he,if (!sep) ret =scnprintf (hpp->buf, hpp->size,"%*s" , - (nr_sort_key -1 ) *HIERARCHY_INDENT ,"" ); + (hists->nr_hpp_node -2 ) *HIERARCHY_INDENT ,"" );advance_hpp (hpp, ret); printed +=fprintf (fp,"%s" , buf);
@@ -504,12 +504,8 @@ static int hist_entry__fprintf(struct hist_entry *he, size_t size,if (size ==0 || size > bfsz) size = hpp.size = bfsz; -if (symbol_conf.report_hierarchy) { -int nr_sort = hists->nr_sort_keys; - -return hist_entry__hierarchy_fprintf (he, &hpp, nr_sort, - hists, fp); - } +if (symbol_conf.report_hierarchy) +return hist_entry__hierarchy_fprintf (he, &hpp, hists, fp);hist_entry__snprintf (he, &hpp);
@@ -521,29 +517,29 @@ static int hist_entry__fprintf(struct hist_entry *he, size_t size,return ret; } -static int print_hierarchy_indent (const char *sep,int nr_sort, +static int print_hierarchy_indent (const char *sep,int indent,const char *line,FILE *fp) { -if (sep !=NULL || nr_sort <1 ) +if (sep !=NULL || indent <2 )return 0 ; -return fprintf (fp,"%-.*s" , (nr_sort -1 ) *HIERARCHY_INDENT , line); +return fprintf (fp,"%-.*s" , (indent -2 ) *HIERARCHY_INDENT , line); }static int print_hierarchy_header (struct hists *hists,struct perf_hpp *hpp,const char *sep,FILE *fp) {bool first = true; -int nr_sort; +int indent;int depth;unsigned width =0 ;unsigned header_width =0 ;struct perf_hpp_fmt *fmt; - nr_sort = hists->nr_sort_keys; + indent = hists->nr_hpp_node;/* preserve max indent depth for column headers */ -print_hierarchy_indent (sep, nr_sort, spaces, fp); +print_hierarchy_indent (sep, indent, spaces, fp);hists__for_each_format (hists, fmt) {if (perf_hpp__is_sort_entry (fmt) ||perf_hpp__is_dynamic_entry (fmt))
@@ -582,7 +578,7 @@ static int print_hierarchy_header(struct hists *hists, struct perf_hpp *hpp,fprintf (fp,"\n# " );/* preserve max indent depth for initial dots */ -print_hierarchy_indent (sep, nr_sort, dots, fp); +print_hierarchy_indent (sep, indent, dots, fp); first = true;hists__for_each_format (hists, fmt) {
tools/perf/util/hist.h +1 -0
@@ -80,6 +80,7 @@ struct hists {struct perf_hpp_list *hpp_list;struct list_head hpp_formats;int nr_sort_keys; +int nr_hpp_node; };struct hist_entry_iter ;
Signature · 1 line
2.5.0
Arnaldo Carvalho de Melo
maintainerPATCH 13/15 perf report: Use hierarchy hpp list on stdio
In reply to Arnaldo Carvalho de MeloFrom: Namhyung Kim <[email protected]>
Now hpp formats are linked using perf_hpp_list_node when hierarchy is enabled. Use this info to print entries with multiple sort keys in a single hierarchy properly.
For example, the below example shows using 4 sort keys with 2 levels.
$ 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--- tools/perf/ui/stdio/hist.c | 103 +++++++++++++++++++++++++-------------------- 1 file changed, 57 insertions(+), 46 deletions(-)
tools/perf/ui/stdio/hist.c +57 -46
@@ -417,6 +417,7 @@ static int hist_entry__hierarchy_fprintf(struct hist_entry *he, {const char *sep = symbol_conf.field_sep;struct perf_hpp_fmt *fmt; +struct perf_hpp_list_node *fmt_node;char *buf = hpp->buf;size_t size = hpp->size;int ret, printed =0 ;
@@ -428,10 +429,10 @@ static int hist_entry__hierarchy_fprintf(struct hist_entry *he, ret =scnprintf (hpp->buf, hpp->size,"%*s" , he->depth *HIERARCHY_INDENT ,"" );advance_hpp (hpp, ret); -hists__for_each_format (he->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 there's no field_sep, we still need * to display initial ' '.
@@ -529,50 +530,49 @@ static int print_hierarchy_indent(const char *sep, int indent,static int print_hierarchy_header (struct hists *hists,struct perf_hpp *hpp,const char *sep,FILE *fp) { -bool first = true; +bool first_node, first_col;int indent;int depth;unsigned width =0 ;unsigned header_width =0 ;struct perf_hpp_fmt *fmt; +struct perf_hpp_list_node *fmt_node; indent = hists->nr_hpp_node;/* preserve max indent depth for column headers */ print_hierarchy_indent (sep, indent, spaces, fp); -hists__for_each_format (hists, fmt) { -if (perf_hpp__is_sort_entry (fmt) ||perf_hpp__is_dynamic_entry (fmt)) -break ; - -if (!first) -fprintf (fp,"%s" , sep ?:" " ); -else - first = false; +/* 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) { fmt->header (fmt, hpp,hists_to_evsel (hists)); -fprintf (fp,"%s" , hpp->buf); +fprintf (fp,"%s%s" , hpp->buf, sep ?:" " ); }/* combine sort headers with ' / ' */ - first = true; -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_node = true; +list_for_each_entry_continue (fmt_node, &hists->hpp_formats, list) { +if (!first_node) header_width +=fprintf (fp," / " ); -else { -fprintf (fp,"%s" , sep ?:" " ); - first = false; - } + first_node = false; - fmt->header (fmt, hpp,hists_to_evsel (hists)); -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) + header_width +=fprintf (fp,"+" ); + first_col = false; + + fmt->header (fmt, hpp,hists_to_evsel (hists)); +rtrim (hpp->buf); - header_width +=fprintf (fp,"%s" ,ltrim (hpp->buf)); + header_width +=fprintf (fp,"%s" ,ltrim (hpp->buf)); + } }fprintf (fp,"\n# " );
@@ -580,29 +580,35 @@ static int print_hierarchy_header(struct hists *hists, struct perf_hpp *hpp,/* preserve max indent depth for initial dots */ print_hierarchy_indent (sep, indent, dots, fp); - first = true; -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); -if (!first) -fprintf (fp,"%s" , sep ?:" " ); -else - first = false; + first_col = true; +perf_hpp_list__for_each_format (&fmt_node->hpp, fmt) { +if (!first_col) +fprintf (fp,"%s" , sep ?:".." ); + first_col = false; width = fmt->width (fmt, hpp,hists_to_evsel (hists));fprintf (fp,"%.*s" , width, dots); } depth =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 ; +list_for_each_entry_continue (fmt_node, &hists->hpp_formats, list) { + first_col = true; + width = depth *HIERARCHY_INDENT ; - width = fmt->width (fmt, hpp,hists_to_evsel (hists)); - width += depth *HIERARCHY_INDENT ; +perf_hpp_list__for_each_format (&fmt_node->hpp, fmt) { +if (perf_hpp__should_skip (fmt, hists)) +continue ; + +if (!first_col) + width++;/* for '+' sign between column header */ + first_col = false; + + width += fmt->width (fmt, hpp,hists_to_evsel (hists)); + }if (width > header_width) header_width = width;
@@ -621,6 +627,7 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, int max_cols, float min_pcnt, FILE *fp) { struct perf_hpp_fmt *fmt; +struct perf_hpp_list_node *fmt_node;struct rb_node *nd;size_t ret =0 ;unsigned int width;
@@ -650,6 +657,10 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,fprintf (fp,"# " );if (symbol_conf.report_hierarchy) { +list_for_each_entry (fmt_node, &hists->hpp_formats, list) { +perf_hpp_list__for_each_format (&fmt_node->hpp, fmt) +perf_hpp__reset_width (fmt, hists); + } nr_rows +=print_hierarchy_header (hists, &dummy_hpp, sep, fp); goto print_entries; }
@@ -734,9 +745,9 @@ print_entries:* display "no entry >= x.xx%" message. */ if (!h->leaf && !hist_entry__has_hierarchy_children (h, min_pcnt)) { -int nr_sort = hists->nr_sort_keys; +int depth = hists->nr_hpp_node + h->depth +1 ; -print_hierarchy_indent (sep, nr_sort + h->depth +1 , spaces, fp); +print_hierarchy_indent (sep, depth, spaces, fp);fprintf (fp,"%*sno entry >= %.2f%%\n" , indent,"" , min_pcnt);if (max_rows && ++nr_rows >= max_rows)
Signature · 1 line
2.5.0
Arnaldo Carvalho de Melo
maintainerPATCH 14/15 perf hists browser: Use hierarchy hpp list
In reply to Arnaldo Carvalho de MeloFrom: Namhyung Kim <[email protected]>
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.
--- tools/perf/ui/browsers/hists.c | 81 +++++++++++++++++++++++------------------- 1 file changed, 45 insertions(+), 36 deletions(-)
tools/perf/ui/browsers/hists.c +45 -36
@@ -1289,6 +1289,7 @@ static int hist_browser__show_hierarchy_entry(struct hist_browser *browser,off_t row_offset = entry->row_offset;bool first = true;struct perf_hpp_fmt *fmt; +struct perf_hpp_list_node *fmt_node;struct hpp_arg arg = { .b = &browser->b, .current_entry = current_entry,
@@ -1320,7 +1321,10 @@ static int hist_browser__show_hierarchy_entry(struct hist_browser *browser,ui_browser__write_nstring (&browser->b,"" , level *HIERARCHY_INDENT ); width -= level *HIERARCHY_INDENT ; -hists__for_each_format (entry->hists, fmt) { +/* the first hpp_list_node is for overhead columns */ + fmt_node =list_first_entry (&entry->hists->hpp_formats, + struct perf_hpp_list_node, list); +perf_hpp_list__for_each_format (&fmt_node->hpp, fmt) {char s[2048 ];struct perf_hpp hpp = { .buf = s,
@@ -1332,10 +1336,6 @@ static int hist_browser__show_hierarchy_entry(struct hist_browser *browser, column++ < browser->b.horiz_scroll)continue ; -if (perf_hpp__is_sort_entry (fmt) || -perf_hpp__is_dynamic_entry (fmt)) -break ; -if (current_entry && browser->b.navkeypressed) {ui_browser__set_color (&browser->b,HE_COLORSET_SELECTED );
@@ -1444,6 +1444,7 @@ static int hist_browser__show_no_entry(struct hist_browser *browser,int column =0 ;int ret;struct perf_hpp_fmt *fmt; +struct perf_hpp_list_node *fmt_node;int indent = browser->hists->nr_hpp_node -2 ;if (current_entry) {
@@ -1461,15 +1462,14 @@ static int hist_browser__show_no_entry(struct hist_browser *browser,ui_browser__write_nstring (&browser->b,"" , level *HIERARCHY_INDENT ); width -= level *HIERARCHY_INDENT ; -hists__for_each_format (browser->hists, fmt) { +/* the first hpp_list_node is for overhead columns */ + fmt_node =list_first_entry (&browser->hists->hpp_formats, + struct perf_hpp_list_node, list); +perf_hpp_list__for_each_format (&fmt_node->hpp, fmt) {if (perf_hpp__should_skip (fmt, browser->hists) || column++ < browser->b.horiz_scroll)continue ; -if (perf_hpp__is_sort_entry (fmt) || -perf_hpp__is_dynamic_entry (fmt)) -break ; - ret = fmt->width (fmt,NULL ,hists_to_evsel (browser->hists));if (first) {
@@ -1551,22 +1551,23 @@ static int hists_browser__scnprintf_hierarchy_headers(struct hist_browser *brows .size = size, };struct perf_hpp_fmt *fmt; +struct perf_hpp_list_node *fmt_node;size_t ret =0 ;int column =0 ;int indent = hists->nr_hpp_node -2 ; -bool first = true; +bool first_node, first_col; ret =scnprintf (buf, size," " );if (advance_hpp_check (&dummy_hpp, ret))return ret; -hists__for_each_format (hists, fmt) { +/* 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 (column++ < browser->b.horiz_scroll)continue ; -if (perf_hpp__is_sort_entry (fmt) ||perf_hpp__is_dynamic_entry (fmt)) -break ; - ret = fmt->header (fmt, &dummy_hpp,hists_to_evsel (hists));if (advance_hpp_check (&dummy_hpp, ret))break ;
@@ -1581,34 +1582,42 @@ static int hists_browser__scnprintf_hierarchy_headers(struct hist_browser *browsif (advance_hpp_check (&dummy_hpp, ret))return ret; -hists__for_each_format (hists, fmt) { -char *start; - -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) { ret =scnprintf (dummy_hpp.buf, dummy_hpp.size," / " );if (advance_hpp_check (&dummy_hpp, ret))break ; } + first_node = false; - ret = fmt->header (fmt, &dummy_hpp,hists_to_evsel (hists)); - dummy_hpp.buf[ret] ='\0' ; -rtrim (dummy_hpp.buf); + first_col = true; +perf_hpp_list__for_each_format (&fmt_node->hpp, fmt) { +char *start; - start =ltrim (dummy_hpp.buf); - ret =strlen (start); +if (perf_hpp__should_skip (fmt, hists)) +continue ; -if (start != dummy_hpp.buf) -memmove (dummy_hpp.buf, start, ret +1 ); +if (!first_col) { + ret =scnprintf (dummy_hpp.buf, dummy_hpp.size,"+" ); +if (advance_hpp_check (&dummy_hpp, ret)) +break ; + } + first_col = false; -if (advance_hpp_check (&dummy_hpp, ret)) -break ; + ret = fmt->header (fmt, &dummy_hpp,hists_to_evsel (hists)); + dummy_hpp.buf[ret] ='\0' ; +rtrim (dummy_hpp.buf); + + start =ltrim (dummy_hpp.buf); + ret =strlen (start); + +if (start != dummy_hpp.buf) +memmove (dummy_hpp.buf, start, ret +1 ); + +if (advance_hpp_check (&dummy_hpp, ret)) +break ; + } }return ret;
@@ -1676,7 +1685,7 @@ static unsigned int hist_browser__refresh(struct ui_browser *browser)break ;if (h->has_no_entry) { -hist_browser__show_no_entry (hb, row, h->depth); +hist_browser__show_no_entry (hb, row, h->depth +1 ); row++; } }else {
Signature · 1 line
2.5.0
Arnaldo Carvalho de Melo
maintainerPATCH 15/15 perf report: Use hierarchy hpp list on gtk
In reply to Arnaldo Carvalho de MeloFrom: Namhyung Kim <[email protected]>
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.
--- tools/perf/ui/gtk/hists.c | 55 ++++++++++++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 22 deletions(-)
tools/perf/ui/gtk/hists.c +33 -22
@@ -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),
Signature · 1 line
2.5.0
PATCH 1/1 perf tool: Build jitdump only on supported archs
In reply to Arnaldo Carvalho de MeloOn Mon, Mar 07, 2016 at 04:44:36PM -0300, Arnaldo Carvalho de Melo wrote:
SNIP
Quoted 7 lines
----------------------------------------------------------------
Adrian Hunter (5):
perf inject: Hit all DSOs for AUX data in JIT and other cases perf session: Simplify tool stubs
perf jit: Letjit_process()return errors
perf jit: Move clockid validation
perf tools: Use 64-bit shifts with (TSC) time conversion
hi,
perf build failed for me on s390x because of jitdump feature.
Attached patch tries to enable the build only on supported archs.
I haven't followed this feature too much, so I might have missed something.. anyway it builds on s390x now ;-) I took the list of archs from util/genelf.h
thanks,
jirka
---
Make jitdump being built only on architectures
defined in util/genelf.h file.
--- tools/perf/arch/arm/Makefile | 1 + tools/perf/arch/arm64/Makefile | 1 + tools/perf/arch/powerpc/Makefile | 1 + tools/perf/arch/x86/Makefile | 1 + tools/perf/builtin-inject.c | 12 +++++++----- tools/perf/config/Makefile | 7 +++++++ tools/perf/util/Build | 2 +- 7 files changed, 19 insertions(+), 6 deletions(-)
tools/perf/arch/arm/Makefile +1 -0
@@ -1,3 +1,4 @@ ifndef NO_DWARF PERF_HAVE_DWARF_REGS := 1 endif +PERF_HAVE_JITDUMP := 1
tools/perf/arch/arm64/Makefile +1 -0
@@ -1,3 +1,4 @@ ifndef NO_DWARF PERF_HAVE_DWARF_REGS := 1 endif +PERF_HAVE_JITDUMP := 1
tools/perf/arch/powerpc/Makefile +1 -0
@@ -3,3 +3,4 @@ PERF_HAVE_DWARF_REGS := 1 endif HAVE_KVM_STAT_SUPPORT := 1 +PERF_HAVE_JITDUMP := 1
tools/perf/arch/x86/Makefile +1 -0
@@ -3,3 +3,4 @@ PERF_HAVE_DWARF_REGS := 1 endif HAVE_KVM_STAT_SUPPORT := 1 PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET := 1 +PERF_HAVE_JITDUMP := 1
tools/perf/builtin-inject.c +7 -5
@@ -73,7 +73,7 @@ static int perf_event__repipe_oe_synth(struct perf_tool *tool,return perf_event__repipe_synth (tool, event); } -#if defined(HAVE_LIBELF_SUPPORT ) && defined(HAVE_DWARF_SUPPORT ) +#ifdef HAVE_JITDUMP static int perf_event__drop_oe (struct perf_tool *tool__maybe_unused ,union perf_event *event__maybe_unused ,struct ordered_events *oe__maybe_unused )
@@ -245,7 +245,7 @@ static int perf_event__repipe_mmap(struct perf_tool *tool,return err; } -#if defined(HAVE_LIBELF_SUPPORT ) && defined(HAVE_DWARF_SUPPORT ) +#if defined(HAVE_JITDUMP ) static int perf_event__jit_repipe_mmap(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample,
@@ -283,7 +283,7 @@ static int perf_event__repipe_mmap2(struct perf_tool *tool,return err; } -#if defined(HAVE_LIBELF_SUPPORT ) && defined(HAVE_DWARF_SUPPORT ) +#if defined(HAVE_JITDUMP ) static int perf_event__jit_repipe_mmap2(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample,
@@ -778,7 +778,9 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) OPT_BOOLEAN('s', "sched-stat", &inject.sched_stat, "Merge sched-stat and sched-switch for getting events " "where and how long tasks slept"), +#ifdef HAVE_JITDUMP OPT_BOOLEAN ('j' ,"jit" , &inject.jit_mode,"merge jitdump files into perf.data file" ), +#endifOPT_INCR ('v' ,"verbose" , &verbose,"be more verbose (show build ids, etc)" ), OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name, "file",
@@ -795,7 +797,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)"perf inject [<options>]" , NULL }; -#if !defined(HAVE_LIBELF_SUPPORT ) || !defined(HAVE_DWARF_SUPPORT ) +#ifndef HAVE_JITDUMP set_option_nobuild (options,'j' ,"jit" ,"NO_LIBELF=1" , true);#endif argc =parse_options (argc, argv, options, inject_usage,0 );
@@ -833,7 +835,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) inject.tool.ordered_events = true; inject.tool.ordering_requires_timestamps = true; } -#if defined(HAVE_LIBELF_SUPPORT ) && defined(HAVE_DWARF_SUPPORT ) +#if defined(HAVE_JITDUMP )if (inject.jit_mode) { inject.tool.mmap2 = perf_event__jit_repipe_mmap2; inject.tool.mmap = perf_event__jit_repipe_mmap;
tools/perf/config/Makefile +7 -0
@@ -328,6 +328,13 @@ ifndef NO_LIBELF endif # NO_LIBBPF endif # NO_LIBELF +ifdef PERF_HAVE_JITDUMP + ifndef NO_DWARF + $(call detected,CONFIG_JITDUMP) + CFLAGS += -DHAVE_JITDUMP + endif +endif + ifeq ($(ARCH),powerpc) ifndef NO_DWARF CFLAGS += -DHAVE_SKIP_CALLCHAIN_IDX
tools/perf/util/Build +1 -1
@@ -108,7 +108,7 @@ libperf-$(CONFIG_ZLIB) += zlib.o libperf-$(CONFIG_LZMA) += lzma.o libperf-y += demangle-java.o -ifdef CONFIG_DWARF +ifdef CONFIG_JITDUMP libperf-$(CONFIG_LIBELF) += jitdump.o libperf-$(CONFIG_LIBELF) += genelf.o libperf-$(CONFIG_LIBELF) += genelf_debug.o
Signature · 1 line
2.4.3
Re: [PATCH] perf tool: Build jitdump only on supported archs
Em Thu, Mar 10, 2016 at 10:32:29AM +0100, Jiri Olsa escreveu:
Quoted 12 lines · Arnaldo Carvalho de Melo
SNIP
Quoted 7 lines
----------------------------------------------------------------
Adrian Hunter (5):
perf inject: Hit all DSOs for AUX data in JIT and other cases perf session: Simplify tool stubs
perf jit: Letjit_process()return errors
perf jit: Move clockid validation
perf tools: Use 64-bit shifts with (TSC) time conversion
Quoted 8 lines
hi,
perf build failed for me on s390x because of jitdump feature.Attached patch tries to enable the build only on supported archs.
I haven't followed this feature too much, so I might have missed something.. anyway it builds on s390x now ;-) I took the list of archs from
util/genelf.h
Hi Jiri,
This may be related to this cset, still not in tip/perf/core:
commit 46dad054a19297af65c417c97cb920aa5bdf7e8c
Author: Arnaldo Carvalho de Melo <[email protected]>
Date: Mon Mar 7 18:48:45 2016 -0300
perf jitdump: DWARF is also needed
Can you check if without this one perf builds on s390?
This patch is to make it build on ubuntu without libdw, i.e. it requires both libdw and libelf, the way I fixed it may not be the best and probably we need to fold these two patches before sending to Ingo, since your patch essentially rewrites my previous patch :-)
Can you please check that?
- Arnaldo
Quoted 147 lines
thanks,
jirka---
Make jitdump being built only on architectures
defined inutil/genelf.hfile.Signed-off-by Jiri Olsa <[email protected]>--- tools/perf/arch/arm/Makefile | 1 + tools/perf/arch/arm64/Makefile | 1 + tools/perf/arch/powerpc/Makefile | 1 + tools/perf/arch/x86/Makefile | 1 + tools/perf/builtin-inject.c | 12 +++++++----- tools/perf/config/Makefile | 7 +++++++ tools/perf/util/Build | 2 +- 7 files changed, 19 insertions(+), 6 deletions(-)tools/perf/arch/arm/Makefile +1
-0@@ -1,3 +1,4 @@ ifndef NO_DWARF PERF_HAVE_DWARF_REGS := 1 endif +PERF_HAVE_JITDUMP := 1tools/perf/arch/arm64/Makefile +1
-0@@ -1,3 +1,4 @@ ifndef NO_DWARF PERF_HAVE_DWARF_REGS := 1 endif +PERF_HAVE_JITDUMP := 1tools/perf/arch/powerpc/Makefile +1
-0@@ -3,3 +3,4 @@ PERF_HAVE_DWARF_REGS := 1 endif HAVE_KVM_STAT_SUPPORT := 1 +PERF_HAVE_JITDUMP := 1tools/perf/arch/x86/Makefile +1
-0@@ -3,3 +3,4 @@ PERF_HAVE_DWARF_REGS := 1 endif HAVE_KVM_STAT_SUPPORT := 1 PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET := 1 +PERF_HAVE_JITDUMP := 1tools/perf/builtin-inject.c +7
-5@@ -73,7 +73,7 @@ static int perf_event__repipe_oe_synth(struct perf_tool *tool,return perf_event__repipe_synth (tool, event); } -#if defined(HAVE_LIBELF_SUPPORT ) && defined(HAVE_DWARF_SUPPORT ) +#ifdef HAVE_JITDUMP static int perf_event__drop_oe (struct perf_tool *tool__maybe_unused ,union perf_event *event__maybe_unused ,struct ordered_events *oe__maybe_unused )@@ -245,7 +245,7 @@ static int perf_event__repipe_mmap(struct perf_tool *tool,return err; } -#if defined(HAVE_LIBELF_SUPPORT ) && defined(HAVE_DWARF_SUPPORT ) +#if defined(HAVE_JITDUMP ) static int perf_event__jit_repipe_mmap(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample,@@ -283,7 +283,7 @@ static int perf_event__repipe_mmap2(struct perf_tool *tool,return err; } -#if defined(HAVE_LIBELF_SUPPORT ) && defined(HAVE_DWARF_SUPPORT ) +#if defined(HAVE_JITDUMP ) static int perf_event__jit_repipe_mmap2(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample,@@ -778,7 +778,9 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) OPT_BOOLEAN('s', "sched-stat", &inject.sched_stat, "Merge sched-stat and sched-switch for getting events " "where and how long tasks slept"), +#ifdef HAVE_JITDUMP OPT_BOOLEAN ('j' ,"jit" , &inject.jit_mode,"merge jitdump files into perf.data file" ), +#endifOPT_INCR ('v' ,"verbose" , &verbose,"be more verbose (show build ids, etc)" ), OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name, "file",@@ -795,7 +797,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)"perf inject [<options>]" , NULL }; -#if !defined(HAVE_LIBELF_SUPPORT ) || !defined(HAVE_DWARF_SUPPORT ) +#ifndef HAVE_JITDUMP set_option_nobuild (options,'j' ,"jit" ,"NO_LIBELF=1" , true);#endif argc =parse_options (argc, argv, options, inject_usage,0 );@@ -833,7 +835,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) inject.tool.ordered_events = true; inject.tool.ordering_requires_timestamps = true; } -#if defined(HAVE_LIBELF_SUPPORT ) && defined(HAVE_DWARF_SUPPORT ) +#if defined(HAVE_JITDUMP )if (inject.jit_mode) { inject.tool.mmap2 = perf_event__jit_repipe_mmap2; inject.tool.mmap = perf_event__jit_repipe_mmap;tools/perf/config/Makefile +7
-0@@ -328,6 +328,13 @@ ifndef NO_LIBELF endif # NO_LIBBPF endif # NO_LIBELF +ifdef PERF_HAVE_JITDUMP + ifndef NO_DWARF + $(call detected,CONFIG_JITDUMP) + CFLAGS += -DHAVE_JITDUMP + endif +endif + ifeq ($(ARCH),powerpc) ifndef NO_DWARF CFLAGS += -DHAVE_SKIP_CALLCHAIN_IDXtools/perf/util/Build +1
-1@@ -108,7 +108,7 @@ libperf-$(CONFIG_ZLIB) += zlib.o libperf-$(CONFIG_LZMA) += lzma.o libperf-y += demangle-java.o -ifdef CONFIG_DWARF +ifdef CONFIG_JITDUMP libperf-$(CONFIG_LIBELF) += jitdump.o libperf-$(CONFIG_LIBELF) += genelf.o libperf-$(CONFIG_LIBELF) += genelf_debug.oSignature · 1 line
2.4.3
Re: [PATCH] perf tool: Build jitdump only on supported archs
Quoted 32 lines · Arnaldo Carvalho de Melo
Em Thu, Mar 10, 2016 at 10:32:29AM +0100, Jiri Olsa escreveu:
Quoted 12 lines · Arnaldo Carvalho de Melo
SNIP
Quoted 7 lines
----------------------------------------------------------------
Adrian Hunter (5):
perf inject: Hit all DSOs for AUX data in JIT and other cases perf session: Simplify tool stubs
perf jit: Letjit_process()return errors
perf jit: Move clockid validation
perf tools: Use 64-bit shifts with (TSC) time conversionQuoted 8 lines
hi,
perf build failed for me on s390x because of jitdump feature.Attached patch tries to enable the build only on supported archs.
I haven't followed this feature too much, so I might have missed something.. anyway it builds on s390x now ;-) I took the list of archs from
util/genelf.hHi Jiri,
This may be related to this cset, still not in tip/perf/core:
commit
46dad054a19297af65c417c97cb920aa5bdf7e8c
Author: Arnaldo Carvalho de Melo <[email protected]>
Date: Mon Mar 7 18:48:45 2016 -0300perf jitdump: DWARF is also needed
Quoted 8 lines
Can you check if without this one perf builds on s390?
This patch is to make it build on ubuntu without libdw, i.e. it requires both libdw and libelf, the way I fixed it may not be the best and probably we need to fold these two patches before sending to Ingo, since your patch essentially rewrites my previous patch :-)
Can you please check that?
well there's following line in util/genelf.h:
#else
#error "unsupported architecture"
#endif
which makes the build fail on unssuported arch,
even without your patch:
CC util/jitdump.o
In file included from util/jitdump.c:23:util/genelf.h:41:2: error: #error "unsupported architecture" util/genelf.h:44:5: error: "GEN_ELF_CLASS" is not defined
mv: cannot stat `util/.jitdump.o.tmp': No such file or directory make[3]: *** [util/jitdump.o] Error 1
jirka
Arnaldo Carvalho de Melo
maintainerRe: [PATCH] perf tool: Build jitdump only on supported archs
Em Thu, Mar 10, 2016 at 05:04:36PM +0100, Jiri Olsa escreveu:
Quoted 42 lines · Arnaldo Carvalho de Melo
Quoted 32 lines
Em Thu, Mar 10, 2016 at 10:32:29AM +0100, Jiri Olsa escreveu:
Quoted 12 lines · Arnaldo Carvalho de Melo
SNIP
Quoted 7 lines
----------------------------------------------------------------
Adrian Hunter (5):
perf inject: Hit all DSOs for AUX data in JIT and other cases perf session: Simplify tool stubs
perf jit: Letjit_process()return errors
perf jit: Move clockid validation
perf tools: Use 64-bit shifts with (TSC) time conversionQuoted 8 lines
hi,
perf build failed for me on s390x because of jitdump feature.Attached patch tries to enable the build only on supported archs.
I haven't followed this feature too much, so I might have missed something.. anyway it builds on s390x now ;-) I took the list of archs from
util/genelf.hHi Jiri,
This may be related to this cset, still not in tip/perf/core:
commit
46dad054a19297af65c417c97cb920aa5bdf7e8c
Author: Arnaldo Carvalho de Melo <[email protected]>
Date: Mon Mar 7 18:48:45 2016 -0300perf jitdump: DWARF is also needed
Quoted 8 lines
Can you check if without this one perf builds on s390?
This patch is to make it build on ubuntu without libdw, i.e. it requires both libdw and libelf, the way I fixed it may not be the best and probably we need to fold these two patches before sending to Ingo, since your patch essentially rewrites my previous patch :-)
Can you please check that?
Quoted 8 lines
well there's following line in
util/genelf.h:#else
#error "unsupported architecture"
#endifwhich makes the build fail on unssuported arch,
even without your patch:
Ok, so I'll just apply your patch, thanks for clarifying.
- Arnaldo
Quoted 9 lines
CC
util/jitdump.o
In file included fromutil/jitdump.c:23:util/genelf.h:41:2: error: #error "unsupported architecture"util/genelf.h:44:5: error: "GEN_ELF_CLASS" is not defined
mv: cannot stat `util/.jitdump.o.tmp': No such file or directory make[3]: *** [util/jitdump.o] Error 1jirka
PATCH v2 1/1 perf tool: Build jitdump only on supported archs
Quoted 45 lines · Arnaldo Carvalho de Melo
Em Thu, Mar 10, 2016 at 05:04:36PM +0100, Jiri Olsa escreveu:
Quoted 44 lines · Arnaldo Carvalho de Melo
Quoted 32 lines
Em Thu, Mar 10, 2016 at 10:32:29AM +0100, Jiri Olsa escreveu:
Quoted 12 lines · Arnaldo Carvalho de Melo
SNIP
Quoted 7 lines
----------------------------------------------------------------
Adrian Hunter (5):
perf inject: Hit all DSOs for AUX data in JIT and other cases perf session: Simplify tool stubs
perf jit: Letjit_process()return errors
perf jit: Move clockid validation
perf tools: Use 64-bit shifts with (TSC) time conversionQuoted 8 lines
hi,
perf build failed for me on s390x because of jitdump feature.Attached patch tries to enable the build only on supported archs.
I haven't followed this feature too much, so I might have missed something.. anyway it builds on s390x now ;-) I took the list of archs from
util/genelf.hHi Jiri,
This may be related to this cset, still not in tip/perf/core:
commit
46dad054a19297af65c417c97cb920aa5bdf7e8c
Author: Arnaldo Carvalho de Melo <[email protected]>
Date: Mon Mar 7 18:48:45 2016 -0300perf jitdump: DWARF is also needed
Quoted 8 lines
Can you check if without this one perf builds on s390?
This patch is to make it build on ubuntu without libdw, i.e. it requires both libdw and libelf, the way I fixed it may not be the best and probably we need to fold these two patches before sending to Ingo, since your patch essentially rewrites my previous patch :-)
Can you please check that?
well there's following line in
util/genelf.h:
Quoted 9 lines
Quoted 6 lines
#else
#error "unsupported architecture"
#endifwhich makes the build fail on unssuported arch,
even without your patch:Ok, so I'll just apply your patch, thanks for clarifying.
oops, just consolidated #if defined into #ifdef, v2 attached
thanks,
jirka
---
Make jitdump being built only on architectures
defined in util/genelf.h file.
--- tools/perf/arch/arm/Makefile | 1 + tools/perf/arch/arm64/Makefile | 1 + tools/perf/arch/powerpc/Makefile | 1 + tools/perf/arch/x86/Makefile | 1 + tools/perf/builtin-inject.c | 12 +++++++----- tools/perf/config/Makefile | 7 +++++++ tools/perf/util/Build | 2 +- 7 files changed, 19 insertions(+), 6 deletions(-)
tools/perf/arch/arm/Makefile +1 -0
@@ -1,3 +1,4 @@ ifndef NO_DWARF PERF_HAVE_DWARF_REGS := 1 endif +PERF_HAVE_JITDUMP := 1
tools/perf/arch/arm64/Makefile +1 -0
@@ -1,3 +1,4 @@ ifndef NO_DWARF PERF_HAVE_DWARF_REGS := 1 endif +PERF_HAVE_JITDUMP := 1
tools/perf/arch/powerpc/Makefile +1 -0
@@ -3,3 +3,4 @@ PERF_HAVE_DWARF_REGS := 1 endif HAVE_KVM_STAT_SUPPORT := 1 +PERF_HAVE_JITDUMP := 1
tools/perf/arch/x86/Makefile +1 -0
@@ -3,3 +3,4 @@ PERF_HAVE_DWARF_REGS := 1 endif HAVE_KVM_STAT_SUPPORT := 1 PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET := 1 +PERF_HAVE_JITDUMP := 1
tools/perf/builtin-inject.c +7 -5
@@ -73,7 +73,7 @@ static int perf_event__repipe_oe_synth(struct perf_tool *tool,return perf_event__repipe_synth (tool, event); } -#if defined(HAVE_LIBELF_SUPPORT ) && defined(HAVE_DWARF_SUPPORT ) +#ifdef HAVE_JITDUMP static int perf_event__drop_oe (struct perf_tool *tool__maybe_unused ,union perf_event *event__maybe_unused ,struct ordered_events *oe__maybe_unused )
@@ -245,7 +245,7 @@ static int perf_event__repipe_mmap(struct perf_tool *tool,return err; } -#if defined(HAVE_LIBELF_SUPPORT ) && defined(HAVE_DWARF_SUPPORT ) +#ifdef HAVE_JITDUMP static int perf_event__jit_repipe_mmap(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample,
@@ -283,7 +283,7 @@ static int perf_event__repipe_mmap2(struct perf_tool *tool,return err; } -#if defined(HAVE_LIBELF_SUPPORT ) && defined(HAVE_DWARF_SUPPORT ) +#ifdef HAVE_JITDUMP static int perf_event__jit_repipe_mmap2(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample,
@@ -778,7 +778,9 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) OPT_BOOLEAN('s', "sched-stat", &inject.sched_stat, "Merge sched-stat and sched-switch for getting events " "where and how long tasks slept"), +#ifdef HAVE_JITDUMP OPT_BOOLEAN ('j' ,"jit" , &inject.jit_mode,"merge jitdump files into perf.data file" ), +#endifOPT_INCR ('v' ,"verbose" , &verbose,"be more verbose (show build ids, etc)" ), OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name, "file",
@@ -795,7 +797,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)"perf inject [<options>]" , NULL }; -#if !defined(HAVE_LIBELF_SUPPORT ) || !defined(HAVE_DWARF_SUPPORT ) +#ifndef HAVE_JITDUMP set_option_nobuild (options,'j' ,"jit" ,"NO_LIBELF=1" , true);#endif argc =parse_options (argc, argv, options, inject_usage,0 );
@@ -833,7 +835,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) inject.tool.ordered_events = true; inject.tool.ordering_requires_timestamps = true; } -#if defined(HAVE_LIBELF_SUPPORT ) && defined(HAVE_DWARF_SUPPORT ) +#ifdef HAVE_JITDUMP if (inject.jit_mode) { inject.tool.mmap2 = perf_event__jit_repipe_mmap2; inject.tool.mmap = perf_event__jit_repipe_mmap;
tools/perf/config/Makefile +7 -0
@@ -328,6 +328,13 @@ ifndef NO_LIBELF endif # NO_LIBBPF endif # NO_LIBELF +ifdef PERF_HAVE_JITDUMP + ifndef NO_DWARF + $(call detected,CONFIG_JITDUMP) + CFLAGS += -DHAVE_JITDUMP + endif +endif + ifeq ($(ARCH),powerpc) ifndef NO_DWARF CFLAGS += -DHAVE_SKIP_CALLCHAIN_IDX
tools/perf/util/Build +1 -1
@@ -108,7 +108,7 @@ libperf-$(CONFIG_ZLIB) += zlib.o libperf-$(CONFIG_LZMA) += lzma.o libperf-y += demangle-java.o -ifdef CONFIG_DWARF +ifdef CONFIG_JITDUMP libperf-$(CONFIG_LIBELF) += jitdump.o libperf-$(CONFIG_LIBELF) += genelf.o libperf-$(CONFIG_LIBELF) += genelf_debug.o
Signature · 1 line
2.4.3
tip-bot for Jiri Olsa
merge bot[tip:perf/core] perf jitdump: Build only on supported archs
perf jitdump: Build only on supported archs
Commit-ID: e12b202f8fb9b62a3997cad8e93401f85293390c Gitweb: http://git.kernel.org/tip/e12b202f8fb9b62a3997cad8e93401f85293390c Author: Jiri Olsa <[email protected]> AuthorDate: Thu, 10 Mar 2016 17:41:13 +0100 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Thu, 10 Mar 2016 16:33:19 -0300
perf jitdump: Build only on supported archs
Build jitdump only on architectures defined in util/genelf.h file, to avoid breaking the build on such arches.
--- tools/perf/arch/arm/Makefile | 1 + tools/perf/arch/arm64/Makefile | 1 + tools/perf/arch/powerpc/Makefile | 1 + tools/perf/arch/x86/Makefile | 1 + tools/perf/builtin-inject.c | 12 +++++++----- tools/perf/config/Makefile | 7 +++++++ tools/perf/util/Build | 2 +- 7 files changed, 19 insertions(+), 6 deletions(-)
tools/perf/arch/arm/Makefile +1 -0
@@ -1,3 +1,4 @@ ifndef NO_DWARF PERF_HAVE_DWARF_REGS := 1 endif +PERF_HAVE_JITDUMP := 1
tools/perf/arch/arm64/Makefile +1 -0
@@ -1,3 +1,4 @@ ifndef NO_DWARF PERF_HAVE_DWARF_REGS := 1 endif +PERF_HAVE_JITDUMP := 1
tools/perf/arch/powerpc/Makefile +1 -0
@@ -3,3 +3,4 @@ PERF_HAVE_DWARF_REGS := 1 endif HAVE_KVM_STAT_SUPPORT := 1 +PERF_HAVE_JITDUMP := 1
tools/perf/arch/x86/Makefile +1 -0
@@ -3,3 +3,4 @@ PERF_HAVE_DWARF_REGS := 1 endif HAVE_KVM_STAT_SUPPORT := 1 PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET := 1 +PERF_HAVE_JITDUMP := 1
tools/perf/builtin-inject.c +7 -5
@@ -73,7 +73,7 @@ static int perf_event__repipe_oe_synth(struct perf_tool *tool,return perf_event__repipe_synth (tool, event); } -#if defined(HAVE_LIBELF_SUPPORT ) && defined(HAVE_DWARF_SUPPORT ) +#ifdef HAVE_JITDUMP static int perf_event__drop_oe (struct perf_tool *tool__maybe_unused ,union perf_event *event__maybe_unused ,struct ordered_events *oe__maybe_unused )
@@ -245,7 +245,7 @@ static int perf_event__repipe_mmap(struct perf_tool *tool,return err; } -#if defined(HAVE_LIBELF_SUPPORT ) && defined(HAVE_DWARF_SUPPORT ) +#ifdef HAVE_JITDUMP static int perf_event__jit_repipe_mmap(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample,
@@ -283,7 +283,7 @@ static int perf_event__repipe_mmap2(struct perf_tool *tool,return err; } -#if defined(HAVE_LIBELF_SUPPORT ) && defined(HAVE_DWARF_SUPPORT ) +#ifdef HAVE_JITDUMP static int perf_event__jit_repipe_mmap2(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample,
@@ -778,7 +778,9 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) OPT_BOOLEAN('s', "sched-stat", &inject.sched_stat, "Merge sched-stat and sched-switch for getting events " "where and how long tasks slept"), +#ifdef HAVE_JITDUMP OPT_BOOLEAN ('j' ,"jit" , &inject.jit_mode,"merge jitdump files into perf.data file" ), +#endifOPT_INCR ('v' ,"verbose" , &verbose,"be more verbose (show build ids, etc)" ), OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name, "file",
@@ -795,7 +797,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)"perf inject [<options>]" , NULL }; -#if !defined(HAVE_LIBELF_SUPPORT ) || !defined(HAVE_DWARF_SUPPORT ) +#ifndef HAVE_JITDUMP set_option_nobuild (options,'j' ,"jit" ,"NO_LIBELF=1" , true);#endif argc =parse_options (argc, argv, options, inject_usage,0 );
@@ -833,7 +835,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) inject.tool.ordered_events = true; inject.tool.ordering_requires_timestamps = true; } -#if defined(HAVE_LIBELF_SUPPORT ) && defined(HAVE_DWARF_SUPPORT ) +#ifdef HAVE_JITDUMP if (inject.jit_mode) { inject.tool.mmap2 = perf_event__jit_repipe_mmap2; inject.tool.mmap = perf_event__jit_repipe_mmap;
tools/perf/config/Makefile +7 -0
@@ -328,6 +328,13 @@ ifndef NO_LIBELF endif # NO_LIBBPF endif # NO_LIBELF +ifdef PERF_HAVE_JITDUMP + ifndef NO_DWARF + $(call detected,CONFIG_JITDUMP) + CFLAGS += -DHAVE_JITDUMP + endif +endif + ifeq ($(ARCH),powerpc) ifndef NO_DWARF CFLAGS += -DHAVE_SKIP_CALLCHAIN_IDX
tools/perf/util/Build +1 -1
@@ -108,7 +108,7 @@ libperf-$(CONFIG_ZLIB) += zlib.o libperf-$(CONFIG_LZMA) += lzma.o libperf-y += demangle-java.o -ifdef CONFIG_DWARF +ifdef CONFIG_JITDUMP libperf-$(CONFIG_LIBELF) += jitdump.o libperf-$(CONFIG_LIBELF) += genelf.o libperf-$(CONFIG_LIBELF) += genelf_debug.o