aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorFrederic Weisbecker <fweisbec@gmail.com>2009-08-07 20:16:25 -0400
committerIngo Molnar <mingo@elte.hu>2009-08-09 06:54:43 -0400
commit25446036cbfc2c89faacdb4fb4603943d2197dc6 (patch)
tree7eb1e94c6c30b1398221309ccaf71f3beacd694a /tools/perf
parentb1a88349c37624755b28ac3b3152b48f52c1f487 (diff)
perf tools: callchain: Fix sum of percentages to be 100% by displaying amount of ignored chains in fractal mode
When we filter the callchains below a given percentage, we ignore them and the end result only shows entries that have an upper percentage than the filter threshold. It seems to users then that we have an imbalance in the percentage, as if the sum inside a profiled branch doesn't reach 100%. Since in the past there have been real perf report bugs that showed the same sypmtom, it would be nice to assure the user that the data is perfect and trustable and it all sums up to 100.00%. So fix this by displaying the remaining hits that have been filtered but without more detail than their amount in each branches. Example while filtering below 50%: 7.73% [k] delay_tsc | |--98.22%-- __const_udelay | | | |--86.37%-- ath5k_hw_register_timeout | | ath5k_hw_noise_floor_calibration | | ath5k_hw_reset | | ath5k_reset | | ath5k_config | | ieee80211_hw_config | | | | | |--88.53%-- ieee80211_scan_work | | | worker_thread | | | kthread | | | child_rip | | --11.47%-- [...] | --13.63%-- [...] --1.78%-- [...] Reported-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Mike Galbraith <efault@gmx.de> LKML-Reference: <1249690585-9145-4-git-send-email-fweisbec@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/builtin-report.c47
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
894static struct symbol *rem_sq_bracket;
895static struct callchain_list rem_hits;
896
897static 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
894static size_t 909static size_t
895callchain__fprintf_graph(FILE *fp, struct callchain_node *self, 910callchain__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