aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/perf/builtin-report.c45
-rw-r--r--tools/perf/util/callchain.c19
-rw-r--r--tools/perf/util/callchain.h6
3 files changed, 49 insertions, 21 deletions
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 0ca46386d936..e8c98179fe45 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -60,6 +60,7 @@ static regex_t parent_regex;
60static int exclude_other = 1; 60static int exclude_other = 1;
61static int callchain; 61static int callchain;
62static enum chain_mode callchain_mode; 62static enum chain_mode callchain_mode;
63static double callchain_min_percent = 0.0;
63 64
64static u64 sample_type; 65static u64 sample_type;
65 66
@@ -1224,7 +1225,7 @@ static void collapse__resort(void)
1224 1225
1225static struct rb_root output_hists; 1226static struct rb_root output_hists;
1226 1227
1227static void output__insert_entry(struct hist_entry *he) 1228static void output__insert_entry(struct hist_entry *he, u64 min_callchain_hits)
1228{ 1229{
1229 struct rb_node **p = &output_hists.rb_node; 1230 struct rb_node **p = &output_hists.rb_node;
1230 struct rb_node *parent = NULL; 1231 struct rb_node *parent = NULL;
@@ -1232,9 +1233,11 @@ static void output__insert_entry(struct hist_entry *he)
1232 1233
1233 if (callchain) { 1234 if (callchain) {
1234 if (callchain_mode == FLAT) 1235 if (callchain_mode == FLAT)
1235 sort_chain_flat(&he->sorted_chain, &he->callchain); 1236 sort_chain_flat(&he->sorted_chain, &he->callchain,
1237 min_callchain_hits);
1236 else if (callchain_mode == GRAPH) 1238 else if (callchain_mode == GRAPH)
1237 sort_chain_graph(&he->sorted_chain, &he->callchain); 1239 sort_chain_graph(&he->sorted_chain, &he->callchain,
1240 min_callchain_hits);
1238 } 1241 }
1239 1242
1240 while (*p != NULL) { 1243 while (*p != NULL) {
@@ -1251,11 +1254,14 @@ static void output__insert_entry(struct hist_entry *he)
1251 rb_insert_color(&he->rb_node, &output_hists); 1254 rb_insert_color(&he->rb_node, &output_hists);
1252} 1255}
1253 1256
1254static void output__resort(void) 1257static void output__resort(u64 total_samples)
1255{ 1258{
1256 struct rb_node *next; 1259 struct rb_node *next;
1257 struct hist_entry *n; 1260 struct hist_entry *n;
1258 struct rb_root *tree = &hist; 1261 struct rb_root *tree = &hist;
1262 u64 min_callchain_hits;
1263
1264 min_callchain_hits = total_samples * (callchain_min_percent / 100);
1259 1265
1260 if (sort__need_collapse) 1266 if (sort__need_collapse)
1261 tree = &collapse_hists; 1267 tree = &collapse_hists;
@@ -1267,7 +1273,7 @@ static void output__resort(void)
1267 next = rb_next(&n->rb_node); 1273 next = rb_next(&n->rb_node);
1268 1274
1269 rb_erase(&n->rb_node, tree); 1275 rb_erase(&n->rb_node, tree);
1270 output__insert_entry(n); 1276 output__insert_entry(n, min_callchain_hits);
1271 } 1277 }
1272} 1278}
1273 1279
@@ -1801,7 +1807,7 @@ done:
1801 dsos__fprintf(stdout); 1807 dsos__fprintf(stdout);
1802 1808
1803 collapse__resort(); 1809 collapse__resort();
1804 output__resort(); 1810 output__resort(total);
1805 output__fprintf(stdout, total); 1811 output__fprintf(stdout, total);
1806 1812
1807 return rc; 1813 return rc;
@@ -1811,19 +1817,36 @@ static int
1811parse_callchain_opt(const struct option *opt __used, const char *arg, 1817parse_callchain_opt(const struct option *opt __used, const char *arg,
1812 int unset __used) 1818 int unset __used)
1813{ 1819{
1820 char *tok;
1821 char *endptr;
1822
1814 callchain = 1; 1823 callchain = 1;
1815 1824
1816 if (!arg) 1825 if (!arg)
1817 return 0; 1826 return 0;
1818 1827
1819 if (!strncmp(arg, "graph", strlen(arg))) 1828 tok = strtok((char *)arg, ",");
1829 if (!tok)
1830 return -1;
1831
1832 /* get the output mode */
1833 if (!strncmp(tok, "graph", strlen(arg)))
1820 callchain_mode = GRAPH; 1834 callchain_mode = GRAPH;
1821 1835
1822 else if (!strncmp(arg, "flat", strlen(arg))) 1836 else if (!strncmp(tok, "flat", strlen(arg)))
1823 callchain_mode = FLAT; 1837 callchain_mode = FLAT;
1824 else 1838 else
1825 return -1; 1839 return -1;
1826 1840
1841 /* get the min percentage */
1842 tok = strtok(NULL, ",");
1843 if (!tok)
1844 return 0;
1845
1846 callchain_min_percent = strtod(tok, &endptr);
1847 if (tok == endptr)
1848 return -1;
1849
1827 return 0; 1850 return 0;
1828} 1851}
1829 1852
@@ -1850,9 +1873,9 @@ static const struct option options[] = {
1850 "regex filter to identify parent, see: '--sort parent'"), 1873 "regex filter to identify parent, see: '--sort parent'"),
1851 OPT_BOOLEAN('x', "exclude-other", &exclude_other, 1874 OPT_BOOLEAN('x', "exclude-other", &exclude_other,
1852 "Only display entries with parent-match"), 1875 "Only display entries with parent-match"),
1853 OPT_CALLBACK_DEFAULT('c', "callchain", NULL, "output_type", 1876 OPT_CALLBACK_DEFAULT('c', "callchain", NULL, "output_type,min_percent",
1854 "Display callchains with output_type: flat, graph. " 1877 "Display callchains using output_type and min percent threshold. "
1855 "Default to flat", &parse_callchain_opt, "flat"), 1878 "Default: flat,0", &parse_callchain_opt, "flat,100"),
1856 OPT_STRING('d', "dsos", &dso_list_str, "dso[,dso...]", 1879 OPT_STRING('d', "dsos", &dso_list_str, "dso[,dso...]",
1857 "only consider symbols in these dsos"), 1880 "only consider symbols in these dsos"),
1858 OPT_STRING('C', "comms", &comm_list_str, "comm[,comm...]", 1881 OPT_STRING('C', "comms", &comm_list_str, "comm[,comm...]",
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index a9873aafcd92..c9900fe6b8b4 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -57,18 +57,19 @@ rb_insert_callchain(struct rb_root *root, struct callchain_node *chain,
57 * Once we get every callchains from the stream, we can now 57 * Once we get every callchains from the stream, we can now
58 * sort them by hit 58 * sort them by hit
59 */ 59 */
60void sort_chain_flat(struct rb_root *rb_root, struct callchain_node *node) 60void sort_chain_flat(struct rb_root *rb_root, struct callchain_node *node,
61 u64 min_hit)
61{ 62{
62 struct callchain_node *child; 63 struct callchain_node *child;
63 64
64 chain_for_each_child(child, node) 65 chain_for_each_child(child, node)
65 sort_chain_flat(rb_root, child); 66 sort_chain_flat(rb_root, child, min_hit);
66 67
67 if (node->hit) 68 if (node->hit && node->hit >= min_hit)
68 rb_insert_callchain(rb_root, node, FLAT); 69 rb_insert_callchain(rb_root, node, FLAT);
69} 70}
70 71
71static void __sort_chain_graph(struct callchain_node *node) 72static void __sort_chain_graph(struct callchain_node *node, u64 min_hit)
72{ 73{
73 struct callchain_node *child; 74 struct callchain_node *child;
74 75
@@ -76,16 +77,18 @@ static void __sort_chain_graph(struct callchain_node *node)
76 node->cumul_hit = node->hit; 77 node->cumul_hit = node->hit;
77 78
78 chain_for_each_child(child, node) { 79 chain_for_each_child(child, node) {
79 __sort_chain_graph(child); 80 __sort_chain_graph(child, min_hit);
80 rb_insert_callchain(&node->rb_root, child, GRAPH); 81 if (child->cumul_hit >= min_hit)
82 rb_insert_callchain(&node->rb_root, child, GRAPH);
81 node->cumul_hit += child->cumul_hit; 83 node->cumul_hit += child->cumul_hit;
82 } 84 }
83} 85}
84 86
85void 87void
86sort_chain_graph(struct rb_root *rb_root, struct callchain_node *chain_root) 88sort_chain_graph(struct rb_root *rb_root, struct callchain_node *chain_root,
89 u64 min_hit)
87{ 90{
88 __sort_chain_graph(chain_root); 91 __sort_chain_graph(chain_root, min_hit);
89 rb_root->rb_node = chain_root->rb_root.rb_node; 92 rb_root->rb_node = chain_root->rb_root.rb_node;
90} 93}
91 94
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index dfa56008d9ad..f3e4776e7430 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -38,6 +38,8 @@ static inline void callchain_init(struct callchain_node *node)
38 38
39void append_chain(struct callchain_node *root, struct ip_callchain *chain, 39void append_chain(struct callchain_node *root, struct ip_callchain *chain,
40 struct symbol **syms); 40 struct symbol **syms);
41void sort_chain_flat(struct rb_root *rb_root, struct callchain_node *node); 41void sort_chain_flat(struct rb_root *rb_root, struct callchain_node *node,
42void sort_chain_graph(struct rb_root *rb_root, struct callchain_node *node); 42 u64 min_hit);
43void sort_chain_graph(struct rb_root *rb_root, struct callchain_node *node,
44 u64 min_hit);
43#endif 45#endif