lkml.org 
[lkml]   [2013]   [Oct]   [31]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 08/14] perf report: Cache cumulative callchains
    Date
    From: Namhyung Kim <namhyung.kim@lge.com>

    It is possble that a callchain has cycles or recursive calls. In that
    case it'll end up having entries more than 100% overhead in the
    output. In order to prevent such entries, cache each callchain node
    and skip if same entry already cumulated.

    Cc: Arun Sharma <asharma@fb.com>
    Cc: Frederic Weisbecker <fweisbec@gmail.com>
    Signed-off-by: Namhyung Kim <namhyung@kernel.org>
    ---
    tools/perf/builtin-report.c | 49 +++++++++++++++++++++++++++++++++++++++++++++
    1 file changed, 49 insertions(+)

    diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
    index 1b152a8b7f51..1a0de9a4a568 100644
    --- a/tools/perf/builtin-report.c
    +++ b/tools/perf/builtin-report.c
    @@ -387,6 +387,11 @@ iter_finish_normal_entry(struct add_entry_iter *iter, struct addr_location *al)
    return err;
    }

    +struct cumulative_cache {
    + struct dso *dso;
    + struct symbol *sym;
    +};
    +
    static int
    iter_prepare_cumulative_entry(struct add_entry_iter *iter,
    struct machine *machine,
    @@ -394,9 +399,31 @@ iter_prepare_cumulative_entry(struct add_entry_iter *iter,
    struct addr_location *al __maybe_unused,
    struct perf_sample *sample)
    {
    + struct callchain_cursor_node *node;
    + struct cumulative_cache *ccache;
    +
    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.
    + */
    + ccache = malloc(sizeof(*ccache) * PERF_MAX_STACK_DEPTH);
    + if (ccache == NULL)
    + return -ENOMEM;
    +
    + node = callchain_cursor_current(&callchain_cursor);
    + if (node == NULL)
    + return 0;
    +
    + ccache[0].dso = node->map->dso;
    + ccache[0].sym = node->sym;
    +
    + iter->priv = ccache;
    + iter->curr = 1;
    +
    + /*
    * The first callchain node always contains same information
    * as a hist entry itself. So skip it in order to prevent
    * double accounting.
    @@ -501,8 +528,29 @@ iter_add_next_cumulative_entry(struct add_entry_iter *iter,
    {
    struct perf_evsel *evsel = iter->evsel;
    struct perf_sample *sample = iter->sample;
    + struct cumulative_cache *ccache = iter->priv;
    struct hist_entry *he;
    int err = 0;
    + 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 (sort__has_sym) {
    + if (ccache[i].sym == al->sym)
    + return 0;
    + } else {
    + /* Not much we can do - just compare the dso. */
    + if (ccache[i].dso == al->map->dso)
    + return 0;
    + }
    + }
    +
    + ccache[i].dso = al->map->dso;
    + ccache[i].sym = al->sym;
    + iter->curr++;

    he = __hists__add_entry(&evsel->hists, al, iter->parent, NULL, NULL,
    sample->period, sample->weight,
    @@ -538,6 +586,7 @@ iter_finish_cumulative_entry(struct add_entry_iter *iter,
    evsel->hists.stats.total_period += sample->period;
    hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);

    + free(iter->priv);
    return 0;
    }

    --
    1.7.11.7


    \
     
     \ /
      Last update: 2013-10-31 08:41    [W:4.225 / U:0.368 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site