summary.c revision 881e1fd61524bd916cdce782f8d3beadd7e5aaec
1/*
2 * This file is part of ltrace.
3 * Copyright (C) 2012 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
31static int num_entries = 0;
32static struct entry_st {
33	char *name;
34	int count;
35	struct timeval tv;
36} *entries = NULL;
37
38static int tot_count = 0;
39static unsigned long int tot_usecs = 0;
40
41static enum callback_status
42fill_struct(const char **namep, struct opt_c_struct *st, void *data)
43{
44	entries = realloc(entries, (num_entries + 1) * sizeof(struct entry_st));
45	if (!entries) {
46		perror("realloc()");
47		exit(1);
48	}
49	entries[num_entries].name = (char *)*namep;
50	entries[num_entries].count = st->count;
51	entries[num_entries].tv = st->tv;
52
53	tot_count += st->count;
54	tot_usecs += 1000000 * st->tv.tv_sec;
55	tot_usecs += st->tv.tv_usec;
56
57	num_entries++;
58	return CBS_CONT;
59}
60
61static int compar(const void *a, const void *b)
62{
63	struct entry_st *en1, *en2;
64
65	en1 = (struct entry_st *)a;
66	en2 = (struct entry_st *)b;
67
68	if (en2->tv.tv_sec - en1->tv.tv_sec) {
69		return (en2->tv.tv_sec - en1->tv.tv_sec);
70	} else {
71		return (en2->tv.tv_usec - en1->tv.tv_usec);
72	}
73}
74
75void show_summary(void)
76{
77	int i;
78
79	num_entries = 0;
80	entries = NULL;
81
82	if (dict_opt_c != NULL)
83		DICT_EACH(dict_opt_c, const char *, struct opt_c_struct, NULL,
84			  fill_struct, NULL);
85
86	qsort(entries, num_entries, sizeof(*entries), compar);
87
88	fprintf(options.output, "%% time     seconds  usecs/call     calls      function\n");
89	fprintf(options.output, "------ ----------- ----------- --------- --------------------\n");
90	for (i = 0; i < num_entries; i++) {
91		unsigned long long int c;
92		unsigned long long int p;
93		c = 1000000 * (int)entries[i].tv.tv_sec +
94		    (int)entries[i].tv.tv_usec;
95		p = 100000 * c / tot_usecs + 5;
96		fprintf(options.output, "%3lu.%02lu %4d.%06d %11lu %9d %s\n",
97		       (unsigned long int)(p / 1000),
98		       (unsigned long int)((p / 10) % 100),
99		       (int)entries[i].tv.tv_sec, (int)entries[i].tv.tv_usec,
100		       (unsigned long int)(c / entries[i].count),
101		       entries[i].count,
102#ifdef USE_DEMANGLE
103		       options.demangle ? my_demangle(entries[i].name) :
104#endif
105		       entries[i].name);
106	}
107	fprintf(options.output, "------ ----------- ----------- --------- --------------------\n");
108	fprintf(options.output, "100.00 %4lu.%06lu             %9d total\n", tot_usecs / 1000000,
109	       tot_usecs % 1000000, tot_count);
110}
111