diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2009-11-17 15:38:02 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-11-19 00:03:41 -0500 |
commit | b269876c8d57fb8c801bea1fc34b461646c5abd0 (patch) | |
tree | c9ac282b3a5f2d18a865180eb85c888f9e8cd338 /tools/perf/builtin-top.c | |
parent | 5a8e5a3065bf04b7673262fd6c46123e4b888d2b (diff) |
perf top: Don't allocate the source parsing members upfront
Defer to parse_source() time allocating it.
Now we use about this much memory:
1724 root 20 0 42104 10m 940 S 0.0 0.4 0:00.23 perf
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
LKML-Reference: <1258490282-1821-3-git-send-email-acme@infradead.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf/builtin-top.c')
-rw-r--r-- | tools/perf/builtin-top.c | 76 |
1 files changed, 45 insertions, 31 deletions
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 49cf87680fe3..07b92c378ae2 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c | |||
@@ -108,6 +108,13 @@ static int display_weighted = -1; | |||
108 | * Symbols | 108 | * Symbols |
109 | */ | 109 | */ |
110 | 110 | ||
111 | struct sym_entry_source { | ||
112 | struct source_line *source; | ||
113 | struct source_line *lines; | ||
114 | struct source_line **lines_tail; | ||
115 | pthread_mutex_t lock; | ||
116 | }; | ||
117 | |||
111 | struct sym_entry { | 118 | struct sym_entry { |
112 | struct rb_node rb_node; | 119 | struct rb_node rb_node; |
113 | struct list_head node; | 120 | struct list_head node; |
@@ -117,10 +124,7 @@ struct sym_entry { | |||
117 | u16 name_len; | 124 | u16 name_len; |
118 | u8 origin; | 125 | u8 origin; |
119 | struct map *map; | 126 | struct map *map; |
120 | struct source_line *source; | 127 | struct sym_entry_source *src; |
121 | struct source_line *lines; | ||
122 | struct source_line **lines_tail; | ||
123 | pthread_mutex_t source_lock; | ||
124 | unsigned long count[0]; | 128 | unsigned long count[0]; |
125 | }; | 129 | }; |
126 | 130 | ||
@@ -172,6 +176,7 @@ static void sig_winch_handler(int sig __used) | |||
172 | static void parse_source(struct sym_entry *syme) | 176 | static void parse_source(struct sym_entry *syme) |
173 | { | 177 | { |
174 | struct symbol *sym; | 178 | struct symbol *sym; |
179 | struct sym_entry_source *source; | ||
175 | struct map *map; | 180 | struct map *map; |
176 | FILE *file; | 181 | FILE *file; |
177 | char command[PATH_MAX*2]; | 182 | char command[PATH_MAX*2]; |
@@ -181,8 +186,17 @@ static void parse_source(struct sym_entry *syme) | |||
181 | if (!syme) | 186 | if (!syme) |
182 | return; | 187 | return; |
183 | 188 | ||
184 | if (syme->lines) { | 189 | if (syme->src == NULL) { |
185 | pthread_mutex_lock(&syme->source_lock); | 190 | syme->src = calloc(1, sizeof(*source)); |
191 | if (syme->src == NULL) | ||
192 | return; | ||
193 | pthread_mutex_init(&syme->src->lock, NULL); | ||
194 | } | ||
195 | |||
196 | source = syme->src; | ||
197 | |||
198 | if (source->lines) { | ||
199 | pthread_mutex_lock(&source->lock); | ||
186 | goto out_assign; | 200 | goto out_assign; |
187 | } | 201 | } |
188 | 202 | ||
@@ -202,8 +216,8 @@ static void parse_source(struct sym_entry *syme) | |||
202 | if (!file) | 216 | if (!file) |
203 | return; | 217 | return; |
204 | 218 | ||
205 | pthread_mutex_lock(&syme->source_lock); | 219 | pthread_mutex_lock(&source->lock); |
206 | syme->lines_tail = &syme->lines; | 220 | source->lines_tail = &source->lines; |
207 | while (!feof(file)) { | 221 | while (!feof(file)) { |
208 | struct source_line *src; | 222 | struct source_line *src; |
209 | size_t dummy = 0; | 223 | size_t dummy = 0; |
@@ -223,8 +237,8 @@ static void parse_source(struct sym_entry *syme) | |||
223 | *c = 0; | 237 | *c = 0; |
224 | 238 | ||
225 | src->next = NULL; | 239 | src->next = NULL; |
226 | *syme->lines_tail = src; | 240 | *source->lines_tail = src; |
227 | syme->lines_tail = &src->next; | 241 | source->lines_tail = &src->next; |
228 | 242 | ||
229 | if (strlen(src->line)>8 && src->line[8] == ':') { | 243 | if (strlen(src->line)>8 && src->line[8] == ':') { |
230 | src->eip = strtoull(src->line, NULL, 16); | 244 | src->eip = strtoull(src->line, NULL, 16); |
@@ -238,7 +252,7 @@ static void parse_source(struct sym_entry *syme) | |||
238 | pclose(file); | 252 | pclose(file); |
239 | out_assign: | 253 | out_assign: |
240 | sym_filter_entry = syme; | 254 | sym_filter_entry = syme; |
241 | pthread_mutex_unlock(&syme->source_lock); | 255 | pthread_mutex_unlock(&source->lock); |
242 | } | 256 | } |
243 | 257 | ||
244 | static void __zero_source_counters(struct sym_entry *syme) | 258 | static void __zero_source_counters(struct sym_entry *syme) |
@@ -246,7 +260,7 @@ static void __zero_source_counters(struct sym_entry *syme) | |||
246 | int i; | 260 | int i; |
247 | struct source_line *line; | 261 | struct source_line *line; |
248 | 262 | ||
249 | line = syme->lines; | 263 | line = syme->src->lines; |
250 | while (line) { | 264 | while (line) { |
251 | for (i = 0; i < nr_counters; i++) | 265 | for (i = 0; i < nr_counters; i++) |
252 | line->count[i] = 0; | 266 | line->count[i] = 0; |
@@ -261,13 +275,13 @@ static void record_precise_ip(struct sym_entry *syme, int counter, u64 ip) | |||
261 | if (syme != sym_filter_entry) | 275 | if (syme != sym_filter_entry) |
262 | return; | 276 | return; |
263 | 277 | ||
264 | if (pthread_mutex_trylock(&syme->source_lock)) | 278 | if (pthread_mutex_trylock(&syme->src->lock)) |
265 | return; | 279 | return; |
266 | 280 | ||
267 | if (!syme->source) | 281 | if (syme->src == NULL || syme->src->source == NULL) |
268 | goto out_unlock; | 282 | goto out_unlock; |
269 | 283 | ||
270 | for (line = syme->lines; line; line = line->next) { | 284 | for (line = syme->src->lines; line; line = line->next) { |
271 | if (line->eip == ip) { | 285 | if (line->eip == ip) { |
272 | line->count[counter]++; | 286 | line->count[counter]++; |
273 | break; | 287 | break; |
@@ -276,7 +290,7 @@ static void record_precise_ip(struct sym_entry *syme, int counter, u64 ip) | |||
276 | break; | 290 | break; |
277 | } | 291 | } |
278 | out_unlock: | 292 | out_unlock: |
279 | pthread_mutex_unlock(&syme->source_lock); | 293 | pthread_mutex_unlock(&syme->src->lock); |
280 | } | 294 | } |
281 | 295 | ||
282 | static void lookup_sym_source(struct sym_entry *syme) | 296 | static void lookup_sym_source(struct sym_entry *syme) |
@@ -287,14 +301,14 @@ static void lookup_sym_source(struct sym_entry *syme) | |||
287 | 301 | ||
288 | sprintf(pattern, "<%s>:", symbol->name); | 302 | sprintf(pattern, "<%s>:", symbol->name); |
289 | 303 | ||
290 | pthread_mutex_lock(&syme->source_lock); | 304 | pthread_mutex_lock(&syme->src->lock); |
291 | for (line = syme->lines; line; line = line->next) { | 305 | for (line = syme->src->lines; line; line = line->next) { |
292 | if (strstr(line->line, pattern)) { | 306 | if (strstr(line->line, pattern)) { |
293 | syme->source = line; | 307 | syme->src->source = line; |
294 | break; | 308 | break; |
295 | } | 309 | } |
296 | } | 310 | } |
297 | pthread_mutex_unlock(&syme->source_lock); | 311 | pthread_mutex_unlock(&syme->src->lock); |
298 | } | 312 | } |
299 | 313 | ||
300 | static void show_lines(struct source_line *queue, int count, int total) | 314 | static void show_lines(struct source_line *queue, int count, int total) |
@@ -324,24 +338,24 @@ static void show_details(struct sym_entry *syme) | |||
324 | if (!syme) | 338 | if (!syme) |
325 | return; | 339 | return; |
326 | 340 | ||
327 | if (!syme->source) | 341 | if (!syme->src->source) |
328 | lookup_sym_source(syme); | 342 | lookup_sym_source(syme); |
329 | 343 | ||
330 | if (!syme->source) | 344 | if (!syme->src->source) |
331 | return; | 345 | return; |
332 | 346 | ||
333 | symbol = sym_entry__symbol(syme); | 347 | symbol = sym_entry__symbol(syme); |
334 | printf("Showing %s for %s\n", event_name(sym_counter), symbol->name); | 348 | printf("Showing %s for %s\n", event_name(sym_counter), symbol->name); |
335 | printf(" Events Pcnt (>=%d%%)\n", sym_pcnt_filter); | 349 | printf(" Events Pcnt (>=%d%%)\n", sym_pcnt_filter); |
336 | 350 | ||
337 | pthread_mutex_lock(&syme->source_lock); | 351 | pthread_mutex_lock(&syme->src->lock); |
338 | line = syme->source; | 352 | line = syme->src->source; |
339 | while (line) { | 353 | while (line) { |
340 | total += line->count[sym_counter]; | 354 | total += line->count[sym_counter]; |
341 | line = line->next; | 355 | line = line->next; |
342 | } | 356 | } |
343 | 357 | ||
344 | line = syme->source; | 358 | line = syme->src->source; |
345 | while (line) { | 359 | while (line) { |
346 | float pcnt = 0.0; | 360 | float pcnt = 0.0; |
347 | 361 | ||
@@ -366,7 +380,7 @@ static void show_details(struct sym_entry *syme) | |||
366 | line->count[sym_counter] = zero ? 0 : line->count[sym_counter] * 7 / 8; | 380 | line->count[sym_counter] = zero ? 0 : line->count[sym_counter] * 7 / 8; |
367 | line = line->next; | 381 | line = line->next; |
368 | } | 382 | } |
369 | pthread_mutex_unlock(&syme->source_lock); | 383 | pthread_mutex_unlock(&syme->src->lock); |
370 | if (more) | 384 | if (more) |
371 | printf("%d lines not displayed, maybe increase display entries [e]\n", more); | 385 | printf("%d lines not displayed, maybe increase display entries [e]\n", more); |
372 | } | 386 | } |
@@ -647,10 +661,10 @@ static void prompt_symbol(struct sym_entry **target, const char *msg) | |||
647 | 661 | ||
648 | /* zero counters of active symbol */ | 662 | /* zero counters of active symbol */ |
649 | if (syme) { | 663 | if (syme) { |
650 | pthread_mutex_lock(&syme->source_lock); | 664 | pthread_mutex_lock(&syme->src->lock); |
651 | __zero_source_counters(syme); | 665 | __zero_source_counters(syme); |
652 | *target = NULL; | 666 | *target = NULL; |
653 | pthread_mutex_unlock(&syme->source_lock); | 667 | pthread_mutex_unlock(&syme->src->lock); |
654 | } | 668 | } |
655 | 669 | ||
656 | fprintf(stdout, "\n%s: ", msg); | 670 | fprintf(stdout, "\n%s: ", msg); |
@@ -826,10 +840,10 @@ static void handle_keypress(int c) | |||
826 | else { | 840 | else { |
827 | struct sym_entry *syme = sym_filter_entry; | 841 | struct sym_entry *syme = sym_filter_entry; |
828 | 842 | ||
829 | pthread_mutex_lock(&syme->source_lock); | 843 | pthread_mutex_lock(&syme->src->lock); |
830 | sym_filter_entry = NULL; | 844 | sym_filter_entry = NULL; |
831 | __zero_source_counters(syme); | 845 | __zero_source_counters(syme); |
832 | pthread_mutex_unlock(&syme->source_lock); | 846 | pthread_mutex_unlock(&syme->src->lock); |
833 | } | 847 | } |
834 | break; | 848 | break; |
835 | case 'U': | 849 | case 'U': |
@@ -915,7 +929,7 @@ static int symbol_filter(struct map *map, struct symbol *sym) | |||
915 | 929 | ||
916 | syme = symbol__priv(sym); | 930 | syme = symbol__priv(sym); |
917 | syme->map = map; | 931 | syme->map = map; |
918 | pthread_mutex_init(&syme->source_lock, NULL); | 932 | syme->src = NULL; |
919 | if (!sym_filter_entry && sym_filter && !strcmp(name, sym_filter)) | 933 | if (!sym_filter_entry && sym_filter && !strcmp(name, sym_filter)) |
920 | sym_filter_entry = syme; | 934 | sym_filter_entry = syme; |
921 | 935 | ||