diff options
| author | Ulrich Drepper <drepper@redhat.com> | 2009-09-04 15:39:51 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2009-09-04 15:50:17 -0400 |
| commit | 6b58e7f146f8d79c08f62087f928e1f01747de71 (patch) | |
| tree | 98669b06646894d1dd8f85c1ae932aa6a8fb42de /tools/perf/util/parse-events.c | |
| parent | 849abde92bd3314a4894f2b4f70b30c2accf8653 (diff) | |
perf tools: Avoid unnecessary work in directory lookups
This patch improves some (common) inefficiencies in the
handling of directory lookups:
- not using the d_type information returned by the kernel
- constructing (absolute) paths for file operation even though
directory-relative operations using the *at functions is
possible
There are more places to fix but this is a start.
Signed-off-by: Ulrich Drepper <drepper@redhat.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Mike Galbraith <efault@gmx.de>
LKML-Reference: <20090904193951.GB6186@ghostprotocols.net>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf/util/parse-events.c')
| -rw-r--r-- | tools/perf/util/parse-events.c | 68 |
1 files changed, 37 insertions, 31 deletions
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 89d46c99bc9c..52219d5a507b 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c | |||
| @@ -1,14 +1,12 @@ | |||
| 1 | 1 | ||
| 2 | #include "../perf.h" | ||
| 3 | #include "util.h" | 2 | #include "util.h" |
| 3 | #include "../perf.h" | ||
| 4 | #include "parse-options.h" | 4 | #include "parse-options.h" |
| 5 | #include "parse-events.h" | 5 | #include "parse-events.h" |
| 6 | #include "exec_cmd.h" | 6 | #include "exec_cmd.h" |
| 7 | #include "string.h" | 7 | #include "string.h" |
| 8 | #include "cache.h" | 8 | #include "cache.h" |
| 9 | 9 | ||
| 10 | extern char *strcasestr(const char *haystack, const char *needle); | ||
| 11 | |||
| 12 | int nr_counters; | 10 | int nr_counters; |
| 13 | 11 | ||
| 14 | struct perf_counter_attr attrs[MAX_COUNTERS]; | 12 | struct perf_counter_attr attrs[MAX_COUNTERS]; |
| @@ -113,11 +111,9 @@ static unsigned long hw_cache_stat[C(MAX)] = { | |||
| 113 | [C(BPU)] = (CACHE_READ), | 111 | [C(BPU)] = (CACHE_READ), |
| 114 | }; | 112 | }; |
| 115 | 113 | ||
| 116 | #define for_each_subsystem(sys_dir, sys_dirent, sys_next, file, st) \ | 114 | #define for_each_subsystem(sys_dir, sys_dirent, sys_next) \ |
| 117 | while (!readdir_r(sys_dir, &sys_dirent, &sys_next) && sys_next) \ | 115 | while (!readdir_r(sys_dir, &sys_dirent, &sys_next) && sys_next) \ |
| 118 | if (snprintf(file, MAXPATHLEN, "%s/%s", debugfs_path, \ | 116 | if (sys_dirent.d_type == DT_DIR && \ |
| 119 | sys_dirent.d_name) && \ | ||
| 120 | (!stat(file, &st)) && (S_ISDIR(st.st_mode)) && \ | ||
| 121 | (strcmp(sys_dirent.d_name, ".")) && \ | 117 | (strcmp(sys_dirent.d_name, ".")) && \ |
| 122 | (strcmp(sys_dirent.d_name, ".."))) | 118 | (strcmp(sys_dirent.d_name, ".."))) |
| 123 | 119 | ||
| @@ -136,11 +132,9 @@ static int tp_event_has_id(struct dirent *sys_dir, struct dirent *evt_dir) | |||
| 136 | return 0; | 132 | return 0; |
| 137 | } | 133 | } |
| 138 | 134 | ||
| 139 | #define for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next, file, st) \ | 135 | #define for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) \ |
| 140 | while (!readdir_r(evt_dir, &evt_dirent, &evt_next) && evt_next) \ | 136 | while (!readdir_r(evt_dir, &evt_dirent, &evt_next) && evt_next) \ |
| 141 | if (snprintf(file, MAXPATHLEN, "%s/%s/%s", debugfs_path, \ | 137 | if (evt_dirent.d_type == DT_DIR && \ |
| 142 | sys_dirent.d_name, evt_dirent.d_name) && \ | ||
| 143 | (!stat(file, &st)) && (S_ISDIR(st.st_mode)) && \ | ||
| 144 | (strcmp(evt_dirent.d_name, ".")) && \ | 138 | (strcmp(evt_dirent.d_name, ".")) && \ |
| 145 | (strcmp(evt_dirent.d_name, "..")) && \ | 139 | (strcmp(evt_dirent.d_name, "..")) && \ |
| 146 | (!tp_event_has_id(&sys_dirent, &evt_dirent))) | 140 | (!tp_event_has_id(&sys_dirent, &evt_dirent))) |
| @@ -163,9 +157,8 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config) | |||
| 163 | struct tracepoint_path *path = NULL; | 157 | struct tracepoint_path *path = NULL; |
| 164 | DIR *sys_dir, *evt_dir; | 158 | DIR *sys_dir, *evt_dir; |
| 165 | struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; | 159 | struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; |
| 166 | struct stat st; | ||
| 167 | char id_buf[4]; | 160 | char id_buf[4]; |
| 168 | int fd; | 161 | int sys_dir_fd, fd; |
| 169 | u64 id; | 162 | u64 id; |
| 170 | char evt_path[MAXPATHLEN]; | 163 | char evt_path[MAXPATHLEN]; |
| 171 | 164 | ||
| @@ -175,17 +168,23 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config) | |||
| 175 | sys_dir = opendir(debugfs_path); | 168 | sys_dir = opendir(debugfs_path); |
| 176 | if (!sys_dir) | 169 | if (!sys_dir) |
| 177 | goto cleanup; | 170 | goto cleanup; |
| 178 | 171 | sys_dir_fd = dirfd(sys_dir); | |
| 179 | for_each_subsystem(sys_dir, sys_dirent, sys_next, evt_path, st) { | 172 | |
| 180 | evt_dir = opendir(evt_path); | 173 | for_each_subsystem(sys_dir, sys_dirent, sys_next) { |
| 181 | if (!evt_dir) | 174 | int dfd = openat(sys_dir_fd, sys_dirent.d_name, |
| 182 | goto cleanup; | 175 | O_RDONLY|O_DIRECTORY), evt_dir_fd; |
| 183 | for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next, | 176 | if (dfd == -1) |
| 184 | evt_path, st) { | 177 | continue; |
| 185 | snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", | 178 | evt_dir = fdopendir(dfd); |
| 186 | debugfs_path, sys_dirent.d_name, | 179 | if (!evt_dir) { |
| 180 | close(dfd); | ||
| 181 | continue; | ||
| 182 | } | ||
| 183 | evt_dir_fd = dirfd(evt_dir); | ||
| 184 | for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) { | ||
| 185 | snprintf(evt_path, MAXPATHLEN, "%s/id", | ||
| 187 | evt_dirent.d_name); | 186 | evt_dirent.d_name); |
| 188 | fd = open(evt_path, O_RDONLY); | 187 | fd = openat(evt_dir_fd, evt_path, O_RDONLY); |
| 189 | if (fd < 0) | 188 | if (fd < 0) |
| 190 | continue; | 189 | continue; |
| 191 | if (read(fd, id_buf, sizeof(id_buf)) < 0) { | 190 | if (read(fd, id_buf, sizeof(id_buf)) < 0) { |
| @@ -629,7 +628,7 @@ static void print_tracepoint_events(void) | |||
| 629 | { | 628 | { |
| 630 | DIR *sys_dir, *evt_dir; | 629 | DIR *sys_dir, *evt_dir; |
| 631 | struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; | 630 | struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; |
| 632 | struct stat st; | 631 | int sys_dir_fd; |
| 633 | char evt_path[MAXPATHLEN]; | 632 | char evt_path[MAXPATHLEN]; |
| 634 | 633 | ||
| 635 | if (valid_debugfs_mount(debugfs_path)) | 634 | if (valid_debugfs_mount(debugfs_path)) |
| @@ -638,13 +637,20 @@ static void print_tracepoint_events(void) | |||
| 638 | sys_dir = opendir(debugfs_path); | 637 | sys_dir = opendir(debugfs_path); |
| 639 | if (!sys_dir) | 638 | if (!sys_dir) |
| 640 | goto cleanup; | 639 | goto cleanup; |
| 641 | 640 | sys_dir_fd = dirfd(sys_dir); | |
| 642 | for_each_subsystem(sys_dir, sys_dirent, sys_next, evt_path, st) { | 641 | |
| 643 | evt_dir = opendir(evt_path); | 642 | for_each_subsystem(sys_dir, sys_dirent, sys_next) { |
| 644 | if (!evt_dir) | 643 | int dfd = openat(sys_dir_fd, sys_dirent.d_name, |
| 645 | goto cleanup; | 644 | O_RDONLY|O_DIRECTORY), evt_dir_fd; |
| 646 | for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next, | 645 | if (dfd == -1) |
| 647 | evt_path, st) { | 646 | continue; |
| 647 | evt_dir = fdopendir(dfd); | ||
| 648 | if (!evt_dir) { | ||
| 649 | close(dfd); | ||
| 650 | continue; | ||
| 651 | } | ||
| 652 | evt_dir_fd = dirfd(evt_dir); | ||
| 653 | for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) { | ||
| 648 | snprintf(evt_path, MAXPATHLEN, "%s:%s", | 654 | snprintf(evt_path, MAXPATHLEN, "%s:%s", |
| 649 | sys_dirent.d_name, evt_dirent.d_name); | 655 | sys_dirent.d_name, evt_dirent.d_name); |
| 650 | fprintf(stderr, " %-40s [%s]\n", evt_path, | 656 | fprintf(stderr, " %-40s [%s]\n", evt_path, |
