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>
This commit is contained in:
committed by
Ingo Molnar
parent
5a8e5a3065
commit
b269876c8d
@@ -108,6 +108,13 @@ static int display_weighted = -1;
|
|||||||
* Symbols
|
* Symbols
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
struct sym_entry_source {
|
||||||
|
struct source_line *source;
|
||||||
|
struct source_line *lines;
|
||||||
|
struct source_line **lines_tail;
|
||||||
|
pthread_mutex_t lock;
|
||||||
|
};
|
||||||
|
|
||||||
struct sym_entry {
|
struct sym_entry {
|
||||||
struct rb_node rb_node;
|
struct rb_node rb_node;
|
||||||
struct list_head node;
|
struct list_head node;
|
||||||
@@ -117,10 +124,7 @@ struct sym_entry {
|
|||||||
u16 name_len;
|
u16 name_len;
|
||||||
u8 origin;
|
u8 origin;
|
||||||
struct map *map;
|
struct map *map;
|
||||||
struct source_line *source;
|
struct sym_entry_source *src;
|
||||||
struct source_line *lines;
|
|
||||||
struct source_line **lines_tail;
|
|
||||||
pthread_mutex_t source_lock;
|
|
||||||
unsigned long count[0];
|
unsigned long count[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -172,6 +176,7 @@ static void sig_winch_handler(int sig __used)
|
|||||||
static void parse_source(struct sym_entry *syme)
|
static void parse_source(struct sym_entry *syme)
|
||||||
{
|
{
|
||||||
struct symbol *sym;
|
struct symbol *sym;
|
||||||
|
struct sym_entry_source *source;
|
||||||
struct map *map;
|
struct map *map;
|
||||||
FILE *file;
|
FILE *file;
|
||||||
char command[PATH_MAX*2];
|
char command[PATH_MAX*2];
|
||||||
@@ -181,8 +186,17 @@ static void parse_source(struct sym_entry *syme)
|
|||||||
if (!syme)
|
if (!syme)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (syme->lines) {
|
if (syme->src == NULL) {
|
||||||
pthread_mutex_lock(&syme->source_lock);
|
syme->src = calloc(1, sizeof(*source));
|
||||||
|
if (syme->src == NULL)
|
||||||
|
return;
|
||||||
|
pthread_mutex_init(&syme->src->lock, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
source = syme->src;
|
||||||
|
|
||||||
|
if (source->lines) {
|
||||||
|
pthread_mutex_lock(&source->lock);
|
||||||
goto out_assign;
|
goto out_assign;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,8 +216,8 @@ static void parse_source(struct sym_entry *syme)
|
|||||||
if (!file)
|
if (!file)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
pthread_mutex_lock(&syme->source_lock);
|
pthread_mutex_lock(&source->lock);
|
||||||
syme->lines_tail = &syme->lines;
|
source->lines_tail = &source->lines;
|
||||||
while (!feof(file)) {
|
while (!feof(file)) {
|
||||||
struct source_line *src;
|
struct source_line *src;
|
||||||
size_t dummy = 0;
|
size_t dummy = 0;
|
||||||
@@ -223,8 +237,8 @@ static void parse_source(struct sym_entry *syme)
|
|||||||
*c = 0;
|
*c = 0;
|
||||||
|
|
||||||
src->next = NULL;
|
src->next = NULL;
|
||||||
*syme->lines_tail = src;
|
*source->lines_tail = src;
|
||||||
syme->lines_tail = &src->next;
|
source->lines_tail = &src->next;
|
||||||
|
|
||||||
if (strlen(src->line)>8 && src->line[8] == ':') {
|
if (strlen(src->line)>8 && src->line[8] == ':') {
|
||||||
src->eip = strtoull(src->line, NULL, 16);
|
src->eip = strtoull(src->line, NULL, 16);
|
||||||
@@ -238,7 +252,7 @@ static void parse_source(struct sym_entry *syme)
|
|||||||
pclose(file);
|
pclose(file);
|
||||||
out_assign:
|
out_assign:
|
||||||
sym_filter_entry = syme;
|
sym_filter_entry = syme;
|
||||||
pthread_mutex_unlock(&syme->source_lock);
|
pthread_mutex_unlock(&source->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __zero_source_counters(struct sym_entry *syme)
|
static void __zero_source_counters(struct sym_entry *syme)
|
||||||
@@ -246,7 +260,7 @@ static void __zero_source_counters(struct sym_entry *syme)
|
|||||||
int i;
|
int i;
|
||||||
struct source_line *line;
|
struct source_line *line;
|
||||||
|
|
||||||
line = syme->lines;
|
line = syme->src->lines;
|
||||||
while (line) {
|
while (line) {
|
||||||
for (i = 0; i < nr_counters; i++)
|
for (i = 0; i < nr_counters; i++)
|
||||||
line->count[i] = 0;
|
line->count[i] = 0;
|
||||||
@@ -261,13 +275,13 @@ static void record_precise_ip(struct sym_entry *syme, int counter, u64 ip)
|
|||||||
if (syme != sym_filter_entry)
|
if (syme != sym_filter_entry)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (pthread_mutex_trylock(&syme->source_lock))
|
if (pthread_mutex_trylock(&syme->src->lock))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!syme->source)
|
if (syme->src == NULL || syme->src->source == NULL)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
|
||||||
for (line = syme->lines; line; line = line->next) {
|
for (line = syme->src->lines; line; line = line->next) {
|
||||||
if (line->eip == ip) {
|
if (line->eip == ip) {
|
||||||
line->count[counter]++;
|
line->count[counter]++;
|
||||||
break;
|
break;
|
||||||
@@ -276,7 +290,7 @@ static void record_precise_ip(struct sym_entry *syme, int counter, u64 ip)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
out_unlock:
|
out_unlock:
|
||||||
pthread_mutex_unlock(&syme->source_lock);
|
pthread_mutex_unlock(&syme->src->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lookup_sym_source(struct sym_entry *syme)
|
static void lookup_sym_source(struct sym_entry *syme)
|
||||||
@@ -287,14 +301,14 @@ static void lookup_sym_source(struct sym_entry *syme)
|
|||||||
|
|
||||||
sprintf(pattern, "<%s>:", symbol->name);
|
sprintf(pattern, "<%s>:", symbol->name);
|
||||||
|
|
||||||
pthread_mutex_lock(&syme->source_lock);
|
pthread_mutex_lock(&syme->src->lock);
|
||||||
for (line = syme->lines; line; line = line->next) {
|
for (line = syme->src->lines; line; line = line->next) {
|
||||||
if (strstr(line->line, pattern)) {
|
if (strstr(line->line, pattern)) {
|
||||||
syme->source = line;
|
syme->src->source = line;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&syme->source_lock);
|
pthread_mutex_unlock(&syme->src->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void show_lines(struct source_line *queue, int count, int total)
|
static void show_lines(struct source_line *queue, int count, int total)
|
||||||
@@ -324,24 +338,24 @@ static void show_details(struct sym_entry *syme)
|
|||||||
if (!syme)
|
if (!syme)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!syme->source)
|
if (!syme->src->source)
|
||||||
lookup_sym_source(syme);
|
lookup_sym_source(syme);
|
||||||
|
|
||||||
if (!syme->source)
|
if (!syme->src->source)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
symbol = sym_entry__symbol(syme);
|
symbol = sym_entry__symbol(syme);
|
||||||
printf("Showing %s for %s\n", event_name(sym_counter), symbol->name);
|
printf("Showing %s for %s\n", event_name(sym_counter), symbol->name);
|
||||||
printf(" Events Pcnt (>=%d%%)\n", sym_pcnt_filter);
|
printf(" Events Pcnt (>=%d%%)\n", sym_pcnt_filter);
|
||||||
|
|
||||||
pthread_mutex_lock(&syme->source_lock);
|
pthread_mutex_lock(&syme->src->lock);
|
||||||
line = syme->source;
|
line = syme->src->source;
|
||||||
while (line) {
|
while (line) {
|
||||||
total += line->count[sym_counter];
|
total += line->count[sym_counter];
|
||||||
line = line->next;
|
line = line->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
line = syme->source;
|
line = syme->src->source;
|
||||||
while (line) {
|
while (line) {
|
||||||
float pcnt = 0.0;
|
float pcnt = 0.0;
|
||||||
|
|
||||||
@@ -366,7 +380,7 @@ static void show_details(struct sym_entry *syme)
|
|||||||
line->count[sym_counter] = zero ? 0 : line->count[sym_counter] * 7 / 8;
|
line->count[sym_counter] = zero ? 0 : line->count[sym_counter] * 7 / 8;
|
||||||
line = line->next;
|
line = line->next;
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&syme->source_lock);
|
pthread_mutex_unlock(&syme->src->lock);
|
||||||
if (more)
|
if (more)
|
||||||
printf("%d lines not displayed, maybe increase display entries [e]\n", more);
|
printf("%d lines not displayed, maybe increase display entries [e]\n", more);
|
||||||
}
|
}
|
||||||
@@ -647,10 +661,10 @@ static void prompt_symbol(struct sym_entry **target, const char *msg)
|
|||||||
|
|
||||||
/* zero counters of active symbol */
|
/* zero counters of active symbol */
|
||||||
if (syme) {
|
if (syme) {
|
||||||
pthread_mutex_lock(&syme->source_lock);
|
pthread_mutex_lock(&syme->src->lock);
|
||||||
__zero_source_counters(syme);
|
__zero_source_counters(syme);
|
||||||
*target = NULL;
|
*target = NULL;
|
||||||
pthread_mutex_unlock(&syme->source_lock);
|
pthread_mutex_unlock(&syme->src->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stdout, "\n%s: ", msg);
|
fprintf(stdout, "\n%s: ", msg);
|
||||||
@@ -826,10 +840,10 @@ static void handle_keypress(int c)
|
|||||||
else {
|
else {
|
||||||
struct sym_entry *syme = sym_filter_entry;
|
struct sym_entry *syme = sym_filter_entry;
|
||||||
|
|
||||||
pthread_mutex_lock(&syme->source_lock);
|
pthread_mutex_lock(&syme->src->lock);
|
||||||
sym_filter_entry = NULL;
|
sym_filter_entry = NULL;
|
||||||
__zero_source_counters(syme);
|
__zero_source_counters(syme);
|
||||||
pthread_mutex_unlock(&syme->source_lock);
|
pthread_mutex_unlock(&syme->src->lock);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'U':
|
case 'U':
|
||||||
@@ -915,7 +929,7 @@ static int symbol_filter(struct map *map, struct symbol *sym)
|
|||||||
|
|
||||||
syme = symbol__priv(sym);
|
syme = symbol__priv(sym);
|
||||||
syme->map = map;
|
syme->map = map;
|
||||||
pthread_mutex_init(&syme->source_lock, NULL);
|
syme->src = NULL;
|
||||||
if (!sym_filter_entry && sym_filter && !strcmp(name, sym_filter))
|
if (!sym_filter_entry && sym_filter && !strcmp(name, sym_filter))
|
||||||
sym_filter_entry = syme;
|
sym_filter_entry = syme;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user