perf inject: Do not load map/dso when injecting build-id
authorNamhyung Kim <namhyung@kernel.org>
Mon, 12 Oct 2020 07:02:12 +0000 (16:02 +0900)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Tue, 13 Oct 2020 14:01:37 +0000 (11:01 -0300)
No need to load symbols in a DSO when injecting build-id.  I guess the
reason was to check the DSO is a special file like anon files.  Use some
helper functions in map.c to check them before reading build-id.  Also
pass sample event's cpumode to a new build-id event.

It brought a speedup in the benchmark of 25 -> 21 msec on my laptop.
Also the memory usage (Max RSS) went down by ~200 KB.

  # Running 'internals/inject-build-id' benchmark:
    Average build-id injection took: 21.389 msec (+- 0.138 msec)
    Average time per event: 2.097 usec (+- 0.014 usec)
    Average memory usage: 8225 KB (+- 0 KB)

Committer notes:

Before:

  $ perf stat -r5 perf bench internals inject-build-id > /dev/null

   Performance counter stats for 'perf bench internals inject-build-id' (5 runs):

            4,020.56 msec task-clock:u              #    1.271 CPUs utilized            ( +-  0.74% )
                   0      context-switches:u        #    0.000 K/sec
                   0      cpu-migrations:u          #    0.000 K/sec
             123,354      page-faults:u             #    0.031 M/sec                    ( +-  0.81% )
       7,119,951,568      cycles:u                  #    1.771 GHz                      ( +-  1.74% )  (83.27%)
         230,086,969      stalled-cycles-frontend:u #    3.23% frontend cycles idle     ( +-  1.97% )  (83.41%)
       1,168,298,765      stalled-cycles-backend:u  #   16.41% backend cycles idle      ( +-  1.13% )  (83.44%)
      11,173,083,669      instructions:u            #    1.57  insn per cycle
                                                    #    0.10  stalled cycles per insn  ( +-  1.58% )  (83.31%)
       2,413,908,936      branches:u                #  600.392 M/sec                    ( +-  1.69% )  (83.26%)
          46,576,289      branch-misses:u           #    1.93% of all branches          ( +-  2.20% )  (83.31%)

              3.1638 +- 0.0309 seconds time elapsed  ( +-  0.98% )

  $

After:

  $ perf stat -r5 perf bench internals inject-build-id > /dev/null

   Performance counter stats for 'perf bench internals inject-build-id' (5 runs):

            2,379.94 msec task-clock:u              #    1.473 CPUs utilized            ( +-  0.18% )
                   0      context-switches:u        #    0.000 K/sec
                   0      cpu-migrations:u          #    0.000 K/sec
              62,584      page-faults:u             #    0.026 M/sec                    ( +-  0.07% )
       2,372,389,668      cycles:u                  #    0.997 GHz                      ( +-  0.29% )  (83.14%)
         106,937,862      stalled-cycles-frontend:u #    4.51% frontend cycles idle     ( +-  4.89% )  (83.20%)
         581,697,915      stalled-cycles-backend:u  #   24.52% backend cycles idle      ( +-  0.71% )  (83.47%)
       3,659,692,199      instructions:u            #    1.54  insn per cycle
                                                    #    0.16  stalled cycles per insn  ( +-  0.10% )  (83.63%)
         791,372,961      branches:u                #  332.518 M/sec                    ( +-  0.27% )  (83.39%)
          10,648,083      branch-misses:u           #    1.35% of all branches          ( +-  0.22% )  (83.16%)

             1.61570 +- 0.00172 seconds time elapsed  ( +-  0.11% )

  $

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Original-patch-by: Stephane Eranian <eranian@google.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Acked-by: Jiri Olsa <jolsa@redhat.com>
Link: https://lore.kernel.org/r/20201012070214.2074921-5-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/builtin-inject.c
tools/perf/util/map.c
tools/perf/util/map.h

index 670157d..248cd9f 100644 (file)
 #include "util/synthetic-events.h"
 #include "util/thread.h"
 #include "util/namespaces.h"
-#include <linux/err.h>
 
+#include <linux/err.h>
 #include <subcmd/parse-options.h>
+#include <uapi/linux/mman.h> /* To get things like MAP_HUGETLB even on older libc headers */
 
 #include <linux/list.h>
 #include <errno.h>
