#include #include #include #include #include #include #include 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; }