[PATCH 14/14] perf script: show overhead events

From: kan . liang
Date: Wed Nov 23 2016 - 12:45:17 EST


From: Kan Liang <kan.liang@xxxxxxxxx>

Introduce a new option --show-overhead to show overhead events in perf
script

Signed-off-by: Kan Liang <kan.liang@xxxxxxxxx>
---
tools/perf/builtin-script.c | 36 ++++++++++++++++++++++++++++++++++++
tools/perf/util/event.c | 37 +++++++++++++++++++++++++++++++++++++
tools/perf/util/event.h | 1 +
3 files changed, 74 insertions(+)

diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index e1daff3..76d9747 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -829,6 +829,7 @@ struct perf_script {
bool show_task_events;
bool show_mmap_events;
bool show_switch_events;
+ bool show_overhead;
bool allocated;
struct cpu_map *cpus;
struct thread_map *threads;
@@ -1264,6 +1265,37 @@ static int process_switch_event(struct perf_tool *tool,
return 0;
}

+static int process_overhead_event(struct perf_tool *tool,
+ union perf_event *event,
+ struct perf_sample *sample,
+ struct machine *machine)
+{
+ struct thread *thread;
+ struct perf_script *script = container_of(tool, struct perf_script, tool);
+ struct perf_session *session = script->session;
+ struct perf_evsel *evsel;
+
+ if (perf_event__process_switch(tool, event, sample, machine) < 0)
+ return -1;
+ if (sample) {
+ evsel = perf_evlist__id2evsel(session->evlist, sample->id);
+ thread = machine__findnew_thread(machine, sample->pid, sample->tid);
+ if (thread == NULL) {
+ pr_debug("problem processing OVERHEAD event, skipping it.\n");
+ return -1;
+ }
+
+ print_sample_start(sample, thread, evsel);
+ perf_event__fprintf(event, stdout);
+ thread__put(thread);
+ } else {
+ /* USER OVERHEAD event */
+ perf_event__fprintf(event, stdout);
+ }
+
+ return 0;
+}
+
static void sig_handler(int sig __maybe_unused)
{
session_done = 1;
@@ -1287,6 +1319,8 @@ static int __cmd_script(struct perf_script *script)
}
if (script->show_switch_events)
script->tool.context_switch = process_switch_event;
+ if (script->show_overhead)
+ script->tool.overhead = process_overhead_event;

ret = perf_session__process_events(script->session);

@@ -2172,6 +2206,8 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
"Show the mmap events"),
OPT_BOOLEAN('\0', "show-switch-events", &script.show_switch_events,
"Show context switch events (if recorded)"),
+ OPT_BOOLEAN('\0', "show-overhead", &script.show_overhead,
+ "Show overhead events"),
OPT_BOOLEAN('f', "force", &file.force, "don't complain, do it"),
OPT_BOOLEAN(0, "ns", &nanosecs,
"Use 9 decimal places when displaying time"),
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 6cd43c9..cd4f3aa 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -1190,6 +1190,39 @@ size_t perf_event__fprintf_switch(union perf_event *event, FILE *fp)
event->context_switch.next_prev_tid);
}

+size_t perf_event__fprintf_overhead(union perf_event *event, FILE *fp)
+{
+ size_t ret;
+
+ if (event->overhead.type == PERF_NMI_OVERHEAD) {
+ ret = fprintf(fp, " [NMI] nr: %llu time: %llu cpu %u\n",
+ event->overhead.entry.nr,
+ event->overhead.entry.time,
+ event->overhead.entry.cpu);
+ } else if (event->overhead.type == PERF_MUX_OVERHEAD) {
+ ret = fprintf(fp, " [MUX] nr: %llu time: %llu cpu %u\n",
+ event->overhead.entry.nr,
+ event->overhead.entry.time,
+ event->overhead.entry.cpu);
+ } else if (event->overhead.type == PERF_SB_OVERHEAD) {
+ ret = fprintf(fp, " [SB] nr: %llu time: %llu cpu %u\n",
+ event->overhead.entry.nr,
+ event->overhead.entry.time,
+ event->overhead.entry.cpu);
+ } else if (event->overhead.type == PERF_USER_WRITE_OVERHEAD) {
+ ret = fprintf(fp, " [USER WRITE] nr: %llu time: %llu cpu %u\n",
+ event->overhead.entry.nr,
+ event->overhead.entry.time,
+ event->overhead.entry.cpu);
+ } else if (event->overhead.type == PERF_USER_ELAPSED_TIME) {
+ ret = fprintf(fp, " [ELAPSED TIME] time: %llu\n",
+ event->overhead.entry.time);
+ } else {
+ ret = fprintf(fp, " unhandled!\n");
+ }
+ return ret;
+}
+
size_t perf_event__fprintf(union perf_event *event, FILE *fp)
{
size_t ret = fprintf(fp, "PERF_RECORD_%s",
@@ -1219,6 +1252,10 @@ size_t perf_event__fprintf(union perf_event *event, FILE *fp)
case PERF_RECORD_SWITCH_CPU_WIDE:
ret += perf_event__fprintf_switch(event, fp);
break;
+ case PERF_RECORD_OVERHEAD:
+ case PERF_RECORD_USER_OVERHEAD:
+ ret += perf_event__fprintf_overhead(event, fp);
+ break;
default:
ret += fprintf(fp, "\n");
}
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index ceb0968..36e295d 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -690,6 +690,7 @@ size_t perf_event__fprintf_switch(union perf_event *event, FILE *fp);
size_t perf_event__fprintf_thread_map(union perf_event *event, FILE *fp);
size_t perf_event__fprintf_cpu_map(union perf_event *event, FILE *fp);
size_t perf_event__fprintf(union perf_event *event, FILE *fp);
+size_t perf_event__fprintf_overhead(union perf_event *event, FILE *fp);

u64 kallsyms__get_function_start(const char *kallsyms_filename,
const char *symbol_name);
--
2.5.5