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