]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/jemalloc/src/stats.c
Use the new insecure-lan-zones option instead of listing each AS112 zone
[FreeBSD/FreeBSD.git] / contrib / jemalloc / src / stats.c
1 #define JEMALLOC_STATS_C_
2 #include "jemalloc/internal/jemalloc_internal.h"
3
4 #define CTL_GET(n, v, t) do {                                           \
5         size_t sz = sizeof(t);                                          \
6         xmallctl(n, v, &sz, NULL, 0);                                   \
7 } while (0)
8
9 #define CTL_M2_GET(n, i, v, t) do {                                     \
10         size_t mib[6];                                                  \
11         size_t miblen = sizeof(mib) / sizeof(size_t);                   \
12         size_t sz = sizeof(t);                                          \
13         xmallctlnametomib(n, mib, &miblen);                             \
14         mib[2] = (i);                                                   \
15         xmallctlbymib(mib, miblen, v, &sz, NULL, 0);                    \
16 } while (0)
17
18 #define CTL_M2_M4_GET(n, i, j, v, t) do {                               \
19         size_t mib[6];                                                  \
20         size_t miblen = sizeof(mib) / sizeof(size_t);                   \
21         size_t sz = sizeof(t);                                          \
22         xmallctlnametomib(n, mib, &miblen);                             \
23         mib[2] = (i);                                                   \
24         mib[4] = (j);                                                   \
25         xmallctlbymib(mib, miblen, v, &sz, NULL, 0);                    \
26 } while (0)
27
28 /******************************************************************************/
29 /* Data. */
30
31 bool    opt_stats_print = false;
32
33 size_t  stats_cactive = 0;
34
35 /******************************************************************************/
36 /* Function prototypes for non-inline static functions. */
37
38 static void     stats_arena_bins_print(void (*write_cb)(void *, const char *),
39     void *cbopaque, unsigned i);
40 static void     stats_arena_lruns_print(void (*write_cb)(void *, const char *),
41     void *cbopaque, unsigned i);
42 static void     stats_arena_hchunks_print(
43     void (*write_cb)(void *, const char *), void *cbopaque, unsigned i);
44 static void     stats_arena_print(void (*write_cb)(void *, const char *),
45     void *cbopaque, unsigned i, bool bins, bool large, bool huge);
46
47 /******************************************************************************/
48
49 static void
50 stats_arena_bins_print(void (*write_cb)(void *, const char *), void *cbopaque,
51     unsigned i)
52 {
53         size_t page;
54         bool config_tcache, in_gap;
55         unsigned nbins, j;
56
57         CTL_GET("arenas.page", &page, size_t);
58
59         CTL_GET("config.tcache", &config_tcache, bool);
60         if (config_tcache) {
61                 malloc_cprintf(write_cb, cbopaque,
62                     "bins:           size ind    allocated      nmalloc"
63                     "      ndalloc    nrequests      curregs      curruns regs"
64                     " pgs  util       nfills     nflushes      newruns"
65                     "       reruns\n");
66         } else {
67                 malloc_cprintf(write_cb, cbopaque,
68                     "bins:           size ind    allocated      nmalloc"
69                     "      ndalloc    nrequests      curregs      curruns regs"
70                     " pgs  util      newruns       reruns\n");
71         }
72         CTL_GET("arenas.nbins", &nbins, unsigned);
73         for (j = 0, in_gap = false; j < nbins; j++) {
74                 uint64_t nruns;
75
76                 CTL_M2_M4_GET("stats.arenas.0.bins.0.nruns", i, j, &nruns,
77                     uint64_t);
78                 if (nruns == 0)
79                         in_gap = true;
80                 else {
81                         size_t reg_size, run_size, curregs, availregs, milli;
82                         size_t curruns;
83                         uint32_t nregs;
84                         uint64_t nmalloc, ndalloc, nrequests, nfills, nflushes;
85                         uint64_t reruns;
86                         char util[6]; /* "x.yyy". */
87
88                         if (in_gap) {
89                                 malloc_cprintf(write_cb, cbopaque,
90                                     "                     ---\n");
91                                 in_gap = false;
92                         }
93                         CTL_M2_GET("arenas.bin.0.size", j, &reg_size, size_t);
94                         CTL_M2_GET("arenas.bin.0.nregs", j, &nregs, uint32_t);
95                         CTL_M2_GET("arenas.bin.0.run_size", j, &run_size,
96                             size_t);
97                         CTL_M2_M4_GET("stats.arenas.0.bins.0.nmalloc", i, j,
98                             &nmalloc, uint64_t);
99                         CTL_M2_M4_GET("stats.arenas.0.bins.0.ndalloc", i, j,
100                             &ndalloc, uint64_t);
101                         CTL_M2_M4_GET("stats.arenas.0.bins.0.curregs", i, j,
102                             &curregs, size_t);
103                         CTL_M2_M4_GET("stats.arenas.0.bins.0.nrequests", i, j,
104                             &nrequests, uint64_t);
105                         if (config_tcache) {
106                                 CTL_M2_M4_GET("stats.arenas.0.bins.0.nfills", i,
107                                     j, &nfills, uint64_t);
108                                 CTL_M2_M4_GET("stats.arenas.0.bins.0.nflushes",
109                                     i, j, &nflushes, uint64_t);
110                         }
111                         CTL_M2_M4_GET("stats.arenas.0.bins.0.nreruns", i, j,
112                             &reruns, uint64_t);
113                         CTL_M2_M4_GET("stats.arenas.0.bins.0.curruns", i, j,
114                             &curruns, size_t);
115
116                         availregs = nregs * curruns;
117                         milli = (availregs != 0) ? (1000 * curregs) / availregs
118                             : 1000;
119                         assert(milli <= 1000);
120                         if (milli < 10) {
121                                 malloc_snprintf(util, sizeof(util),
122                                     "0.00%zu", milli);
123                         } else if (milli < 100) {
124                                 malloc_snprintf(util, sizeof(util), "0.0%zu",
125                                     milli);
126                         } else if (milli < 1000) {
127                                 malloc_snprintf(util, sizeof(util), "0.%zu",
128                                     milli);
129                         } else
130                                 malloc_snprintf(util, sizeof(util), "1");
131
132                         if (config_tcache) {
133                                 malloc_cprintf(write_cb, cbopaque,
134                                     "%20zu %3u %12zu %12"FMTu64
135                                     " %12"FMTu64" %12"FMTu64" %12zu"
136                                     " %12zu %4u %3zu %-5s %12"FMTu64
137                                     " %12"FMTu64" %12"FMTu64" %12"FMTu64"\n",
138                                     reg_size, j, curregs * reg_size, nmalloc,
139                                     ndalloc, nrequests, curregs, curruns, nregs,
140                                     run_size / page, util, nfills, nflushes,
141                                     nruns, reruns);
142                         } else {
143                                 malloc_cprintf(write_cb, cbopaque,
144                                     "%20zu %3u %12zu %12"FMTu64
145                                     " %12"FMTu64" %12"FMTu64" %12zu"
146                                     " %12zu %4u %3zu %-5s %12"FMTu64
147                                     " %12"FMTu64"\n",
148                                     reg_size, j, curregs * reg_size, nmalloc,
149                                     ndalloc, nrequests, curregs, curruns, nregs,
150                                     run_size / page, util, nruns, reruns);
151                         }
152                 }
153         }
154         if (in_gap) {
155                 malloc_cprintf(write_cb, cbopaque,
156                     "                     ---\n");
157         }
158 }
159
160 static void
161 stats_arena_lruns_print(void (*write_cb)(void *, const char *), void *cbopaque,
162     unsigned i)
163 {
164         unsigned nbins, nlruns, j;
165         bool in_gap;
166
167         malloc_cprintf(write_cb, cbopaque,
168             "large:          size ind    allocated      nmalloc      ndalloc"
169             "    nrequests      curruns\n");
170         CTL_GET("arenas.nbins", &nbins, unsigned);
171         CTL_GET("arenas.nlruns", &nlruns, unsigned);
172         for (j = 0, in_gap = false; j < nlruns; j++) {
173                 uint64_t nmalloc, ndalloc, nrequests;
174                 size_t run_size, curruns;
175
176                 CTL_M2_M4_GET("stats.arenas.0.lruns.0.nmalloc", i, j, &nmalloc,
177                     uint64_t);
178                 CTL_M2_M4_GET("stats.arenas.0.lruns.0.ndalloc", i, j, &ndalloc,
179                     uint64_t);
180                 CTL_M2_M4_GET("stats.arenas.0.lruns.0.nrequests", i, j,
181                     &nrequests, uint64_t);
182                 if (nrequests == 0)
183                         in_gap = true;
184                 else {
185                         CTL_M2_GET("arenas.lrun.0.size", j, &run_size, size_t);
186                         CTL_M2_M4_GET("stats.arenas.0.lruns.0.curruns", i, j,
187                             &curruns, size_t);
188                         if (in_gap) {
189                                 malloc_cprintf(write_cb, cbopaque,
190                                     "                     ---\n");
191                                 in_gap = false;
192                         }
193                         malloc_cprintf(write_cb, cbopaque,
194                             "%20zu %3u %12zu %12"FMTu64" %12"FMTu64
195                             " %12"FMTu64" %12zu\n",
196                             run_size, nbins + j, curruns * run_size, nmalloc,
197                             ndalloc, nrequests, curruns);
198                 }
199         }
200         if (in_gap) {
201                 malloc_cprintf(write_cb, cbopaque,
202                     "                     ---\n");
203         }
204 }
205
206 static void
207 stats_arena_hchunks_print(void (*write_cb)(void *, const char *),
208     void *cbopaque, unsigned i)
209 {
210         unsigned nbins, nlruns, nhchunks, j;
211         bool in_gap;
212
213         malloc_cprintf(write_cb, cbopaque,
214             "huge:           size ind    allocated      nmalloc      ndalloc"
215             "    nrequests   curhchunks\n");
216         CTL_GET("arenas.nbins", &nbins, unsigned);
217         CTL_GET("arenas.nlruns", &nlruns, unsigned);
218         CTL_GET("arenas.nhchunks", &nhchunks, unsigned);
219         for (j = 0, in_gap = false; j < nhchunks; j++) {
220                 uint64_t nmalloc, ndalloc, nrequests;
221                 size_t hchunk_size, curhchunks;
222
223                 CTL_M2_M4_GET("stats.arenas.0.hchunks.0.nmalloc", i, j,
224                     &nmalloc, uint64_t);
225                 CTL_M2_M4_GET("stats.arenas.0.hchunks.0.ndalloc", i, j,
226                     &ndalloc, uint64_t);
227                 CTL_M2_M4_GET("stats.arenas.0.hchunks.0.nrequests", i, j,
228                     &nrequests, uint64_t);
229                 if (nrequests == 0)
230                         in_gap = true;
231                 else {
232                         CTL_M2_GET("arenas.hchunk.0.size", j, &hchunk_size,
233                             size_t);
234                         CTL_M2_M4_GET("stats.arenas.0.hchunks.0.curhchunks", i,
235                             j, &curhchunks, size_t);
236                         if (in_gap) {
237                                 malloc_cprintf(write_cb, cbopaque,
238                                     "                     ---\n");
239                                 in_gap = false;
240                         }
241                         malloc_cprintf(write_cb, cbopaque,
242                             "%20zu %3u %12zu %12"FMTu64" %12"FMTu64
243                             " %12"FMTu64" %12zu\n",
244                             hchunk_size, nbins + nlruns + j,
245                             curhchunks * hchunk_size, nmalloc, ndalloc,
246                             nrequests, curhchunks);
247                 }
248         }
249         if (in_gap) {
250                 malloc_cprintf(write_cb, cbopaque,
251                     "                     ---\n");
252         }
253 }
254
255 static void
256 stats_arena_print(void (*write_cb)(void *, const char *), void *cbopaque,
257     unsigned i, bool bins, bool large, bool huge)
258 {
259         unsigned nthreads;
260         const char *dss;
261         ssize_t lg_dirty_mult;
262         size_t page, pactive, pdirty, mapped;
263         size_t metadata_mapped, metadata_allocated;
264         uint64_t npurge, nmadvise, purged;
265         size_t small_allocated;
266         uint64_t small_nmalloc, small_ndalloc, small_nrequests;
267         size_t large_allocated;
268         uint64_t large_nmalloc, large_ndalloc, large_nrequests;
269         size_t huge_allocated;
270         uint64_t huge_nmalloc, huge_ndalloc, huge_nrequests;
271
272         CTL_GET("arenas.page", &page, size_t);
273
274         CTL_M2_GET("stats.arenas.0.nthreads", i, &nthreads, unsigned);
275         malloc_cprintf(write_cb, cbopaque,
276             "assigned threads: %u\n", nthreads);
277         CTL_M2_GET("stats.arenas.0.dss", i, &dss, const char *);
278         malloc_cprintf(write_cb, cbopaque, "dss allocation precedence: %s\n",
279             dss);
280         CTL_M2_GET("stats.arenas.0.lg_dirty_mult", i, &lg_dirty_mult, ssize_t);
281         if (lg_dirty_mult >= 0) {
282                 malloc_cprintf(write_cb, cbopaque,
283                     "min active:dirty page ratio: %u:1\n",
284                     (1U << lg_dirty_mult));
285         } else {
286                 malloc_cprintf(write_cb, cbopaque,
287                     "min active:dirty page ratio: N/A\n");
288         }
289         CTL_M2_GET("stats.arenas.0.pactive", i, &pactive, size_t);
290         CTL_M2_GET("stats.arenas.0.pdirty", i, &pdirty, size_t);
291         CTL_M2_GET("stats.arenas.0.npurge", i, &npurge, uint64_t);
292         CTL_M2_GET("stats.arenas.0.nmadvise", i, &nmadvise, uint64_t);
293         CTL_M2_GET("stats.arenas.0.purged", i, &purged, uint64_t);
294         malloc_cprintf(write_cb, cbopaque,
295             "dirty pages: %zu:%zu active:dirty, %"FMTu64" sweep%s, %"FMTu64
296             " madvise%s, %"FMTu64" purged\n", pactive, pdirty, npurge, npurge ==
297             1 ? "" : "s", nmadvise, nmadvise == 1 ? "" : "s", purged);
298
299         malloc_cprintf(write_cb, cbopaque,
300             "                            allocated      nmalloc      ndalloc"
301             "    nrequests\n");
302         CTL_M2_GET("stats.arenas.0.small.allocated", i, &small_allocated,
303             size_t);
304         CTL_M2_GET("stats.arenas.0.small.nmalloc", i, &small_nmalloc, uint64_t);
305         CTL_M2_GET("stats.arenas.0.small.ndalloc", i, &small_ndalloc, uint64_t);
306         CTL_M2_GET("stats.arenas.0.small.nrequests", i, &small_nrequests,
307             uint64_t);
308         malloc_cprintf(write_cb, cbopaque,
309             "small:                   %12zu %12"FMTu64" %12"FMTu64
310             " %12"FMTu64"\n",
311             small_allocated, small_nmalloc, small_ndalloc, small_nrequests);
312         CTL_M2_GET("stats.arenas.0.large.allocated", i, &large_allocated,
313             size_t);
314         CTL_M2_GET("stats.arenas.0.large.nmalloc", i, &large_nmalloc, uint64_t);
315         CTL_M2_GET("stats.arenas.0.large.ndalloc", i, &large_ndalloc, uint64_t);
316         CTL_M2_GET("stats.arenas.0.large.nrequests", i, &large_nrequests,
317             uint64_t);
318         malloc_cprintf(write_cb, cbopaque,
319             "large:                   %12zu %12"FMTu64" %12"FMTu64
320             " %12"FMTu64"\n",
321             large_allocated, large_nmalloc, large_ndalloc, large_nrequests);
322         CTL_M2_GET("stats.arenas.0.huge.allocated", i, &huge_allocated, size_t);
323         CTL_M2_GET("stats.arenas.0.huge.nmalloc", i, &huge_nmalloc, uint64_t);
324         CTL_M2_GET("stats.arenas.0.huge.ndalloc", i, &huge_ndalloc, uint64_t);
325         CTL_M2_GET("stats.arenas.0.huge.nrequests", i, &huge_nrequests,
326             uint64_t);
327         malloc_cprintf(write_cb, cbopaque,
328             "huge:                    %12zu %12"FMTu64" %12"FMTu64
329             " %12"FMTu64"\n",
330             huge_allocated, huge_nmalloc, huge_ndalloc, huge_nrequests);
331         malloc_cprintf(write_cb, cbopaque,
332             "total:                   %12zu %12"FMTu64" %12"FMTu64
333             " %12"FMTu64"\n",
334             small_allocated + large_allocated + huge_allocated,
335             small_nmalloc + large_nmalloc + huge_nmalloc,
336             small_ndalloc + large_ndalloc + huge_ndalloc,
337             small_nrequests + large_nrequests + huge_nrequests);
338         malloc_cprintf(write_cb, cbopaque,
339             "active:                  %12zu\n", pactive * page);
340         CTL_M2_GET("stats.arenas.0.mapped", i, &mapped, size_t);
341         malloc_cprintf(write_cb, cbopaque,
342             "mapped:                  %12zu\n", mapped);
343         CTL_M2_GET("stats.arenas.0.metadata.mapped", i, &metadata_mapped,
344             size_t);
345         CTL_M2_GET("stats.arenas.0.metadata.allocated", i, &metadata_allocated,
346             size_t);
347         malloc_cprintf(write_cb, cbopaque,
348             "metadata: mapped: %zu, allocated: %zu\n",
349             metadata_mapped, metadata_allocated);
350
351         if (bins)
352                 stats_arena_bins_print(write_cb, cbopaque, i);
353         if (large)
354                 stats_arena_lruns_print(write_cb, cbopaque, i);
355         if (huge)
356                 stats_arena_hchunks_print(write_cb, cbopaque, i);
357 }
358
359 void
360 stats_print(void (*write_cb)(void *, const char *), void *cbopaque,
361     const char *opts)
362 {
363         int err;
364         uint64_t epoch;
365         size_t u64sz;
366         bool general = true;
367         bool merged = true;
368         bool unmerged = true;
369         bool bins = true;
370         bool large = true;
371         bool huge = true;
372
373         /*
374          * Refresh stats, in case mallctl() was called by the application.
375          *
376          * Check for OOM here, since refreshing the ctl cache can trigger
377          * allocation.  In practice, none of the subsequent mallctl()-related
378          * calls in this function will cause OOM if this one succeeds.
379          * */
380         epoch = 1;
381         u64sz = sizeof(uint64_t);
382         err = je_mallctl("epoch", &epoch, &u64sz, &epoch, sizeof(uint64_t));
383         if (err != 0) {
384                 if (err == EAGAIN) {
385                         malloc_write("<jemalloc>: Memory allocation failure in "
386                             "mallctl(\"epoch\", ...)\n");
387                         return;
388                 }
389                 malloc_write("<jemalloc>: Failure in mallctl(\"epoch\", "
390                     "...)\n");
391                 abort();
392         }
393
394         if (opts != NULL) {
395                 unsigned i;
396
397                 for (i = 0; opts[i] != '\0'; i++) {
398                         switch (opts[i]) {
399                         case 'g':
400                                 general = false;
401                                 break;
402                         case 'm':
403                                 merged = false;
404                                 break;
405                         case 'a':
406                                 unmerged = false;
407                                 break;
408                         case 'b':
409                                 bins = false;
410                                 break;
411                         case 'l':
412                                 large = false;
413                                 break;
414                         case 'h':
415                                 huge = false;
416                                 break;
417                         default:;
418                         }
419                 }
420         }
421
422         malloc_cprintf(write_cb, cbopaque,
423             "___ Begin jemalloc statistics ___\n");
424         if (general) {
425                 const char *cpv;
426                 bool bv;
427                 unsigned uv;
428                 ssize_t ssv;
429                 size_t sv, bsz, ssz, sssz, cpsz;
430
431                 bsz = sizeof(bool);
432                 ssz = sizeof(size_t);
433                 sssz = sizeof(ssize_t);
434                 cpsz = sizeof(const char *);
435
436                 CTL_GET("version", &cpv, const char *);
437                 malloc_cprintf(write_cb, cbopaque, "Version: %s\n", cpv);
438                 CTL_GET("config.debug", &bv, bool);
439                 malloc_cprintf(write_cb, cbopaque, "Assertions %s\n",
440                     bv ? "enabled" : "disabled");
441
442 #define OPT_WRITE_BOOL(n)                                               \
443                 if (je_mallctl("opt."#n, &bv, &bsz, NULL, 0) == 0) {    \
444                         malloc_cprintf(write_cb, cbopaque,              \
445                             "  opt."#n": %s\n", bv ? "true" : "false"); \
446                 }
447 #define OPT_WRITE_BOOL_MUTABLE(n, m) {                                  \
448                 bool bv2;                                               \
449                 if (je_mallctl("opt."#n, &bv, &bsz, NULL, 0) == 0 &&    \
450                     je_mallctl(#m, &bv2, &bsz, NULL, 0) == 0) {         \
451                         malloc_cprintf(write_cb, cbopaque,              \
452                             "  opt."#n": %s ("#m": %s)\n", bv ? "true"  \
453                             : "false", bv2 ? "true" : "false");         \
454                 }                                                       \
455 }
456 #define OPT_WRITE_SIZE_T(n)                                             \
457                 if (je_mallctl("opt."#n, &sv, &ssz, NULL, 0) == 0) {    \
458                         malloc_cprintf(write_cb, cbopaque,              \
459                         "  opt."#n": %zu\n", sv);                       \
460                 }
461 #define OPT_WRITE_SSIZE_T(n)                                            \
462                 if (je_mallctl("opt."#n, &ssv, &sssz, NULL, 0) == 0) {  \
463                         malloc_cprintf(write_cb, cbopaque,              \
464                             "  opt."#n": %zd\n", ssv);                  \
465                 }
466 #define OPT_WRITE_SSIZE_T_MUTABLE(n, m) {                               \
467                 ssize_t ssv2;                                           \
468                 if (je_mallctl("opt."#n, &ssv, &sssz, NULL, 0) == 0 &&  \
469                     je_mallctl(#m, &ssv2, &sssz, NULL, 0) == 0) {       \
470                         malloc_cprintf(write_cb, cbopaque,              \
471                             "  opt."#n": %zd ("#m": %zd)\n",            \
472                             ssv, ssv2);                                 \
473                 }                                                       \
474 }
475 #define OPT_WRITE_CHAR_P(n)                                             \
476                 if (je_mallctl("opt."#n, &cpv, &cpsz, NULL, 0) == 0) {  \
477                         malloc_cprintf(write_cb, cbopaque,              \
478                             "  opt."#n": \"%s\"\n", cpv);               \
479                 }
480
481                 malloc_cprintf(write_cb, cbopaque,
482                     "Run-time option settings:\n");
483                 OPT_WRITE_BOOL(abort)
484                 OPT_WRITE_SIZE_T(lg_chunk)
485                 OPT_WRITE_CHAR_P(dss)
486                 OPT_WRITE_SIZE_T(narenas)
487                 OPT_WRITE_SSIZE_T_MUTABLE(lg_dirty_mult, arenas.lg_dirty_mult)
488                 OPT_WRITE_BOOL(stats_print)
489                 OPT_WRITE_CHAR_P(junk)
490                 OPT_WRITE_SIZE_T(quarantine)
491                 OPT_WRITE_BOOL(redzone)
492                 OPT_WRITE_BOOL(zero)
493                 OPT_WRITE_BOOL(utrace)
494                 OPT_WRITE_BOOL(valgrind)
495                 OPT_WRITE_BOOL(xmalloc)
496                 OPT_WRITE_BOOL(tcache)
497                 OPT_WRITE_SSIZE_T(lg_tcache_max)
498                 OPT_WRITE_BOOL(prof)
499                 OPT_WRITE_CHAR_P(prof_prefix)
500                 OPT_WRITE_BOOL_MUTABLE(prof_active, prof.active)
501                 OPT_WRITE_BOOL_MUTABLE(prof_thread_active_init,
502                     prof.thread_active_init)
503                 OPT_WRITE_SSIZE_T(lg_prof_sample)
504                 OPT_WRITE_BOOL(prof_accum)
505                 OPT_WRITE_SSIZE_T(lg_prof_interval)
506                 OPT_WRITE_BOOL(prof_gdump)
507                 OPT_WRITE_BOOL(prof_final)
508                 OPT_WRITE_BOOL(prof_leak)
509
510 #undef OPT_WRITE_BOOL
511 #undef OPT_WRITE_BOOL_MUTABLE
512 #undef OPT_WRITE_SIZE_T
513 #undef OPT_WRITE_SSIZE_T
514 #undef OPT_WRITE_CHAR_P
515
516                 malloc_cprintf(write_cb, cbopaque, "CPUs: %u\n", ncpus);
517
518                 CTL_GET("arenas.narenas", &uv, unsigned);
519                 malloc_cprintf(write_cb, cbopaque, "Arenas: %u\n", uv);
520
521                 malloc_cprintf(write_cb, cbopaque, "Pointer size: %zu\n",
522                     sizeof(void *));
523
524                 CTL_GET("arenas.quantum", &sv, size_t);
525                 malloc_cprintf(write_cb, cbopaque, "Quantum size: %zu\n",
526                     sv);
527
528                 CTL_GET("arenas.page", &sv, size_t);
529                 malloc_cprintf(write_cb, cbopaque, "Page size: %zu\n", sv);
530
531                 CTL_GET("arenas.lg_dirty_mult", &ssv, ssize_t);
532                 if (ssv >= 0) {
533                         malloc_cprintf(write_cb, cbopaque,
534                             "Min active:dirty page ratio per arena: %u:1\n",
535                             (1U << ssv));
536                 } else {
537                         malloc_cprintf(write_cb, cbopaque,
538                             "Min active:dirty page ratio per arena: N/A\n");
539                 }
540                 if (je_mallctl("arenas.tcache_max", &sv, &ssz, NULL, 0) == 0) {
541                         malloc_cprintf(write_cb, cbopaque,
542                             "Maximum thread-cached size class: %zu\n", sv);
543                 }
544                 if (je_mallctl("opt.prof", &bv, &bsz, NULL, 0) == 0 && bv) {
545                         CTL_GET("prof.lg_sample", &sv, size_t);
546                         malloc_cprintf(write_cb, cbopaque,
547                             "Average profile sample interval: %"FMTu64
548                             " (2^%zu)\n", (((uint64_t)1U) << sv), sv);
549
550                         CTL_GET("opt.lg_prof_interval", &ssv, ssize_t);
551                         if (ssv >= 0) {
552                                 malloc_cprintf(write_cb, cbopaque,
553                                     "Average profile dump interval: %"FMTu64
554                                     " (2^%zd)\n",
555                                     (((uint64_t)1U) << ssv), ssv);
556                         } else {
557                                 malloc_cprintf(write_cb, cbopaque,
558                                     "Average profile dump interval: N/A\n");
559                         }
560                 }
561                 CTL_GET("opt.lg_chunk", &sv, size_t);
562                 malloc_cprintf(write_cb, cbopaque,
563                     "Chunk size: %zu (2^%zu)\n", (ZU(1) << sv), sv);
564         }
565
566         if (config_stats) {
567                 size_t *cactive;
568                 size_t allocated, active, metadata, resident, mapped;
569
570                 CTL_GET("stats.cactive", &cactive, size_t *);
571                 CTL_GET("stats.allocated", &allocated, size_t);
572                 CTL_GET("stats.active", &active, size_t);
573                 CTL_GET("stats.metadata", &metadata, size_t);
574                 CTL_GET("stats.resident", &resident, size_t);
575                 CTL_GET("stats.mapped", &mapped, size_t);
576                 malloc_cprintf(write_cb, cbopaque,
577                     "Allocated: %zu, active: %zu, metadata: %zu,"
578                     " resident: %zu, mapped: %zu\n",
579                     allocated, active, metadata, resident, mapped);
580                 malloc_cprintf(write_cb, cbopaque,
581                     "Current active ceiling: %zu\n",
582                     atomic_read_z(cactive));
583
584                 if (merged) {
585                         unsigned narenas;
586
587                         CTL_GET("arenas.narenas", &narenas, unsigned);
588                         {
589                                 VARIABLE_ARRAY(bool, initialized, narenas);
590                                 size_t isz;
591                                 unsigned i, ninitialized;
592
593                                 isz = sizeof(bool) * narenas;
594                                 xmallctl("arenas.initialized", initialized,
595                                     &isz, NULL, 0);
596                                 for (i = ninitialized = 0; i < narenas; i++) {
597                                         if (initialized[i])
598                                                 ninitialized++;
599                                 }
600
601                                 if (ninitialized > 1 || !unmerged) {
602                                         /* Print merged arena stats. */
603                                         malloc_cprintf(write_cb, cbopaque,
604                                             "\nMerged arenas stats:\n");
605                                         stats_arena_print(write_cb, cbopaque,
606                                             narenas, bins, large, huge);
607                                 }
608                         }
609                 }
610
611                 if (unmerged) {
612                         unsigned narenas;
613
614                         /* Print stats for each arena. */
615
616                         CTL_GET("arenas.narenas", &narenas, unsigned);
617                         {
618                                 VARIABLE_ARRAY(bool, initialized, narenas);
619                                 size_t isz;
620                                 unsigned i;
621
622                                 isz = sizeof(bool) * narenas;
623                                 xmallctl("arenas.initialized", initialized,
624                                     &isz, NULL, 0);
625
626                                 for (i = 0; i < narenas; i++) {
627                                         if (initialized[i]) {
628                                                 malloc_cprintf(write_cb,
629                                                     cbopaque,
630                                                     "\narenas[%u]:\n", i);
631                                                 stats_arena_print(write_cb,
632                                                     cbopaque, i, bins, large,
633                                                     huge);
634                                         }
635                                 }
636                         }
637                 }
638         }
639         malloc_cprintf(write_cb, cbopaque, "--- End jemalloc statistics ---\n");
640 }