perf probe: Speed up perf probe --list by caching debuginfo

Speed up the "perf probe --list" by caching the last used debuginfo.
perf probe --list always open and load debuginfo for each entry of probe
list. This takes very a long time.

E.g. with vfs_* events (total 96 probes)

  [root@localhost perf]# time  ./perf probe -l &> /dev/null

  real    0m25.376s
  user    0m24.381s
  sys     0m1.012s

To solve this issue, this adds debuginfo_cache to cache the
last used debuginfo on memory.

With this fix, the perf-probe --list significantly improves
its speed.

  [root@localhost perf]#  time  ./perf probe -l &> /dev/null

  real    0m0.161s
  user    0m0.136s
  sys     0m0.025s

Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Naohiro Aota <naota@elisp.net>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20150617145854.19715.15314.stgit@localhost.localdomain
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Masami Hiramatsu 2015-06-17 23:58:54 +09:00 committed by Arnaldo Carvalho de Melo
parent d350bd571f
commit 7737af010b

View File

@ -429,6 +429,41 @@ static struct debuginfo *open_debuginfo(const char *module, bool silent)
return ret;
}
/* For caching the last debuginfo */
static struct debuginfo *debuginfo_cache;
static char *debuginfo_cache_path;
static struct debuginfo *debuginfo_cache__open(const char *module, bool silent)
{
if ((debuginfo_cache_path && !strcmp(debuginfo_cache_path, module)) ||
(!debuginfo_cache_path && !module && debuginfo_cache))
goto out;
/* Copy module path */
free(debuginfo_cache_path);
if (module) {
debuginfo_cache_path = strdup(module);
if (!debuginfo_cache_path) {
debuginfo__delete(debuginfo_cache);
debuginfo_cache = NULL;
goto out;
}
}
debuginfo_cache = open_debuginfo(module, silent);
if (!debuginfo_cache)
zfree(&debuginfo_cache_path);
out:
return debuginfo_cache;
}
static void debuginfo_cache__exit(void)
{
debuginfo__delete(debuginfo_cache);
debuginfo_cache = NULL;
zfree(&debuginfo_cache_path);
}
static int get_text_start_address(const char *exec, unsigned long *address)
{
@ -490,12 +525,11 @@ static int find_perf_probe_point_from_dwarf(struct probe_trace_point *tp,
pr_debug("try to find information at %" PRIx64 " in %s\n", addr,
tp->module ? : "kernel");
dinfo = open_debuginfo(tp->module, verbose == 0);
if (dinfo) {
dinfo = debuginfo_cache__open(tp->module, verbose == 0);
if (dinfo)
ret = debuginfo__find_probe_point(dinfo,
(unsigned long)addr, pp);
debuginfo__delete(dinfo);
} else
else
ret = -ENOENT;
if (ret > 0) {
@ -930,6 +964,10 @@ out:
#else /* !HAVE_DWARF_SUPPORT */
static void debuginfo_cache__exit(void)
{
}
static int
find_perf_probe_point_from_dwarf(struct probe_trace_point *tp __maybe_unused,
struct perf_probe_point *pp __maybe_unused,
@ -2266,6 +2304,8 @@ next:
break;
}
strlist__delete(rawlist);
/* Cleanup cached debuginfo if needed */
debuginfo_cache__exit();
return ret;
}