diff options
| author | Jiri Olsa <jolsa@kernel.org> | 2014-04-30 09:47:27 -0400 |
|---|---|---|
| committer | Jiri Olsa <jolsa@kernel.org> | 2014-06-12 10:53:20 -0400 |
| commit | c658045197814b7d762662f9aa9f652379121a03 (patch) | |
| tree | 4f61850960139bbf9382480c32a4247f8a907ab1 /tools | |
| parent | bda6ee4a94d1e1be0c1428d37bc0d3da2e5793ad (diff) | |
perf tools: Cache dso data file descriptor
Caching dso data file descriptors to avoid expensive re-opens
especially during DWARF unwind.
We keep dsos data file descriptors open until their count reaches
the half of the current fd open limit (RLIMIT_NOFILE). In this case
we close file descriptor of the first opened dso object.
We've got overall speedup (~27% for my workload) of report:
'perf report --stdio -i perf-test.data' (3 runs)
(perf-test.data size was around 12GB)
current code:
545,640,944,228 cycles ( +- 0.53% )
785,255,798,320 instructions ( +- 0.03% )
366.340910010 seconds time elapsed ( +- 3.65% )
after change:
435,895,036,114 cycles ( +- 0.26% )
636,790,271,176 instructions ( +- 0.04% )
266.481463387 seconds time elapsed ( +- 0.13% )
Acked-by: Namhyung Kim <namhyung@kernel.org>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jean Pihet <jean.pihet@linaro.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1401892622-30848-7-git-send-email-jolsa@kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/perf/util/dso.c | 61 | ||||
| -rw-r--r-- | tools/perf/util/unwind-libunwind.c | 2 |
2 files changed, 59 insertions, 4 deletions
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index 76e5c13afc8f..fbf6cc98b8a9 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c | |||
| @@ -1,4 +1,6 @@ | |||
| 1 | #include <asm/bug.h> | 1 | #include <asm/bug.h> |
| 2 | #include <sys/time.h> | ||
| 3 | #include <sys/resource.h> | ||
| 2 | #include "symbol.h" | 4 | #include "symbol.h" |
| 3 | #include "dso.h" | 5 | #include "dso.h" |
| 4 | #include "machine.h" | 6 | #include "machine.h" |
| @@ -180,12 +182,20 @@ static int __open_dso(struct dso *dso, struct machine *machine) | |||
| 180 | return fd; | 182 | return fd; |
| 181 | } | 183 | } |
| 182 | 184 | ||
| 185 | static void check_data_close(void); | ||
| 186 | |||
| 183 | static int open_dso(struct dso *dso, struct machine *machine) | 187 | static int open_dso(struct dso *dso, struct machine *machine) |
| 184 | { | 188 | { |
| 185 | int fd = __open_dso(dso, machine); | 189 | int fd = __open_dso(dso, machine); |
| 186 | 190 | ||
| 187 | if (fd > 0) | 191 | if (fd > 0) { |
| 188 | dso__list_add(dso); | 192 | dso__list_add(dso); |
| 193 | /* | ||
| 194 | * Check if we crossed the allowed number | ||
| 195 | * of opened DSOs and close one if needed. | ||
| 196 | */ | ||
| 197 | check_data_close(); | ||
| 198 | } | ||
| 189 | 199 | ||
| 190 | return fd; | 200 | return fd; |
| 191 | } | 201 | } |
| @@ -204,6 +214,54 @@ static void close_dso(struct dso *dso) | |||
| 204 | close_data_fd(dso); | 214 | close_data_fd(dso); |
| 205 | } | 215 | } |
| 206 | 216 | ||
| 217 | static void close_first_dso(void) | ||
| 218 | { | ||
| 219 | struct dso *dso; | ||
| 220 | |||
| 221 | dso = list_first_entry(&dso__data_open, struct dso, data.open_entry); | ||
| 222 | close_dso(dso); | ||
| 223 | } | ||
| 224 | |||
| 225 | static rlim_t get_fd_limit(void) | ||
| 226 | { | ||
| 227 | struct rlimit l; | ||
| 228 | rlim_t limit = 0; | ||
| 229 | |||
| 230 | /* Allow half of the current open fd limit. */ | ||
| 231 | if (getrlimit(RLIMIT_NOFILE, &l) == 0) { | ||
| 232 | if (l.rlim_cur == RLIM_INFINITY) | ||
| 233 | limit = l.rlim_cur; | ||
| 234 | else | ||
| 235 | limit = l.rlim_cur / 2; | ||
| 236 | } else { | ||
| 237 | pr_err("failed to get fd limit\n"); | ||
| 238 | limit = 1; | ||
| 239 | } | ||
| 240 | |||
| 241 | return limit; | ||
| 242 | } | ||
| 243 | |||
| 244 | static bool may_cache_fd(void) | ||
| 245 | { | ||
| 246 | static rlim_t limit; | ||
| 247 | |||
| 248 | if (!limit) | ||
| 249 | limit = get_fd_limit(); | ||
| 250 | |||
| 251 | if (limit == RLIM_INFINITY) | ||
| 252 | return true; | ||
| 253 | |||
| 254 | return limit > (rlim_t) dso__data_open_cnt; | ||
| 255 | } | ||
| 256 | |||
| 257 | static void check_data_close(void) | ||
| 258 | { | ||
| 259 | bool cache_fd = may_cache_fd(); | ||
| 260 | |||
| 261 | if (!cache_fd) | ||
| 262 | close_first_dso(); | ||
| 263 | } | ||
| 264 | |||
| 207 | void dso__data_close(struct dso *dso) | 265 | void dso__data_close(struct dso *dso) |
| 208 | { | 266 | { |
| 209 | close_dso(dso); | 267 | close_dso(dso); |
| @@ -356,7 +414,6 @@ dso_cache__read(struct dso *dso, struct machine *machine, | |||
| 356 | if (ret <= 0) | 414 | if (ret <= 0) |
| 357 | free(cache); | 415 | free(cache); |
| 358 | 416 | ||
| 359 | dso__data_close(dso); | ||
| 360 | return ret; | 417 | return ret; |
| 361 | } | 418 | } |
| 362 | 419 | ||
diff --git a/tools/perf/util/unwind-libunwind.c b/tools/perf/util/unwind-libunwind.c index 4f8dd9ee3899..25578b98f5c5 100644 --- a/tools/perf/util/unwind-libunwind.c +++ b/tools/perf/util/unwind-libunwind.c | |||
| @@ -250,7 +250,6 @@ static int read_unwind_spec_eh_frame(struct dso *dso, struct machine *machine, | |||
| 250 | 250 | ||
| 251 | /* Check the .eh_frame section for unwinding info */ | 251 | /* Check the .eh_frame section for unwinding info */ |
| 252 | offset = elf_section_offset(fd, ".eh_frame_hdr"); | 252 | offset = elf_section_offset(fd, ".eh_frame_hdr"); |
| 253 | dso__data_close(dso); | ||
| 254 | 253 | ||
| 255 | if (offset) | 254 | if (offset) |
| 256 | ret = unwind_spec_ehframe(dso, machine, offset, | 255 | ret = unwind_spec_ehframe(dso, machine, offset, |
| @@ -271,7 +270,6 @@ static int read_unwind_spec_debug_frame(struct dso *dso, | |||
| 271 | 270 | ||
| 272 | /* Check the .debug_frame section for unwinding info */ | 271 | /* Check the .debug_frame section for unwinding info */ |
| 273 | *offset = elf_section_offset(fd, ".debug_frame"); | 272 | *offset = elf_section_offset(fd, ".debug_frame"); |
| 274 | dso__data_close(dso); | ||
| 275 | 273 | ||
| 276 | if (*offset) | 274 | if (*offset) |
| 277 | return 0; | 275 | return 0; |
