diff options
author | Zhang, Yanmin <yanmin_zhang@linux.intel.com> | 2010-04-19 01:32:50 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2010-04-19 05:37:24 -0400 |
commit | a1645ce12adb6c9cc9e19d7695466204e3f017fe (patch) | |
tree | 5d31aaaf534997e6e9cebc07f38eca35f76986cf /tools/perf/builtin-top.c | |
parent | ff9d07a0e7ce756a183e7c2e483aec452ee6b574 (diff) |
perf: 'perf kvm' tool for monitoring guest performance from host
Here is the patch of userspace perf tool.
Signed-off-by: Zhang Yanmin <yanmin_zhang@linux.intel.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'tools/perf/builtin-top.c')
-rw-r--r-- | tools/perf/builtin-top.c | 75 |
1 files changed, 61 insertions, 14 deletions
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 40f24dd46ef4..dfd7ea7dabdd 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c | |||
@@ -420,8 +420,9 @@ static double sym_weight(const struct sym_entry *sym) | |||
420 | } | 420 | } |
421 | 421 | ||
422 | static long samples; | 422 | static long samples; |
423 | static long userspace_samples; | 423 | static long kernel_samples, us_samples; |
424 | static long exact_samples; | 424 | static long exact_samples; |
425 | static long guest_us_samples, guest_kernel_samples; | ||
425 | static const char CONSOLE_CLEAR[] = "[H[2J"; | 426 | static const char CONSOLE_CLEAR[] = "[H[2J"; |
426 | 427 | ||
427 | static void __list_insert_active_sym(struct sym_entry *syme) | 428 | static void __list_insert_active_sym(struct sym_entry *syme) |
@@ -461,7 +462,10 @@ static void print_sym_table(void) | |||
461 | int printed = 0, j; | 462 | int printed = 0, j; |
462 | int counter, snap = !display_weighted ? sym_counter : 0; | 463 | int counter, snap = !display_weighted ? sym_counter : 0; |
463 | float samples_per_sec = samples/delay_secs; | 464 | float samples_per_sec = samples/delay_secs; |
464 | float ksamples_per_sec = (samples-userspace_samples)/delay_secs; | 465 | float ksamples_per_sec = kernel_samples/delay_secs; |
466 | float us_samples_per_sec = (us_samples)/delay_secs; | ||
467 | float guest_kernel_samples_per_sec = (guest_kernel_samples)/delay_secs; | ||
468 | float guest_us_samples_per_sec = (guest_us_samples)/delay_secs; | ||
465 | float esamples_percent = (100.0*exact_samples)/samples; | 469 | float esamples_percent = (100.0*exact_samples)/samples; |
466 | float sum_ksamples = 0.0; | 470 | float sum_ksamples = 0.0; |
467 | struct sym_entry *syme, *n; | 471 | struct sym_entry *syme, *n; |
@@ -470,7 +474,8 @@ static void print_sym_table(void) | |||
470 | int sym_width = 0, dso_width = 0, dso_short_width = 0; | 474 | int sym_width = 0, dso_width = 0, dso_short_width = 0; |
471 | const int win_width = winsize.ws_col - 1; | 475 | const int win_width = winsize.ws_col - 1; |
472 | 476 | ||
473 | samples = userspace_samples = exact_samples = 0; | 477 | samples = us_samples = kernel_samples = exact_samples = 0; |
478 | guest_kernel_samples = guest_us_samples = 0; | ||
474 | 479 | ||
475 | /* Sort the active symbols */ | 480 | /* Sort the active symbols */ |
476 | pthread_mutex_lock(&active_symbols_lock); | 481 | pthread_mutex_lock(&active_symbols_lock); |
@@ -501,10 +506,30 @@ static void print_sym_table(void) | |||
501 | puts(CONSOLE_CLEAR); | 506 | puts(CONSOLE_CLEAR); |
502 | 507 | ||
503 | printf("%-*.*s\n", win_width, win_width, graph_dotted_line); | 508 | printf("%-*.*s\n", win_width, win_width, graph_dotted_line); |
504 | printf( " PerfTop:%8.0f irqs/sec kernel:%4.1f%% exact: %4.1f%% [", | 509 | if (!perf_guest) { |
505 | samples_per_sec, | 510 | printf(" PerfTop:%8.0f irqs/sec kernel:%4.1f%%" |
506 | 100.0 - (100.0*((samples_per_sec-ksamples_per_sec)/samples_per_sec)), | 511 | " exact: %4.1f%% [", |
507 | esamples_percent); | 512 | samples_per_sec, |
513 | 100.0 - (100.0 * ((samples_per_sec - ksamples_per_sec) / | ||
514 | samples_per_sec)), | ||
515 | esamples_percent); | ||
516 | } else { | ||
517 | printf(" PerfTop:%8.0f irqs/sec kernel:%4.1f%% us:%4.1f%%" | ||
518 | " guest kernel:%4.1f%% guest us:%4.1f%%" | ||
519 | " exact: %4.1f%% [", | ||
520 | samples_per_sec, | ||
521 | 100.0 - (100.0 * ((samples_per_sec-ksamples_per_sec) / | ||
522 | samples_per_sec)), | ||
523 | 100.0 - (100.0 * ((samples_per_sec-us_samples_per_sec) / | ||
524 | samples_per_sec)), | ||
525 | 100.0 - (100.0 * ((samples_per_sec - | ||
526 | guest_kernel_samples_per_sec) / | ||
527 | samples_per_sec)), | ||
528 | 100.0 - (100.0 * ((samples_per_sec - | ||
529 | guest_us_samples_per_sec) / | ||
530 | samples_per_sec)), | ||
531 | esamples_percent); | ||
532 | } | ||
508 | 533 | ||
509 | if (nr_counters == 1 || !display_weighted) { | 534 | if (nr_counters == 1 || !display_weighted) { |
510 | printf("%Ld", (u64)attrs[0].sample_period); | 535 | printf("%Ld", (u64)attrs[0].sample_period); |
@@ -597,7 +622,6 @@ static void print_sym_table(void) | |||
597 | 622 | ||
598 | syme = rb_entry(nd, struct sym_entry, rb_node); | 623 | syme = rb_entry(nd, struct sym_entry, rb_node); |
599 | sym = sym_entry__symbol(syme); | 624 | sym = sym_entry__symbol(syme); |
600 | |||
601 | if (++printed > print_entries || (int)syme->snap_count < count_filter) | 625 | if (++printed > print_entries || (int)syme->snap_count < count_filter) |
602 | continue; | 626 | continue; |
603 | 627 | ||
@@ -761,7 +785,7 @@ static int key_mapped(int c) | |||
761 | return 0; | 785 | return 0; |
762 | } | 786 | } |
763 | 787 | ||
764 | static void handle_keypress(int c) | 788 | static void handle_keypress(struct perf_session *session, int c) |
765 | { | 789 | { |
766 | if (!key_mapped(c)) { | 790 | if (!key_mapped(c)) { |
767 | struct pollfd stdin_poll = { .fd = 0, .events = POLLIN }; | 791 | struct pollfd stdin_poll = { .fd = 0, .events = POLLIN }; |
@@ -830,7 +854,7 @@ static void handle_keypress(int c) | |||
830 | case 'Q': | 854 | case 'Q': |
831 | printf("exiting.\n"); | 855 | printf("exiting.\n"); |
832 | if (dump_symtab) | 856 | if (dump_symtab) |
833 | dsos__fprintf(stderr); | 857 | dsos__fprintf(&session->kerninfo_root, stderr); |
834 | exit(0); | 858 | exit(0); |
835 | case 's': | 859 | case 's': |
836 | prompt_symbol(&sym_filter_entry, "Enter details symbol"); | 860 | prompt_symbol(&sym_filter_entry, "Enter details symbol"); |
@@ -866,6 +890,7 @@ static void *display_thread(void *arg __used) | |||
866 | struct pollfd stdin_poll = { .fd = 0, .events = POLLIN }; | 890 | struct pollfd stdin_poll = { .fd = 0, .events = POLLIN }; |
867 | struct termios tc, save; | 891 | struct termios tc, save; |
868 | int delay_msecs, c; | 892 | int delay_msecs, c; |
893 | struct perf_session *session = (struct perf_session *) arg; | ||
869 | 894 | ||
870 | tcgetattr(0, &save); | 895 | tcgetattr(0, &save); |
871 | tc = save; | 896 | tc = save; |
@@ -886,7 +911,7 @@ repeat: | |||
886 | c = getc(stdin); | 911 | c = getc(stdin); |
887 | tcsetattr(0, TCSAFLUSH, &save); | 912 | tcsetattr(0, TCSAFLUSH, &save); |
888 | 913 | ||
889 | handle_keypress(c); | 914 | handle_keypress(session, c); |
890 | goto repeat; | 915 | goto repeat; |
891 | 916 | ||
892 | return NULL; | 917 | return NULL; |
@@ -957,24 +982,46 @@ static void event__process_sample(const event_t *self, | |||
957 | u64 ip = self->ip.ip; | 982 | u64 ip = self->ip.ip; |
958 | struct sym_entry *syme; | 983 | struct sym_entry *syme; |
959 | struct addr_location al; | 984 | struct addr_location al; |
985 | struct kernel_info *kerninfo; | ||
960 | u8 origin = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; | 986 | u8 origin = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; |
961 | 987 | ||
962 | ++samples; | 988 | ++samples; |
963 | 989 | ||
964 | switch (origin) { | 990 | switch (origin) { |
965 | case PERF_RECORD_MISC_USER: | 991 | case PERF_RECORD_MISC_USER: |
966 | ++userspace_samples; | 992 | ++us_samples; |
967 | if (hide_user_symbols) | 993 | if (hide_user_symbols) |
968 | return; | 994 | return; |
995 | kerninfo = kerninfo__findhost(&session->kerninfo_root); | ||
969 | break; | 996 | break; |
970 | case PERF_RECORD_MISC_KERNEL: | 997 | case PERF_RECORD_MISC_KERNEL: |
998 | ++kernel_samples; | ||
971 | if (hide_kernel_symbols) | 999 | if (hide_kernel_symbols) |
972 | return; | 1000 | return; |
1001 | kerninfo = kerninfo__findhost(&session->kerninfo_root); | ||
973 | break; | 1002 | break; |
1003 | case PERF_RECORD_MISC_GUEST_KERNEL: | ||
1004 | ++guest_kernel_samples; | ||
1005 | kerninfo = kerninfo__find(&session->kerninfo_root, | ||
1006 | self->ip.pid); | ||
1007 | break; | ||
1008 | case PERF_RECORD_MISC_GUEST_USER: | ||
1009 | ++guest_us_samples; | ||
1010 | /* | ||
1011 | * TODO: we don't process guest user from host side | ||
1012 | * except simple counting. | ||
1013 | */ | ||
1014 | return; | ||
974 | default: | 1015 | default: |
975 | return; | 1016 | return; |
976 | } | 1017 | } |
977 | 1018 | ||
1019 | if (!kerninfo && perf_guest) { | ||
1020 | pr_err("Can't find guest [%d]'s kernel information\n", | ||
1021 | self->ip.pid); | ||
1022 | return; | ||
1023 | } | ||
1024 | |||
978 | if (self->header.misc & PERF_RECORD_MISC_EXACT) | 1025 | if (self->header.misc & PERF_RECORD_MISC_EXACT) |
979 | exact_samples++; | 1026 | exact_samples++; |
980 | 1027 | ||
@@ -994,7 +1041,7 @@ static void event__process_sample(const event_t *self, | |||
994 | * --hide-kernel-symbols, even if the user specifies an | 1041 | * --hide-kernel-symbols, even if the user specifies an |
995 | * invalid --vmlinux ;-) | 1042 | * invalid --vmlinux ;-) |
996 | */ | 1043 | */ |
997 | if (al.map == session->vmlinux_maps[MAP__FUNCTION] && | 1044 | if (al.map == kerninfo->vmlinux_maps[MAP__FUNCTION] && |
998 | RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION])) { | 1045 | RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION])) { |
999 | pr_err("The %s file can't be used\n", | 1046 | pr_err("The %s file can't be used\n", |
1000 | symbol_conf.vmlinux_name); | 1047 | symbol_conf.vmlinux_name); |
@@ -1261,7 +1308,7 @@ static int __cmd_top(void) | |||
1261 | 1308 | ||
1262 | perf_session__mmap_read(session); | 1309 | perf_session__mmap_read(session); |
1263 | 1310 | ||
1264 | if (pthread_create(&thread, NULL, display_thread, NULL)) { | 1311 | if (pthread_create(&thread, NULL, display_thread, session)) { |
1265 | printf("Could not create display thread.\n"); | 1312 | printf("Could not create display thread.\n"); |
1266 | exit(-1); | 1313 | exit(-1); |
1267 | } | 1314 | } |