summary.c revision 2834f72014dc8b13ba13b9a06da744dd023f3555
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
31struct entry_st {
32	const char *name;
33	unsigned count;
34	struct timeval tv;
35};
36
37struct fill_struct_data {
38	struct vect entries;
39	unsigned tot_count;
40	unsigned long tot_usecs;
41};
42
43static enum callback_status
44fill_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
57static int
58compar(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
66static enum callback_status
67dump_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
89void
90show_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}
117