Imported Upstream version 0.7.91
[platform/upstream/ltrace.git] / summary.c
1 /*
2  * This file is part of ltrace.
3  * Copyright (C) 2012,2013 Petr Machata, Red Hat Inc.
4  * Copyright (C) 2003,2008,2009 Juan Cespedes
5  * Copyright (C) 2006 Ian Wienand
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License as
9  * published by the Free Software Foundation; either version 2 of the
10  * License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20  * 02110-1301 USA
21  */
22
23 #include "config.h"
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <sys/time.h>
28
29 #include "common.h"
30
31 struct entry_st {
32         const char *name;
33         unsigned count;
34         struct timeval tv;
35 };
36
37 struct fill_struct_data {
38         struct vect entries;
39         unsigned tot_count;
40         unsigned long tot_usecs;
41 };
42
43 static enum callback_status
44 fill_struct(const char **namep, struct opt_c_struct *st, void *u)
45 {
46         struct fill_struct_data *data = u;
47         struct entry_st entry = { *namep, st->count, st->tv };
48         if (VECT_PUSHBACK(&data->entries, &entry) < 0)
49                 return CBS_STOP;
50
51         data->tot_count += st->count;
52         data->tot_usecs += 1000000 * st->tv.tv_sec;
53         data->tot_usecs += st->tv.tv_usec;
54         return CBS_CONT;
55 }
56
57 static int
58 compar(const struct entry_st *en1, const struct entry_st *en2)
59 {
60         if (en2->tv.tv_sec - en1->tv.tv_sec)
61                 return en2->tv.tv_sec - en1->tv.tv_sec;
62         else
63                 return en2->tv.tv_usec - en1->tv.tv_usec;
64 }
65
66 static enum callback_status
67 dump_one(struct entry_st *entry, void *u)
68 {
69         struct fill_struct_data *data = u;
70         unsigned long long int c;
71         unsigned long long int p;
72         c = 1000000 * (int)entry->tv.tv_sec +
73                 (int)entry->tv.tv_usec;
74         p = 100000 * c / data->tot_usecs + 5;
75         fprintf(options.output, "%3lu.%02lu %4d.%06d %11lu %9d %s\n",
76                 (unsigned long int)(p / 1000),
77                 (unsigned long int)((p / 10) % 100),
78                 (int)entry->tv.tv_sec, (int)entry->tv.tv_usec,
79                 (unsigned long int)(c / entry->count),
80                 entry->count,
81 #ifdef USE_DEMANGLE
82                 options.demangle ? my_demangle(entry->name) :
83 #endif
84                 entry->name);
85
86         return CBS_CONT;
87 }
88
89 void
90 show_summary(void)
91 {
92         struct fill_struct_data cdata = {};
93         VECT_INIT(&cdata.entries, struct entry_st);
94
95         if (dict_opt_c != NULL) {
96                 DICT_EACH(dict_opt_c, const char *, struct opt_c_struct, NULL,
97                           fill_struct, &cdata);
98
99                 VECT_QSORT(&cdata.entries, struct entry_st, &compar);
100         }
101
102         fprintf(options.output,
103                 "%% time     seconds  usecs/call     calls      function\n");
104         fprintf(options.output,
105                 "------ ----------- ----------- --------- --------------------\n");
106
107         VECT_EACH(&cdata.entries, struct entry_st, NULL, dump_one, &cdata);
108
109         fprintf(options.output,
110                 "------ ----------- ----------- --------- --------------------\n");
111         fprintf(options.output, "100.00 %4lu.%06lu             %9d total\n",
112                 cdata.tot_usecs / 1000000,
113                 cdata.tot_usecs % 1000000, cdata.tot_count);
114
115         vect_destroy(&cdata.entries, NULL, NULL);
116 }