From 626a6b784e91bc61ca9fe0f9dd5bb60cb91ccb6b Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Thu, 14 Jul 2016 08:34:45 +0000 Subject: [PATCH] perf tools: Enable overwrite settings This patch allows following config terms and option: Globally setting events to overwrite; # perf record --overwrite ... Set specific events to be overwrite or no-overwrite. # perf record --event cycles/overwrite/ ... # perf record --event cycles/no-overwrite/ ... Add missing config terms and update the config term array size because the longest string length has changed. For overwritable events, it automatically selects attr.write_backward since perf requires it to be backward for reading. Test result: # perf record --overwrite -e syscalls:*enter_nanosleep* usleep 1 [ perf record: Woken up 2 times to write data ] [ perf record: Captured and wrote 0.011 MB perf.data (1 samples) ] # perf evlist -v syscalls:sys_enter_nanosleep: type: 2, size: 112, config: 0x134, { sample_period, sample_freq }: 1, sample_type: IP|TID|TIME|CPU|PERIOD|RAW, disabled: 1, inherit: 1, mmap: 1, comm: 1, enable_on_exec: 1, task: 1, sample_id_all: 1, exclude_guest: 1, mmap2: 1, comm_exec: 1, write_backward: 1 # Tip: use 'perf evlist --trace-fields' to show fields for tracepoint events Signed-off-by: Wang Nan Tested-by: Arnaldo Carvalho de Melo Acked-by: Jiri Olsa Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Nilay Vaish Cc: Zefan Li Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/1468485287-33422-14-git-send-email-wangnan0@huawei.com Signed-off-by: He Kuang Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-record.txt | 14 ++++++++++++++ tools/perf/builtin-record.c | 1 + tools/perf/perf.h | 1 + tools/perf/tests/backward-ring-buffer.c | 10 +++++----- tools/perf/util/evsel.c | 4 ++++ tools/perf/util/evsel.h | 2 ++ tools/perf/util/parse-events.c | 20 ++++++++++++++++++-- tools/perf/util/parse-events.h | 2 ++ tools/perf/util/parse-events.l | 2 ++ 9 files changed, 49 insertions(+), 7 deletions(-) diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt index 5b46b1d1a37c..384c630436f8 100644 --- a/tools/perf/Documentation/perf-record.txt +++ b/tools/perf/Documentation/perf-record.txt @@ -367,6 +367,20 @@ options. 'perf record --dry-run -e' can act as a BPF script compiler if llvm.dump-obj in config file is set to true. +--overwrite:: +Makes all events use an overwritable ring buffer. An overwritable ring +buffer works like a flight recorder: when it gets full, the kernel will +overwrite the oldest records, that thus will never make it to the +perf.data file. + +When '--overwrite' and '--switch-output' are used perf records and drops +events until it receives a signal, meaning that something unusual was +detected that warrants taking a snapshot of the most current events, +those fitting in the ring buffer at that moment. + +'overwrite' attribute can also be set or canceled for an event using +config terms. For example: 'cycles/overwrite/' and 'instructions/no-overwrite/'. + SEE ALSO -------- linkperf:perf-stat[1], linkperf:perf-list[1] diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index b87070b1f492..39c7486f0607 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -1399,6 +1399,7 @@ struct option __record_options[] = { OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit, &record.opts.no_inherit_set, "child tasks do not inherit counters"), + OPT_BOOLEAN(0, "overwrite", &record.opts.overwrite, "use overwrite mode"), OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"), OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]", "number of mmap data pages and AUX area tracing mmap pages", diff --git a/tools/perf/perf.h b/tools/perf/perf.h index cd8f1b150f9e..608b42bdb1b6 100644 --- a/tools/perf/perf.h +++ b/tools/perf/perf.h @@ -59,6 +59,7 @@ struct record_opts { bool record_switch_events; bool all_kernel; bool all_user; + bool overwrite; unsigned int freq; unsigned int mmap_pages; unsigned int auxtrace_mmap_pages; diff --git a/tools/perf/tests/backward-ring-buffer.c b/tools/perf/tests/backward-ring-buffer.c index db9cd3048655..615780cbfe1d 100644 --- a/tools/perf/tests/backward-ring-buffer.c +++ b/tools/perf/tests/backward-ring-buffer.c @@ -108,7 +108,11 @@ int test__backward_ring_buffer(int subtest __maybe_unused) } bzero(&parse_error, sizeof(parse_error)); - err = parse_events(evlist, "syscalls:sys_enter_prctl", &parse_error); + /* + * Set backward bit, ring buffer should be writing from end. Record + * it in aux evlist + */ + err = parse_events(evlist, "syscalls:sys_enter_prctl/overwrite/", &parse_error); if (err) { pr_debug("Failed to parse tracepoint event, try use root\n"); ret = TEST_SKIP; @@ -117,10 +121,6 @@ int test__backward_ring_buffer(int subtest __maybe_unused) perf_evlist__config(evlist, &opts, NULL); - /* Set backward bit, ring buffer should be writing from end */ - evlist__for_each_entry(evlist, evsel) - evsel->attr.write_backward = 1; - err = perf_evlist__open(evlist); if (err < 0) { pr_debug("perf_evlist__open: %s\n", diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 9ac2f92ce88d..8c54df61fe64 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -695,6 +695,9 @@ static void apply_config_terms(struct perf_evsel *evsel, */ attr->inherit = term->val.inherit ? 1 : 0; break; + case PERF_EVSEL__CONFIG_TERM_OVERWRITE: + attr->write_backward = term->val.overwrite ? 1 : 0; + break; default: break; } @@ -776,6 +779,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts, attr->sample_id_all = perf_missing_features.sample_id_all ? 0 : 1; attr->inherit = !opts->no_inherit; + attr->write_backward = opts->overwrite ? 1 : 0; perf_evsel__set_sample_bit(evsel, IP); perf_evsel__set_sample_bit(evsel, TID); diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index e60cbfc2cd35..8a4a6c9f1480 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -45,6 +45,7 @@ enum { PERF_EVSEL__CONFIG_TERM_STACK_USER, PERF_EVSEL__CONFIG_TERM_INHERIT, PERF_EVSEL__CONFIG_TERM_MAX_STACK, + PERF_EVSEL__CONFIG_TERM_OVERWRITE, PERF_EVSEL__CONFIG_TERM_MAX, }; @@ -59,6 +60,7 @@ struct perf_evsel_config_term { u64 stack_user; int max_stack; bool inherit; + bool overwrite; } val; }; diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 375af0e02831..6c913c3914fb 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -902,6 +902,8 @@ static const char *config_term_names[__PARSE_EVENTS__TERM_TYPE_NR] = { [PARSE_EVENTS__TERM_TYPE_NOINHERIT] = "no-inherit", [PARSE_EVENTS__TERM_TYPE_INHERIT] = "inherit", [PARSE_EVENTS__TERM_TYPE_MAX_STACK] = "max-stack", + [PARSE_EVENTS__TERM_TYPE_OVERWRITE] = "overwrite", + [PARSE_EVENTS__TERM_TYPE_NOOVERWRITE] = "no-overwrite", }; static bool config_term_shrinked; @@ -994,6 +996,12 @@ do { \ case PARSE_EVENTS__TERM_TYPE_NOINHERIT: CHECK_TYPE_VAL(NUM); break; + case PARSE_EVENTS__TERM_TYPE_OVERWRITE: + CHECK_TYPE_VAL(NUM); + break; + case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE: + CHECK_TYPE_VAL(NUM); + break; case PARSE_EVENTS__TERM_TYPE_NAME: CHECK_TYPE_VAL(STR); break; @@ -1046,6 +1054,8 @@ static int config_term_tracepoint(struct perf_event_attr *attr, case PARSE_EVENTS__TERM_TYPE_INHERIT: case PARSE_EVENTS__TERM_TYPE_NOINHERIT: case PARSE_EVENTS__TERM_TYPE_MAX_STACK: + case PARSE_EVENTS__TERM_TYPE_OVERWRITE: + case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE: return config_term_common(attr, term, err); default: if (err) { @@ -1118,6 +1128,12 @@ do { \ case PARSE_EVENTS__TERM_TYPE_MAX_STACK: ADD_CONFIG_TERM(MAX_STACK, max_stack, term->val.num); break; + case PARSE_EVENTS__TERM_TYPE_OVERWRITE: + ADD_CONFIG_TERM(OVERWRITE, overwrite, term->val.num ? 1 : 0); + break; + case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE: + ADD_CONFIG_TERM(OVERWRITE, overwrite, term->val.num ? 0 : 1); + break; default: break; } @@ -2412,9 +2428,9 @@ static void config_terms_list(char *buf, size_t buf_sz) char *parse_events_formats_error_string(char *additional_terms) { char *str; - /* "branch_type" is the longest name */ + /* "no-overwrite" is the longest name */ char static_terms[__PARSE_EVENTS__TERM_TYPE_NR * - (sizeof("branch_type") - 1)]; + (sizeof("no-overwrite") - 1)]; config_terms_list(static_terms, sizeof(static_terms)); /* valid terms */ diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index b4aa7eb2df73..d1edbf8cc66a 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h @@ -69,6 +69,8 @@ enum { PARSE_EVENTS__TERM_TYPE_NOINHERIT, PARSE_EVENTS__TERM_TYPE_INHERIT, PARSE_EVENTS__TERM_TYPE_MAX_STACK, + PARSE_EVENTS__TERM_TYPE_NOOVERWRITE, + PARSE_EVENTS__TERM_TYPE_OVERWRITE, __PARSE_EVENTS__TERM_TYPE_NR, }; diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l index 3c15b33b2e84..7a2519435da0 100644 --- a/tools/perf/util/parse-events.l +++ b/tools/perf/util/parse-events.l @@ -202,6 +202,8 @@ stack-size { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_STACKSIZE); } max-stack { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_MAX_STACK); } inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_INHERIT); } no-inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOINHERIT); } +overwrite { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_OVERWRITE); } +no-overwrite { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOOVERWRITE); } , { return ','; } "/" { BEGIN(INITIAL); return '/'; } {name_minus} { return str(yyscanner, PE_NAME); } -- 2.20.1