aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKan Liang <kan.liang@intel.com>2015-05-10 15:13:15 -0400
committerIngo Molnar <mingo@kernel.org>2015-06-07 10:09:06 -0400
commitc4937a91ea56b546234b0608a413ebad90536d26 (patch)
tree5bcefc489a99022a8ffb70d5328703286a42885d
parentf38b0dbb491a6987e198aa6b428db8692a6480f8 (diff)
perf tools: handle PERF_RECORD_LOST_SAMPLES
This patch modifies the perf tool to handle the new RECORD type, PERF_RECORD_LOST_SAMPLES. The number of lost-sample events is stored in .nr_events[PERF_RECORD_LOST_SAMPLES]. The exact number of samples which the kernel dropped is stored in total_lost_samples. When the percentage of dropped samples is greater than 5%, a warning is printed. Here are some examples: Eg 1, Recording different frequently-occurring events is safe with the patch. Only a very low drop rate is associated with such actions. $ perf record -e '{cycles:p,instructions:p}' -c 20003 --no-time ~/tchain ~/tchain $ perf report -D | tail SAMPLE events: 120243 MMAP2 events: 5 LOST_SAMPLES events: 24 FINISHED_ROUND events: 15 cycles:p stats: TOTAL events: 59348 SAMPLE events: 59348 instructions:p stats: TOTAL events: 60895 SAMPLE events: 60895 $ perf report --stdio --group # To display the perf.data header info, please use --header/--header-only options. # # # Total Lost Samples: 24 # # Samples: 120K of event 'anon group { cycles:p, instructions:p }' # Event count (approx.): 24048600000 # # Overhead Command Shared Object Symbol # ................ ........... ................ .................................. # 99.74% 99.86% tchain_edit tchain_edit [.] f3 0.09% 0.02% tchain_edit tchain_edit [.] f2 0.04% 0.00% tchain_edit [kernel.vmlinux] [k] ixgbe_read_reg Eg 2, Recording the same thing multiple times can lead to high drop rate, but it is not a useful configuration. $ perf record -e '{cycles:p,cycles:p}' -c 20003 --no-time ~/tchain Warning: Processed 600592 samples and lost 99.73% samples! [perf record: Woken up 148 times to write data] [perf record: Captured and wrote 36.922 MB perf.data (1206322 samples)] [perf record: Woken up 1 times to write data] [perf record: Captured and wrote 0.121 MB perf.data (1629 samples)] Signed-off-by: Kan Liang <kan.liang@intel.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: acme@infradead.org Cc: eranian@google.com Link: http://lkml.kernel.org/r/1431285195-14269-9-git-send-email-kan.liang@intel.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--tools/perf/builtin-report.c1
-rw-r--r--tools/perf/util/event.c9
-rw-r--r--tools/perf/util/event.h17
-rw-r--r--tools/perf/util/machine.c10
-rw-r--r--tools/perf/util/machine.h2
-rw-r--r--tools/perf/util/session.c19
-rw-r--r--tools/perf/util/tool.h1
7 files changed, 59 insertions, 0 deletions
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 56025d90622f..628090b478ab 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -320,6 +320,7 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
320{ 320{
321 struct perf_evsel *pos; 321 struct perf_evsel *pos;
322 322
323 fprintf(stdout, "#\n# Total Lost Samples: %lu\n#\n", evlist->stats.total_lost_samples);
323 evlist__for_each(evlist, pos) { 324 evlist__for_each(evlist, pos) {
324 struct hists *hists = evsel__hists(pos); 325 struct hists *hists = evsel__hists(pos);
325 const char *evname = perf_evsel__name(pos); 326 const char *evname = perf_evsel__name(pos);
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index c1925968a8af..793b1503d437 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -25,6 +25,7 @@ static const char *perf_event__names[] = {
25 [PERF_RECORD_SAMPLE] = "SAMPLE", 25 [PERF_RECORD_SAMPLE] = "SAMPLE",
26 [PERF_RECORD_AUX] = "AUX", 26 [PERF_RECORD_AUX] = "AUX",
27 [PERF_RECORD_ITRACE_START] = "ITRACE_START", 27 [PERF_RECORD_ITRACE_START] = "ITRACE_START",
28 [PERF_RECORD_LOST_SAMPLES] = "LOST_SAMPLES",
28 [PERF_RECORD_HEADER_ATTR] = "ATTR", 29 [PERF_RECORD_HEADER_ATTR] = "ATTR",
29 [PERF_RECORD_HEADER_EVENT_TYPE] = "EVENT_TYPE", 30 [PERF_RECORD_HEADER_EVENT_TYPE] = "EVENT_TYPE",
30 [PERF_RECORD_HEADER_TRACING_DATA] = "TRACING_DATA", 31 [PERF_RECORD_HEADER_TRACING_DATA] = "TRACING_DATA",
@@ -712,6 +713,14 @@ int perf_event__process_itrace_start(struct perf_tool *tool __maybe_unused,
712 return machine__process_itrace_start_event(machine, event); 713 return machine__process_itrace_start_event(machine, event);
713} 714}
714 715
716int perf_event__process_lost_samples(struct perf_tool *tool __maybe_unused,
717 union perf_event *event,
718 struct perf_sample *sample,
719 struct machine *machine)
720{
721 return machine__process_lost_samples_event(machine, event, sample);
722}
723
715size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp) 724size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp)
716{ 725{
717 return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 "]: %c %s\n", 726 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 97179abc80a1..5dc51ada05df 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -52,6 +52,11 @@ struct lost_event {
52 u64 lost; 52 u64 lost;
53}; 53};
54 54
55struct lost_samples_event {
56 struct perf_event_header header;
57 u64 lost;
58};
59
55/* 60/*
56 * PERF_FORMAT_ENABLED | PERF_FORMAT_RUNNING | PERF_FORMAT_ID 61 * PERF_FORMAT_ENABLED | PERF_FORMAT_RUNNING | PERF_FORMAT_ID
57 */ 62 */
@@ -235,6 +240,12 @@ enum auxtrace_error_type {
235 * total_lost tells exactly how many events the kernel in fact lost, i.e. it is 240 * total_lost tells exactly how many events the kernel in fact lost, i.e. it is
236 * the sum of all struct lost_event.lost fields reported. 241 * the sum of all struct lost_event.lost fields reported.
237 * 242 *
243 * The kernel discards mixed up samples and sends the number in a
244 * PERF_RECORD_LOST_SAMPLES event. The number of lost-samples events is stored
245 * in .nr_events[PERF_RECORD_LOST_SAMPLES] while total_lost_samples tells
246 * exactly how many samples the kernel in fact dropped, i.e. it is the sum of
247 * all struct lost_samples_event.lost fields reported.
248 *
238 * The total_period is needed because by default auto-freq is used, so 249 * The total_period is needed because by default auto-freq is used, so
239 * multipling nr_events[PERF_EVENT_SAMPLE] by a frequency isn't possible to get 250 * multipling nr_events[PERF_EVENT_SAMPLE] by a frequency isn't possible to get
240 * the total number of low level events, it is necessary to to sum all struct 251 * the total number of low level events, it is necessary to to sum all struct
@@ -244,6 +255,7 @@ struct events_stats {
244 u64 total_period; 255 u64 total_period;
245 u64 total_non_filtered_period; 256 u64 total_non_filtered_period;
246 u64 total_lost; 257 u64 total_lost;
258 u64 total_lost_samples;
247 u64 total_invalid_chains; 259 u64 total_invalid_chains;
248 u32 nr_events[PERF_RECORD_HEADER_MAX]; 260 u32 nr_events[PERF_RECORD_HEADER_MAX];
249 u32 nr_non_filtered_samples; 261 u32 nr_non_filtered_samples;
@@ -342,6 +354,7 @@ union perf_event {
342 struct comm_event comm; 354 struct comm_event comm;
343 struct fork_event fork; 355 struct fork_event fork;
344 struct lost_event lost; 356 struct lost_event lost;
357 struct lost_samples_event lost_samples;
345 struct read_event read; 358 struct read_event read;
346 struct throttle_event throttle; 359 struct throttle_event throttle;
347 struct sample_event sample; 360 struct sample_event sample;
@@ -390,6 +403,10 @@ int perf_event__process_lost(struct perf_tool *tool,
390 union perf_event *event, 403 union perf_event *event,
391 struct perf_sample *sample, 404 struct perf_sample *sample,
392 struct machine *machine); 405 struct machine *machine);
406int perf_event__process_lost_samples(struct perf_tool *tool,
407 union perf_event *event,
408 struct perf_sample *sample,
409 struct machine *machine);
393int perf_event__process_aux(struct perf_tool *tool, 410int perf_event__process_aux(struct perf_tool *tool,
394 union perf_event *event, 411 union perf_event *event,
395 struct perf_sample *sample, 412 struct perf_sample *sample,
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 9e02c86f39f5..f15ed24a22ac 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -482,6 +482,14 @@ int machine__process_lost_event(struct machine *machine __maybe_unused,
482 return 0; 482 return 0;
483} 483}
484 484
485int machine__process_lost_samples_event(struct machine *machine __maybe_unused,
486 union perf_event *event, struct perf_sample *sample)
487{
488 dump_printf(": id:%" PRIu64 ": lost samples :%" PRIu64 "\n",
489 sample->id, event->lost_samples.lost);
490 return 0;
491}
492
485static struct dso* 493static struct dso*
486machine__module_dso(struct machine *machine, struct kmod_path *m, 494machine__module_dso(struct machine *machine, struct kmod_path *m,
487 const char *filename) 495 const char *filename)
@@ -1419,6 +1427,8 @@ int machine__process_event(struct machine *machine, union perf_event *event,
1419 ret = machine__process_aux_event(machine, event); break; 1427 ret = machine__process_aux_event(machine, event); break;
1420 case PERF_RECORD_ITRACE_START: 1428 case PERF_RECORD_ITRACE_START:
1421 ret = machine__process_itrace_start_event(machine, event); 1429 ret = machine__process_itrace_start_event(machine, event);
1430 case PERF_RECORD_LOST_SAMPLES:
1431 ret = machine__process_lost_samples_event(machine, event, sample); break;
1422 break; 1432 break;
1423 default: 1433 default:
1424 ret = -1; 1434 ret = -1;
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index 39a0ca06cbd8..8e1f796fd137 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -81,6 +81,8 @@ int machine__process_fork_event(struct machine *machine, union perf_event *event
81 struct perf_sample *sample); 81 struct perf_sample *sample);
82int machine__process_lost_event(struct machine *machine, union perf_event *event, 82int machine__process_lost_event(struct machine *machine, union perf_event *event,
83 struct perf_sample *sample); 83 struct perf_sample *sample);
84int machine__process_lost_samples_event(struct machine *machine, union perf_event *event,
85 struct perf_sample *sample);
84int machine__process_aux_event(struct machine *machine, 86int machine__process_aux_event(struct machine *machine,
85 union perf_event *event); 87 union perf_event *event);
86int machine__process_itrace_start_event(struct machine *machine, 88int machine__process_itrace_start_event(struct machine *machine,
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 39fe09d5a87e..88d87bf3049f 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -325,6 +325,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
325 tool->exit = process_event_stub; 325 tool->exit = process_event_stub;
326 if (tool->lost == NULL) 326 if (tool->lost == NULL)
327 tool->lost = perf_event__process_lost; 327 tool->lost = perf_event__process_lost;
328 if (tool->lost_samples == NULL)
329 tool->lost_samples = perf_event__process_lost_samples;
328 if (tool->aux == NULL) 330 if (tool->aux == NULL)
329 tool->aux = perf_event__process_aux; 331 tool->aux = perf_event__process_aux;
330 if (tool->itrace_start == NULL) 332 if (tool->itrace_start == NULL)
@@ -606,6 +608,7 @@ static perf_event__swap_op perf_event__swap_ops[] = {
606 [PERF_RECORD_SAMPLE] = perf_event__all64_swap, 608 [PERF_RECORD_SAMPLE] = perf_event__all64_swap,
607 [PERF_RECORD_AUX] = perf_event__aux_swap, 609 [PERF_RECORD_AUX] = perf_event__aux_swap,
608 [PERF_RECORD_ITRACE_START] = perf_event__itrace_start_swap, 610 [PERF_RECORD_ITRACE_START] = perf_event__itrace_start_swap,
611 [PERF_RECORD_LOST_SAMPLES] = perf_event__all64_swap,
609 [PERF_RECORD_HEADER_ATTR] = perf_event__hdr_attr_swap, 612 [PERF_RECORD_HEADER_ATTR] = perf_event__hdr_attr_swap,
610 [PERF_RECORD_HEADER_EVENT_TYPE] = perf_event__event_type_swap, 613 [PERF_RECORD_HEADER_EVENT_TYPE] = perf_event__event_type_swap,
611 [PERF_RECORD_HEADER_TRACING_DATA] = perf_event__tracing_data_swap, 614 [PERF_RECORD_HEADER_TRACING_DATA] = perf_event__tracing_data_swap,
@@ -1049,6 +1052,10 @@ static int machines__deliver_event(struct machines *machines,
1049 if (tool->lost == perf_event__process_lost) 1052 if (tool->lost == perf_event__process_lost)
1050 evlist->stats.total_lost += event->lost.lost; 1053 evlist->stats.total_lost += event->lost.lost;
1051 return tool->lost(tool, event, sample, machine); 1054 return tool->lost(tool, event, sample, machine);
1055 case PERF_RECORD_LOST_SAMPLES:
1056 if (tool->lost_samples == perf_event__process_lost_samples)
1057 evlist->stats.total_lost_samples += event->lost_samples.lost;
1058 return tool->lost_samples(tool, event, sample, machine);
1052 case PERF_RECORD_READ: 1059 case PERF_RECORD_READ:
1053 return tool->read(tool, event, sample, evsel, machine); 1060 return tool->read(tool, event, sample, evsel, machine);
1054 case PERF_RECORD_THROTTLE: 1061 case PERF_RECORD_THROTTLE:
@@ -1286,6 +1293,18 @@ static void perf_session__warn_about_errors(const struct perf_session *session)
1286 stats->nr_events[PERF_RECORD_LOST]); 1293 stats->nr_events[PERF_RECORD_LOST]);
1287 } 1294 }
1288 1295
1296 if (session->tool->lost_samples == perf_event__process_lost_samples) {
1297 double drop_rate;
1298
1299 drop_rate = (double)stats->total_lost_samples /
1300 (double) (stats->nr_events[PERF_RECORD_SAMPLE] + stats->total_lost_samples);
1301 if (drop_rate > 0.05) {
1302 ui__warning("Processed %lu samples and lost %3.2f%% samples!\n\n",
1303 stats->nr_events[PERF_RECORD_SAMPLE] + stats->total_lost_samples,
1304 drop_rate * 100.0);
1305 }
1306 }
1307
1289 if (stats->nr_unknown_events != 0) { 1308 if (stats->nr_unknown_events != 0) {
1290 ui__warning("Found %u unknown events!\n\n" 1309 ui__warning("Found %u unknown events!\n\n"
1291 "Is this an older tool processing a perf.data " 1310 "Is this an older tool processing a perf.data "
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
index 7f282ad1d2bd..c307dd438286 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -43,6 +43,7 @@ struct perf_tool {
43 fork, 43 fork,
44 exit, 44 exit,
45 lost, 45 lost,
46 lost_samples,
46 aux, 47 aux,
47 itrace_start, 48 itrace_start,
48 throttle, 49 throttle,