init version.
[bush.git] / lib / malloc / stats.c
blob233d54bb5ee2345f83a10a4e88f9e88daa62dbe3
1 /* stats.c - malloc statistics */
3 /* Copyright (C) 2001-2020 Free Software Foundation, Inc.
5 This file is part of GNU Bush, the Bourne-Again SHell.
7 Bush 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.
12 Bush 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.
17 You should have received a copy of the GNU General Public License
18 along with Bush. If not, see <http://www.gnu.org/licenses/>.
21 #ifdef HAVE_CONFIG_H
22 # include <config.h>
23 #endif
25 #include "imalloc.h"
27 #ifdef MALLOC_STATS
29 #include <stdio.h>
30 #ifdef HAVE_UNISTD_H
31 # include <unistd.h>
32 #endif
33 #include <string.h>
35 #include "mstats.h"
37 extern int malloc_free_blocks PARAMS((int));
39 extern int malloc_mmap_threshold;
41 extern struct _malstats _mstats;
43 extern FILE *_imalloc_fopen PARAMS((char *, char *, char *, char *, size_t));
45 struct bucket_stats
46 malloc_bucket_stats (size)
47 int size;
49 struct bucket_stats v;
51 v.nfree = 0;
53 if (size < 0 || size >= NBUCKETS)
55 v.blocksize = 0;
56 v.nused = v.nmal = v.nmorecore = v.nlesscore = v.nsplit = 0;
57 return v;
60 v.blocksize = 1 << (size + 3);
61 v.nused = _mstats.nmalloc[size];
62 v.nmal = _mstats.tmalloc[size];
63 v.nmorecore = _mstats.nmorecore[size];
64 v.nlesscore = _mstats.nlesscore[size];
65 v.nsplit = _mstats.nsplit[size];
66 v.ncoalesce = _mstats.ncoalesce[size];
68 v.nfree = malloc_free_blocks (size); /* call back to malloc.c */
70 return v;
73 /* Return a copy of _MSTATS, with two additional fields filled in:
74 BYTESFREE is the total number of bytes on free lists. BYTESUSED
75 is the total number of bytes in use. These two fields are fairly
76 expensive to compute, so we do it only when asked to. */
77 struct _malstats
78 malloc_stats ()
80 struct _malstats result;
81 struct bucket_stats v;
82 register int i;
84 result = _mstats;
85 result.bytesused = result.bytesfree = 0;
86 for (i = 0; i < NBUCKETS; i++)
88 v = malloc_bucket_stats (i);
89 result.bytesfree += v.nfree * v.blocksize;
90 result.bytesused += v.nused * v.blocksize;
92 return (result);
95 static void
96 _print_malloc_stats (s, fp)
97 char *s;
98 FILE *fp;
100 register int i;
101 unsigned long totused, totfree;
102 struct bucket_stats v;
104 fprintf (fp, "Memory allocation statistics: %s\n size\tfree\tin use\ttotal\tmorecore lesscore split\tcoalesce\n", s ? s : "");
105 for (i = totused = totfree = 0; i < NBUCKETS; i++)
107 v = malloc_bucket_stats (i);
108 /* Show where the mmap threshold is; sizes greater than this use mmap to
109 allocate and munmap to free (munmap shows up as lesscore). */
110 if (i == malloc_mmap_threshold+1)
111 fprintf (fp, "--------\n");
112 if (v.nmal > 0)
113 fprintf (fp, "%8lu\t%4d\t%6d\t%5d%8d\t%8d %5d %8d\n", (unsigned long)v.blocksize, v.nfree, v.nused, v.nmal, v.nmorecore, v.nlesscore, v.nsplit, v.ncoalesce);
114 totfree += v.nfree * v.blocksize;
115 totused += v.nused * v.blocksize;
117 fprintf (fp, "\nTotal bytes in use: %lu, total bytes free: %lu\n",
118 totused, totfree);
119 fprintf (fp, "\nTotal bytes requested by application: %lu\n", (unsigned long)_mstats.bytesreq);
120 fprintf (fp, "Total mallocs: %d, total frees: %d, total reallocs: %d (%d copies)\n",
121 _mstats.nmal, _mstats.nfre, _mstats.nrealloc, _mstats.nrcopy);
122 fprintf (fp, "Total sbrks: %d, total bytes via sbrk: %d\n",
123 _mstats.nsbrk, _mstats.tsbrk);
124 fprintf (fp, "Total mmaps: %d, total bytes via mmap: %d\n",
125 _mstats.nmmap, _mstats.tmmap);
126 fprintf (fp, "Total blocks split: %d, total block coalesces: %d\n",
127 _mstats.tbsplit, _mstats.tbcoalesce);
130 void
131 print_malloc_stats (s)
132 char *s;
134 _print_malloc_stats (s, stderr);
137 void
138 fprint_malloc_stats (s, fp)
139 char *s;
140 FILE *fp;
142 _print_malloc_stats (s, fp);
145 #define TRACEROOT "/var/tmp/maltrace/stats."
147 void
148 trace_malloc_stats (s, fn)
149 char *s, *fn;
151 FILE *fp;
152 char defname[sizeof (TRACEROOT) + 64];
153 static char mallbuf[1024];
155 fp = _imalloc_fopen (s, fn, TRACEROOT, defname, sizeof (defname));
156 if (fp)
158 setvbuf (fp, mallbuf, _IOFBF, sizeof (mallbuf));
159 _print_malloc_stats (s, fp);
160 fflush(fp);
161 fclose(fp);
165 #endif /* MALLOC_STATS */
167 #if defined (MALLOC_STATS) || defined (MALLOC_TRACE)
168 FILE *
169 _imalloc_fopen (s, fn, def, defbuf, defsiz)
170 char *s;
171 char *fn;
172 char *def;
173 char *defbuf;
174 size_t defsiz;
176 char fname[1024];
177 long l;
178 FILE *fp;
180 l = (long)getpid ();
181 if (fn == 0)
183 sprintf (defbuf, "%s%ld", def, l);
184 fp = fopen(defbuf, "w");
186 else
188 char *p, *q, *r;
189 char pidbuf[32];
190 int sp;
192 sprintf (pidbuf, "%ld", l);
193 if ((strlen (pidbuf) + strlen (fn) + 2) >= sizeof (fname))
194 return ((FILE *)0);
195 for (sp = 0, p = fname, q = fn; *q; )
197 if (sp == 0 && *q == '%' && q[1] == 'p')
199 sp = 1;
200 for (r = pidbuf; *r; )
201 *p++ = *r++;
202 q += 2;
204 else
205 *p++ = *q++;
207 *p = '\0';
208 fp = fopen (fname, "w");
211 return fp;
213 #endif /* MALLOC_STATS || MALLOC_TRACE */