1 #include "test/jemalloc_test.h"
2
TEST_BEGIN(test_stats_summary)3 TEST_BEGIN(test_stats_summary) {
4 size_t sz, allocated, active, resident, mapped;
5 int expected = config_stats ? 0 : ENOENT;
6
7 sz = sizeof(size_t);
8 assert_d_eq(mallctl("stats.allocated", (void *)&allocated, &sz, NULL,
9 0), expected, "Unexpected mallctl() result");
10 assert_d_eq(mallctl("stats.active", (void *)&active, &sz, NULL, 0),
11 expected, "Unexpected mallctl() result");
12 assert_d_eq(mallctl("stats.resident", (void *)&resident, &sz, NULL, 0),
13 expected, "Unexpected mallctl() result");
14 assert_d_eq(mallctl("stats.mapped", (void *)&mapped, &sz, NULL, 0),
15 expected, "Unexpected mallctl() result");
16
17 if (config_stats) {
18 assert_zu_le(allocated, active,
19 "allocated should be no larger than active");
20 assert_zu_lt(active, resident,
21 "active should be less than resident");
22 assert_zu_lt(active, mapped,
23 "active should be less than mapped");
24 }
25 }
26 TEST_END
27
TEST_BEGIN(test_stats_large)28 TEST_BEGIN(test_stats_large) {
29 void *p;
30 uint64_t epoch;
31 size_t allocated;
32 uint64_t nmalloc, ndalloc, nrequests;
33 size_t sz;
34 int expected = config_stats ? 0 : ENOENT;
35
36 p = mallocx(SC_SMALL_MAXCLASS + 1, MALLOCX_ARENA(0));
37 assert_ptr_not_null(p, "Unexpected mallocx() failure");
38
39 assert_d_eq(mallctl("epoch", NULL, NULL, (void *)&epoch, sizeof(epoch)),
40 0, "Unexpected mallctl() failure");
41
42 sz = sizeof(size_t);
43 assert_d_eq(mallctl("stats.arenas.0.large.allocated",
44 (void *)&allocated, &sz, NULL, 0), expected,
45 "Unexpected mallctl() result");
46 sz = sizeof(uint64_t);
47 assert_d_eq(mallctl("stats.arenas.0.large.nmalloc", (void *)&nmalloc,
48 &sz, NULL, 0), expected, "Unexpected mallctl() result");
49 assert_d_eq(mallctl("stats.arenas.0.large.ndalloc", (void *)&ndalloc,
50 &sz, NULL, 0), expected, "Unexpected mallctl() result");
51 assert_d_eq(mallctl("stats.arenas.0.large.nrequests",
52 (void *)&nrequests, &sz, NULL, 0), expected,
53 "Unexpected mallctl() result");
54
55 if (config_stats) {
56 assert_zu_gt(allocated, 0,
57 "allocated should be greater than zero");
58 assert_u64_ge(nmalloc, ndalloc,
59 "nmalloc should be at least as large as ndalloc");
60 assert_u64_le(nmalloc, nrequests,
61 "nmalloc should no larger than nrequests");
62 }
63
64 dallocx(p, 0);
65 }
66 TEST_END
67
TEST_BEGIN(test_stats_arenas_summary)68 TEST_BEGIN(test_stats_arenas_summary) {
69 void *little, *large;
70 uint64_t epoch;
71 size_t sz;
72 int expected = config_stats ? 0 : ENOENT;
73 size_t mapped;
74 uint64_t dirty_npurge, dirty_nmadvise, dirty_purged;
75 uint64_t muzzy_npurge, muzzy_nmadvise, muzzy_purged;
76
77 little = mallocx(SC_SMALL_MAXCLASS, MALLOCX_ARENA(0));
78 assert_ptr_not_null(little, "Unexpected mallocx() failure");
79 large = mallocx((1U << SC_LG_LARGE_MINCLASS),
80 MALLOCX_ARENA(0));
81 assert_ptr_not_null(large, "Unexpected mallocx() failure");
82
83 dallocx(little, 0);
84 dallocx(large, 0);
85
86 assert_d_eq(mallctl("thread.tcache.flush", NULL, NULL, NULL, 0),
87 opt_tcache ? 0 : EFAULT, "Unexpected mallctl() result");
88 assert_d_eq(mallctl("arena.0.purge", NULL, NULL, NULL, 0), 0,
89 "Unexpected mallctl() failure");
90
91 assert_d_eq(mallctl("epoch", NULL, NULL, (void *)&epoch, sizeof(epoch)),
92 0, "Unexpected mallctl() failure");
93
94 sz = sizeof(size_t);
95 assert_d_eq(mallctl("stats.arenas.0.mapped", (void *)&mapped, &sz, NULL,
96 0), expected, "Unexepected mallctl() result");
97
98 sz = sizeof(uint64_t);
99 assert_d_eq(mallctl("stats.arenas.0.dirty_npurge",
100 (void *)&dirty_npurge, &sz, NULL, 0), expected,
101 "Unexepected mallctl() result");
102 assert_d_eq(mallctl("stats.arenas.0.dirty_nmadvise",
103 (void *)&dirty_nmadvise, &sz, NULL, 0), expected,
104 "Unexepected mallctl() result");
105 assert_d_eq(mallctl("stats.arenas.0.dirty_purged",
106 (void *)&dirty_purged, &sz, NULL, 0), expected,
107 "Unexepected mallctl() result");
108 assert_d_eq(mallctl("stats.arenas.0.muzzy_npurge",
109 (void *)&muzzy_npurge, &sz, NULL, 0), expected,
110 "Unexepected mallctl() result");
111 assert_d_eq(mallctl("stats.arenas.0.muzzy_nmadvise",
112 (void *)&muzzy_nmadvise, &sz, NULL, 0), expected,
113 "Unexepected mallctl() result");
114 assert_d_eq(mallctl("stats.arenas.0.muzzy_purged",
115 (void *)&muzzy_purged, &sz, NULL, 0), expected,
116 "Unexepected mallctl() result");
117
118 if (config_stats) {
119 if (!background_thread_enabled()) {
120 assert_u64_gt(dirty_npurge + muzzy_npurge, 0,
121 "At least one purge should have occurred");
122 }
123 assert_u64_le(dirty_nmadvise, dirty_purged,
124 "dirty_nmadvise should be no greater than dirty_purged");
125 assert_u64_le(muzzy_nmadvise, muzzy_purged,
126 "muzzy_nmadvise should be no greater than muzzy_purged");
127 }
128 }
129 TEST_END
130
131 void *
thd_start(void * arg)132 thd_start(void *arg) {
133 return NULL;
134 }
135
136 static void
no_lazy_lock(void)137 no_lazy_lock(void) {
138 thd_t thd;
139
140 thd_create(&thd, thd_start, NULL);
141 thd_join(thd, NULL);
142 }
143
TEST_BEGIN(test_stats_arenas_small)144 TEST_BEGIN(test_stats_arenas_small) {
145 void *p;
146 size_t sz, allocated;
147 uint64_t epoch, nmalloc, ndalloc, nrequests;
148 int expected = config_stats ? 0 : ENOENT;
149
150 no_lazy_lock(); /* Lazy locking would dodge tcache testing. */
151
152 p = mallocx(SC_SMALL_MAXCLASS, MALLOCX_ARENA(0));
153 assert_ptr_not_null(p, "Unexpected mallocx() failure");
154
155 assert_d_eq(mallctl("thread.tcache.flush", NULL, NULL, NULL, 0),
156 opt_tcache ? 0 : EFAULT, "Unexpected mallctl() result");
157
158 assert_d_eq(mallctl("epoch", NULL, NULL, (void *)&epoch, sizeof(epoch)),
159 0, "Unexpected mallctl() failure");
160
161 sz = sizeof(size_t);
162 assert_d_eq(mallctl("stats.arenas.0.small.allocated",
163 (void *)&allocated, &sz, NULL, 0), expected,
164 "Unexpected mallctl() result");
165 sz = sizeof(uint64_t);
166 assert_d_eq(mallctl("stats.arenas.0.small.nmalloc", (void *)&nmalloc,
167 &sz, NULL, 0), expected, "Unexpected mallctl() result");
168 assert_d_eq(mallctl("stats.arenas.0.small.ndalloc", (void *)&ndalloc,
169 &sz, NULL, 0), expected, "Unexpected mallctl() result");
170 assert_d_eq(mallctl("stats.arenas.0.small.nrequests",
171 (void *)&nrequests, &sz, NULL, 0), expected,
172 "Unexpected mallctl() result");
173
174 if (config_stats) {
175 assert_zu_gt(allocated, 0,
176 "allocated should be greater than zero");
177 assert_u64_gt(nmalloc, 0,
178 "nmalloc should be no greater than zero");
179 assert_u64_ge(nmalloc, ndalloc,
180 "nmalloc should be at least as large as ndalloc");
181 assert_u64_gt(nrequests, 0,
182 "nrequests should be greater than zero");
183 }
184
185 dallocx(p, 0);
186 }
187 TEST_END
188
TEST_BEGIN(test_stats_arenas_large)189 TEST_BEGIN(test_stats_arenas_large) {
190 void *p;
191 size_t sz, allocated;
192 uint64_t epoch, nmalloc, ndalloc;
193 int expected = config_stats ? 0 : ENOENT;
194
195 p = mallocx((1U << SC_LG_LARGE_MINCLASS), MALLOCX_ARENA(0));
196 assert_ptr_not_null(p, "Unexpected mallocx() failure");
197
198 assert_d_eq(mallctl("epoch", NULL, NULL, (void *)&epoch, sizeof(epoch)),
199 0, "Unexpected mallctl() failure");
200
201 sz = sizeof(size_t);
202 assert_d_eq(mallctl("stats.arenas.0.large.allocated",
203 (void *)&allocated, &sz, NULL, 0), expected,
204 "Unexpected mallctl() result");
205 sz = sizeof(uint64_t);
206 assert_d_eq(mallctl("stats.arenas.0.large.nmalloc", (void *)&nmalloc,
207 &sz, NULL, 0), expected, "Unexpected mallctl() result");
208 assert_d_eq(mallctl("stats.arenas.0.large.ndalloc", (void *)&ndalloc,
209 &sz, NULL, 0), expected, "Unexpected mallctl() result");
210
211 if (config_stats) {
212 assert_zu_gt(allocated, 0,
213 "allocated should be greater than zero");
214 assert_u64_gt(nmalloc, 0,
215 "nmalloc should be greater than zero");
216 assert_u64_ge(nmalloc, ndalloc,
217 "nmalloc should be at least as large as ndalloc");
218 }
219
220 dallocx(p, 0);
221 }
222 TEST_END
223
224 static void
gen_mallctl_str(char * cmd,char * name,unsigned arena_ind)225 gen_mallctl_str(char *cmd, char *name, unsigned arena_ind) {
226 sprintf(cmd, "stats.arenas.%u.bins.0.%s", arena_ind, name);
227 }
228
TEST_BEGIN(test_stats_arenas_bins)229 TEST_BEGIN(test_stats_arenas_bins) {
230 void *p;
231 size_t sz, curslabs, curregs, nonfull_slabs;
232 uint64_t epoch, nmalloc, ndalloc, nrequests, nfills, nflushes;
233 uint64_t nslabs, nreslabs;
234 int expected = config_stats ? 0 : ENOENT;
235
236 /* Make sure allocation below isn't satisfied by tcache. */
237 assert_d_eq(mallctl("thread.tcache.flush", NULL, NULL, NULL, 0),
238 opt_tcache ? 0 : EFAULT, "Unexpected mallctl() result");
239
240 unsigned arena_ind, old_arena_ind;
241 sz = sizeof(unsigned);
242 assert_d_eq(mallctl("arenas.create", (void *)&arena_ind, &sz, NULL, 0),
243 0, "Arena creation failure");
244 sz = sizeof(arena_ind);
245 assert_d_eq(mallctl("thread.arena", (void *)&old_arena_ind, &sz,
246 (void *)&arena_ind, sizeof(arena_ind)), 0,
247 "Unexpected mallctl() failure");
248
249 p = malloc(bin_infos[0].reg_size);
250 assert_ptr_not_null(p, "Unexpected malloc() failure");
251
252 assert_d_eq(mallctl("thread.tcache.flush", NULL, NULL, NULL, 0),
253 opt_tcache ? 0 : EFAULT, "Unexpected mallctl() result");
254
255 assert_d_eq(mallctl("epoch", NULL, NULL, (void *)&epoch, sizeof(epoch)),
256 0, "Unexpected mallctl() failure");
257
258 char cmd[128];
259 sz = sizeof(uint64_t);
260 gen_mallctl_str(cmd, "nmalloc", arena_ind);
261 assert_d_eq(mallctl(cmd, (void *)&nmalloc, &sz, NULL, 0), expected,
262 "Unexpected mallctl() result");
263 gen_mallctl_str(cmd, "ndalloc", arena_ind);
264 assert_d_eq(mallctl(cmd, (void *)&ndalloc, &sz, NULL, 0), expected,
265 "Unexpected mallctl() result");
266 gen_mallctl_str(cmd, "nrequests", arena_ind);
267 assert_d_eq(mallctl(cmd, (void *)&nrequests, &sz, NULL, 0), expected,
268 "Unexpected mallctl() result");
269 sz = sizeof(size_t);
270 gen_mallctl_str(cmd, "curregs", arena_ind);
271 assert_d_eq(mallctl(cmd, (void *)&curregs, &sz, NULL, 0), expected,
272 "Unexpected mallctl() result");
273
274 sz = sizeof(uint64_t);
275 gen_mallctl_str(cmd, "nfills", arena_ind);
276 assert_d_eq(mallctl(cmd, (void *)&nfills, &sz, NULL, 0), expected,
277 "Unexpected mallctl() result");
278 gen_mallctl_str(cmd, "nflushes", arena_ind);
279 assert_d_eq(mallctl(cmd, (void *)&nflushes, &sz, NULL, 0), expected,
280 "Unexpected mallctl() result");
281
282 gen_mallctl_str(cmd, "nslabs", arena_ind);
283 assert_d_eq(mallctl(cmd, (void *)&nslabs, &sz, NULL, 0), expected,
284 "Unexpected mallctl() result");
285 gen_mallctl_str(cmd, "nreslabs", arena_ind);
286 assert_d_eq(mallctl(cmd, (void *)&nreslabs, &sz, NULL, 0), expected,
287 "Unexpected mallctl() result");
288 sz = sizeof(size_t);
289 gen_mallctl_str(cmd, "curslabs", arena_ind);
290 assert_d_eq(mallctl(cmd, (void *)&curslabs, &sz, NULL, 0), expected,
291 "Unexpected mallctl() result");
292 gen_mallctl_str(cmd, "nonfull_slabs", arena_ind);
293 assert_d_eq(mallctl(cmd, (void *)&nonfull_slabs, &sz, NULL, 0),
294 expected, "Unexpected mallctl() result");
295
296 if (config_stats) {
297 assert_u64_gt(nmalloc, 0,
298 "nmalloc should be greater than zero");
299 assert_u64_ge(nmalloc, ndalloc,
300 "nmalloc should be at least as large as ndalloc");
301 assert_u64_gt(nrequests, 0,
302 "nrequests should be greater than zero");
303 assert_zu_gt(curregs, 0,
304 "allocated should be greater than zero");
305 if (opt_tcache) {
306 assert_u64_gt(nfills, 0,
307 "At least one fill should have occurred");
308 assert_u64_gt(nflushes, 0,
309 "At least one flush should have occurred");
310 }
311 assert_u64_gt(nslabs, 0,
312 "At least one slab should have been allocated");
313 assert_zu_gt(curslabs, 0,
314 "At least one slab should be currently allocated");
315 assert_zu_eq(nonfull_slabs, 0,
316 "slabs_nonfull should be empty");
317 }
318
319 dallocx(p, 0);
320 }
321 TEST_END
322
TEST_BEGIN(test_stats_arenas_lextents)323 TEST_BEGIN(test_stats_arenas_lextents) {
324 void *p;
325 uint64_t epoch, nmalloc, ndalloc;
326 size_t curlextents, sz, hsize;
327 int expected = config_stats ? 0 : ENOENT;
328
329 sz = sizeof(size_t);
330 assert_d_eq(mallctl("arenas.lextent.0.size", (void *)&hsize, &sz, NULL,
331 0), 0, "Unexpected mallctl() failure");
332
333 p = mallocx(hsize, MALLOCX_ARENA(0));
334 assert_ptr_not_null(p, "Unexpected mallocx() failure");
335
336 assert_d_eq(mallctl("epoch", NULL, NULL, (void *)&epoch, sizeof(epoch)),
337 0, "Unexpected mallctl() failure");
338
339 sz = sizeof(uint64_t);
340 assert_d_eq(mallctl("stats.arenas.0.lextents.0.nmalloc",
341 (void *)&nmalloc, &sz, NULL, 0), expected,
342 "Unexpected mallctl() result");
343 assert_d_eq(mallctl("stats.arenas.0.lextents.0.ndalloc",
344 (void *)&ndalloc, &sz, NULL, 0), expected,
345 "Unexpected mallctl() result");
346 sz = sizeof(size_t);
347 assert_d_eq(mallctl("stats.arenas.0.lextents.0.curlextents",
348 (void *)&curlextents, &sz, NULL, 0), expected,
349 "Unexpected mallctl() result");
350
351 if (config_stats) {
352 assert_u64_gt(nmalloc, 0,
353 "nmalloc should be greater than zero");
354 assert_u64_ge(nmalloc, ndalloc,
355 "nmalloc should be at least as large as ndalloc");
356 assert_u64_gt(curlextents, 0,
357 "At least one extent should be currently allocated");
358 }
359
360 dallocx(p, 0);
361 }
362 TEST_END
363
364 int
main(void)365 main(void) {
366 return test_no_reentrancy(
367 test_stats_summary,
368 test_stats_large,
369 test_stats_arenas_summary,
370 test_stats_arenas_small,
371 test_stats_arenas_large,
372 test_stats_arenas_bins,
373 test_stats_arenas_lextents);
374 }
375