It missed to decay periods in callchains when decaying hist entries.
This resulted in more than 100 percent overhead in callchains in the
fractal style output.

Reported-by: Arnaldo Carvalho de Melo <a...@kernel.org>
Signed-off-by: Namhyung Kim <namhy...@kernel.org>
---
 tools/perf/util/callchain.c | 28 ++++++++++++++++++++++++++++
 tools/perf/util/callchain.h |  1 +
 tools/perf/util/hist.c      |  1 +
 3 files changed, 30 insertions(+)

diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 564377d2bebf..53c43eb9489e 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -925,6 +925,34 @@ void free_callchain(struct callchain_root *root)
        free_callchain_node(&root->node);
 }
 
+static u64 decay_callchain_node(struct callchain_node *node)
+{
+       struct callchain_node *child;
+       struct rb_node *n;
+       u64 child_hits = 0;
+
+       n = rb_first(&node->rb_root_in);
+       while (n) {
+               child = container_of(n, struct callchain_node, rb_node_in);
+
+               child_hits += decay_callchain_node(child);
+               n = rb_next(n);
+       }
+
+       node->hit = (node->hit * 7) / 8;
+       node->children_hit = child_hits;
+
+       return node->hit;
+}
+
+void decay_callchain(struct callchain_root *root)
+{
+       if (!symbol_conf.use_callchain)
+               return;
+
+       decay_callchain_node(&root->node);
+}
+
 int callchain_node__make_parent_list(struct callchain_node *node)
 {
        struct callchain_node *parent = node->parent;
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index 8ac8f043004c..18dd22269764 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -253,6 +253,7 @@ int callchain_node__fprintf_value(struct callchain_node 
*node,
                                  FILE *fp, u64 total);
 
 void free_callchain(struct callchain_root *root);
+void decay_callchain(struct callchain_root *root);
 int callchain_node__make_parent_list(struct callchain_node *node);
 
 #endif /* __PERF_CALLCHAIN_H */
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index afc9b8f1b36c..888776b43cb0 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -254,6 +254,7 @@ static bool hists__decay_entry(struct hists *hists, struct 
hist_entry *he)
        he_stat__decay(&he->stat);
        if (symbol_conf.cumulate_callchain)
                he_stat__decay(he->stat_acc);
+       decay_callchain(he->callchain);
 
        diff = prev_period - he->stat.period;
 
-- 
2.6.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to