diff options
Diffstat (limited to 'Documentation/perf_counter/builtin-top.c')
-rw-r--r-- | Documentation/perf_counter/builtin-top.c | 204 |
1 files changed, 4 insertions, 200 deletions
diff --git a/Documentation/perf_counter/builtin-top.c b/Documentation/perf_counter/builtin-top.c index 601bddbc30d5..98e8690b6bcb 100644 --- a/Documentation/perf_counter/builtin-top.c +++ b/Documentation/perf_counter/builtin-top.c | |||
@@ -28,25 +28,6 @@ | |||
28 | 8.54 - ffffffff805001a3 : ip_queue_xmit | 28 | 8.54 - ffffffff805001a3 : ip_queue_xmit |
29 | */ | 29 | */ |
30 | 30 | ||
31 | /* | ||
32 | * perfstat: /usr/bin/time -alike performance counter statistics utility | ||
33 | |||
34 | It summarizes the counter events of all tasks (and child tasks), | ||
35 | covering all CPUs that the command (or workload) executes on. | ||
36 | It only counts the per-task events of the workload started, | ||
37 | independent of how many other tasks run on those CPUs. | ||
38 | |||
39 | Sample output: | ||
40 | |||
41 | $ ./perfstat -e 1 -e 3 -e 5 ls -lR /usr/include/ >/dev/null | ||
42 | |||
43 | Performance counter stats for 'ls': | ||
44 | |||
45 | 163516953 instructions | ||
46 | 2295 cache-misses | ||
47 | 2855182 branch-misses | ||
48 | */ | ||
49 | |||
50 | /* | 31 | /* |
51 | * Copyright (C) 2008, Red Hat Inc, Ingo Molnar <mingo@redhat.com> | 32 | * Copyright (C) 2008, Red Hat Inc, Ingo Molnar <mingo@redhat.com> |
52 | * | 33 | * |
@@ -149,7 +130,6 @@ asmlinkage int sys_perf_counter_open( | |||
149 | 130 | ||
150 | #define EID(type, id) (((__u64)(type) << PERF_COUNTER_TYPE_SHIFT) | (id)) | 131 | #define EID(type, id) (((__u64)(type) << PERF_COUNTER_TYPE_SHIFT) | (id)) |
151 | 132 | ||
152 | static int run_perfstat = 0; | ||
153 | static int system_wide = 0; | 133 | static int system_wide = 0; |
154 | 134 | ||
155 | static int nr_counters = 0; | 135 | static int nr_counters = 0; |
@@ -203,7 +183,7 @@ struct source_line { | |||
203 | static struct source_line *lines; | 183 | static struct source_line *lines; |
204 | static struct source_line **lines_tail; | 184 | static struct source_line **lines_tail; |
205 | 185 | ||
206 | const unsigned int default_count[] = { | 186 | static const unsigned int default_count[] = { |
207 | 1000000, | 187 | 1000000, |
208 | 1000000, | 188 | 1000000, |
209 | 10000, | 189 | 10000, |
@@ -291,26 +271,8 @@ static void display_events_help(void) | |||
291 | " rNNN: raw PMU events (eventsel+umask)\n\n"); | 271 | " rNNN: raw PMU events (eventsel+umask)\n\n"); |
292 | } | 272 | } |
293 | 273 | ||
294 | static void display_perfstat_help(void) | ||
295 | { | ||
296 | printf( | ||
297 | "Usage: perfstat [<events...>] <cmd...>\n\n" | ||
298 | "PerfStat Options (up to %d event types can be specified):\n\n", | ||
299 | MAX_COUNTERS); | ||
300 | |||
301 | display_events_help(); | ||
302 | |||
303 | printf( | ||
304 | " -l # scale counter values\n" | ||
305 | " -a # system-wide collection\n"); | ||
306 | exit(0); | ||
307 | } | ||
308 | |||
309 | static void display_help(void) | 274 | static void display_help(void) |
310 | { | 275 | { |
311 | if (run_perfstat) | ||
312 | return display_perfstat_help(); | ||
313 | |||
314 | printf( | 276 | printf( |
315 | "Usage: kerneltop [<options>]\n" | 277 | "Usage: kerneltop [<options>]\n" |
316 | " Or: kerneltop -S [<options>] COMMAND [ARGS]\n\n" | 278 | " Or: kerneltop -S [<options>] COMMAND [ARGS]\n\n" |
@@ -320,8 +282,6 @@ static void display_help(void) | |||
320 | display_events_help(); | 282 | display_events_help(); |
321 | 283 | ||
322 | printf( | 284 | printf( |
323 | " -S --stat # perfstat COMMAND\n" | ||
324 | " -a # system-wide collection (for perfstat)\n\n" | ||
325 | " -c CNT --count=CNT # event period to sample\n\n" | 285 | " -c CNT --count=CNT # event period to sample\n\n" |
326 | " -C CPU --cpu=CPU # CPU (-1 for all) [default: -1]\n" | 286 | " -C CPU --cpu=CPU # CPU (-1 for all) [default: -1]\n" |
327 | " -p PID --pid=PID # PID of sampled task (-1 for all) [default: -1]\n\n" | 287 | " -p PID --pid=PID # PID of sampled task (-1 for all) [default: -1]\n\n" |
@@ -420,151 +380,6 @@ again: | |||
420 | return 0; | 380 | return 0; |
421 | } | 381 | } |
422 | 382 | ||
423 | |||
424 | /* | ||
425 | * perfstat | ||
426 | */ | ||
427 | |||
428 | char fault_here[1000000]; | ||
429 | |||
430 | static void create_perfstat_counter(int counter) | ||
431 | { | ||
432 | struct perf_counter_hw_event hw_event; | ||
433 | |||
434 | memset(&hw_event, 0, sizeof(hw_event)); | ||
435 | hw_event.config = event_id[counter]; | ||
436 | hw_event.record_type = 0; | ||
437 | hw_event.nmi = 0; | ||
438 | if (scale) | ||
439 | hw_event.read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | | ||
440 | PERF_FORMAT_TOTAL_TIME_RUNNING; | ||
441 | |||
442 | if (system_wide) { | ||
443 | int cpu; | ||
444 | for (cpu = 0; cpu < nr_cpus; cpu ++) { | ||
445 | fd[cpu][counter] = sys_perf_counter_open(&hw_event, -1, cpu, -1, 0); | ||
446 | if (fd[cpu][counter] < 0) { | ||
447 | printf("perfstat error: syscall returned with %d (%s)\n", | ||
448 | fd[cpu][counter], strerror(errno)); | ||
449 | exit(-1); | ||
450 | } | ||
451 | } | ||
452 | } else { | ||
453 | hw_event.inherit = 1; | ||
454 | hw_event.disabled = 1; | ||
455 | |||
456 | fd[0][counter] = sys_perf_counter_open(&hw_event, 0, -1, -1, 0); | ||
457 | if (fd[0][counter] < 0) { | ||
458 | printf("perfstat error: syscall returned with %d (%s)\n", | ||
459 | fd[0][counter], strerror(errno)); | ||
460 | exit(-1); | ||
461 | } | ||
462 | } | ||
463 | } | ||
464 | |||
465 | int do_perfstat(int argc, char *argv[]) | ||
466 | { | ||
467 | unsigned long long t0, t1; | ||
468 | int counter; | ||
469 | ssize_t res; | ||
470 | int status; | ||
471 | int pid; | ||
472 | |||
473 | if (!system_wide) | ||
474 | nr_cpus = 1; | ||
475 | |||
476 | for (counter = 0; counter < nr_counters; counter++) | ||
477 | create_perfstat_counter(counter); | ||
478 | |||
479 | argc -= optind; | ||
480 | argv += optind; | ||
481 | |||
482 | if (!argc) | ||
483 | display_help(); | ||
484 | |||
485 | /* | ||
486 | * Enable counters and exec the command: | ||
487 | */ | ||
488 | t0 = rdclock(); | ||
489 | prctl(PR_TASK_PERF_COUNTERS_ENABLE); | ||
490 | |||
491 | if ((pid = fork()) < 0) | ||
492 | perror("failed to fork"); | ||
493 | if (!pid) { | ||
494 | if (execvp(argv[0], argv)) { | ||
495 | perror(argv[0]); | ||
496 | exit(-1); | ||
497 | } | ||
498 | } | ||
499 | while (wait(&status) >= 0) | ||
500 | ; | ||
501 | prctl(PR_TASK_PERF_COUNTERS_DISABLE); | ||
502 | t1 = rdclock(); | ||
503 | |||
504 | fflush(stdout); | ||
505 | |||
506 | fprintf(stderr, "\n"); | ||
507 | fprintf(stderr, " Performance counter stats for \'%s\':\n", | ||
508 | argv[0]); | ||
509 | fprintf(stderr, "\n"); | ||
510 | |||
511 | for (counter = 0; counter < nr_counters; counter++) { | ||
512 | int cpu, nv; | ||
513 | __u64 count[3], single_count[3]; | ||
514 | int scaled; | ||
515 | |||
516 | count[0] = count[1] = count[2] = 0; | ||
517 | nv = scale ? 3 : 1; | ||
518 | for (cpu = 0; cpu < nr_cpus; cpu ++) { | ||
519 | res = read(fd[cpu][counter], | ||
520 | single_count, nv * sizeof(__u64)); | ||
521 | assert(res == nv * sizeof(__u64)); | ||
522 | |||
523 | count[0] += single_count[0]; | ||
524 | if (scale) { | ||
525 | count[1] += single_count[1]; | ||
526 | count[2] += single_count[2]; | ||
527 | } | ||
528 | } | ||
529 | |||
530 | scaled = 0; | ||
531 | if (scale) { | ||
532 | if (count[2] == 0) { | ||
533 | fprintf(stderr, " %14s %-20s\n", | ||
534 | "<not counted>", event_name(counter)); | ||
535 | continue; | ||
536 | } | ||
537 | if (count[2] < count[1]) { | ||
538 | scaled = 1; | ||
539 | count[0] = (unsigned long long) | ||
540 | ((double)count[0] * count[1] / count[2] + 0.5); | ||
541 | } | ||
542 | } | ||
543 | |||
544 | if (event_id[counter] == EID(PERF_TYPE_SOFTWARE, PERF_COUNT_CPU_CLOCK) || | ||
545 | event_id[counter] == EID(PERF_TYPE_SOFTWARE, PERF_COUNT_TASK_CLOCK)) { | ||
546 | |||
547 | double msecs = (double)count[0] / 1000000; | ||
548 | |||
549 | fprintf(stderr, " %14.6f %-20s (msecs)", | ||
550 | msecs, event_name(counter)); | ||
551 | } else { | ||
552 | fprintf(stderr, " %14Ld %-20s (events)", | ||
553 | count[0], event_name(counter)); | ||
554 | } | ||
555 | if (scaled) | ||
556 | fprintf(stderr, " (scaled from %.2f%%)", | ||
557 | (double) count[2] / count[1] * 100); | ||
558 | fprintf(stderr, "\n"); | ||
559 | } | ||
560 | fprintf(stderr, "\n"); | ||
561 | fprintf(stderr, " Wall-clock time elapsed: %12.6f msecs\n", | ||
562 | (double)(t1-t0)/1e6); | ||
563 | fprintf(stderr, "\n"); | ||
564 | |||
565 | return 0; | ||
566 | } | ||
567 | |||
568 | /* | 383 | /* |
569 | * Symbols | 384 | * Symbols |
570 | */ | 385 | */ |
@@ -805,7 +620,7 @@ static int read_symbol(FILE *in, struct sym_entry *s) | |||
805 | return 0; | 620 | return 0; |
806 | } | 621 | } |
807 | 622 | ||
808 | int compare_addr(const void *__sym1, const void *__sym2) | 623 | static int compare_addr(const void *__sym1, const void *__sym2) |
809 | { | 624 | { |
810 | const struct sym_entry *sym1 = __sym1, *sym2 = __sym2; | 625 | const struct sym_entry *sym1 = __sym1, *sym2 = __sym2; |
811 | 626 | ||
@@ -1070,9 +885,6 @@ static void process_options(int argc, char **argv) | |||
1070 | { | 885 | { |
1071 | int error = 0, counter; | 886 | int error = 0, counter; |
1072 | 887 | ||
1073 | if (strstr(argv[0], "perfstat")) | ||
1074 | run_perfstat = 1; | ||
1075 | |||
1076 | for (;;) { | 888 | for (;;) { |
1077 | int option_index = 0; | 889 | int option_index = 0; |
1078 | /** Options for getopt */ | 890 | /** Options for getopt */ |
@@ -1134,7 +946,6 @@ static void process_options(int argc, char **argv) | |||
1134 | tid = atoi(optarg); break; | 946 | tid = atoi(optarg); break; |
1135 | case 'r': realtime_prio = atoi(optarg); break; | 947 | case 'r': realtime_prio = atoi(optarg); break; |
1136 | case 's': sym_filter = strdup(optarg); break; | 948 | case 's': sym_filter = strdup(optarg); break; |
1137 | case 'S': run_perfstat = 1; break; | ||
1138 | case 'x': vmlinux = strdup(optarg); break; | 949 | case 'x': vmlinux = strdup(optarg); break; |
1139 | case 'z': zero = 1; break; | 950 | case 'z': zero = 1; break; |
1140 | case 'm': mmap_pages = atoi(optarg); break; | 951 | case 'm': mmap_pages = atoi(optarg); break; |
@@ -1147,12 +958,8 @@ static void process_options(int argc, char **argv) | |||
1147 | display_help(); | 958 | display_help(); |
1148 | 959 | ||
1149 | if (!nr_counters) { | 960 | if (!nr_counters) { |
1150 | if (run_perfstat) | 961 | nr_counters = 1; |
1151 | nr_counters = 8; | 962 | event_id[0] = 0; |
1152 | else { | ||
1153 | nr_counters = 1; | ||
1154 | event_id[0] = 0; | ||
1155 | } | ||
1156 | } | 963 | } |
1157 | 964 | ||
1158 | for (counter = 0; counter < nr_counters; counter++) { | 965 | for (counter = 0; counter < nr_counters; counter++) { |
@@ -1308,9 +1115,6 @@ int cmd_top(int argc, char **argv, const char *prefix) | |||
1308 | assert(nr_cpus <= MAX_NR_CPUS); | 1115 | assert(nr_cpus <= MAX_NR_CPUS); |
1309 | assert(nr_cpus >= 0); | 1116 | assert(nr_cpus >= 0); |
1310 | 1117 | ||
1311 | if (run_perfstat) | ||
1312 | return do_perfstat(argc, argv); | ||
1313 | |||
1314 | if (tid != -1 || profile_cpu != -1) | 1118 | if (tid != -1 || profile_cpu != -1) |
1315 | nr_cpus = 1; | 1119 | nr_cpus = 1; |
1316 | 1120 | ||