diff options
| -rw-r--r-- | tools/perf/builtin-report.c | 47 |
1 files changed, 44 insertions, 3 deletions
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index c4a8e108e521..99274cec0adb 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
| @@ -891,6 +891,21 @@ ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, int depth, | |||
| 891 | return ret; | 891 | return ret; |
| 892 | } | 892 | } |
| 893 | 893 | ||
| 894 | static struct symbol *rem_sq_bracket; | ||
| 895 | static struct callchain_list rem_hits; | ||
| 896 | |||
| 897 | static void init_rem_hits(void) | ||
| 898 | { | ||
| 899 | rem_sq_bracket = malloc(sizeof(*rem_sq_bracket) + 6); | ||
| 900 | if (!rem_sq_bracket) { | ||
| 901 | fprintf(stderr, "Not enough memory to display remaining hits\n"); | ||
| 902 | return; | ||
| 903 | } | ||
| 904 | |||
| 905 | strcpy(rem_sq_bracket->name, "[...]"); | ||
| 906 | rem_hits.sym = rem_sq_bracket; | ||
| 907 | } | ||
| 908 | |||
| 894 | static size_t | 909 | static size_t |
| 895 | callchain__fprintf_graph(FILE *fp, struct callchain_node *self, | 910 | callchain__fprintf_graph(FILE *fp, struct callchain_node *self, |
| 896 | u64 total_samples, int depth, int depth_mask) | 911 | u64 total_samples, int depth, int depth_mask) |
| @@ -900,6 +915,7 @@ callchain__fprintf_graph(FILE *fp, struct callchain_node *self, | |||
| 900 | struct callchain_list *chain; | 915 | struct callchain_list *chain; |
| 901 | int new_depth_mask = depth_mask; | 916 | int new_depth_mask = depth_mask; |
| 902 | u64 new_total; | 917 | u64 new_total; |
| 918 | u64 remaining; | ||
| 903 | size_t ret = 0; | 919 | size_t ret = 0; |
| 904 | int i; | 920 | int i; |
| 905 | 921 | ||
| @@ -908,17 +924,25 @@ callchain__fprintf_graph(FILE *fp, struct callchain_node *self, | |||
| 908 | else | 924 | else |
| 909 | new_total = total_samples; | 925 | new_total = total_samples; |
| 910 | 926 | ||
| 927 | remaining = new_total; | ||
| 928 | |||
| 911 | node = rb_first(&self->rb_root); | 929 | node = rb_first(&self->rb_root); |
| 912 | while (node) { | 930 | while (node) { |
| 931 | u64 cumul; | ||
| 932 | |||
| 913 | child = rb_entry(node, struct callchain_node, rb_node); | 933 | child = rb_entry(node, struct callchain_node, rb_node); |
| 934 | cumul = cumul_hits(child); | ||
| 935 | remaining -= cumul; | ||
| 914 | 936 | ||
| 915 | /* | 937 | /* |
| 916 | * The depth mask manages the output of pipes that show | 938 | * The depth mask manages the output of pipes that show |
| 917 | * the depth. We don't want to keep the pipes of the current | 939 | * the depth. We don't want to keep the pipes of the current |
| 918 | * level for the last child of this depth | 940 | * level for the last child of this depth. |
| 941 | * Except if we have remaining filtered hits. They will | ||
| 942 | * supersede the last child | ||
| 919 | */ | 943 | */ |
| 920 | next = rb_next(node); | 944 | next = rb_next(node); |
| 921 | if (!next) | 945 | if (!next && (callchain_param.mode != CHAIN_GRAPH_REL || !remaining)) |
| 922 | new_depth_mask &= ~(1 << (depth - 1)); | 946 | new_depth_mask &= ~(1 << (depth - 1)); |
| 923 | 947 | ||
| 924 | /* | 948 | /* |
| @@ -933,7 +957,7 @@ callchain__fprintf_graph(FILE *fp, struct callchain_node *self, | |||
| 933 | ret += ipchain__fprintf_graph(fp, chain, depth, | 957 | ret += ipchain__fprintf_graph(fp, chain, depth, |
| 934 | new_depth_mask, i++, | 958 | new_depth_mask, i++, |
| 935 | new_total, | 959 | new_total, |
| 936 | cumul_hits(child)); | 960 | cumul); |
| 937 | } | 961 | } |
| 938 | ret += callchain__fprintf_graph(fp, child, new_total, | 962 | ret += callchain__fprintf_graph(fp, child, new_total, |
| 939 | depth + 1, | 963 | depth + 1, |
| @@ -941,6 +965,19 @@ callchain__fprintf_graph(FILE *fp, struct callchain_node *self, | |||
| 941 | node = next; | 965 | node = next; |
| 942 | } | 966 | } |
| 943 | 967 | ||
| 968 | if (callchain_param.mode == CHAIN_GRAPH_REL && | ||
| 969 | remaining && remaining != new_total) { | ||
| 970 | |||
| 971 | if (!rem_sq_bracket) | ||
| 972 | return ret; | ||
| 973 | |||
| 974 | new_depth_mask &= ~(1 << (depth - 1)); | ||
| 975 | |||
| 976 | ret += ipchain__fprintf_graph(fp, &rem_hits, depth, | ||
| 977 | new_depth_mask, 0, new_total, | ||
| 978 | remaining); | ||
| 979 | } | ||
| 980 | |||
| 944 | return ret; | 981 | return ret; |
| 945 | } | 982 | } |
| 946 | 983 | ||
| @@ -1361,6 +1398,8 @@ static size_t output__fprintf(FILE *fp, u64 total_samples) | |||
| 1361 | unsigned int width; | 1398 | unsigned int width; |
| 1362 | char *col_width = col_width_list_str; | 1399 | char *col_width = col_width_list_str; |
| 1363 | 1400 | ||
| 1401 | init_rem_hits(); | ||
| 1402 | |||
| 1364 | fprintf(fp, "# Samples: %Ld\n", (u64)total_samples); | 1403 | fprintf(fp, "# Samples: %Ld\n", (u64)total_samples); |
| 1365 | fprintf(fp, "#\n"); | 1404 | fprintf(fp, "#\n"); |
| 1366 | 1405 | ||
| @@ -1432,6 +1471,8 @@ print_entries: | |||
| 1432 | } | 1471 | } |
| 1433 | fprintf(fp, "\n"); | 1472 | fprintf(fp, "\n"); |
| 1434 | 1473 | ||
| 1474 | free(rem_sq_bracket); | ||
| 1475 | |||
| 1435 | return ret; | 1476 | return ret; |
| 1436 | } | 1477 | } |
| 1437 | 1478 | ||
