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 | |
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')
-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, |