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