X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=summary.c;h=9103f7102cecb383fefa59fa131d680d491d8916;hb=8b7c2b422eb5a79348ab56c8e8ce80a9ab1b62b9;hp=937da1a661a422c112d7cd38fbf1c6321d5ca7c2;hpb=689b9dbb8d7f88ab91e7741932ed000b6e49be9a;p=platform%2Fupstream%2Fltrace.git diff --git a/summary.c b/summary.c index 937da1a..9103f71 100644 --- a/summary.c +++ b/summary.c @@ -1,5 +1,6 @@ /* * This file is part of ltrace. + * Copyright (C) 2012,2013 Petr Machata, Red Hat Inc. * Copyright (C) 2003,2008,2009 Juan Cespedes * Copyright (C) 2006 Ian Wienand * @@ -21,87 +22,180 @@ #include "config.h" +#include #include #include -#include +#include + +#include "summary.h" +#include "dict.h" +#include "library.h" +#include "options.h" + +struct entry_st { + const char *name; + unsigned count; + struct timeval tv; +}; -#include "common.h" +struct fill_struct_data { + struct vect entries; + unsigned tot_count; + unsigned long tot_usecs; +}; -static int num_entries = 0; -static struct entry_st { - char *name; +struct opt_c_struct { int count; struct timeval tv; -} *entries = NULL; +}; -static int tot_count = 0; -static unsigned long int tot_usecs = 0; +static struct dict *dict_opt_c; -static void fill_struct(void *key, void *value, void *data) +struct timedelta +calc_time_spent(struct timeval start) { - struct opt_c_struct *st = (struct opt_c_struct *)value; + struct timeval tv; + gettimeofday(&tv, NULL); - entries = realloc(entries, (num_entries + 1) * sizeof(struct entry_st)); - if (!entries) { - perror("realloc()"); - exit(1); + struct timeval diff; + diff.tv_sec = tv.tv_sec - start.tv_sec; + if (tv.tv_usec >= start.tv_usec) { + diff.tv_usec = tv.tv_usec - start.tv_usec; + } else { + diff.tv_sec--; + diff.tv_usec = 1000000 + tv.tv_usec - start.tv_usec; } - entries[num_entries].name = (char *)key; - entries[num_entries].count = st->count; - entries[num_entries].tv = st->tv; - tot_count += st->count; - tot_usecs += 1000000 * st->tv.tv_sec; - tot_usecs += st->tv.tv_usec; + struct timedelta ret = { diff }; + return ret; +} - num_entries++; +static enum callback_status +fill_struct(const char **namep, struct opt_c_struct *st, void *u) +{ + struct fill_struct_data *data = u; + struct entry_st entry = { *namep, st->count, st->tv }; + if (VECT_PUSHBACK(&data->entries, &entry) < 0) + return CBS_STOP; + + data->tot_count += st->count; + data->tot_usecs += 1000000 * st->tv.tv_sec; + data->tot_usecs += st->tv.tv_usec; + return CBS_CONT; } -static int compar(const void *a, const void *b) +static int +compar(const struct entry_st *en1, const struct entry_st *en2) { - struct entry_st *en1, *en2; + if (en2->tv.tv_sec - en1->tv.tv_sec) + return en2->tv.tv_sec - en1->tv.tv_sec; + else + return en2->tv.tv_usec - en1->tv.tv_usec; +} + +static enum callback_status +dump_one(struct entry_st *entry, void *u) +{ + struct fill_struct_data *data = u; + unsigned long long int c; + unsigned long long int p; + c = 1000000 * (int)entry->tv.tv_sec + + (int)entry->tv.tv_usec; + p = 100000 * c / data->tot_usecs + 5; + fprintf(options.output, "%3lu.%02lu %4d.%06d %11lu %9d %s\n", + (unsigned long int)(p / 1000), + (unsigned long int)((p / 10) % 100), + (int)entry->tv.tv_sec, (int)entry->tv.tv_usec, + (unsigned long int)(c / entry->count), + entry->count, +#ifdef USE_DEMANGLE + options.demangle ? my_demangle(entry->name) : +#endif + entry->name); - en1 = (struct entry_st *)a; - en2 = (struct entry_st *)b; + return CBS_CONT; +} - if (en2->tv.tv_sec - en1->tv.tv_sec) { - return (en2->tv.tv_sec - en1->tv.tv_sec); - } else { - return (en2->tv.tv_usec - en1->tv.tv_usec); +void +show_summary(void) +{ + struct fill_struct_data cdata = {}; + VECT_INIT(&cdata.entries, struct entry_st); + + if (dict_opt_c != NULL) { + DICT_EACH(dict_opt_c, const char *, struct opt_c_struct, NULL, + fill_struct, &cdata); + + VECT_QSORT(&cdata.entries, struct entry_st, &compar); } + + fprintf(options.output, + "%% time seconds usecs/call calls function\n"); + fprintf(options.output, + "------ ----------- ----------- --------- --------------------\n"); + + VECT_EACH(&cdata.entries, struct entry_st, NULL, dump_one, &cdata); + + fprintf(options.output, + "------ ----------- ----------- --------- --------------------\n"); + fprintf(options.output, "100.00 %4lu.%06lu %9d total\n", + cdata.tot_usecs / 1000000, + cdata.tot_usecs % 1000000, cdata.tot_count); + + vect_destroy(&cdata.entries, NULL, NULL); } -void show_summary(void) +static void +free_stringp_cb(const char **stringp, void *data) { - int i; - - num_entries = 0; - entries = NULL; - - dict_apply_to_all(dict_opt_c, fill_struct, NULL); - - qsort(entries, num_entries, sizeof(*entries), compar); - - fprintf(options.output, "%% time seconds usecs/call calls function\n"); - fprintf(options.output, "------ ----------- ----------- --------- --------------------\n"); - for (i = 0; i < num_entries; i++) { - unsigned long long int c; - unsigned long long int p; - c = 1000000 * (int)entries[i].tv.tv_sec + - (int)entries[i].tv.tv_usec; - p = 100000 * c / tot_usecs + 5; - fprintf(options.output, "%3lu.%02lu %4d.%06d %11lu %9d %s\n", - (unsigned long int)(p / 1000), - (unsigned long int)((p / 10) % 100), - (int)entries[i].tv.tv_sec, (int)entries[i].tv.tv_usec, - (unsigned long int)(c / entries[i].count), - entries[i].count, -#ifdef USE_DEMANGLE - options.demangle ? my_demangle(entries[i].name) : -#endif - entries[i].name); + free((char *)*stringp); +} + +void +summary_account_call(struct library_symbol *libsym, struct timedelta spent) +{ + assert(options.summary); + + if (dict_opt_c == NULL) { + dict_opt_c = malloc(sizeof(*dict_opt_c)); + if (dict_opt_c == NULL) { + oom: + fprintf(stderr, + "Can't allocate memory for " + "keeping track of -c.\n"); + free(dict_opt_c); + options.summary = 0; + return; + } + DICT_INIT(dict_opt_c, char *, struct opt_c_struct, + dict_hash_string, dict_eq_string, NULL); + } + + struct opt_c_struct *st = DICT_FIND_REF(dict_opt_c, &libsym->name, + struct opt_c_struct); + if (st == NULL) { + const char *na = strdup(libsym->name); + struct opt_c_struct new_st = {.count = 0, .tv = {0, 0}}; + if (na == NULL + || DICT_INSERT(dict_opt_c, &na, &new_st) < 0) { + free((char *) na); + DICT_DESTROY(dict_opt_c, const char *, + struct opt_c_struct, + free_stringp_cb, NULL, NULL); + goto oom; + } + st = DICT_FIND_REF(dict_opt_c, &libsym->name, + struct opt_c_struct); + assert(st != NULL); + } + + if (st->tv.tv_usec + spent.tm.tv_usec > 1000000) { + st->tv.tv_usec += spent.tm.tv_usec - 1000000; + st->tv.tv_sec++; + } else { + st->tv.tv_usec += spent.tm.tv_usec; } - fprintf(options.output, "------ ----------- ----------- --------- --------------------\n"); - fprintf(options.output, "100.00 %4lu.%06lu %9d total\n", tot_usecs / 1000000, - tot_usecs % 1000000, tot_count); + st->count++; + st->tv.tv_sec += spent.tm.tv_sec; + return; }