blob: 8665918d6e863aac21010369a7ce900534616388 [file] [log] [blame]
Jari Aaltof73dda02001-11-13 17:56:06 +00001/* stats.c - malloc statistics */
2
Jari Aaltob80f6442004-07-27 13:29:18 +00003/* Copyright (C) 2001-2003 Free Software Foundation, Inc.
Jari Aaltof73dda02001-11-13 17:56:06 +00004
Jari Aalto31859422009-01-12 13:36:28 +00005 This file is part of GNU Bash, the Bourne-Again SHell.
Jari Aaltof73dda02001-11-13 17:56:06 +00006
Jari Aalto31859422009-01-12 13:36:28 +00007 Bash is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
Jari Aaltof73dda02001-11-13 17:56:06 +000011
Jari Aalto31859422009-01-12 13:36:28 +000012 Bash is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Bash. If not, see <http://www.gnu.org/licenses/>.
19*/
Jari Aaltof73dda02001-11-13 17:56:06 +000020
21#ifdef HAVE_CONFIG_H
22# include <config.h>
23#endif
24
25#include "imalloc.h"
26
27#ifdef MALLOC_STATS
28
29#include <stdio.h>
Jari Aalto7117c2d2002-07-17 14:10:11 +000030#ifdef HAVE_UNISTD_H
31# include <unistd.h>
32#endif
Jari Aalto06285672006-10-10 14:15:34 +000033#include <string.h>
Jari Aalto7117c2d2002-07-17 14:10:11 +000034
Jari Aaltof73dda02001-11-13 17:56:06 +000035#include "mstats.h"
36
Jari Aalto7117c2d2002-07-17 14:10:11 +000037extern int malloc_free_blocks __P((int));
38
39extern struct _malstats _mstats;
Jari Aaltof73dda02001-11-13 17:56:06 +000040
Jari Aaltob80f6442004-07-27 13:29:18 +000041extern FILE *_imalloc_fopen __P((char *, char *, char *, char *, size_t));
42
Jari Aaltof73dda02001-11-13 17:56:06 +000043struct bucket_stats
44malloc_bucket_stats (size)
45 int size;
46{
47 struct bucket_stats v;
48
49 v.nfree = 0;
50
51 if (size < 0 || size >= NBUCKETS)
52 {
53 v.blocksize = 0;
Jari Aalto7117c2d2002-07-17 14:10:11 +000054 v.nused = v.nmal = v.nmorecore = v.nlesscore = v.nsplit = 0;
Jari Aaltof73dda02001-11-13 17:56:06 +000055 return v;
56 }
57
58 v.blocksize = 1 << (size + 3);
59 v.nused = _mstats.nmalloc[size];
60 v.nmal = _mstats.tmalloc[size];
61 v.nmorecore = _mstats.nmorecore[size];
Jari Aalto7117c2d2002-07-17 14:10:11 +000062 v.nlesscore = _mstats.nlesscore[size];
Jari Aaltof73dda02001-11-13 17:56:06 +000063 v.nsplit = _mstats.nsplit[size];
Jari Aalto7117c2d2002-07-17 14:10:11 +000064 v.ncoalesce = _mstats.ncoalesce[size];
Jari Aaltof73dda02001-11-13 17:56:06 +000065
66 v.nfree = malloc_free_blocks (size); /* call back to malloc.c */
67
68 return v;
69}
70
71/* Return a copy of _MSTATS, with two additional fields filled in:
72 BYTESFREE is the total number of bytes on free lists. BYTESUSED
73 is the total number of bytes in use. These two fields are fairly
74 expensive to compute, so we do it only when asked to. */
75struct _malstats
76malloc_stats ()
77{
78 struct _malstats result;
79 struct bucket_stats v;
80 register int i;
81
82 result = _mstats;
83 result.bytesused = result.bytesfree = 0;
84 for (i = 0; i < NBUCKETS; i++)
85 {
86 v = malloc_bucket_stats (i);
87 result.bytesfree += v.nfree * v.blocksize;
88 result.bytesused += v.nused * v.blocksize;
89 }
90 return (result);
91}
92
93static void
94_print_malloc_stats (s, fp)
95 char *s;
96 FILE *fp;
97{
98 register int i;
99 unsigned long totused, totfree;
100 struct bucket_stats v;
101
Jari Aalto7117c2d2002-07-17 14:10:11 +0000102 fprintf (fp, "Memory allocation statistics: %s\n size\tfree\tin use\ttotal\tmorecore lesscore split\tcoalesce\n", s ? s : "");
Jari Aaltof73dda02001-11-13 17:56:06 +0000103 for (i = totused = totfree = 0; i < NBUCKETS; i++)
104 {
105 v = malloc_bucket_stats (i);
Jari Aalto7117c2d2002-07-17 14:10:11 +0000106 if (v.nmal > 0)
107 fprintf (fp, "%8lu\t%4d\t%6d\t%5d\t%8d\t%d %5d %8d\n", (unsigned long)v.blocksize, v.nfree, v.nused, v.nmal, v.nmorecore, v.nlesscore, v.nsplit, v.ncoalesce);
Jari Aaltof73dda02001-11-13 17:56:06 +0000108 totfree += v.nfree * v.blocksize;
109 totused += v.nused * v.blocksize;
110 }
111 fprintf (fp, "\nTotal bytes in use: %lu, total bytes free: %lu\n",
112 totused, totfree);
Jari Aalto7117c2d2002-07-17 14:10:11 +0000113 fprintf (fp, "\nTotal bytes requested by application: %lu\n", _mstats.bytesreq);
Jari Aaltof73dda02001-11-13 17:56:06 +0000114 fprintf (fp, "Total mallocs: %d, total frees: %d, total reallocs: %d (%d copies)\n",
115 _mstats.nmal, _mstats.nfre, _mstats.nrealloc, _mstats.nrcopy);
116 fprintf (fp, "Total sbrks: %d, total bytes via sbrk: %d\n",
117 _mstats.nsbrk, _mstats.tsbrk);
118 fprintf (fp, "Total blocks split: %d, total block coalesces: %d\n",
119 _mstats.tbsplit, _mstats.tbcoalesce);
120}
121
122void
123print_malloc_stats (s)
124 char *s;
125{
126 _print_malloc_stats (s, stderr);
127}
128
129void
130fprint_malloc_stats (s, fp)
131 char *s;
132 FILE *fp;
133{
134 _print_malloc_stats (s, fp);
135}
136
Jari Aaltob80f6442004-07-27 13:29:18 +0000137#define TRACEROOT "/var/tmp/maltrace/stats."
Jari Aaltof73dda02001-11-13 17:56:06 +0000138
139void
Jari Aalto7117c2d2002-07-17 14:10:11 +0000140trace_malloc_stats (s, fn)
141 char *s, *fn;
Jari Aaltof73dda02001-11-13 17:56:06 +0000142{
Jari Aaltob80f6442004-07-27 13:29:18 +0000143 FILE *fp;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000144 char defname[sizeof (TRACEROOT) + 64];
Jari Aaltob80f6442004-07-27 13:29:18 +0000145 static char mallbuf[1024];
146
147 fp = _imalloc_fopen (s, fn, TRACEROOT, defname, sizeof (defname));
148 if (fp)
149 {
150 setvbuf (fp, mallbuf, _IOFBF, sizeof (mallbuf));
151 _print_malloc_stats (s, fp);
152 fflush(fp);
153 fclose(fp);
154 }
155}
156
157#endif /* MALLOC_STATS */
158
159#if defined (MALLOC_STATS) || defined (MALLOC_TRACE)
160FILE *
161_imalloc_fopen (s, fn, def, defbuf, defsiz)
162 char *s;
163 char *fn;
164 char *def;
165 char *defbuf;
166 size_t defsiz;
167{
Jari Aalto7117c2d2002-07-17 14:10:11 +0000168 char fname[1024];
169 long l;
Jari Aaltof73dda02001-11-13 17:56:06 +0000170 FILE *fp;
171
Jari Aalto7117c2d2002-07-17 14:10:11 +0000172 l = (long)getpid ();
173 if (fn == 0)
174 {
Jari Aaltob80f6442004-07-27 13:29:18 +0000175 sprintf (defbuf, "%s%ld", def, l);
176 fp = fopen(defbuf, "w");
Jari Aalto7117c2d2002-07-17 14:10:11 +0000177 }
178 else
179 {
180 char *p, *q, *r;
181 char pidbuf[32];
182 int sp;
183
184 sprintf (pidbuf, "%ld", l);
185 if ((strlen (pidbuf) + strlen (fn) + 2) >= sizeof (fname))
Jari Aalto31859422009-01-12 13:36:28 +0000186 return ((FILE *)0);
Jari Aalto7117c2d2002-07-17 14:10:11 +0000187 for (sp = 0, p = fname, q = fn; *q; )
188 {
189 if (sp == 0 && *q == '%' && q[1] == 'p')
190 {
191 sp = 1;
192 for (r = pidbuf; *r; )
193 *p++ = *r++;
194 q += 2;
195 }
196 else
197 *p++ = *q++;
198 }
199 *p = '\0';
200 fp = fopen (fname, "w");
201 }
Jari Aaltof73dda02001-11-13 17:56:06 +0000202
Jari Aaltob80f6442004-07-27 13:29:18 +0000203 return fp;
204}
205#endif /* MALLOC_STATS || MALLOC_TRACE */