]> git.ipfire.org Git - thirdparty/bash.git/blob - lib/malloc/stats.c
bash-4.4 rc1 release
[thirdparty/bash.git] / lib / malloc / stats.c
1 /* stats.c - malloc statistics */
2
3 /* Copyright (C) 2001-2003 Free Software Foundation, Inc.
4
5 This file is part of GNU Bash, the Bourne-Again SHell.
6
7 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.
11
12 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 */
20
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>
30 #ifdef HAVE_UNISTD_H
31 # include <unistd.h>
32 #endif
33 #include <string.h>
34
35 #include "mstats.h"
36
37 extern int malloc_free_blocks __P((int));
38
39 extern struct _malstats _mstats;
40
41 extern FILE *_imalloc_fopen __P((char *, char *, char *, char *, size_t));
42
43 struct bucket_stats
44 malloc_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;
54 v.nused = v.nmal = v.nmorecore = v.nlesscore = v.nsplit = 0;
55 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];
62 v.nlesscore = _mstats.nlesscore[size];
63 v.nsplit = _mstats.nsplit[size];
64 v.ncoalesce = _mstats.ncoalesce[size];
65
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. */
75 struct _malstats
76 malloc_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
93 static 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
102 fprintf (fp, "Memory allocation statistics: %s\n size\tfree\tin use\ttotal\tmorecore lesscore split\tcoalesce\n", s ? s : "");
103 for (i = totused = totfree = 0; i < NBUCKETS; i++)
104 {
105 v = malloc_bucket_stats (i);
106 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);
108 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);
113 fprintf (fp, "\nTotal bytes requested by application: %lu\n", (unsigned long)_mstats.bytesreq);
114 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
122 void
123 print_malloc_stats (s)
124 char *s;
125 {
126 _print_malloc_stats (s, stderr);
127 }
128
129 void
130 fprint_malloc_stats (s, fp)
131 char *s;
132 FILE *fp;
133 {
134 _print_malloc_stats (s, fp);
135 }
136
137 #define TRACEROOT "/var/tmp/maltrace/stats."
138
139 void
140 trace_malloc_stats (s, fn)
141 char *s, *fn;
142 {
143 FILE *fp;
144 char defname[sizeof (TRACEROOT) + 64];
145 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)
160 FILE *
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 {
168 char fname[1024];
169 long l;
170 FILE *fp;
171
172 l = (long)getpid ();
173 if (fn == 0)
174 {
175 sprintf (defbuf, "%s%ld", def, l);
176 fp = fopen(defbuf, "w");
177 }
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))
186 return ((FILE *)0);
187 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 }
202
203 return fp;
204 }
205 #endif /* MALLOC_STATS || MALLOC_TRACE */