aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2011-10-29 10:15:04 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2011-11-02 10:27:23 -0400
commit7b27509fc62686c53e9301560034e6b0b001174d (patch)
tree7b4fc36012d76d5319537df73fd5f7f50104b137 /tools
parent1ca4ff41a3d887b8211e4a6c6c89c8f153d6bfa0 (diff)
perf hists browser: Warn about lost events
Just like the old perf top --tui and the --stdio version. But because we have the initial menu to choose which event to show in a session with multiple events we can see how many chunks were lost in each of the event types, clarifying which events are being affected the most. Cc: David Ahern <dsahern@gmail.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Link: http://lkml.kernel.org/n/tip-47yyqbubmjzch2chezmb21m6@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/builtin-top.c37
-rw-r--r--tools/perf/util/hist.h1
-rw-r--r--tools/perf/util/session.c29
-rw-r--r--tools/perf/util/top.h1
-rw-r--r--tools/perf/util/ui/browser.c21
-rw-r--r--tools/perf/util/ui/browser.h3
-rw-r--r--tools/perf/util/ui/browsers/hists.c49
7 files changed, 112 insertions, 29 deletions
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 31aa82c39e2..8577bfeb087 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -89,6 +89,7 @@ static bool vmlinux_warned;
89static bool inherit = false; 89static bool inherit = false;
90static int realtime_prio = 0; 90static int realtime_prio = 0;
91static bool group = false; 91static bool group = false;
92static bool sample_id_all_avail = true;
92static unsigned int mmap_pages = 128; 93static unsigned int mmap_pages = 128;
93 94
94static bool dump_symtab = false; 95static bool dump_symtab = false;
@@ -289,11 +290,13 @@ static void print_sym_table(void)
289 290
290 printf("%-*.*s\n", win_width, win_width, graph_dotted_line); 291 printf("%-*.*s\n", win_width, win_width, graph_dotted_line);
291 292
292 if (top.total_lost_warned != top.session->hists.stats.total_lost) { 293 if (top.sym_evsel->hists.stats.nr_lost_warned !=
293 top.total_lost_warned = top.session->hists.stats.total_lost; 294 top.sym_evsel->hists.stats.nr_events[PERF_RECORD_LOST]) {
294 color_fprintf(stdout, PERF_COLOR_RED, "WARNING:"); 295 top.sym_evsel->hists.stats.nr_lost_warned =
295 printf(" LOST %" PRIu64 " events, Check IO/CPU overload\n", 296 top.sym_evsel->hists.stats.nr_events[PERF_RECORD_LOST];
296 top.total_lost_warned); 297 color_fprintf(stdout, PERF_COLOR_RED,
298 "WARNING: LOST %d chunks, Check IO/CPU overload",
299 top.sym_evsel->hists.stats.nr_lost_warned);
297 ++printed; 300 ++printed;
298 } 301 }
299 302
@@ -671,6 +674,7 @@ static int symbol_filter(struct map *map __used, struct symbol *sym)
671} 674}
672 675
673static void perf_event__process_sample(const union perf_event *event, 676static void perf_event__process_sample(const union perf_event *event,
677 struct perf_evsel *evsel,
674 struct perf_sample *sample, 678 struct perf_sample *sample,
675 struct perf_session *session) 679 struct perf_session *session)
676{ 680{
@@ -770,12 +774,8 @@ static void perf_event__process_sample(const union perf_event *event,
770 } 774 }
771 775
772 if (al.sym == NULL || !al.sym->ignore) { 776 if (al.sym == NULL || !al.sym->ignore) {
773 struct perf_evsel *evsel;
774 struct hist_entry *he; 777 struct hist_entry *he;
775 778
776 evsel = perf_evlist__id2evsel(top.evlist, sample->id);
777 assert(evsel != NULL);
778
779 if ((sort__has_parent || symbol_conf.use_callchain) && 779 if ((sort__has_parent || symbol_conf.use_callchain) &&
780 sample->callchain) { 780 sample->callchain) {
781 err = perf_session__resolve_callchain(session, al.thread, 781 err = perf_session__resolve_callchain(session, al.thread,
@@ -807,6 +807,7 @@ static void perf_event__process_sample(const union perf_event *event,
807static void perf_session__mmap_read_idx(struct perf_session *self, int idx) 807static void perf_session__mmap_read_idx(struct perf_session *self, int idx)
808{ 808{
809 struct perf_sample sample; 809 struct perf_sample sample;
810 struct perf_evsel *evsel;
810 union perf_event *event; 811 union perf_event *event;
811 int ret; 812 int ret;
812 813
@@ -817,10 +818,16 @@ static void perf_session__mmap_read_idx(struct perf_session *self, int idx)
817 continue; 818 continue;
818 } 819 }
819 820
821 evsel = perf_evlist__id2evsel(self->evlist, sample.id);
822 assert(evsel != NULL);
823
820 if (event->header.type == PERF_RECORD_SAMPLE) 824 if (event->header.type == PERF_RECORD_SAMPLE)
821 perf_event__process_sample(event, &sample, self); 825 perf_event__process_sample(event, evsel, &sample, self);
822 else 826 else if (event->header.type < PERF_RECORD_MAX) {
827 hists__inc_nr_events(&evsel->hists, event->header.type);
823 perf_event__process(event, &sample, self); 828 perf_event__process(event, &sample, self);
829 } else
830 ++self->hists.stats.nr_unknown_events;
824 } 831 }
825} 832}
826 833
@@ -864,6 +871,8 @@ static void start_counters(struct perf_evlist *evlist)
864 attr->mmap = 1; 871 attr->mmap = 1;
865 attr->comm = 1; 872 attr->comm = 1;
866 attr->inherit = inherit; 873 attr->inherit = inherit;
874retry_sample_id:
875 attr->sample_id_all = sample_id_all_avail ? 1 : 0;
867try_again: 876try_again:
868 if (perf_evsel__open(counter, top.evlist->cpus, 877 if (perf_evsel__open(counter, top.evlist->cpus,
869 top.evlist->threads, group, 878 top.evlist->threads, group,
@@ -873,6 +882,12 @@ try_again:
873 if (err == EPERM || err == EACCES) { 882 if (err == EPERM || err == EACCES) {
874 ui__error_paranoid(); 883 ui__error_paranoid();
875 goto out_err; 884 goto out_err;
885 } else if (err == EINVAL && sample_id_all_avail) {
886 /*
887 * Old kernel, no attr->sample_id_type_all field
888 */
889 sample_id_all_avail = false;
890 goto retry_sample_id;
876 } 891 }
877 /* 892 /*
878 * If it's cycles then fall back to hrtimer 893 * If it's cycles then fall back to hrtimer
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index ff93ddc91c5..c86c1d27bd1 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -28,6 +28,7 @@ struct events_stats {
28 u64 total_lost; 28 u64 total_lost;
29 u64 total_invalid_chains; 29 u64 total_invalid_chains;
30 u32 nr_events[PERF_RECORD_HEADER_MAX]; 30 u32 nr_events[PERF_RECORD_HEADER_MAX];
31 u32 nr_lost_warned;
31 u32 nr_unknown_events; 32 u32 nr_unknown_events;
32 u32 nr_invalid_chains; 33 u32 nr_invalid_chains;
33 u32 nr_unknown_id; 34 u32 nr_unknown_id;
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 91c6442ef96..da354fe5e08 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -738,10 +738,27 @@ static int perf_session_deliver_event(struct perf_session *session,
738 738
739 dump_event(session, event, file_offset, sample); 739 dump_event(session, event, file_offset, sample);
740 740
741 evsel = perf_evlist__id2evsel(session->evlist, sample->id);
742 if (evsel != NULL && event->header.type != PERF_RECORD_SAMPLE) {
743 /*
744 * XXX We're leaving PERF_RECORD_SAMPLE unnacounted here
745 * because the tools right now may apply filters, discarding
746 * some of the samples. For consistency, in the future we
747 * should have something like nr_filtered_samples and remove
748 * the sample->period from total_sample_period, etc, KISS for
749 * now tho.
750 *
751 * Also testing against NULL allows us to handle files without
752 * attr.sample_id_all and/or without PERF_SAMPLE_ID. In the
753 * future probably it'll be a good idea to restrict event
754 * processing via perf_session to files with both set.
755 */
756 hists__inc_nr_events(&evsel->hists, event->header.type);
757 }
758
741 switch (event->header.type) { 759 switch (event->header.type) {
742 case PERF_RECORD_SAMPLE: 760 case PERF_RECORD_SAMPLE:
743 dump_sample(session, event, sample); 761 dump_sample(session, event, sample);
744 evsel = perf_evlist__id2evsel(session->evlist, sample->id);
745 if (evsel == NULL) { 762 if (evsel == NULL) {
746 ++session->hists.stats.nr_unknown_id; 763 ++session->hists.stats.nr_unknown_id;
747 return -1; 764 return -1;
@@ -874,11 +891,11 @@ static void perf_session__warn_about_errors(const struct perf_session *session,
874 const struct perf_event_ops *ops) 891 const struct perf_event_ops *ops)
875{ 892{
876 if (ops->lost == perf_event__process_lost && 893 if (ops->lost == perf_event__process_lost &&
877 session->hists.stats.total_lost != 0) { 894 session->hists.stats.nr_events[PERF_RECORD_LOST] != 0) {
878 ui__warning("Processed %" PRIu64 " events and LOST %" PRIu64 895 ui__warning("Processed %d events and lost %d chunks!\n\n"
879 "!\n\nCheck IO/CPU overload!\n\n", 896 "Check IO/CPU overload!\n\n",
880 session->hists.stats.total_period, 897 session->hists.stats.nr_events[0],
881 session->hists.stats.total_lost); 898 session->hists.stats.nr_events[PERF_RECORD_LOST]);
882 } 899 }
883 900
884 if (session->hists.stats.nr_unknown_events != 0) { 901 if (session->hists.stats.nr_unknown_events != 0) {
diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h
index 01d1057f307..39965096795 100644
--- a/tools/perf/util/top.h
+++ b/tools/perf/util/top.h
@@ -19,7 +19,6 @@ struct perf_top {
19 u64 kernel_samples, us_samples; 19 u64 kernel_samples, us_samples;
20 u64 exact_samples; 20 u64 exact_samples;
21 u64 guest_us_samples, guest_kernel_samples; 21 u64 guest_us_samples, guest_kernel_samples;
22 u64 total_lost_warned;
23 int print_entries, count_filter, delay_secs; 22 int print_entries, count_filter, delay_secs;
24 int freq; 23 int freq;
25 pid_t target_pid, target_tid; 24 pid_t target_pid, target_tid;
diff --git a/tools/perf/util/ui/browser.c b/tools/perf/util/ui/browser.c
index d2051be04f1..556829124b0 100644
--- a/tools/perf/util/ui/browser.c
+++ b/tools/perf/util/ui/browser.c
@@ -176,16 +176,29 @@ void ui_browser__handle_resize(struct ui_browser *browser)
176 ui_browser__refresh(browser); 176 ui_browser__refresh(browser);
177} 177}
178 178
179int ui_browser__warning(struct ui_browser *browser, const char *format, ...) 179int ui_browser__warning(struct ui_browser *browser, int timeout,
180 const char *format, ...)
180{ 181{
181 va_list args; 182 va_list args;
182 int key; 183 char *text;
184 int key = 0, err;
183 185
184 va_start(args, format); 186 va_start(args, format);
185 while ((key = __ui__warning("Warning!", format, args)) == K_RESIZE) 187 err = vasprintf(&text, format, args);
186 ui_browser__handle_resize(browser);
187 va_end(args); 188 va_end(args);
188 189
190 if (err < 0) {
191 va_start(args, format);
192 ui_helpline__vpush(format, args);
193 va_end(args);
194 } else {
195 while ((key == ui__question_window("Warning!", text,
196 "Press any key...",
197 timeout)) == K_RESIZE)
198 ui_browser__handle_resize(browser);
199 free(text);
200 }
201
189 return key; 202 return key;
190} 203}
191 204
diff --git a/tools/perf/util/ui/browser.h b/tools/perf/util/ui/browser.h
index fb1c59883e6..84d761b730c 100644
--- a/tools/perf/util/ui/browser.h
+++ b/tools/perf/util/ui/browser.h
@@ -45,7 +45,8 @@ int ui_browser__run(struct ui_browser *browser, int delay_secs);
45void ui_browser__update_nr_entries(struct ui_browser *browser, u32 nr_entries); 45void ui_browser__update_nr_entries(struct ui_browser *browser, u32 nr_entries);
46void ui_browser__handle_resize(struct ui_browser *browser); 46void ui_browser__handle_resize(struct ui_browser *browser);
47 47
48int ui_browser__warning(struct ui_browser *browser, const char *format, ...); 48int ui_browser__warning(struct ui_browser *browser, int timeout,
49 const char *format, ...);
49int ui_browser__help_window(struct ui_browser *browser, const char *text); 50int ui_browser__help_window(struct ui_browser *browser, const char *text);
50bool ui_browser__dialog_yesno(struct ui_browser *browser, const char *text); 51bool ui_browser__dialog_yesno(struct ui_browser *browser, const char *text);
51 52
diff --git a/tools/perf/util/ui/browsers/hists.c b/tools/perf/util/ui/browsers/hists.c
index b8733c0770c..d0c94b45968 100644
--- a/tools/perf/util/ui/browsers/hists.c
+++ b/tools/perf/util/ui/browsers/hists.c
@@ -295,6 +295,15 @@ static void hist_browser__set_folding(struct hist_browser *self, bool unfold)
295 ui_browser__reset_index(&self->b); 295 ui_browser__reset_index(&self->b);
296} 296}
297 297
298static void ui_browser__warn_lost_events(struct ui_browser *browser)
299{
300 ui_browser__warning(browser, 4,
301 "Events are being lost, check IO/CPU overload!\n\n"
302 "You may want to run 'perf' using a RT scheduler policy:\n\n"
303 " perf top -r 80\n\n"
304 "Or reduce the sampling frequency.");
305}
306
298static int hist_browser__run(struct hist_browser *self, const char *ev_name, 307static int hist_browser__run(struct hist_browser *self, const char *ev_name,
299 void(*timer)(void *arg), void *arg, int delay_secs) 308 void(*timer)(void *arg), void *arg, int delay_secs)
300{ 309{
@@ -318,8 +327,15 @@ static int hist_browser__run(struct hist_browser *self, const char *ev_name,
318 case K_TIMER: 327 case K_TIMER:
319 timer(arg); 328 timer(arg);
320 ui_browser__update_nr_entries(&self->b, self->hists->nr_entries); 329 ui_browser__update_nr_entries(&self->b, self->hists->nr_entries);
321 hists__browser_title(self->hists, title, sizeof(title), 330
322 ev_name); 331 if (self->hists->stats.nr_lost_warned !=
332 self->hists->stats.nr_events[PERF_RECORD_LOST]) {
333 self->hists->stats.nr_lost_warned =
334 self->hists->stats.nr_events[PERF_RECORD_LOST];
335 ui_browser__warn_lost_events(&self->b);
336 }
337
338 hists__browser_title(self->hists, title, sizeof(title), ev_name);
323 ui_browser__show_title(&self->b, title); 339 ui_browser__show_title(&self->b, title);
324 continue; 340 continue;
325 case 'D': { /* Debug */ 341 case 'D': { /* Debug */
@@ -883,7 +899,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
883 goto out_free_stack; 899 goto out_free_stack;
884 case 'a': 900 case 'a':
885 if (!browser->has_symbols) { 901 if (!browser->has_symbols) {
886 ui_browser__warning(&browser->b, 902 ui_browser__warning(&browser->b, delay_secs * 2,
887 "Annotation is only available for symbolic views, " 903 "Annotation is only available for symbolic views, "
888 "include \"sym\" in --sort to use it."); 904 "include \"sym\" in --sort to use it.");
889 continue; 905 continue;
@@ -1061,6 +1077,7 @@ out:
1061struct perf_evsel_menu { 1077struct perf_evsel_menu {
1062 struct ui_browser b; 1078 struct ui_browser b;
1063 struct perf_evsel *selection; 1079 struct perf_evsel *selection;
1080 bool lost_events, lost_events_warned;
1064}; 1081};
1065 1082
1066static void perf_evsel_menu__write(struct ui_browser *browser, 1083static void perf_evsel_menu__write(struct ui_browser *browser,
@@ -1073,14 +1090,29 @@ static void perf_evsel_menu__write(struct ui_browser *browser,
1073 unsigned long nr_events = evsel->hists.stats.nr_events[PERF_RECORD_SAMPLE]; 1090 unsigned long nr_events = evsel->hists.stats.nr_events[PERF_RECORD_SAMPLE];
1074 const char *ev_name = event_name(evsel); 1091 const char *ev_name = event_name(evsel);
1075 char bf[256], unit; 1092 char bf[256], unit;
1093 const char *warn = " ";
1094 size_t printed;
1076 1095
1077 ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED : 1096 ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED :
1078 HE_COLORSET_NORMAL); 1097 HE_COLORSET_NORMAL);
1079 1098
1080 nr_events = convert_unit(nr_events, &unit); 1099 nr_events = convert_unit(nr_events, &unit);
1081 snprintf(bf, sizeof(bf), "%lu%c%s%s", nr_events, 1100 printed = snprintf(bf, sizeof(bf), "%lu%c%s%s", nr_events,
1082 unit, unit == ' ' ? "" : " ", ev_name); 1101 unit, unit == ' ' ? "" : " ", ev_name);
1083 slsmg_write_nstring(bf, browser->width); 1102 slsmg_printf("%s", bf);
1103
1104 nr_events = evsel->hists.stats.nr_events[PERF_RECORD_LOST];
1105 if (nr_events != 0) {
1106 menu->lost_events = true;
1107 if (!current_entry)
1108 ui_browser__set_color(browser, HE_COLORSET_TOP);
1109 nr_events = convert_unit(nr_events, &unit);
1110 snprintf(bf, sizeof(bf), ": %ld%c%schunks LOST!", nr_events,
1111 unit, unit == ' ' ? "" : " ");
1112 warn = bf;
1113 }
1114
1115 slsmg_write_nstring(warn, browser->width - printed);
1084 1116
1085 if (current_entry) 1117 if (current_entry)
1086 menu->selection = evsel; 1118 menu->selection = evsel;
@@ -1105,6 +1137,11 @@ static int perf_evsel_menu__run(struct perf_evsel_menu *menu,
1105 switch (key) { 1137 switch (key) {
1106 case K_TIMER: 1138 case K_TIMER:
1107 timer(arg); 1139 timer(arg);
1140
1141 if (!menu->lost_events_warned && menu->lost_events) {
1142 ui_browser__warn_lost_events(&menu->b);
1143 menu->lost_events_warned = true;
1144 }
1108 continue; 1145 continue;
1109 case K_RIGHT: 1146 case K_RIGHT:
1110 case K_ENTER: 1147 case K_ENTER: