diff options
Diffstat (limited to 'tools/perf')
-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 | ||