From 45de34bbe3e1b8f4c8bc8ecaf6c915b4b4c545f8 Mon Sep 17 00:00:00 2001 From: Stephane Eranian Date: Tue, 1 Jun 2010 21:25:01 +0200 Subject: perf buildid: add perfconfig option to specify buildid cache dir MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds the ability to specify an alternate directory to store the buildid cache (buildids, copy of binaries). By default, it is hardcoded to $HOME/.debug. This directory contains immutable data. The layout of the directory is such that no conflicts in filenames are possible. A modification in a file, yields a different buildid and thus a different location in the subdir hierarchy. You may want to put the buildid cache elsewhere because of disk space limitation or simply to share the cache between users. It is also useful for remote collect vs. local analysis of profiles. This patch adds a new config option to the perfconfig file. Under the tag 'buildid', there is a dir option. For instance, if you have: $ cat /etc/perfconfig [buildid] dir = /var/cache/perf-buildid All buildids and binaries are be saved in the directory specified. The perf record, buildid-list, buildid-cache, report, annotate, and archive commands will it to pull information out. The option can be set in the system-wide perfconfig file or in the $HOME/.perfconfig file. Cc: David S. Miller Cc: Frédéric Weisbecker Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Tom Zanussi LKML-Reference: <4c055fb7.df0ce30a.5f0d.ffffae52@mx.google.com> Signed-off-by: Stephane Eranian Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/build-id.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'tools/perf/util/build-id.c') diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c index 70c5cf87d020..5c26e2d314af 100644 --- a/tools/perf/util/build-id.c +++ b/tools/perf/util/build-id.c @@ -43,19 +43,17 @@ struct perf_event_ops build_id__mark_dso_hit_ops = { char *dso__build_id_filename(struct dso *self, char *bf, size_t size) { char build_id_hex[BUILD_ID_SIZE * 2 + 1]; - const char *home; if (!self->has_build_id) return NULL; build_id__sprintf(self->build_id, sizeof(self->build_id), build_id_hex); - home = getenv("HOME"); if (bf == NULL) { - if (asprintf(&bf, "%s/%s/.build-id/%.2s/%s", home, - DEBUG_CACHE_DIR, build_id_hex, build_id_hex + 2) < 0) + if (asprintf(&bf, "%s/.build-id/%.2s/%s", buildid_dir, + build_id_hex, build_id_hex + 2) < 0) return NULL; } else - snprintf(bf, size, "%s/%s/.build-id/%.2s/%s", home, - DEBUG_CACHE_DIR, build_id_hex, build_id_hex + 2); + snprintf(bf, size, "%s/.build-id/%.2s/%s", buildid_dir, + build_id_hex, build_id_hex + 2); return bf; } -- cgit v1.2.3 From 591765fdaf7ea1888157f342b67b0461f2e5ed9b Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 30 Jul 2010 18:28:42 -0300 Subject: perf tools: Release thread resources on PERF_RECORD_EXIT For long running sessions with many threads with short lifetimes the amount of memory that the buildid process takes is too much. Since we don't have hist_entries that may be pointing to them, we can just release the resources associated with each thread when the exit (PERF_RECORD_EXIT) event is received. For normal processing we need to annotate maps with hits, and thus hist_entries pointing to it and drop the ones that had none. Will be done in a followup patch. Cc: David S. Miller Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Tom Zanussi LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/build-id.c | 18 ++++++++++++++++++ tools/perf/util/map.c | 33 +++++++++++++++++++++++++++++++++ tools/perf/util/map.h | 1 + tools/perf/util/thread.c | 7 +++++++ tools/perf/util/thread.h | 2 ++ 5 files changed, 61 insertions(+) (limited to 'tools/perf/util/build-id.c') diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c index 5c26e2d314af..e437edb72417 100644 --- a/tools/perf/util/build-id.c +++ b/tools/perf/util/build-id.c @@ -12,6 +12,7 @@ #include "event.h" #include "symbol.h" #include +#include "debug.h" static int build_id__mark_dso_hit(event_t *event, struct perf_session *session) { @@ -34,10 +35,27 @@ static int build_id__mark_dso_hit(event_t *event, struct perf_session *session) return 0; } +static int event__exit_del_thread(event_t *self, struct perf_session *session) +{ + struct thread *thread = perf_session__findnew(session, self->fork.tid); + + dump_printf("(%d:%d):(%d:%d)\n", self->fork.pid, self->fork.tid, + self->fork.ppid, self->fork.ptid); + + if (thread) { + rb_erase(&thread->rb_node, &session->threads); + session->last_match = NULL; + thread__delete(thread); + } + + return 0; +} + struct perf_event_ops build_id__mark_dso_hit_ops = { .sample = build_id__mark_dso_hit, .mmap = event__process_mmap, .fork = event__process_task, + .exit = event__exit_del_thread, }; char *dso__build_id_filename(struct dso *self, char *bf, size_t size) diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index 37cab9038538..2ddbae319de5 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c @@ -228,6 +228,39 @@ void map_groups__init(struct map_groups *self) self->machine = NULL; } +static void maps__delete(struct rb_root *self) +{ + struct rb_node *next = rb_first(self); + + while (next) { + struct map *pos = rb_entry(next, struct map, rb_node); + + next = rb_next(&pos->rb_node); + rb_erase(&pos->rb_node, self); + map__delete(pos); + } +} + +static void maps__delete_removed(struct list_head *self) +{ + struct map *pos, *n; + + list_for_each_entry_safe(pos, n, self, node) { + list_del(&pos->node); + map__delete(pos); + } +} + +void map_groups__exit(struct map_groups *self) +{ + int i; + + for (i = 0; i < MAP__NR_TYPES; ++i) { + maps__delete(&self->maps[i]); + maps__delete_removed(&self->removed_maps[i]); + } +} + void map_groups__flush(struct map_groups *self) { int type; diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h index 3b2f706c0ba2..20eba420ddae 100644 --- a/tools/perf/util/map.h +++ b/tools/perf/util/map.h @@ -127,6 +127,7 @@ size_t __map_groups__fprintf_maps(struct map_groups *self, void maps__insert(struct rb_root *maps, struct map *map); struct map *maps__find(struct rb_root *maps, u64 addr); void map_groups__init(struct map_groups *self); +void map_groups__exit(struct map_groups *self); int map_groups__clone(struct map_groups *self, struct map_groups *parent, enum map_type type); size_t map_groups__fprintf(struct map_groups *self, int verbose, FILE *fp); diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index 9a448b47400c..8c72d888e449 100644 --- a/tools/perf/util/thread.c +++ b/tools/perf/util/thread.c @@ -62,6 +62,13 @@ static struct thread *thread__new(pid_t pid) return self; } +void thread__delete(struct thread *self) +{ + map_groups__exit(&self->mg); + free(self->comm); + free(self); +} + int thread__set_comm(struct thread *self, const char *comm) { int err; diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h index ee6bbcf277ca..688500ff826f 100644 --- a/tools/perf/util/thread.h +++ b/tools/perf/util/thread.h @@ -20,6 +20,8 @@ struct thread { struct perf_session; +void thread__delete(struct thread *self); + int find_all_tid(int pid, pid_t ** all_tid); int thread__set_comm(struct thread *self, const char *comm); int thread__comm_len(struct thread *self); -- cgit v1.2.3