mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	perf report: Support forced leader feature in pipe mode
Stephane reported a problem with forced leader in pipe mode, where
report does not force the group output. The reason is that we don't
force the leader in pipe mode.
This patch adds HEADER_LAST_FEATURE mark to have a point where we have
all events and features received, and force the group if requested.
  $ perf record --group -e '{cycles, instructions}' -o - kill | perf report -i - --group
  SNIP
  #         Overhead  Command  Shared Object     Symbol
  # ................  .......  ................  .......................
  #
      28.36%   0.00%  kill     libc-2.25.so      [.] __unregister_atfork
      26.32%   0.00%  kill     libc-2.25.so      [.] _dl_addr
      26.10%   0.00%  kill     ld-2.25.so        [.] _dl_relocate_object
      17.32%   0.00%  kill     ld-2.25.so        [.] __tunables_init
       1.70%   0.01%  kill     [unknown]         [k] 0xffffffffafa01a40
       0.20%   0.00%  kill     ld-2.25.so        [.] _start
       0.00%  48.77%  kill     ld-2.25.so        [.] do_lookup_x
       0.00%  42.97%  kill     libc-2.25.so      [.] _IO_getline
       0.00%   6.35%  kill     ld-2.25.so        [.] strcmp
       0.00%   1.71%  kill     ld-2.25.so        [.] _dl_sysdep_start
       0.00%   0.19%  kill     ld-2.25.so        [.] _dl_start
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Tested-by: Stephane Eranian <eranian@google.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20180314092205.23291-2-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
			
			
This commit is contained in:
		
							parent
							
								
									a2015516c5
								
							
						
					
					
						commit
						57b5de4639
					
				
					 2 changed files with 53 additions and 15 deletions
				
			
		| 
						 | 
					@ -68,6 +68,7 @@ struct report {
 | 
				
			||||||
	bool			header;
 | 
						bool			header;
 | 
				
			||||||
	bool			header_only;
 | 
						bool			header_only;
 | 
				
			||||||
	bool			nonany_branch_mode;
 | 
						bool			nonany_branch_mode;
 | 
				
			||||||
 | 
						bool			group_set;
 | 
				
			||||||
	int			max_stack;
 | 
						int			max_stack;
 | 
				
			||||||
	struct perf_read_values	show_threads_values;
 | 
						struct perf_read_values	show_threads_values;
 | 
				
			||||||
	const char		*pretty_printing_style;
 | 
						const char		*pretty_printing_style;
 | 
				
			||||||
| 
						 | 
					@ -193,6 +194,45 @@ static int hist_iter__branch_callback(struct hist_entry_iter *iter,
 | 
				
			||||||
	return err;
 | 
						return err;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Events in data file are not collect in groups, but we still want
 | 
				
			||||||
 | 
					 * the group display. Set the artificial group and set the leader's
 | 
				
			||||||
 | 
					 * forced_leader flag to notify the display code.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static void setup_forced_leader(struct report *report,
 | 
				
			||||||
 | 
									struct perf_evlist *evlist)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (report->group_set && !evlist->nr_groups) {
 | 
				
			||||||
 | 
							struct perf_evsel *leader = perf_evlist__first(evlist);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							perf_evlist__set_leader(evlist);
 | 
				
			||||||
 | 
							leader->forced_leader = true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int process_feature_event(struct perf_tool *tool,
 | 
				
			||||||
 | 
									 union perf_event *event,
 | 
				
			||||||
 | 
									 struct perf_session *session __maybe_unused)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct report *rep = container_of(tool, struct report, tool);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (event->feat.feat_id < HEADER_LAST_FEATURE)
 | 
				
			||||||
 | 
							return perf_event__process_feature(tool, event, session);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (event->feat.feat_id != HEADER_LAST_FEATURE) {
 | 
				
			||||||
 | 
							pr_err("failed: wrong feature ID: %" PRIu64 "\n",
 | 
				
			||||||
 | 
							       event->feat.feat_id);
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * All features are received, we can force the
 | 
				
			||||||
 | 
						 * group if needed.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						setup_forced_leader(rep, session->evlist);
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int process_sample_event(struct perf_tool *tool,
 | 
					static int process_sample_event(struct perf_tool *tool,
 | 
				
			||||||
				union perf_event *event,
 | 
									union perf_event *event,
 | 
				
			||||||
				struct perf_sample *sample,
 | 
									struct perf_sample *sample,
 | 
				
			||||||
| 
						 | 
					@ -940,7 +980,6 @@ int cmd_report(int argc, const char **argv)
 | 
				
			||||||
		"perf report [<options>]",
 | 
							"perf report [<options>]",
 | 
				
			||||||
		NULL
 | 
							NULL
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
	bool group_set = false;
 | 
					 | 
				
			||||||
	struct report report = {
 | 
						struct report report = {
 | 
				
			||||||
		.tool = {
 | 
							.tool = {
 | 
				
			||||||
			.sample		 = process_sample_event,
 | 
								.sample		 = process_sample_event,
 | 
				
			||||||
| 
						 | 
					@ -958,7 +997,7 @@ int cmd_report(int argc, const char **argv)
 | 
				
			||||||
			.id_index	 = perf_event__process_id_index,
 | 
								.id_index	 = perf_event__process_id_index,
 | 
				
			||||||
			.auxtrace_info	 = perf_event__process_auxtrace_info,
 | 
								.auxtrace_info	 = perf_event__process_auxtrace_info,
 | 
				
			||||||
			.auxtrace	 = perf_event__process_auxtrace,
 | 
								.auxtrace	 = perf_event__process_auxtrace,
 | 
				
			||||||
			.feature	 = perf_event__process_feature,
 | 
								.feature	 = process_feature_event,
 | 
				
			||||||
			.ordered_events	 = true,
 | 
								.ordered_events	 = true,
 | 
				
			||||||
			.ordering_requires_timestamps = true,
 | 
								.ordering_requires_timestamps = true,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
| 
						 | 
					@ -1060,7 +1099,7 @@ int cmd_report(int argc, const char **argv)
 | 
				
			||||||
		   "Specify disassembler style (e.g. -M intel for intel syntax)"),
 | 
							   "Specify disassembler style (e.g. -M intel for intel syntax)"),
 | 
				
			||||||
	OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period,
 | 
						OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period,
 | 
				
			||||||
		    "Show a column with the sum of periods"),
 | 
							    "Show a column with the sum of periods"),
 | 
				
			||||||
	OPT_BOOLEAN_SET(0, "group", &symbol_conf.event_group, &group_set,
 | 
						OPT_BOOLEAN_SET(0, "group", &symbol_conf.event_group, &report.group_set,
 | 
				
			||||||
		    "Show event group information together"),
 | 
							    "Show event group information together"),
 | 
				
			||||||
	OPT_CALLBACK_NOOPT('b', "branch-stack", &branch_mode, "",
 | 
						OPT_CALLBACK_NOOPT('b', "branch-stack", &branch_mode, "",
 | 
				
			||||||
		    "use branch records for per branch histogram filling",
 | 
							    "use branch records for per branch histogram filling",
 | 
				
			||||||
| 
						 | 
					@ -1177,17 +1216,7 @@ int cmd_report(int argc, const char **argv)
 | 
				
			||||||
	has_br_stack = perf_header__has_feat(&session->header,
 | 
						has_br_stack = perf_header__has_feat(&session->header,
 | 
				
			||||||
					     HEADER_BRANCH_STACK);
 | 
										     HEADER_BRANCH_STACK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						setup_forced_leader(&report, session->evlist);
 | 
				
			||||||
	 * Events in data file are not collect in groups, but we still want
 | 
					 | 
				
			||||||
	 * the group display. Set the artificial group and set the leader's
 | 
					 | 
				
			||||||
	 * forced_leader flag to notify the display code.
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	if (group_set && !session->evlist->nr_groups) {
 | 
					 | 
				
			||||||
		struct perf_evsel *leader = perf_evlist__first(session->evlist);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		perf_evlist__set_leader(session->evlist);
 | 
					 | 
				
			||||||
		leader->forced_leader = true;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (itrace_synth_opts.last_branch)
 | 
						if (itrace_synth_opts.last_branch)
 | 
				
			||||||
		has_br_stack = true;
 | 
							has_br_stack = true;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3415,8 +3415,17 @@ int perf_event__synthesize_features(struct perf_tool *tool,
 | 
				
			||||||
			return ret;
 | 
								return ret;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Send HEADER_LAST_FEATURE mark. */
 | 
				
			||||||
 | 
						fe = ff.buf;
 | 
				
			||||||
 | 
						fe->feat_id     = HEADER_LAST_FEATURE;
 | 
				
			||||||
 | 
						fe->header.type = PERF_RECORD_HEADER_FEATURE;
 | 
				
			||||||
 | 
						fe->header.size = sizeof(*fe);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = process(tool, ff.buf, NULL, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	free(ff.buf);
 | 
						free(ff.buf);
 | 
				
			||||||
	return 0;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int perf_event__process_feature(struct perf_tool *tool,
 | 
					int perf_event__process_feature(struct perf_tool *tool,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue