198 lines
4.8 KiB
C
198 lines
4.8 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
#include <ctype.h>
|
|
#include <Eina.h>
|
|
|
|
enum {
|
|
BYTES, KB, MB, SIZE, COUNT
|
|
};
|
|
|
|
typedef struct _Group Group;
|
|
|
|
struct _Group
|
|
{
|
|
char *trace;
|
|
unsigned long total;
|
|
unsigned long count;
|
|
};
|
|
|
|
static Eina_Hash *groups = NULL;
|
|
static Eina_List *sorted = NULL;
|
|
static int size = BYTES;
|
|
static int sort = SIZE;
|
|
|
|
static int
|
|
listsort(const void *data1, const void *data2)
|
|
{
|
|
Group *g = (Group *)data1;
|
|
Group *gg = (Group *)data2;
|
|
if (sort == SIZE) return (int)(g->total - gg->total);
|
|
else if (sort == COUNT) return (int)(g->count - gg->count);
|
|
return (int)(g->total - gg->total);
|
|
}
|
|
|
|
static Eina_Bool
|
|
hashwalk(const Eina_Hash *hash, const void *key, void *data, void *fdata)
|
|
{
|
|
Group *g = data;
|
|
sorted = eina_list_append(sorted, g);
|
|
return EINA_TRUE;
|
|
}
|
|
|
|
int
|
|
main(int argc, char **argv)
|
|
{
|
|
FILE *f;
|
|
char *file;
|
|
char buf[4096];
|
|
int i;
|
|
int group = 0;
|
|
Group *g;
|
|
Eina_List *l;
|
|
unsigned long total_count = 0, total_size = 0;
|
|
|
|
eina_init();
|
|
if (argc < 1)
|
|
{
|
|
printf("usage: mtdump MTOUTFILE [OPT]\n"
|
|
"OPT can be 0 or more of:\n"
|
|
" -f N - group by trace of up to N functions in backtrace (0 == unlimited)\n"
|
|
" -m - show size in Mb\n"
|
|
" -k - show size in Kb\n"
|
|
" -b - show size in bytes\n"
|
|
" -s - sout by size\n"
|
|
" -c - sout by count\n"
|
|
);
|
|
exit(1);
|
|
}
|
|
for (i = 0; i < argc; i++)
|
|
{
|
|
if (!strcmp(argv[i], "-f"))
|
|
{
|
|
i++;
|
|
group = atoi(argv[i]);
|
|
}
|
|
else if (!strcmp(argv[i], "-m"))
|
|
{
|
|
size = MB;
|
|
}
|
|
else if (!strcmp(argv[i], "-k"))
|
|
{
|
|
size = KB;
|
|
}
|
|
else if (!strcmp(argv[i], "-b"))
|
|
{
|
|
size = BYTES;
|
|
}
|
|
else if (!strcmp(argv[i], "-s"))
|
|
{
|
|
sort = SIZE;
|
|
}
|
|
else if (!strcmp(argv[i], "-c"))
|
|
{
|
|
sort = COUNT;
|
|
}
|
|
else
|
|
file = argv[i];
|
|
}
|
|
f = fopen(file, "r");
|
|
if (!f)
|
|
{
|
|
perror("fopen");
|
|
exit(1);
|
|
}
|
|
|
|
groups = eina_hash_string_superfast_new(NULL);
|
|
while (fgets(buf, sizeof(buf) - 1, f))
|
|
{
|
|
int len;
|
|
unsigned long bytes = 0;
|
|
char *p;
|
|
|
|
len = strlen(buf);
|
|
if (len < 2) continue;
|
|
if ((len > 1) && (buf[len - 1] == '\n'))
|
|
{
|
|
buf[len - 1] = 0;
|
|
len--;
|
|
}
|
|
sscanf(buf, "%lu", &bytes);
|
|
p = strchr(buf, '|');
|
|
if (p)
|
|
{
|
|
char trace[4096] = "", *t;
|
|
|
|
p += 2;
|
|
if (group == 0)
|
|
{
|
|
strcpy(trace, p);
|
|
}
|
|
else
|
|
{
|
|
i = group;
|
|
t = trace;
|
|
while (*p)
|
|
{
|
|
if (isspace(*p))
|
|
{
|
|
i--;
|
|
if (i == 0) break;
|
|
}
|
|
*t = *p;
|
|
t++; p++;
|
|
}
|
|
*t = 0;
|
|
}
|
|
g = eina_hash_find(groups, trace);
|
|
if (!g)
|
|
{
|
|
g = calloc(1, sizeof(Group));
|
|
g->trace = strdup(trace);
|
|
eina_hash_add(groups, trace, g);
|
|
}
|
|
g->total += bytes;
|
|
g->count++;
|
|
}
|
|
}
|
|
fclose(f);
|
|
eina_hash_foreach(groups, hashwalk, NULL);
|
|
printf("|-- MEM --|- COUNT --|----------------------------------------------\n");
|
|
sorted = eina_list_sort(sorted, eina_list_count(sorted), listsort);
|
|
EINA_LIST_FOREACH(sorted, l, g)
|
|
{
|
|
switch (size)
|
|
{
|
|
case MB:
|
|
printf("%10lu [%8lu] %s\n", g->total / (1024 * 1024), g->count, g->trace);
|
|
break;
|
|
case KB:
|
|
printf("%10lu [%8lu] %s\n", g->total / 1024, g->count, g->trace);
|
|
break;
|
|
default:
|
|
printf("%10lu [%8lu] %s\n", g->total, g->count, g->trace);
|
|
break;
|
|
}
|
|
total_count += g->count;
|
|
total_size += g->total;
|
|
}
|
|
printf("|-- MEM --|- COUNT --|----------------------------------------------\n");
|
|
printf("Total allocs: %lu\n", total_count);
|
|
switch (size)
|
|
{
|
|
case MB:
|
|
printf("Total memory: %lu Mb\n", total_size / (1024 * 1024));
|
|
break;
|
|
case KB:
|
|
printf("Total memory: %lu Kb\n", total_size / 1024);
|
|
break;
|
|
default:
|
|
printf("Total memory: %lu bytes\n", total_size);
|
|
break;
|
|
}
|
|
exit(0);
|
|
return 0;
|
|
}
|