|
@@ -700,7 +700,22 @@ static int
|
|
|
iter_prepare_cumulative_entry(struct hist_entry_iter *iter __maybe_unused,
|
|
|
struct addr_location *al __maybe_unused)
|
|
|
{
|
|
|
+ struct hist_entry **he_cache;
|
|
|
+
|
|
|
callchain_cursor_commit(&callchain_cursor);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * This is for detecting cycles or recursions so that they're
|
|
|
+ * cumulated only one time to prevent entries more than 100%
|
|
|
+ * overhead.
|
|
|
+ */
|
|
|
+ he_cache = malloc(sizeof(*he_cache) * (PERF_MAX_STACK_DEPTH + 1));
|
|
|
+ if (he_cache == NULL)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ iter->priv = he_cache;
|
|
|
+ iter->curr = 0;
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -710,6 +725,7 @@ iter_add_single_cumulative_entry(struct hist_entry_iter *iter,
|
|
|
{
|
|
|
struct perf_evsel *evsel = iter->evsel;
|
|
|
struct perf_sample *sample = iter->sample;
|
|
|
+ struct hist_entry **he_cache = iter->priv;
|
|
|
struct hist_entry *he;
|
|
|
int err = 0;
|
|
|
|
|
@@ -720,6 +736,7 @@ iter_add_single_cumulative_entry(struct hist_entry_iter *iter,
|
|
|
return -ENOMEM;
|
|
|
|
|
|
iter->he = he;
|
|
|
+ he_cache[iter->curr++] = he;
|
|
|
|
|
|
/*
|
|
|
* The iter->he will be over-written after ->add_next_entry()
|
|
@@ -754,7 +771,29 @@ iter_add_next_cumulative_entry(struct hist_entry_iter *iter,
|
|
|
{
|
|
|
struct perf_evsel *evsel = iter->evsel;
|
|
|
struct perf_sample *sample = iter->sample;
|
|
|
+ struct hist_entry **he_cache = iter->priv;
|
|
|
struct hist_entry *he;
|
|
|
+ struct hist_entry he_tmp = {
|
|
|
+ .cpu = al->cpu,
|
|
|
+ .thread = al->thread,
|
|
|
+ .comm = thread__comm(al->thread),
|
|
|
+ .ip = al->addr,
|
|
|
+ .ms = {
|
|
|
+ .map = al->map,
|
|
|
+ .sym = al->sym,
|
|
|
+ },
|
|
|
+ .parent = iter->parent,
|
|
|
+ };
|
|
|
+ int i;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Check if there's duplicate entries in the callchain.
|
|
|
+ * It's possible that it has cycles or recursive calls.
|
|
|
+ */
|
|
|
+ for (i = 0; i < iter->curr; i++) {
|
|
|
+ if (hist_entry__cmp(he_cache[i], &he_tmp) == 0)
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
|
|
|
he = __hists__add_entry(&evsel->hists, al, iter->parent, NULL, NULL,
|
|
|
sample->period, sample->weight,
|
|
@@ -763,6 +802,7 @@ iter_add_next_cumulative_entry(struct hist_entry_iter *iter,
|
|
|
return -ENOMEM;
|
|
|
|
|
|
iter->he = he;
|
|
|
+ he_cache[iter->curr++] = he;
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -771,7 +811,9 @@ static int
|
|
|
iter_finish_cumulative_entry(struct hist_entry_iter *iter,
|
|
|
struct addr_location *al __maybe_unused)
|
|
|
{
|
|
|
+ zfree(&iter->priv);
|
|
|
iter->he = NULL;
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
|