Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S938960AbcKWRr1 (ORCPT ); Wed, 23 Nov 2016 12:47:27 -0500 Received: from mga14.intel.com ([192.55.52.115]:40678 "EHLO mga14.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S938622AbcKWRpA (ORCPT ); Wed, 23 Nov 2016 12:45:00 -0500 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.31,539,1473145200"; d="scan'208";a="1072652948" From: kan.liang@intel.com To: peterz@infradead.org, mingo@redhat.com, acme@kernel.org, linux-kernel@vger.kernel.org Cc: alexander.shishkin@linux.intel.com, tglx@linutronix.de, namhyung@kernel.org, jolsa@kernel.org, adrian.hunter@intel.com, wangnan0@huawei.com, mark.rutland@arm.com, andi@firstfloor.org, Kan Liang Subject: [PATCH 05/14] perf tools: handle PERF_RECORD_OVERHEAD record type Date: Wed, 23 Nov 2016 04:44:43 -0500 Message-Id: <1479894292-16277-6-git-send-email-kan.liang@intel.com> X-Mailer: git-send-email 2.5.5 In-Reply-To: <1479894292-16277-1-git-send-email-kan.liang@intel.com> References: <1479894292-16277-1-git-send-email-kan.liang@intel.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 9311 Lines: 267 From: Kan Liang The infrastructure to handle PERF_RECORD_OVERHEAD record type. A new perf report option is also introduced as a knob to show the overhead information. Signed-off-by: Kan Liang --- tools/include/uapi/linux/perf_event.h | 33 ++++++++++++++++++++++++++++++++ tools/perf/Documentation/perf-report.txt | 3 +++ tools/perf/builtin-report.c | 6 ++++++ tools/perf/util/event.c | 9 +++++++++ tools/perf/util/event.h | 11 +++++++++++ tools/perf/util/machine.c | 8 ++++++++ tools/perf/util/machine.h | 2 ++ tools/perf/util/session.c | 5 +++++ tools/perf/util/symbol.h | 3 ++- tools/perf/util/tool.h | 1 + 10 files changed, 80 insertions(+), 1 deletion(-) diff --git a/tools/include/uapi/linux/perf_event.h b/tools/include/uapi/linux/perf_event.h index c66a485..5e7c522 100644 --- a/tools/include/uapi/linux/perf_event.h +++ b/tools/include/uapi/linux/perf_event.h @@ -862,6 +862,17 @@ enum perf_event_type { */ PERF_RECORD_SWITCH_CPU_WIDE = 15, + /* + * Records perf overhead + * struct { + * struct perf_event_header header; + * u32 type; + * struct perf_overhead_entry entry; + * struct sample_id sample_id; + * }; + */ + PERF_RECORD_OVERHEAD = 16, + PERF_RECORD_MAX, /* non-ABI */ }; @@ -980,4 +991,26 @@ struct perf_branch_entry { reserved:44; }; +enum perf_record_overhead_type { + PERF_NMI_OVERHEAD = 0, + PERF_MUX_OVERHEAD, + PERF_SB_OVERHEAD, + + PERF_OVERHEAD_MAX, +}; + +/* + * single overhead record layout: + * + * cpu: The cpu which overhead occues + * nr: Times of overhead happens. + * E.g. for NMI, nr == times of NMI handler are called. + * time: Total overhead cost(ns) + */ +struct perf_overhead_entry { + __u32 cpu; + __u64 nr; + __u64 time; +}; + #endif /* _UAPI_LINUX_PERF_EVENT_H */ diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt index 2d17462..fea8bea 100644 --- a/tools/perf/Documentation/perf-report.txt +++ b/tools/perf/Documentation/perf-report.txt @@ -412,6 +412,9 @@ include::itrace.txt[] --hierarchy:: Enable hierarchical output. +--show-overhead:: + Show extra overhead which perf brings during monitoring + include::callchain-overhead-calculation.txt[] SEE ALSO diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 3dfbfff..1416c39 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -368,6 +368,10 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist, struct perf_evsel *pos; fprintf(stdout, "#\n# Total Lost Samples: %" PRIu64 "\n#\n", evlist->stats.total_lost_samples); + if (symbol_conf.show_overhead) { + fprintf(stdout, "# Overhead:\n"); + fprintf(stdout, "#\n"); + } evlist__for_each_entry(evlist, pos) { struct hists *hists = evsel__hists(pos); const char *evname = perf_evsel__name(pos); @@ -830,6 +834,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) OPT_CALLBACK_DEFAULT(0, "stdio-color", NULL, "mode", "'always' (default), 'never' or 'auto' only applicable to --stdio mode", stdio__config_color, "always"), + OPT_BOOLEAN(0, "show-overhead", &symbol_conf.show_overhead, + "Show perf overhead"), OPT_END() }; struct perf_data_file file = { diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 8ab0d7d..ca98c4c 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -31,6 +31,7 @@ static const char *perf_event__names[] = { [PERF_RECORD_LOST_SAMPLES] = "LOST_SAMPLES", [PERF_RECORD_SWITCH] = "SWITCH", [PERF_RECORD_SWITCH_CPU_WIDE] = "SWITCH_CPU_WIDE", + [PERF_RECORD_OVERHEAD] = "OVERHEAD", [PERF_RECORD_HEADER_ATTR] = "ATTR", [PERF_RECORD_HEADER_EVENT_TYPE] = "EVENT_TYPE", [PERF_RECORD_HEADER_TRACING_DATA] = "TRACING_DATA", @@ -1056,6 +1057,14 @@ int perf_event__process_switch(struct perf_tool *tool __maybe_unused, return machine__process_switch_event(machine, event); } +int perf_event__process_overhead(struct perf_tool *tool __maybe_unused, + union perf_event *event, + struct perf_sample *sample __maybe_unused, + struct machine *machine) +{ + return machine__process_overhead_event(machine, event); +} + size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp) { return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 "]: %c %s\n", diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index c735c53..d1b179b 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h @@ -480,6 +480,12 @@ struct time_conv_event { u64 time_zero; }; +struct perf_overhead { + struct perf_event_header header; + u32 type; + struct perf_overhead_entry entry; +}; + union perf_event { struct perf_event_header header; struct mmap_event mmap; @@ -509,6 +515,7 @@ union perf_event { struct stat_event stat; struct stat_round_event stat_round; struct time_conv_event time_conv; + struct perf_overhead overhead; }; void perf_event__print_totals(void); @@ -587,6 +594,10 @@ int perf_event__process_switch(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, struct machine *machine); +int perf_event__process_overhead(struct perf_tool *tool, + union perf_event *event, + struct perf_sample *sample, + struct machine *machine); int perf_event__process_mmap(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 9b33bef..1101757 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -555,6 +555,12 @@ int machine__process_switch_event(struct machine *machine __maybe_unused, return 0; } +int machine__process_overhead_event(struct machine *machine __maybe_unused, + union perf_event *event __maybe_unused) +{ + return 0; +} + static void dso__adjust_kmod_long_name(struct dso *dso, const char *filename) { const char *dup_filename; @@ -1536,6 +1542,8 @@ int machine__process_event(struct machine *machine, union perf_event *event, case PERF_RECORD_SWITCH: case PERF_RECORD_SWITCH_CPU_WIDE: ret = machine__process_switch_event(machine, event); break; + case PERF_RECORD_OVERHEAD: + ret = machine__process_overhead_event(machine, event); break; default: ret = -1; break; diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h index 354de6e..ec2dd4d 100644 --- a/tools/perf/util/machine.h +++ b/tools/perf/util/machine.h @@ -97,6 +97,8 @@ int machine__process_itrace_start_event(struct machine *machine, union perf_event *event); int machine__process_switch_event(struct machine *machine, union perf_event *event); +int machine__process_overhead_event(struct machine *machine, + union perf_event *event); int machine__process_mmap_event(struct machine *machine, union perf_event *event, struct perf_sample *sample); int machine__process_mmap2_event(struct machine *machine, union perf_event *event, diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index f268201..bc0bc21 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -373,6 +373,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool) tool->itrace_start = perf_event__process_itrace_start; if (tool->context_switch == NULL) tool->context_switch = perf_event__process_switch; + if (tool->overhead == NULL) + tool->overhead = perf_event__process_overhead; if (tool->read == NULL) tool->read = process_event_sample_stub; if (tool->throttle == NULL) @@ -786,6 +788,7 @@ static perf_event__swap_op perf_event__swap_ops[] = { [PERF_RECORD_LOST_SAMPLES] = perf_event__all64_swap, [PERF_RECORD_SWITCH] = perf_event__switch_swap, [PERF_RECORD_SWITCH_CPU_WIDE] = perf_event__switch_swap, + [PERF_RECORD_OVERHEAD] = perf_event__all64_swap, [PERF_RECORD_HEADER_ATTR] = perf_event__hdr_attr_swap, [PERF_RECORD_HEADER_EVENT_TYPE] = perf_event__event_type_swap, [PERF_RECORD_HEADER_TRACING_DATA] = perf_event__tracing_data_swap, @@ -1267,6 +1270,8 @@ static int machines__deliver_event(struct machines *machines, case PERF_RECORD_SWITCH: case PERF_RECORD_SWITCH_CPU_WIDE: return tool->context_switch(tool, event, sample, machine); + case PERF_RECORD_OVERHEAD: + return tool->overhead(tool, event, sample, machine); default: ++evlist->stats.nr_unknown_events; return -1; diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 2d0a905..2d96bdb 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -117,7 +117,8 @@ struct symbol_conf { show_ref_callgraph, hide_unresolved, raw_trace, - report_hierarchy; + report_hierarchy, + show_overhead; const char *vmlinux_name, *kallsyms_name, *source_prefix, diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h index ac2590a..c5bbb34 100644 --- a/tools/perf/util/tool.h +++ b/tools/perf/util/tool.h @@ -47,6 +47,7 @@ struct perf_tool { aux, itrace_start, context_switch, + overhead, throttle, unthrottle; event_attr_op attr; -- 2.5.5