@@ -436,21 +437,22 @@ static int dso__read_build_id(struct dso *dso)
 }
 
 static int dso__inject_build_id(struct dso *dso, struct perf_tool *tool,
-                               struct machine *machine)
+                               struct machine *machine, u8 cpumode, u32 flags)
 {
-       u16 misc = PERF_RECORD_MISC_USER;
        int err;
 
+       if (is_anon_memory(dso->long_name) || flags & MAP_HUGETLB)
+               return 0;
+       if (is_no_dso_memory(dso->long_name))
+               return 0;
+
        if (dso__read_build_id(dso) < 0) {
                pr_debug("no build_id found for %s\n", dso->long_name);
                return -1;
        }
 
-       if (dso->kernel)
-               misc = PERF_RECORD_MISC_KERNEL;
-
-       err = perf_event__synthesize_build_id(tool, dso, misc, perf_event__repipe,
-                                             machine);
+       err = perf_event__synthesize_build_id(tool, dso, cpumode,
+                                             perf_event__repipe, machine);
        if (err) {
                pr_err("Can't synthesize build_id event for %s\n", dso->long_name);
                return -1;
@@ -477,19 +479,8 @@ int perf_event__inject_buildid(struct perf_tool *tool, union perf_event *event,
        if (thread__find_map(thread, sample->cpumode, sample->ip, &al)) {
                if (!al.map->dso->hit) {
                        al.map->dso->hit = 1;
-                       if (map__load(al.map) >= 0) {
-                               dso__inject_build_id(al.map->dso, tool, machine);
-                               /*
-                                * If this fails, too bad, let the other side
-                                * account this as unresolved.
-                                */
-                       } else {
-#ifdef HAVE_LIBELF_SUPPORT
-                               pr_warning("no symbols found in %s, maybe "
-                                          "install a debug package?\n",
-                                          al.map->dso->long_name);
-#endif
-                       }
+                       dso__inject_build_id(al.map->dso, tool, machine,
+                                            sample->cpumode, al.map->flags);
                }
        }
 
index cc0faf8..8b305e6 100644 (file)
 
 static void __maps__insert(struct maps *maps, struct map *map);
 
-static inline int is_anon_memory(const char *filename, u32 flags)
-{
-       return flags & MAP_HUGETLB ||
-              !strcmp(filename, "//anon") ||
-              !strncmp(filename, "/dev/zero", sizeof("/dev/zero") - 1) ||
-              !strncmp(filename, "/anon_hugepage", sizeof("/anon_hugepage") - 1);
-}
-
-static inline int is_no_dso_memory(const char *filename)
-{
-       return !strncmp(filename, "[stack", 6) ||
-              !strncmp(filename, "/SYSV",5)   ||
-              !strcmp(filename, "[heap]");
-}
-
 static inline int is_android_lib(const char *filename)
 {
        return strstarts(filename, "/data/app-lib/") ||
@@ -158,7 +143,7 @@ struct map *map__new(struct machine *machine, u64 start, u64 len,
                int anon, no_dso, vdso, android;
 
                android = is_android_lib(filename);
-               anon = is_anon_memory(filename, flags);
+               anon = is_anon_memory(filename) || flags & MAP_HUGETLB;
                vdso = is_vdso_map(filename);
                no_dso = is_no_dso_memory(filename);
                map->prot = prot;
index c2f5d28..b1c0686 100644 (file)
@@ -171,4 +171,18 @@ static inline bool is_bpf_image(const char *name)
        return strncmp(name, "bpf_trampoline_", sizeof("bpf_trampoline_") - 1) == 0 ||
               strncmp(name, "bpf_dispatcher_", sizeof("bpf_dispatcher_") - 1) == 0;
 }
+
+static inline int is_anon_memory(const char *filename)
+{
+       return !strcmp(filename, "//anon") ||
+              !strncmp(filename, "/dev/zero", sizeof("/dev/zero") - 1) ||
+              !strncmp(filename, "/anon_hugepage", sizeof("/anon_hugepage") - 1);
+}
+
+static inline int is_no_dso_memory(const char *filename)
+{
+       return !strncmp(filename, "[stack", 6) ||
+              !strncmp(filename, "/SYSV", 5)  ||
+              !strcmp(filename, "[heap]");
+}
 #endif /* __PERF_MAP_H */