diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2012-10-17 16:13:12 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2012-10-25 08:57:43 -0400 |
commit | 1302d88e66f12a7b46a5598e641d93f0713007e0 (patch) | |
tree | 7a68411556ee154d201d8635a1c542152bae34c3 /tools/perf/builtin-trace.c | |
parent | efd5745e43f3aabd95d521289e0caa0e30668cf4 (diff) |
perf trace: Use sched:sched_stat_runtime to provide a thread summary
[root@sandy ~]# perf trace --sched --duration 0.100 --pid `pidof firefox`
<SNIP>
17079.847 ( 0.009 ms): 17643 poll(ufds: 140037623086496, nfds: 11, timeout_msecs: 0) = 0 Timeout
17079.892 ( 0.010 ms): 17643 read(fd: 4, buf: 140038178943092, count: 4096 ) = -1 EAGAIN Resource temporarily unavailable
17079.921 ( 0.013 ms): 17643 poll(ufds: 140037623086496, nfds: 11, timeout_msecs: 0) = 0 Timeout
17079.949 ( 0.009 ms): 17643 read(fd: 4, buf: 140038178943092, count: 4096 ) = -1 EAGAIN Resource temporarily unavailable
^C
_____________________________________________________________________
__) Summary of events (__
[ task - pid ] [ events ] [ ratio ] [ runtime ]
_____________________________________________________________________
firefox - 17643 : 18013 [ 72.2% ] 359.110 ms
firefox - 17663 : 41 [ 0.2% ] 21.439 ms
firefox - 17664 : 6840 [ 27.4% ] 133.642 ms
firefox - 17667 : 46 [ 0.2% ] 0.682 ms
[root@sandy ~]#
This is equivalent to the 'perf trace summary' subcomand in the tmp.perf/trace2
branch.
Another example, setting a huge duration filter to get just a system
wide summary:
[root@sandy ~]# perf trace --duration 10000.0 --sched
^C
_____________________________________________________________________
__) Summary of events (__
[ task - pid ] [ events ] [ ratio ] [ runtime ]
_____________________________________________________________________
scsi_eh_1 - 258 : 15 [ 0.0% ] 0.133 ms
kworker/0:1H - 322 : 13 [ 0.0% ] 0.032 ms
jbd2/dm-0-8 - 384 : 4 [ 0.0% ] 0.115 ms
flush-253:0 - 470 : 1 [ 0.0% ] 0.027 ms
firefox - 950 : 4783 [ 0.1% ] 24.863 ms
firefox - 992 : 1883 [ 0.1% ] 6.808 ms
firefox - 995 : 35 [ 0.0% ] 0.111 ms
ksoftirqd/6 - 4362 : 2 [ 0.0% ] 0.005 ms
ksoftirqd/7 - 4365 : 1 [ 0.0% ] 0.007 ms
Xorg - 4671 : 148 [ 0.0% ] 0.912 ms
gnome-settings- - 4846 : 14 [ 0.0% ] 0.086 ms
seahorse-daemon - 4847 : 14 [ 0.0% ] 0.092 ms
gnome-panel - 4875 : 46 [ 0.0% ] 0.159 ms
gnome-power-man - 4918 : 16 [ 0.0% ] 0.065 ms
gvfs-afc-volume - 4992 : 77 [ 0.0% ] 0.136 ms
gnome-screensav - 5114 : 24 [ 0.0% ] 0.128 ms
xchat - 8082 : 466 [ 0.0% ] 2.019 ms
synergyc - 8369 : 941 [ 0.0% ] 3.291 ms
synergyc - 8371 : 85 [ 0.0% ] 1.817 ms
jbd2/dm-4-8 - 9352 : 4 [ 0.0% ] 0.109 ms
rpcbind - 9786 : 3 [ 0.0% ] 0.017 ms
rtkit-daemon - 12802 : 10 [ 0.0% ] 0.038 ms
rtkit-daemon - 12803 : 8 [ 0.0% ] 0.000 ms
udisks-daemon - 13020 : 27 [ 0.0% ] 0.240 ms
kworker/7:0 - 14651 : 669 [ 0.0% ] 2.616 ms
kworker/5:1 - 16220 : 2 [ 0.0% ] 0.069 ms
kworker/4:0 - 19776 : 13 [ 0.0% ] 0.176 ms
openvpn - 20131 : 133 [ 0.0% ] 0.762 ms
plugin-containe - 20508 : 60658 [ 1.7% ] 131.153 ms
npviewer.bin - 20520 : 72208 [ 2.0% ] 138.945 ms
npviewer.bin - 20542 : 35 [ 0.0% ] 0.074 ms
npviewer.bin - 20543 : 30 [ 0.0% ] 0.074 ms
npviewer.bin - 20547 : 35 [ 0.0% ] 0.092 ms
npviewer.bin - 20552 : 35 [ 0.0% ] 0.093 ms
sshd - 20645 : 32 [ 0.0% ] 0.071 ms
npviewer.bin - 21053 : 35 [ 0.0% ] 0.074 ms
npviewer.bin - 21054 : 35 [ 0.0% ] 0.097 ms
kworker/0:2 - 21169 : 149 [ 0.0% ] 1.143 ms
kworker/3:0 - 22171 : 113 [ 0.0% ] 96.892 ms
flush-253:4 - 22410 : 1 [ 0.0% ] 0.028 ms
kworker/6:0 - 24581 : 25 [ 0.0% ] 0.275 ms
kworker/1:0 - 25572 : 4 [ 0.0% ] 0.103 ms
kworker/2:1 - 26299 : 138 [ 0.0% ] 1.440 ms
kworker/0:0 - 26325 : 1 [ 0.0% ] 0.003 ms
perf - 26330 : 3506967 [ 96.1% ] 6648.310 ms
[root@sandy ~]#
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Namhyung Kim <namhyung@gmail.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/n/tip-mzuli0srnxyi1o029py6537x@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/builtin-trace.c')
-rw-r--r-- | tools/perf/builtin-trace.c | 88 |
1 files changed, 87 insertions, 1 deletions
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index c95a3e9b0331..7932ffa29889 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c | |||
@@ -69,6 +69,7 @@ struct thread_trace { | |||
69 | bool entry_pending; | 69 | bool entry_pending; |
70 | unsigned long nr_events; | 70 | unsigned long nr_events; |
71 | char *entry_str; | 71 | char *entry_str; |
72 | double runtime_ms; | ||
72 | }; | 73 | }; |
73 | 74 | ||
74 | static struct thread_trace *thread_trace__new(void) | 75 | static struct thread_trace *thread_trace__new(void) |
@@ -109,8 +110,10 @@ struct trace { | |||
109 | struct machine host; | 110 | struct machine host; |
110 | u64 base_time; | 111 | u64 base_time; |
111 | unsigned long nr_events; | 112 | unsigned long nr_events; |
113 | bool sched; | ||
112 | bool multiple_threads; | 114 | bool multiple_threads; |
113 | double duration_filter; | 115 | double duration_filter; |
116 | double runtime_ms; | ||
114 | }; | 117 | }; |
115 | 118 | ||
116 | static bool trace__filter_duration(struct trace *trace, double t) | 119 | static bool trace__filter_duration(struct trace *trace, double t) |
@@ -389,6 +392,31 @@ out: | |||
389 | return 0; | 392 | return 0; |
390 | } | 393 | } |
391 | 394 | ||
395 | static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evsel, | ||
396 | struct perf_sample *sample) | ||
397 | { | ||
398 | u64 runtime = perf_evsel__intval(evsel, sample, "runtime"); | ||
399 | double runtime_ms = (double)runtime / NSEC_PER_MSEC; | ||
400 | struct thread *thread = machine__findnew_thread(&trace->host, sample->tid); | ||
401 | struct thread_trace *ttrace = thread__trace(thread); | ||
402 | |||
403 | if (ttrace == NULL) | ||
404 | goto out_dump; | ||
405 | |||
406 | ttrace->runtime_ms += runtime_ms; | ||
407 | trace->runtime_ms += runtime_ms; | ||
408 | return 0; | ||
409 | |||
410 | out_dump: | ||
411 | printf("%s: comm=%s,pid=%u,runtime=%" PRIu64 ",vruntime=%" PRIu64 ")\n", | ||
412 | evsel->name, | ||
413 | perf_evsel__strval(evsel, sample, "comm"), | ||
414 | (pid_t)perf_evsel__intval(evsel, sample, "pid"), | ||
415 | runtime, | ||
416 | perf_evsel__intval(evsel, sample, "vruntime")); | ||
417 | return 0; | ||
418 | } | ||
419 | |||
392 | static int trace__run(struct trace *trace, int argc, const char **argv) | 420 | static int trace__run(struct trace *trace, int argc, const char **argv) |
393 | { | 421 | { |
394 | struct perf_evlist *evlist = perf_evlist__new(NULL, NULL); | 422 | struct perf_evlist *evlist = perf_evlist__new(NULL, NULL); |
@@ -408,6 +436,13 @@ static int trace__run(struct trace *trace, int argc, const char **argv) | |||
408 | goto out_delete_evlist; | 436 | goto out_delete_evlist; |
409 | } | 437 | } |
410 | 438 | ||
439 | if (trace->sched && | ||
440 | perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime", | ||
441 | trace__sched_stat_runtime)) { | ||
442 | printf("Couldn't read the sched_stat_runtime tracepoint information!\n"); | ||
443 | goto out_delete_evlist; | ||
444 | } | ||
445 | |||
411 | err = perf_evlist__create_maps(evlist, &trace->opts.target); | 446 | err = perf_evlist__create_maps(evlist, &trace->opts.target); |
412 | if (err < 0) { | 447 | if (err < 0) { |
413 | printf("Problems parsing the target to trace, check your options!\n"); | 448 | printf("Problems parsing the target to trace, check your options!\n"); |
@@ -521,6 +556,51 @@ out: | |||
521 | return err; | 556 | return err; |
522 | } | 557 | } |
523 | 558 | ||
559 | static size_t trace__fprintf_threads_header(FILE *fp) | ||
560 | { | ||
561 | size_t printed; | ||
562 | |||
563 | printed = fprintf(fp, "\n _____________________________________________________________________\n"); | ||
564 | printed += fprintf(fp," __) Summary of events (__\n\n"); | ||
565 | printed += fprintf(fp," [ task - pid ] [ events ] [ ratio ] [ runtime ]\n"); | ||
566 | printed += fprintf(fp," _____________________________________________________________________\n\n"); | ||
567 | |||
568 | return printed; | ||
569 | } | ||
570 | |||
571 | static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp) | ||
572 | { | ||
573 | size_t printed = trace__fprintf_threads_header(fp); | ||
574 | struct rb_node *nd; | ||
575 | |||
576 | for (nd = rb_first(&trace->host.threads); nd; nd = rb_next(nd)) { | ||
577 | struct thread *thread = rb_entry(nd, struct thread, rb_node); | ||
578 | struct thread_trace *ttrace = thread->priv; | ||
579 | const char *color; | ||
580 | double ratio; | ||
581 | |||
582 | if (ttrace == NULL) | ||
583 | continue; | ||
584 | |||
585 | ratio = (double)ttrace->nr_events / trace->nr_events * 100.0; | ||
586 | |||
587 | color = PERF_COLOR_NORMAL; | ||
588 | if (ratio > 50.0) | ||
589 | color = PERF_COLOR_RED; | ||
590 | else if (ratio > 25.0) | ||
591 | color = PERF_COLOR_GREEN; | ||
592 | else if (ratio > 5.0) | ||
593 | color = PERF_COLOR_YELLOW; | ||
594 | |||
595 | printed += color_fprintf(fp, color, "%20s", thread->comm); | ||
596 | printed += fprintf(fp, " - %-5d :%11lu [", thread->pid, ttrace->nr_events); | ||
597 | printed += color_fprintf(fp, color, "%5.1f%%", ratio); | ||
598 | printed += fprintf(fp, " ] %10.3f ms\n", ttrace->runtime_ms); | ||
599 | } | ||
600 | |||
601 | return printed; | ||
602 | } | ||
603 | |||
524 | static int trace__set_duration(const struct option *opt, const char *str, | 604 | static int trace__set_duration(const struct option *opt, const char *str, |
525 | int unset __maybe_unused) | 605 | int unset __maybe_unused) |
526 | { | 606 | { |
@@ -571,6 +651,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) | |||
571 | OPT_CALLBACK(0, "duration", &trace, "float", | 651 | OPT_CALLBACK(0, "duration", &trace, "float", |
572 | "show only events with duration > N.M ms", | 652 | "show only events with duration > N.M ms", |
573 | trace__set_duration), | 653 | trace__set_duration), |
654 | OPT_BOOLEAN(0, "sched", &trace.sched, "show blocking scheduler events"), | ||
574 | OPT_END() | 655 | OPT_END() |
575 | }; | 656 | }; |
576 | int err; | 657 | int err; |
@@ -595,5 +676,10 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) | |||
595 | if (!argc && perf_target__none(&trace.opts.target)) | 676 | if (!argc && perf_target__none(&trace.opts.target)) |
596 | trace.opts.target.system_wide = true; | 677 | trace.opts.target.system_wide = true; |
597 | 678 | ||
598 | return trace__run(&trace, argc, argv); | 679 | err = trace__run(&trace, argc, argv); |
680 | |||
681 | if (trace.sched && !err) | ||
682 | trace__fprintf_thread_summary(&trace, stdout); | ||
683 | |||
684 | return err; | ||
599 | } | 685 | } |