]>
Commit | Line | Data |
---|---|---|
970d7e83 LB |
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); \ | |
3b2f2976 | 6 | xmallctl(n, (void *)v, &sz, NULL, 0); \ |
970d7e83 LB |
7 | } while (0) |
8 | ||
54a0048b | 9 | #define CTL_M2_GET(n, i, v, t) do { \ |
970d7e83 LB |
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); \ | |
54a0048b | 14 | mib[2] = (i); \ |
3b2f2976 | 15 | xmallctlbymib(mib, miblen, (void *)v, &sz, NULL, 0); \ |
970d7e83 LB |
16 | } while (0) |
17 | ||
54a0048b | 18 | #define CTL_M2_M4_GET(n, i, j, v, t) do { \ |
970d7e83 LB |
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); \ | |
54a0048b SL |
23 | mib[2] = (i); \ |
24 | mib[4] = (j); \ | |
3b2f2976 | 25 | xmallctlbymib(mib, miblen, (void *)v, &sz, NULL, 0); \ |
970d7e83 LB |
26 | } while (0) |
27 | ||
28 | /******************************************************************************/ | |
29 | /* Data. */ | |
30 | ||
31 | bool opt_stats_print = false; | |
32 | ||
33 | size_t stats_cactive = 0; | |
34 | ||
970d7e83 LB |
35 | /******************************************************************************/ |
36 | ||
37 | static void | |
38 | stats_arena_bins_print(void (*write_cb)(void *, const char *), void *cbopaque, | |
3b2f2976 | 39 | bool json, bool large, bool huge, unsigned i) |
970d7e83 LB |
40 | { |
41 | size_t page; | |
3b2f2976 | 42 | bool in_gap, in_gap_prev; |
54a0048b | 43 | unsigned nbins, j; |
970d7e83 LB |
44 | |
45 | CTL_GET("arenas.page", &page, size_t); | |
46 | ||
3b2f2976 XL |
47 | CTL_GET("arenas.nbins", &nbins, unsigned); |
48 | if (json) { | |
970d7e83 | 49 | malloc_cprintf(write_cb, cbopaque, |
3b2f2976 | 50 | "\t\t\t\t\"bins\": [\n"); |
970d7e83 | 51 | } else { |
3b2f2976 XL |
52 | if (config_tcache) { |
53 | malloc_cprintf(write_cb, cbopaque, | |
54 | "bins: size ind allocated nmalloc" | |
55 | " ndalloc nrequests curregs" | |
56 | " curruns regs pgs util nfills" | |
57 | " nflushes newruns reruns\n"); | |
58 | } else { | |
59 | malloc_cprintf(write_cb, cbopaque, | |
60 | "bins: size ind allocated nmalloc" | |
61 | " ndalloc nrequests curregs" | |
62 | " curruns regs pgs util newruns" | |
63 | " reruns\n"); | |
64 | } | |
970d7e83 | 65 | } |
54a0048b | 66 | for (j = 0, in_gap = false; j < nbins; j++) { |
970d7e83 | 67 | uint64_t nruns; |
3b2f2976 XL |
68 | size_t reg_size, run_size, curregs; |
69 | size_t curruns; | |
70 | uint32_t nregs; | |
71 | uint64_t nmalloc, ndalloc, nrequests, nfills, nflushes; | |
72 | uint64_t nreruns; | |
970d7e83 | 73 | |
54a0048b SL |
74 | CTL_M2_M4_GET("stats.arenas.0.bins.0.nruns", i, j, &nruns, |
75 | uint64_t); | |
3b2f2976 XL |
76 | in_gap_prev = in_gap; |
77 | in_gap = (nruns == 0); | |
970d7e83 | 78 | |
3b2f2976 XL |
79 | if (!json && in_gap_prev && !in_gap) { |
80 | malloc_cprintf(write_cb, cbopaque, | |
81 | " ---\n"); | |
82 | } | |
83 | ||
84 | CTL_M2_GET("arenas.bin.0.size", j, ®_size, size_t); | |
85 | CTL_M2_GET("arenas.bin.0.nregs", j, &nregs, uint32_t); | |
86 | CTL_M2_GET("arenas.bin.0.run_size", j, &run_size, size_t); | |
87 | ||
88 | CTL_M2_M4_GET("stats.arenas.0.bins.0.nmalloc", i, j, &nmalloc, | |
89 | uint64_t); | |
90 | CTL_M2_M4_GET("stats.arenas.0.bins.0.ndalloc", i, j, &ndalloc, | |
91 | uint64_t); | |
92 | CTL_M2_M4_GET("stats.arenas.0.bins.0.curregs", i, j, &curregs, | |
93 | size_t); | |
94 | CTL_M2_M4_GET("stats.arenas.0.bins.0.nrequests", i, j, | |
95 | &nrequests, uint64_t); | |
96 | if (config_tcache) { | |
97 | CTL_M2_M4_GET("stats.arenas.0.bins.0.nfills", i, j, | |
98 | &nfills, uint64_t); | |
99 | CTL_M2_M4_GET("stats.arenas.0.bins.0.nflushes", i, j, | |
100 | &nflushes, uint64_t); | |
101 | } | |
102 | CTL_M2_M4_GET("stats.arenas.0.bins.0.nreruns", i, j, &nreruns, | |
103 | uint64_t); | |
104 | CTL_M2_M4_GET("stats.arenas.0.bins.0.curruns", i, j, &curruns, | |
105 | size_t); | |
106 | ||
107 | if (json) { | |
108 | malloc_cprintf(write_cb, cbopaque, | |
109 | "\t\t\t\t\t{\n" | |
110 | "\t\t\t\t\t\t\"nmalloc\": %"FMTu64",\n" | |
111 | "\t\t\t\t\t\t\"ndalloc\": %"FMTu64",\n" | |
112 | "\t\t\t\t\t\t\"curregs\": %zu,\n" | |
113 | "\t\t\t\t\t\t\"nrequests\": %"FMTu64",\n", | |
114 | nmalloc, | |
115 | ndalloc, | |
116 | curregs, | |
117 | nrequests); | |
970d7e83 | 118 | if (config_tcache) { |
3b2f2976 XL |
119 | malloc_cprintf(write_cb, cbopaque, |
120 | "\t\t\t\t\t\t\"nfills\": %"FMTu64",\n" | |
121 | "\t\t\t\t\t\t\"nflushes\": %"FMTu64",\n", | |
122 | nfills, | |
123 | nflushes); | |
970d7e83 | 124 | } |
3b2f2976 XL |
125 | malloc_cprintf(write_cb, cbopaque, |
126 | "\t\t\t\t\t\t\"nreruns\": %"FMTu64",\n" | |
127 | "\t\t\t\t\t\t\"curruns\": %zu\n" | |
128 | "\t\t\t\t\t}%s\n", | |
129 | nreruns, | |
130 | curruns, | |
131 | (j + 1 < nbins) ? "," : ""); | |
132 | } else if (!in_gap) { | |
133 | size_t availregs, milli; | |
134 | char util[6]; /* "x.yyy". */ | |
54a0048b SL |
135 | |
136 | availregs = nregs * curruns; | |
137 | milli = (availregs != 0) ? (1000 * curregs) / availregs | |
138 | : 1000; | |
3b2f2976 XL |
139 | |
140 | if (milli > 1000) { | |
141 | /* | |
142 | * Race detected: the counters were read in | |
143 | * separate mallctl calls and concurrent | |
144 | * operations happened in between. In this case | |
145 | * no meaningful utilization can be computed. | |
146 | */ | |
147 | malloc_snprintf(util, sizeof(util), " race"); | |
148 | } else if (milli < 10) { | |
54a0048b SL |
149 | malloc_snprintf(util, sizeof(util), |
150 | "0.00%zu", milli); | |
151 | } else if (milli < 100) { | |
152 | malloc_snprintf(util, sizeof(util), "0.0%zu", | |
153 | milli); | |
154 | } else if (milli < 1000) { | |
155 | malloc_snprintf(util, sizeof(util), "0.%zu", | |
156 | milli); | |
3b2f2976 XL |
157 | } else { |
158 | assert(milli == 1000); | |
54a0048b | 159 | malloc_snprintf(util, sizeof(util), "1"); |
3b2f2976 | 160 | } |
54a0048b | 161 | |
970d7e83 LB |
162 | if (config_tcache) { |
163 | malloc_cprintf(write_cb, cbopaque, | |
54a0048b SL |
164 | "%20zu %3u %12zu %12"FMTu64 |
165 | " %12"FMTu64" %12"FMTu64" %12zu" | |
166 | " %12zu %4u %3zu %-5s %12"FMTu64 | |
167 | " %12"FMTu64" %12"FMTu64" %12"FMTu64"\n", | |
168 | reg_size, j, curregs * reg_size, nmalloc, | |
169 | ndalloc, nrequests, curregs, curruns, nregs, | |
170 | run_size / page, util, nfills, nflushes, | |
3b2f2976 | 171 | nruns, nreruns); |
970d7e83 LB |
172 | } else { |
173 | malloc_cprintf(write_cb, cbopaque, | |
54a0048b SL |
174 | "%20zu %3u %12zu %12"FMTu64 |
175 | " %12"FMTu64" %12"FMTu64" %12zu" | |
176 | " %12zu %4u %3zu %-5s %12"FMTu64 | |
177 | " %12"FMTu64"\n", | |
178 | reg_size, j, curregs * reg_size, nmalloc, | |
179 | ndalloc, nrequests, curregs, curruns, nregs, | |
3b2f2976 | 180 | run_size / page, util, nruns, nreruns); |
970d7e83 LB |
181 | } |
182 | } | |
183 | } | |
3b2f2976 | 184 | if (json) { |
54a0048b | 185 | malloc_cprintf(write_cb, cbopaque, |
3b2f2976 XL |
186 | "\t\t\t\t]%s\n", (large || huge) ? "," : ""); |
187 | } else { | |
188 | if (in_gap) { | |
189 | malloc_cprintf(write_cb, cbopaque, | |
190 | " ---\n"); | |
191 | } | |
970d7e83 LB |
192 | } |
193 | } | |
194 | ||
195 | static void | |
196 | stats_arena_lruns_print(void (*write_cb)(void *, const char *), void *cbopaque, | |
3b2f2976 | 197 | bool json, bool huge, unsigned i) |
970d7e83 | 198 | { |
54a0048b | 199 | unsigned nbins, nlruns, j; |
3b2f2976 | 200 | bool in_gap, in_gap_prev; |
970d7e83 | 201 | |
54a0048b SL |
202 | CTL_GET("arenas.nbins", &nbins, unsigned); |
203 | CTL_GET("arenas.nlruns", &nlruns, unsigned); | |
3b2f2976 XL |
204 | if (json) { |
205 | malloc_cprintf(write_cb, cbopaque, | |
206 | "\t\t\t\t\"lruns\": [\n"); | |
207 | } else { | |
208 | malloc_cprintf(write_cb, cbopaque, | |
209 | "large: size ind allocated nmalloc" | |
210 | " ndalloc nrequests curruns\n"); | |
211 | } | |
54a0048b | 212 | for (j = 0, in_gap = false; j < nlruns; j++) { |
970d7e83 LB |
213 | uint64_t nmalloc, ndalloc, nrequests; |
214 | size_t run_size, curruns; | |
215 | ||
54a0048b | 216 | CTL_M2_M4_GET("stats.arenas.0.lruns.0.nmalloc", i, j, &nmalloc, |
970d7e83 | 217 | uint64_t); |
54a0048b | 218 | CTL_M2_M4_GET("stats.arenas.0.lruns.0.ndalloc", i, j, &ndalloc, |
7453a54e | 219 | uint64_t); |
54a0048b SL |
220 | CTL_M2_M4_GET("stats.arenas.0.lruns.0.nrequests", i, j, |
221 | &nrequests, uint64_t); | |
3b2f2976 XL |
222 | in_gap_prev = in_gap; |
223 | in_gap = (nrequests == 0); | |
224 | ||
225 | if (!json && in_gap_prev && !in_gap) { | |
226 | malloc_cprintf(write_cb, cbopaque, | |
227 | " ---\n"); | |
228 | } | |
229 | ||
230 | CTL_M2_GET("arenas.lrun.0.size", j, &run_size, size_t); | |
231 | CTL_M2_M4_GET("stats.arenas.0.lruns.0.curruns", i, j, &curruns, | |
232 | size_t); | |
233 | if (json) { | |
234 | malloc_cprintf(write_cb, cbopaque, | |
235 | "\t\t\t\t\t{\n" | |
236 | "\t\t\t\t\t\t\"curruns\": %zu\n" | |
237 | "\t\t\t\t\t}%s\n", | |
238 | curruns, | |
239 | (j + 1 < nlruns) ? "," : ""); | |
240 | } else if (!in_gap) { | |
54a0048b SL |
241 | malloc_cprintf(write_cb, cbopaque, |
242 | "%20zu %3u %12zu %12"FMTu64" %12"FMTu64 | |
243 | " %12"FMTu64" %12zu\n", | |
244 | run_size, nbins + j, curruns * run_size, nmalloc, | |
245 | ndalloc, nrequests, curruns); | |
246 | } | |
247 | } | |
3b2f2976 | 248 | if (json) { |
54a0048b | 249 | malloc_cprintf(write_cb, cbopaque, |
3b2f2976 XL |
250 | "\t\t\t\t]%s\n", huge ? "," : ""); |
251 | } else { | |
252 | if (in_gap) { | |
253 | malloc_cprintf(write_cb, cbopaque, | |
254 | " ---\n"); | |
255 | } | |
54a0048b SL |
256 | } |
257 | } | |
258 | ||
259 | static void | |
260 | stats_arena_hchunks_print(void (*write_cb)(void *, const char *), | |
3b2f2976 | 261 | void *cbopaque, bool json, unsigned i) |
54a0048b SL |
262 | { |
263 | unsigned nbins, nlruns, nhchunks, j; | |
3b2f2976 | 264 | bool in_gap, in_gap_prev; |
54a0048b | 265 | |
54a0048b SL |
266 | CTL_GET("arenas.nbins", &nbins, unsigned); |
267 | CTL_GET("arenas.nlruns", &nlruns, unsigned); | |
268 | CTL_GET("arenas.nhchunks", &nhchunks, unsigned); | |
3b2f2976 XL |
269 | if (json) { |
270 | malloc_cprintf(write_cb, cbopaque, | |
271 | "\t\t\t\t\"hchunks\": [\n"); | |
272 | } else { | |
273 | malloc_cprintf(write_cb, cbopaque, | |
274 | "huge: size ind allocated nmalloc" | |
275 | " ndalloc nrequests curhchunks\n"); | |
276 | } | |
54a0048b SL |
277 | for (j = 0, in_gap = false; j < nhchunks; j++) { |
278 | uint64_t nmalloc, ndalloc, nrequests; | |
279 | size_t hchunk_size, curhchunks; | |
280 | ||
281 | CTL_M2_M4_GET("stats.arenas.0.hchunks.0.nmalloc", i, j, | |
282 | &nmalloc, uint64_t); | |
283 | CTL_M2_M4_GET("stats.arenas.0.hchunks.0.ndalloc", i, j, | |
284 | &ndalloc, uint64_t); | |
285 | CTL_M2_M4_GET("stats.arenas.0.hchunks.0.nrequests", i, j, | |
286 | &nrequests, uint64_t); | |
3b2f2976 XL |
287 | in_gap_prev = in_gap; |
288 | in_gap = (nrequests == 0); | |
289 | ||
290 | if (!json && in_gap_prev && !in_gap) { | |
291 | malloc_cprintf(write_cb, cbopaque, | |
292 | " ---\n"); | |
293 | } | |
294 | ||
295 | CTL_M2_GET("arenas.hchunk.0.size", j, &hchunk_size, size_t); | |
296 | CTL_M2_M4_GET("stats.arenas.0.hchunks.0.curhchunks", i, j, | |
297 | &curhchunks, size_t); | |
298 | if (json) { | |
299 | malloc_cprintf(write_cb, cbopaque, | |
300 | "\t\t\t\t\t{\n" | |
301 | "\t\t\t\t\t\t\"curhchunks\": %zu\n" | |
302 | "\t\t\t\t\t}%s\n", | |
303 | curhchunks, | |
304 | (j + 1 < nhchunks) ? "," : ""); | |
305 | } else if (!in_gap) { | |
970d7e83 | 306 | malloc_cprintf(write_cb, cbopaque, |
54a0048b SL |
307 | "%20zu %3u %12zu %12"FMTu64" %12"FMTu64 |
308 | " %12"FMTu64" %12zu\n", | |
309 | hchunk_size, nbins + nlruns + j, | |
310 | curhchunks * hchunk_size, nmalloc, ndalloc, | |
311 | nrequests, curhchunks); | |
970d7e83 LB |
312 | } |
313 | } | |
3b2f2976 | 314 | if (json) { |
54a0048b | 315 | malloc_cprintf(write_cb, cbopaque, |
3b2f2976 XL |
316 | "\t\t\t\t]\n"); |
317 | } else { | |
318 | if (in_gap) { | |
319 | malloc_cprintf(write_cb, cbopaque, | |
320 | " ---\n"); | |
321 | } | |
54a0048b | 322 | } |
970d7e83 LB |
323 | } |
324 | ||
325 | static void | |
326 | stats_arena_print(void (*write_cb)(void *, const char *), void *cbopaque, | |
3b2f2976 | 327 | bool json, unsigned i, bool bins, bool large, bool huge) |
970d7e83 LB |
328 | { |
329 | unsigned nthreads; | |
330 | const char *dss; | |
54a0048b | 331 | ssize_t lg_dirty_mult, decay_time; |
3b2f2976 | 332 | size_t page, pactive, pdirty, mapped, retained; |
54a0048b | 333 | size_t metadata_mapped, metadata_allocated; |
970d7e83 LB |
334 | uint64_t npurge, nmadvise, purged; |
335 | size_t small_allocated; | |
336 | uint64_t small_nmalloc, small_ndalloc, small_nrequests; | |
337 | size_t large_allocated; | |
338 | uint64_t large_nmalloc, large_ndalloc, large_nrequests; | |
1a4d82fc JJ |
339 | size_t huge_allocated; |
340 | uint64_t huge_nmalloc, huge_ndalloc, huge_nrequests; | |
970d7e83 LB |
341 | |
342 | CTL_GET("arenas.page", &page, size_t); | |
343 | ||
54a0048b | 344 | CTL_M2_GET("stats.arenas.0.nthreads", i, &nthreads, unsigned); |
3b2f2976 XL |
345 | if (json) { |
346 | malloc_cprintf(write_cb, cbopaque, | |
347 | "\t\t\t\t\"nthreads\": %u,\n", nthreads); | |
348 | } else { | |
349 | malloc_cprintf(write_cb, cbopaque, | |
350 | "assigned threads: %u\n", nthreads); | |
351 | } | |
352 | ||
54a0048b | 353 | CTL_M2_GET("stats.arenas.0.dss", i, &dss, const char *); |
3b2f2976 XL |
354 | if (json) { |
355 | malloc_cprintf(write_cb, cbopaque, | |
356 | "\t\t\t\t\"dss\": \"%s\",\n", dss); | |
357 | } else { | |
358 | malloc_cprintf(write_cb, cbopaque, | |
359 | "dss allocation precedence: %s\n", dss); | |
360 | } | |
361 | ||
54a0048b | 362 | CTL_M2_GET("stats.arenas.0.lg_dirty_mult", i, &lg_dirty_mult, ssize_t); |
3b2f2976 XL |
363 | if (json) { |
364 | malloc_cprintf(write_cb, cbopaque, | |
365 | "\t\t\t\t\"lg_dirty_mult\": %zd,\n", lg_dirty_mult); | |
366 | } else { | |
367 | if (opt_purge == purge_mode_ratio) { | |
368 | if (lg_dirty_mult >= 0) { | |
369 | malloc_cprintf(write_cb, cbopaque, | |
370 | "min active:dirty page ratio: %u:1\n", | |
371 | (1U << lg_dirty_mult)); | |
372 | } else { | |
373 | malloc_cprintf(write_cb, cbopaque, | |
374 | "min active:dirty page ratio: N/A\n"); | |
375 | } | |
54a0048b SL |
376 | } |
377 | } | |
3b2f2976 | 378 | |
54a0048b | 379 | CTL_M2_GET("stats.arenas.0.decay_time", i, &decay_time, ssize_t); |
3b2f2976 XL |
380 | if (json) { |
381 | malloc_cprintf(write_cb, cbopaque, | |
382 | "\t\t\t\t\"decay_time\": %zd,\n", decay_time); | |
383 | } else { | |
384 | if (opt_purge == purge_mode_decay) { | |
385 | if (decay_time >= 0) { | |
386 | malloc_cprintf(write_cb, cbopaque, | |
387 | "decay time: %zd\n", decay_time); | |
388 | } else { | |
389 | malloc_cprintf(write_cb, cbopaque, | |
390 | "decay time: N/A\n"); | |
391 | } | |
392 | } | |
54a0048b | 393 | } |
3b2f2976 | 394 | |
54a0048b SL |
395 | CTL_M2_GET("stats.arenas.0.pactive", i, &pactive, size_t); |
396 | CTL_M2_GET("stats.arenas.0.pdirty", i, &pdirty, size_t); | |
397 | CTL_M2_GET("stats.arenas.0.npurge", i, &npurge, uint64_t); | |
398 | CTL_M2_GET("stats.arenas.0.nmadvise", i, &nmadvise, uint64_t); | |
399 | CTL_M2_GET("stats.arenas.0.purged", i, &purged, uint64_t); | |
3b2f2976 XL |
400 | if (json) { |
401 | malloc_cprintf(write_cb, cbopaque, | |
402 | "\t\t\t\t\"pactive\": %zu,\n", pactive); | |
403 | malloc_cprintf(write_cb, cbopaque, | |
404 | "\t\t\t\t\"pdirty\": %zu,\n", pdirty); | |
405 | malloc_cprintf(write_cb, cbopaque, | |
406 | "\t\t\t\t\"npurge\": %"FMTu64",\n", npurge); | |
407 | malloc_cprintf(write_cb, cbopaque, | |
408 | "\t\t\t\t\"nmadvise\": %"FMTu64",\n", nmadvise); | |
409 | malloc_cprintf(write_cb, cbopaque, | |
410 | "\t\t\t\t\"purged\": %"FMTu64",\n", purged); | |
411 | } else { | |
412 | malloc_cprintf(write_cb, cbopaque, | |
413 | "purging: dirty: %zu, sweeps: %"FMTu64", madvises: %"FMTu64 | |
414 | ", purged: %"FMTu64"\n", pdirty, npurge, nmadvise, purged); | |
415 | } | |
970d7e83 | 416 | |
54a0048b SL |
417 | CTL_M2_GET("stats.arenas.0.small.allocated", i, &small_allocated, |
418 | size_t); | |
419 | CTL_M2_GET("stats.arenas.0.small.nmalloc", i, &small_nmalloc, uint64_t); | |
420 | CTL_M2_GET("stats.arenas.0.small.ndalloc", i, &small_ndalloc, uint64_t); | |
421 | CTL_M2_GET("stats.arenas.0.small.nrequests", i, &small_nrequests, | |
422 | uint64_t); | |
3b2f2976 XL |
423 | if (json) { |
424 | malloc_cprintf(write_cb, cbopaque, | |
425 | "\t\t\t\t\"small\": {\n"); | |
426 | ||
427 | malloc_cprintf(write_cb, cbopaque, | |
428 | "\t\t\t\t\t\"allocated\": %zu,\n", small_allocated); | |
429 | malloc_cprintf(write_cb, cbopaque, | |
430 | "\t\t\t\t\t\"nmalloc\": %"FMTu64",\n", small_nmalloc); | |
431 | malloc_cprintf(write_cb, cbopaque, | |
432 | "\t\t\t\t\t\"ndalloc\": %"FMTu64",\n", small_ndalloc); | |
433 | malloc_cprintf(write_cb, cbopaque, | |
434 | "\t\t\t\t\t\"nrequests\": %"FMTu64"\n", small_nrequests); | |
435 | ||
436 | malloc_cprintf(write_cb, cbopaque, | |
437 | "\t\t\t\t},\n"); | |
438 | } else { | |
439 | malloc_cprintf(write_cb, cbopaque, | |
440 | " allocated nmalloc" | |
441 | " ndalloc nrequests\n"); | |
442 | malloc_cprintf(write_cb, cbopaque, | |
443 | "small: %12zu %12"FMTu64" %12"FMTu64 | |
444 | " %12"FMTu64"\n", | |
445 | small_allocated, small_nmalloc, small_ndalloc, | |
446 | small_nrequests); | |
447 | } | |
448 | ||
54a0048b SL |
449 | CTL_M2_GET("stats.arenas.0.large.allocated", i, &large_allocated, |
450 | size_t); | |
451 | CTL_M2_GET("stats.arenas.0.large.nmalloc", i, &large_nmalloc, uint64_t); | |
452 | CTL_M2_GET("stats.arenas.0.large.ndalloc", i, &large_ndalloc, uint64_t); | |
453 | CTL_M2_GET("stats.arenas.0.large.nrequests", i, &large_nrequests, | |
454 | uint64_t); | |
3b2f2976 XL |
455 | if (json) { |
456 | malloc_cprintf(write_cb, cbopaque, | |
457 | "\t\t\t\t\"large\": {\n"); | |
458 | ||
459 | malloc_cprintf(write_cb, cbopaque, | |
460 | "\t\t\t\t\t\"allocated\": %zu,\n", large_allocated); | |
461 | malloc_cprintf(write_cb, cbopaque, | |
462 | "\t\t\t\t\t\"nmalloc\": %"FMTu64",\n", large_nmalloc); | |
463 | malloc_cprintf(write_cb, cbopaque, | |
464 | "\t\t\t\t\t\"ndalloc\": %"FMTu64",\n", large_ndalloc); | |
465 | malloc_cprintf(write_cb, cbopaque, | |
466 | "\t\t\t\t\t\"nrequests\": %"FMTu64"\n", large_nrequests); | |
467 | ||
468 | malloc_cprintf(write_cb, cbopaque, | |
469 | "\t\t\t\t},\n"); | |
470 | } else { | |
471 | malloc_cprintf(write_cb, cbopaque, | |
472 | "large: %12zu %12"FMTu64" %12"FMTu64 | |
473 | " %12"FMTu64"\n", | |
474 | large_allocated, large_nmalloc, large_ndalloc, | |
475 | large_nrequests); | |
476 | } | |
477 | ||
54a0048b SL |
478 | CTL_M2_GET("stats.arenas.0.huge.allocated", i, &huge_allocated, size_t); |
479 | CTL_M2_GET("stats.arenas.0.huge.nmalloc", i, &huge_nmalloc, uint64_t); | |
480 | CTL_M2_GET("stats.arenas.0.huge.ndalloc", i, &huge_ndalloc, uint64_t); | |
481 | CTL_M2_GET("stats.arenas.0.huge.nrequests", i, &huge_nrequests, | |
482 | uint64_t); | |
3b2f2976 XL |
483 | if (json) { |
484 | malloc_cprintf(write_cb, cbopaque, | |
485 | "\t\t\t\t\"huge\": {\n"); | |
486 | ||
487 | malloc_cprintf(write_cb, cbopaque, | |
488 | "\t\t\t\t\t\"allocated\": %zu,\n", huge_allocated); | |
489 | malloc_cprintf(write_cb, cbopaque, | |
490 | "\t\t\t\t\t\"nmalloc\": %"FMTu64",\n", huge_nmalloc); | |
491 | malloc_cprintf(write_cb, cbopaque, | |
492 | "\t\t\t\t\t\"ndalloc\": %"FMTu64",\n", huge_ndalloc); | |
493 | malloc_cprintf(write_cb, cbopaque, | |
494 | "\t\t\t\t\t\"nrequests\": %"FMTu64"\n", huge_nrequests); | |
495 | ||
496 | malloc_cprintf(write_cb, cbopaque, | |
497 | "\t\t\t\t},\n"); | |
498 | } else { | |
499 | malloc_cprintf(write_cb, cbopaque, | |
500 | "huge: %12zu %12"FMTu64" %12"FMTu64 | |
501 | " %12"FMTu64"\n", | |
502 | huge_allocated, huge_nmalloc, huge_ndalloc, huge_nrequests); | |
503 | malloc_cprintf(write_cb, cbopaque, | |
504 | "total: %12zu %12"FMTu64" %12"FMTu64 | |
505 | " %12"FMTu64"\n", | |
506 | small_allocated + large_allocated + huge_allocated, | |
507 | small_nmalloc + large_nmalloc + huge_nmalloc, | |
508 | small_ndalloc + large_ndalloc + huge_ndalloc, | |
509 | small_nrequests + large_nrequests + huge_nrequests); | |
510 | } | |
511 | if (!json) { | |
512 | malloc_cprintf(write_cb, cbopaque, | |
513 | "active: %12zu\n", pactive * page); | |
514 | } | |
515 | ||
54a0048b | 516 | CTL_M2_GET("stats.arenas.0.mapped", i, &mapped, size_t); |
3b2f2976 XL |
517 | if (json) { |
518 | malloc_cprintf(write_cb, cbopaque, | |
519 | "\t\t\t\t\"mapped\": %zu,\n", mapped); | |
520 | } else { | |
521 | malloc_cprintf(write_cb, cbopaque, | |
522 | "mapped: %12zu\n", mapped); | |
523 | } | |
524 | ||
525 | CTL_M2_GET("stats.arenas.0.retained", i, &retained, size_t); | |
526 | if (json) { | |
527 | malloc_cprintf(write_cb, cbopaque, | |
528 | "\t\t\t\t\"retained\": %zu,\n", retained); | |
529 | } else { | |
530 | malloc_cprintf(write_cb, cbopaque, | |
531 | "retained: %12zu\n", retained); | |
532 | } | |
533 | ||
54a0048b SL |
534 | CTL_M2_GET("stats.arenas.0.metadata.mapped", i, &metadata_mapped, |
535 | size_t); | |
536 | CTL_M2_GET("stats.arenas.0.metadata.allocated", i, &metadata_allocated, | |
537 | size_t); | |
3b2f2976 XL |
538 | if (json) { |
539 | malloc_cprintf(write_cb, cbopaque, | |
540 | "\t\t\t\t\"metadata\": {\n"); | |
541 | ||
542 | malloc_cprintf(write_cb, cbopaque, | |
543 | "\t\t\t\t\t\"mapped\": %zu,\n", metadata_mapped); | |
544 | malloc_cprintf(write_cb, cbopaque, | |
545 | "\t\t\t\t\t\"allocated\": %zu\n", metadata_allocated); | |
546 | ||
547 | malloc_cprintf(write_cb, cbopaque, | |
548 | "\t\t\t\t}%s\n", (bins || large || huge) ? "," : ""); | |
549 | } else { | |
550 | malloc_cprintf(write_cb, cbopaque, | |
551 | "metadata: mapped: %zu, allocated: %zu\n", | |
552 | metadata_mapped, metadata_allocated); | |
553 | } | |
970d7e83 | 554 | |
3b2f2976 XL |
555 | if (bins) { |
556 | stats_arena_bins_print(write_cb, cbopaque, json, large, huge, | |
557 | i); | |
558 | } | |
970d7e83 | 559 | if (large) |
3b2f2976 | 560 | stats_arena_lruns_print(write_cb, cbopaque, json, huge, i); |
54a0048b | 561 | if (huge) |
3b2f2976 | 562 | stats_arena_hchunks_print(write_cb, cbopaque, json, i); |
970d7e83 LB |
563 | } |
564 | ||
3b2f2976 XL |
565 | static void |
566 | stats_general_print(void (*write_cb)(void *, const char *), void *cbopaque, | |
567 | bool json, bool more) | |
970d7e83 | 568 | { |
3b2f2976 XL |
569 | const char *cpv; |
570 | bool bv; | |
571 | unsigned uv; | |
572 | uint32_t u32v; | |
573 | uint64_t u64v; | |
574 | ssize_t ssv; | |
575 | size_t sv, bsz, usz, ssz, sssz, cpsz; | |
970d7e83 | 576 | |
3b2f2976 XL |
577 | bsz = sizeof(bool); |
578 | usz = sizeof(unsigned); | |
579 | ssz = sizeof(size_t); | |
580 | sssz = sizeof(ssize_t); | |
581 | cpsz = sizeof(const char *); | |
970d7e83 | 582 | |
3b2f2976 XL |
583 | CTL_GET("version", &cpv, const char *); |
584 | if (json) { | |
585 | malloc_cprintf(write_cb, cbopaque, | |
586 | "\t\t\"version\": \"%s\",\n", cpv); | |
587 | } else | |
588 | malloc_cprintf(write_cb, cbopaque, "Version: %s\n", cpv); | |
970d7e83 | 589 | |
3b2f2976 XL |
590 | /* config. */ |
591 | #define CONFIG_WRITE_BOOL_JSON(n, c) \ | |
592 | if (json) { \ | |
593 | CTL_GET("config."#n, &bv, bool); \ | |
594 | malloc_cprintf(write_cb, cbopaque, \ | |
595 | "\t\t\t\""#n"\": %s%s\n", bv ? "true" : "false", \ | |
596 | (c)); \ | |
970d7e83 LB |
597 | } |
598 | ||
3b2f2976 XL |
599 | if (json) { |
600 | malloc_cprintf(write_cb, cbopaque, | |
601 | "\t\t\"config\": {\n"); | |
602 | } | |
603 | ||
604 | CONFIG_WRITE_BOOL_JSON(cache_oblivious, ",") | |
605 | ||
606 | CTL_GET("config.debug", &bv, bool); | |
607 | if (json) { | |
608 | malloc_cprintf(write_cb, cbopaque, | |
609 | "\t\t\t\"debug\": %s,\n", bv ? "true" : "false"); | |
610 | } else { | |
970d7e83 LB |
611 | malloc_cprintf(write_cb, cbopaque, "Assertions %s\n", |
612 | bv ? "enabled" : "disabled"); | |
3b2f2976 XL |
613 | } |
614 | ||
615 | CONFIG_WRITE_BOOL_JSON(fill, ",") | |
616 | CONFIG_WRITE_BOOL_JSON(lazy_lock, ",") | |
617 | ||
618 | if (json) { | |
619 | malloc_cprintf(write_cb, cbopaque, | |
620 | "\t\t\t\"malloc_conf\": \"%s\",\n", | |
621 | config_malloc_conf); | |
622 | } else { | |
54a0048b SL |
623 | malloc_cprintf(write_cb, cbopaque, |
624 | "config.malloc_conf: \"%s\"\n", config_malloc_conf); | |
3b2f2976 XL |
625 | } |
626 | ||
627 | CONFIG_WRITE_BOOL_JSON(munmap, ",") | |
628 | CONFIG_WRITE_BOOL_JSON(prof, ",") | |
629 | CONFIG_WRITE_BOOL_JSON(prof_libgcc, ",") | |
630 | CONFIG_WRITE_BOOL_JSON(prof_libunwind, ",") | |
631 | CONFIG_WRITE_BOOL_JSON(stats, ",") | |
632 | CONFIG_WRITE_BOOL_JSON(tcache, ",") | |
633 | CONFIG_WRITE_BOOL_JSON(tls, ",") | |
634 | CONFIG_WRITE_BOOL_JSON(utrace, ",") | |
635 | CONFIG_WRITE_BOOL_JSON(valgrind, ",") | |
636 | CONFIG_WRITE_BOOL_JSON(xmalloc, "") | |
637 | ||
638 | if (json) { | |
639 | malloc_cprintf(write_cb, cbopaque, | |
640 | "\t\t},\n"); | |
641 | } | |
642 | #undef CONFIG_WRITE_BOOL_JSON | |
970d7e83 | 643 | |
3b2f2976 XL |
644 | /* opt. */ |
645 | #define OPT_WRITE_BOOL(n, c) \ | |
646 | if (je_mallctl("opt."#n, (void *)&bv, &bsz, NULL, 0) == 0) { \ | |
647 | if (json) { \ | |
648 | malloc_cprintf(write_cb, cbopaque, \ | |
649 | "\t\t\t\""#n"\": %s%s\n", bv ? "true" : \ | |
650 | "false", (c)); \ | |
651 | } else { \ | |
970d7e83 LB |
652 | malloc_cprintf(write_cb, cbopaque, \ |
653 | " opt."#n": %s\n", bv ? "true" : "false"); \ | |
3b2f2976 XL |
654 | } \ |
655 | } | |
656 | #define OPT_WRITE_BOOL_MUTABLE(n, m, c) { \ | |
657 | bool bv2; \ | |
658 | if (je_mallctl("opt."#n, (void *)&bv, &bsz, NULL, 0) == 0 && \ | |
659 | je_mallctl(#m, &bv2, (void *)&bsz, NULL, 0) == 0) { \ | |
660 | if (json) { \ | |
661 | malloc_cprintf(write_cb, cbopaque, \ | |
662 | "\t\t\t\""#n"\": %s%s\n", bv ? "true" : \ | |
663 | "false", (c)); \ | |
664 | } else { \ | |
1a4d82fc JJ |
665 | malloc_cprintf(write_cb, cbopaque, \ |
666 | " opt."#n": %s ("#m": %s)\n", bv ? "true" \ | |
667 | : "false", bv2 ? "true" : "false"); \ | |
668 | } \ | |
3b2f2976 | 669 | } \ |
1a4d82fc | 670 | } |
3b2f2976 XL |
671 | #define OPT_WRITE_UNSIGNED(n, c) \ |
672 | if (je_mallctl("opt."#n, (void *)&uv, &usz, NULL, 0) == 0) { \ | |
673 | if (json) { \ | |
54a0048b | 674 | malloc_cprintf(write_cb, cbopaque, \ |
3b2f2976 XL |
675 | "\t\t\t\""#n"\": %u%s\n", uv, (c)); \ |
676 | } else { \ | |
677 | malloc_cprintf(write_cb, cbopaque, \ | |
678 | " opt."#n": %u\n", uv); \ | |
679 | } \ | |
680 | } | |
681 | #define OPT_WRITE_SIZE_T(n, c) \ | |
682 | if (je_mallctl("opt."#n, (void *)&sv, &ssz, NULL, 0) == 0) { \ | |
683 | if (json) { \ | |
684 | malloc_cprintf(write_cb, cbopaque, \ | |
685 | "\t\t\t\""#n"\": %zu%s\n", sv, (c)); \ | |
686 | } else { \ | |
970d7e83 LB |
687 | malloc_cprintf(write_cb, cbopaque, \ |
688 | " opt."#n": %zu\n", sv); \ | |
3b2f2976 XL |
689 | } \ |
690 | } | |
691 | #define OPT_WRITE_SSIZE_T(n, c) \ | |
692 | if (je_mallctl("opt."#n, (void *)&ssv, &sssz, NULL, 0) == 0) { \ | |
693 | if (json) { \ | |
694 | malloc_cprintf(write_cb, cbopaque, \ | |
695 | "\t\t\t\""#n"\": %zd%s\n", ssv, (c)); \ | |
696 | } else { \ | |
970d7e83 LB |
697 | malloc_cprintf(write_cb, cbopaque, \ |
698 | " opt."#n": %zd\n", ssv); \ | |
3b2f2976 XL |
699 | } \ |
700 | } | |
701 | #define OPT_WRITE_SSIZE_T_MUTABLE(n, m, c) { \ | |
702 | ssize_t ssv2; \ | |
703 | if (je_mallctl("opt."#n, (void *)&ssv, &sssz, NULL, 0) == 0 && \ | |
704 | je_mallctl(#m, (void *)&ssv2, &sssz, NULL, 0) == 0) { \ | |
705 | if (json) { \ | |
706 | malloc_cprintf(write_cb, cbopaque, \ | |
707 | "\t\t\t\""#n"\": %zd%s\n", ssv, (c)); \ | |
708 | } else { \ | |
54a0048b SL |
709 | malloc_cprintf(write_cb, cbopaque, \ |
710 | " opt."#n": %zd ("#m": %zd)\n", \ | |
711 | ssv, ssv2); \ | |
712 | } \ | |
3b2f2976 | 713 | } \ |
54a0048b | 714 | } |
3b2f2976 XL |
715 | #define OPT_WRITE_CHAR_P(n, c) \ |
716 | if (je_mallctl("opt."#n, (void *)&cpv, &cpsz, NULL, 0) == 0) { \ | |
717 | if (json) { \ | |
718 | malloc_cprintf(write_cb, cbopaque, \ | |
719 | "\t\t\t\""#n"\": \"%s\"%s\n", cpv, (c)); \ | |
720 | } else { \ | |
970d7e83 LB |
721 | malloc_cprintf(write_cb, cbopaque, \ |
722 | " opt."#n": \"%s\"\n", cpv); \ | |
3b2f2976 XL |
723 | } \ |
724 | } | |
970d7e83 | 725 | |
3b2f2976 XL |
726 | if (json) { |
727 | malloc_cprintf(write_cb, cbopaque, | |
728 | "\t\t\"opt\": {\n"); | |
729 | } else { | |
970d7e83 LB |
730 | malloc_cprintf(write_cb, cbopaque, |
731 | "Run-time option settings:\n"); | |
3b2f2976 XL |
732 | } |
733 | OPT_WRITE_BOOL(abort, ",") | |
734 | OPT_WRITE_SIZE_T(lg_chunk, ",") | |
735 | OPT_WRITE_CHAR_P(dss, ",") | |
736 | OPT_WRITE_UNSIGNED(narenas, ",") | |
737 | OPT_WRITE_CHAR_P(purge, ",") | |
738 | if (json || opt_purge == purge_mode_ratio) { | |
739 | OPT_WRITE_SSIZE_T_MUTABLE(lg_dirty_mult, | |
740 | arenas.lg_dirty_mult, ",") | |
741 | } | |
742 | if (json || opt_purge == purge_mode_decay) { | |
743 | OPT_WRITE_SSIZE_T_MUTABLE(decay_time, arenas.decay_time, ",") | |
744 | } | |
745 | OPT_WRITE_CHAR_P(junk, ",") | |
746 | OPT_WRITE_SIZE_T(quarantine, ",") | |
747 | OPT_WRITE_BOOL(redzone, ",") | |
748 | OPT_WRITE_BOOL(zero, ",") | |
749 | OPT_WRITE_BOOL(utrace, ",") | |
750 | OPT_WRITE_BOOL(xmalloc, ",") | |
751 | OPT_WRITE_BOOL(tcache, ",") | |
752 | OPT_WRITE_SSIZE_T(lg_tcache_max, ",") | |
753 | OPT_WRITE_BOOL(thp, ",") | |
754 | OPT_WRITE_BOOL(prof, ",") | |
755 | OPT_WRITE_CHAR_P(prof_prefix, ",") | |
756 | OPT_WRITE_BOOL_MUTABLE(prof_active, prof.active, ",") | |
757 | OPT_WRITE_BOOL_MUTABLE(prof_thread_active_init, prof.thread_active_init, | |
758 | ",") | |
759 | OPT_WRITE_SSIZE_T_MUTABLE(lg_prof_sample, prof.lg_sample, ",") | |
760 | OPT_WRITE_BOOL(prof_accum, ",") | |
761 | OPT_WRITE_SSIZE_T(lg_prof_interval, ",") | |
762 | OPT_WRITE_BOOL(prof_gdump, ",") | |
763 | OPT_WRITE_BOOL(prof_final, ",") | |
764 | OPT_WRITE_BOOL(prof_leak, ",") | |
765 | /* | |
766 | * stats_print is always emitted, so as long as stats_print comes last | |
767 | * it's safe to unconditionally omit the comma here (rather than having | |
768 | * to conditionally omit it elsewhere depending on configuration). | |
769 | */ | |
770 | OPT_WRITE_BOOL(stats_print, "") | |
771 | if (json) { | |
772 | malloc_cprintf(write_cb, cbopaque, | |
773 | "\t\t},\n"); | |
774 | } | |
970d7e83 LB |
775 | |
776 | #undef OPT_WRITE_BOOL | |
1a4d82fc | 777 | #undef OPT_WRITE_BOOL_MUTABLE |
970d7e83 LB |
778 | #undef OPT_WRITE_SIZE_T |
779 | #undef OPT_WRITE_SSIZE_T | |
780 | #undef OPT_WRITE_CHAR_P | |
781 | ||
3b2f2976 XL |
782 | /* arenas. */ |
783 | if (json) { | |
784 | malloc_cprintf(write_cb, cbopaque, | |
785 | "\t\t\"arenas\": {\n"); | |
786 | } | |
970d7e83 | 787 | |
3b2f2976 XL |
788 | CTL_GET("arenas.narenas", &uv, unsigned); |
789 | if (json) { | |
790 | malloc_cprintf(write_cb, cbopaque, | |
791 | "\t\t\t\"narenas\": %u,\n", uv); | |
792 | } else | |
970d7e83 LB |
793 | malloc_cprintf(write_cb, cbopaque, "Arenas: %u\n", uv); |
794 | ||
3b2f2976 XL |
795 | CTL_GET("arenas.lg_dirty_mult", &ssv, ssize_t); |
796 | if (json) { | |
797 | malloc_cprintf(write_cb, cbopaque, | |
798 | "\t\t\t\"lg_dirty_mult\": %zd,\n", ssv); | |
799 | } else if (opt_purge == purge_mode_ratio) { | |
800 | if (ssv >= 0) { | |
801 | malloc_cprintf(write_cb, cbopaque, | |
802 | "Min active:dirty page ratio per arena: " | |
803 | "%u:1\n", (1U << ssv)); | |
804 | } else { | |
805 | malloc_cprintf(write_cb, cbopaque, | |
806 | "Min active:dirty page ratio per arena: " | |
807 | "N/A\n"); | |
808 | } | |
809 | } | |
810 | CTL_GET("arenas.decay_time", &ssv, ssize_t); | |
811 | if (json) { | |
812 | malloc_cprintf(write_cb, cbopaque, | |
813 | "\t\t\t\"decay_time\": %zd,\n", ssv); | |
814 | } else if (opt_purge == purge_mode_decay) { | |
815 | malloc_cprintf(write_cb, cbopaque, | |
816 | "Unused dirty page decay time: %zd%s\n", | |
817 | ssv, (ssv < 0) ? " (no decay)" : ""); | |
818 | } | |
970d7e83 | 819 | |
3b2f2976 XL |
820 | CTL_GET("arenas.quantum", &sv, size_t); |
821 | if (json) { | |
822 | malloc_cprintf(write_cb, cbopaque, | |
823 | "\t\t\t\"quantum\": %zu,\n", sv); | |
824 | } else | |
825 | malloc_cprintf(write_cb, cbopaque, "Quantum size: %zu\n", sv); | |
970d7e83 | 826 | |
3b2f2976 XL |
827 | CTL_GET("arenas.page", &sv, size_t); |
828 | if (json) { | |
829 | malloc_cprintf(write_cb, cbopaque, | |
830 | "\t\t\t\"page\": %zu,\n", sv); | |
831 | } else | |
970d7e83 LB |
832 | malloc_cprintf(write_cb, cbopaque, "Page size: %zu\n", sv); |
833 | ||
3b2f2976 XL |
834 | if (je_mallctl("arenas.tcache_max", (void *)&sv, &ssz, NULL, 0) == 0) { |
835 | if (json) { | |
836 | malloc_cprintf(write_cb, cbopaque, | |
837 | "\t\t\t\"tcache_max\": %zu,\n", sv); | |
838 | } else { | |
839 | malloc_cprintf(write_cb, cbopaque, | |
840 | "Maximum thread-cached size class: %zu\n", sv); | |
54a0048b | 841 | } |
3b2f2976 XL |
842 | } |
843 | ||
844 | if (json) { | |
845 | unsigned nbins, nlruns, nhchunks, i; | |
846 | ||
847 | CTL_GET("arenas.nbins", &nbins, unsigned); | |
848 | malloc_cprintf(write_cb, cbopaque, | |
849 | "\t\t\t\"nbins\": %u,\n", nbins); | |
850 | ||
851 | if (config_tcache) { | |
852 | CTL_GET("arenas.nhbins", &uv, unsigned); | |
970d7e83 | 853 | malloc_cprintf(write_cb, cbopaque, |
3b2f2976 | 854 | "\t\t\t\"nhbins\": %u,\n", uv); |
970d7e83 | 855 | } |
3b2f2976 XL |
856 | |
857 | malloc_cprintf(write_cb, cbopaque, | |
858 | "\t\t\t\"bin\": [\n"); | |
859 | for (i = 0; i < nbins; i++) { | |
970d7e83 | 860 | malloc_cprintf(write_cb, cbopaque, |
3b2f2976 XL |
861 | "\t\t\t\t{\n"); |
862 | ||
863 | CTL_M2_GET("arenas.bin.0.size", i, &sv, size_t); | |
864 | malloc_cprintf(write_cb, cbopaque, | |
865 | "\t\t\t\t\t\"size\": %zu,\n", sv); | |
866 | ||
867 | CTL_M2_GET("arenas.bin.0.nregs", i, &u32v, uint32_t); | |
868 | malloc_cprintf(write_cb, cbopaque, | |
869 | "\t\t\t\t\t\"nregs\": %"FMTu32",\n", u32v); | |
870 | ||
871 | CTL_M2_GET("arenas.bin.0.run_size", i, &sv, size_t); | |
872 | malloc_cprintf(write_cb, cbopaque, | |
873 | "\t\t\t\t\t\"run_size\": %zu\n", sv); | |
874 | ||
875 | malloc_cprintf(write_cb, cbopaque, | |
876 | "\t\t\t\t}%s\n", (i + 1 < nbins) ? "," : ""); | |
970d7e83 | 877 | } |
3b2f2976 XL |
878 | malloc_cprintf(write_cb, cbopaque, |
879 | "\t\t\t],\n"); | |
880 | ||
881 | CTL_GET("arenas.nlruns", &nlruns, unsigned); | |
882 | malloc_cprintf(write_cb, cbopaque, | |
883 | "\t\t\t\"nlruns\": %u,\n", nlruns); | |
884 | ||
885 | malloc_cprintf(write_cb, cbopaque, | |
886 | "\t\t\t\"lrun\": [\n"); | |
887 | for (i = 0; i < nlruns; i++) { | |
970d7e83 | 888 | malloc_cprintf(write_cb, cbopaque, |
3b2f2976 | 889 | "\t\t\t\t{\n"); |
970d7e83 | 890 | |
3b2f2976 XL |
891 | CTL_M2_GET("arenas.lrun.0.size", i, &sv, size_t); |
892 | malloc_cprintf(write_cb, cbopaque, | |
893 | "\t\t\t\t\t\"size\": %zu\n", sv); | |
894 | ||
895 | malloc_cprintf(write_cb, cbopaque, | |
896 | "\t\t\t\t}%s\n", (i + 1 < nlruns) ? "," : ""); | |
897 | } | |
898 | malloc_cprintf(write_cb, cbopaque, | |
899 | "\t\t\t],\n"); | |
900 | ||
901 | CTL_GET("arenas.nhchunks", &nhchunks, unsigned); | |
902 | malloc_cprintf(write_cb, cbopaque, | |
903 | "\t\t\t\"nhchunks\": %u,\n", nhchunks); | |
904 | ||
905 | malloc_cprintf(write_cb, cbopaque, | |
906 | "\t\t\t\"hchunk\": [\n"); | |
907 | for (i = 0; i < nhchunks; i++) { | |
908 | malloc_cprintf(write_cb, cbopaque, | |
909 | "\t\t\t\t{\n"); | |
910 | ||
911 | CTL_M2_GET("arenas.hchunk.0.size", i, &sv, size_t); | |
912 | malloc_cprintf(write_cb, cbopaque, | |
913 | "\t\t\t\t\t\"size\": %zu\n", sv); | |
914 | ||
915 | malloc_cprintf(write_cb, cbopaque, | |
916 | "\t\t\t\t}%s\n", (i + 1 < nhchunks) ? "," : ""); | |
970d7e83 | 917 | } |
54a0048b | 918 | malloc_cprintf(write_cb, cbopaque, |
3b2f2976 XL |
919 | "\t\t\t]\n"); |
920 | ||
921 | malloc_cprintf(write_cb, cbopaque, | |
922 | "\t\t}%s\n", (config_prof || more) ? "," : ""); | |
970d7e83 LB |
923 | } |
924 | ||
3b2f2976 XL |
925 | /* prof. */ |
926 | if (config_prof && json) { | |
927 | malloc_cprintf(write_cb, cbopaque, | |
928 | "\t\t\"prof\": {\n"); | |
929 | ||
930 | CTL_GET("prof.thread_active_init", &bv, bool); | |
931 | malloc_cprintf(write_cb, cbopaque, | |
932 | "\t\t\t\"thread_active_init\": %s,\n", bv ? "true" : | |
933 | "false"); | |
934 | ||
935 | CTL_GET("prof.active", &bv, bool); | |
936 | malloc_cprintf(write_cb, cbopaque, | |
937 | "\t\t\t\"active\": %s,\n", bv ? "true" : "false"); | |
938 | ||
939 | CTL_GET("prof.gdump", &bv, bool); | |
940 | malloc_cprintf(write_cb, cbopaque, | |
941 | "\t\t\t\"gdump\": %s,\n", bv ? "true" : "false"); | |
942 | ||
943 | CTL_GET("prof.interval", &u64v, uint64_t); | |
944 | malloc_cprintf(write_cb, cbopaque, | |
945 | "\t\t\t\"interval\": %"FMTu64",\n", u64v); | |
970d7e83 | 946 | |
3b2f2976 XL |
947 | CTL_GET("prof.lg_sample", &ssv, ssize_t); |
948 | malloc_cprintf(write_cb, cbopaque, | |
949 | "\t\t\t\"lg_sample\": %zd\n", ssv); | |
950 | ||
951 | malloc_cprintf(write_cb, cbopaque, | |
952 | "\t\t}%s\n", more ? "," : ""); | |
953 | } | |
954 | } | |
955 | ||
956 | static void | |
957 | stats_print_helper(void (*write_cb)(void *, const char *), void *cbopaque, | |
958 | bool json, bool merged, bool unmerged, bool bins, bool large, bool huge) | |
959 | { | |
960 | size_t *cactive; | |
961 | size_t allocated, active, metadata, resident, mapped, retained; | |
962 | ||
963 | CTL_GET("stats.cactive", &cactive, size_t *); | |
964 | CTL_GET("stats.allocated", &allocated, size_t); | |
965 | CTL_GET("stats.active", &active, size_t); | |
966 | CTL_GET("stats.metadata", &metadata, size_t); | |
967 | CTL_GET("stats.resident", &resident, size_t); | |
968 | CTL_GET("stats.mapped", &mapped, size_t); | |
969 | CTL_GET("stats.retained", &retained, size_t); | |
970 | if (json) { | |
971 | malloc_cprintf(write_cb, cbopaque, | |
972 | "\t\t\"stats\": {\n"); | |
973 | ||
974 | malloc_cprintf(write_cb, cbopaque, | |
975 | "\t\t\t\"cactive\": %zu,\n", atomic_read_z(cactive)); | |
976 | malloc_cprintf(write_cb, cbopaque, | |
977 | "\t\t\t\"allocated\": %zu,\n", allocated); | |
978 | malloc_cprintf(write_cb, cbopaque, | |
979 | "\t\t\t\"active\": %zu,\n", active); | |
980 | malloc_cprintf(write_cb, cbopaque, | |
981 | "\t\t\t\"metadata\": %zu,\n", metadata); | |
982 | malloc_cprintf(write_cb, cbopaque, | |
983 | "\t\t\t\"resident\": %zu,\n", resident); | |
984 | malloc_cprintf(write_cb, cbopaque, | |
985 | "\t\t\t\"mapped\": %zu,\n", mapped); | |
986 | malloc_cprintf(write_cb, cbopaque, | |
987 | "\t\t\t\"retained\": %zu\n", retained); | |
988 | ||
989 | malloc_cprintf(write_cb, cbopaque, | |
990 | "\t\t}%s\n", (merged || unmerged) ? "," : ""); | |
991 | } else { | |
970d7e83 | 992 | malloc_cprintf(write_cb, cbopaque, |
54a0048b | 993 | "Allocated: %zu, active: %zu, metadata: %zu," |
3b2f2976 XL |
994 | " resident: %zu, mapped: %zu, retained: %zu\n", |
995 | allocated, active, metadata, resident, mapped, retained); | |
970d7e83 | 996 | malloc_cprintf(write_cb, cbopaque, |
54a0048b SL |
997 | "Current active ceiling: %zu\n", |
998 | atomic_read_z(cactive)); | |
3b2f2976 | 999 | } |
970d7e83 | 1000 | |
3b2f2976 XL |
1001 | if (merged || unmerged) { |
1002 | unsigned narenas; | |
1003 | ||
1004 | if (json) { | |
1005 | malloc_cprintf(write_cb, cbopaque, | |
1006 | "\t\t\"stats.arenas\": {\n"); | |
1007 | } | |
1008 | ||
1009 | CTL_GET("arenas.narenas", &narenas, unsigned); | |
1010 | { | |
1011 | VARIABLE_ARRAY(bool, initialized, narenas); | |
1012 | size_t isz; | |
1013 | unsigned i, j, ninitialized; | |
1014 | ||
1015 | isz = sizeof(bool) * narenas; | |
1016 | xmallctl("arenas.initialized", (void *)initialized, | |
1017 | &isz, NULL, 0); | |
1018 | for (i = ninitialized = 0; i < narenas; i++) { | |
1019 | if (initialized[i]) | |
1020 | ninitialized++; | |
1021 | } | |
970d7e83 | 1022 | |
3b2f2976 XL |
1023 | /* Merged stats. */ |
1024 | if (merged && (ninitialized > 1 || !unmerged)) { | |
1025 | /* Print merged arena stats. */ | |
1026 | if (json) { | |
1027 | malloc_cprintf(write_cb, cbopaque, | |
1028 | "\t\t\t\"merged\": {\n"); | |
1029 | } else { | |
970d7e83 LB |
1030 | malloc_cprintf(write_cb, cbopaque, |
1031 | "\nMerged arenas stats:\n"); | |
3b2f2976 XL |
1032 | } |
1033 | stats_arena_print(write_cb, cbopaque, json, | |
1034 | narenas, bins, large, huge); | |
1035 | if (json) { | |
1036 | malloc_cprintf(write_cb, cbopaque, | |
1037 | "\t\t\t}%s\n", unmerged ? "," : | |
1038 | ""); | |
1039 | } | |
1040 | } | |
1041 | ||
1042 | /* Unmerged stats. */ | |
1043 | if (unmerged) { | |
1044 | for (i = j = 0; i < narenas; i++) { | |
1045 | if (initialized[i]) { | |
1046 | if (json) { | |
1047 | j++; | |
1048 | malloc_cprintf(write_cb, | |
1049 | cbopaque, | |
1050 | "\t\t\t\"%u\": {\n", | |
1051 | i); | |
1052 | } else { | |
1053 | malloc_cprintf(write_cb, | |
1054 | cbopaque, | |
1055 | "\narenas[%u]:\n", | |
1056 | i); | |
1057 | } | |
1058 | stats_arena_print(write_cb, | |
1059 | cbopaque, json, i, bins, | |
1060 | large, huge); | |
1061 | if (json) { | |
1062 | malloc_cprintf(write_cb, | |
1063 | cbopaque, | |
1064 | "\t\t\t}%s\n", (j < | |
1065 | ninitialized) ? "," | |
1066 | : ""); | |
1067 | } | |
1068 | } | |
970d7e83 LB |
1069 | } |
1070 | } | |
1071 | } | |
1072 | ||
3b2f2976 XL |
1073 | if (json) { |
1074 | malloc_cprintf(write_cb, cbopaque, | |
1075 | "\t\t}\n"); | |
1076 | } | |
1077 | } | |
1078 | } | |
970d7e83 | 1079 | |
3b2f2976 XL |
1080 | void |
1081 | stats_print(void (*write_cb)(void *, const char *), void *cbopaque, | |
1082 | const char *opts) | |
1083 | { | |
1084 | int err; | |
1085 | uint64_t epoch; | |
1086 | size_t u64sz; | |
1087 | bool json = false; | |
1088 | bool general = true; | |
1089 | bool merged = config_stats; | |
1090 | bool unmerged = config_stats; | |
1091 | bool bins = true; | |
1092 | bool large = true; | |
1093 | bool huge = true; | |
970d7e83 | 1094 | |
3b2f2976 XL |
1095 | /* |
1096 | * Refresh stats, in case mallctl() was called by the application. | |
1097 | * | |
1098 | * Check for OOM here, since refreshing the ctl cache can trigger | |
1099 | * allocation. In practice, none of the subsequent mallctl()-related | |
1100 | * calls in this function will cause OOM if this one succeeds. | |
1101 | * */ | |
1102 | epoch = 1; | |
1103 | u64sz = sizeof(uint64_t); | |
1104 | err = je_mallctl("epoch", (void *)&epoch, &u64sz, (void *)&epoch, | |
1105 | sizeof(uint64_t)); | |
1106 | if (err != 0) { | |
1107 | if (err == EAGAIN) { | |
1108 | malloc_write("<jemalloc>: Memory allocation failure in " | |
1109 | "mallctl(\"epoch\", ...)\n"); | |
1110 | return; | |
1111 | } | |
1112 | malloc_write("<jemalloc>: Failure in mallctl(\"epoch\", " | |
1113 | "...)\n"); | |
1114 | abort(); | |
1115 | } | |
970d7e83 | 1116 | |
3b2f2976 XL |
1117 | if (opts != NULL) { |
1118 | unsigned i; | |
970d7e83 | 1119 | |
3b2f2976 XL |
1120 | for (i = 0; opts[i] != '\0'; i++) { |
1121 | switch (opts[i]) { | |
1122 | case 'J': | |
1123 | json = true; | |
1124 | break; | |
1125 | case 'g': | |
1126 | general = false; | |
1127 | break; | |
1128 | case 'm': | |
1129 | merged = false; | |
1130 | break; | |
1131 | case 'a': | |
1132 | unmerged = false; | |
1133 | break; | |
1134 | case 'b': | |
1135 | bins = false; | |
1136 | break; | |
1137 | case 'l': | |
1138 | large = false; | |
1139 | break; | |
1140 | case 'h': | |
1141 | huge = false; | |
1142 | break; | |
1143 | default:; | |
970d7e83 LB |
1144 | } |
1145 | } | |
1146 | } | |
3b2f2976 XL |
1147 | |
1148 | if (json) { | |
1149 | malloc_cprintf(write_cb, cbopaque, | |
1150 | "{\n" | |
1151 | "\t\"jemalloc\": {\n"); | |
1152 | } else { | |
1153 | malloc_cprintf(write_cb, cbopaque, | |
1154 | "___ Begin jemalloc statistics ___\n"); | |
1155 | } | |
1156 | ||
1157 | if (general) { | |
1158 | bool more = (merged || unmerged); | |
1159 | stats_general_print(write_cb, cbopaque, json, more); | |
1160 | } | |
1161 | if (config_stats) { | |
1162 | stats_print_helper(write_cb, cbopaque, json, merged, unmerged, | |
1163 | bins, large, huge); | |
1164 | } | |
1165 | if (json) { | |
1166 | malloc_cprintf(write_cb, cbopaque, | |
1167 | "\t}\n" | |
1168 | "}\n"); | |
1169 | } else { | |
1170 | malloc_cprintf(write_cb, cbopaque, | |
1171 | "--- End jemalloc statistics ---\n"); | |
1172 | } | |
970d7e83 | 1173 | } |