xref: /aosp_15_r20/external/jemalloc_new/test/unit/stats.c (revision 1208bc7e437ced7eb82efac44ba17e3beba411da)
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 	test_skip_if(known_failure_on_android);
230 	void *p;
231 	size_t sz, curslabs, curregs;
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 
293 	if (config_stats) {
294 		assert_u64_gt(nmalloc, 0,
295 		    "nmalloc should be greater than zero");
296 		assert_u64_ge(nmalloc, ndalloc,
297 		    "nmalloc should be at least as large as ndalloc");
298 		assert_u64_gt(nrequests, 0,
299 		    "nrequests should be greater than zero");
300 		assert_zu_gt(curregs, 0,
301 		    "allocated should be greater than zero");
302 		if (opt_tcache) {
303 			assert_u64_gt(nfills, 0,
304 			    "At least one fill should have occurred");
305 			assert_u64_gt(nflushes, 0,
306 			    "At least one flush should have occurred");
307 		}
308 		assert_u64_gt(nslabs, 0,
309 		    "At least one slab should have been allocated");
310 		assert_zu_gt(curslabs, 0,
311 		    "At least one slab should be currently allocated");
312 	}
313 
314 	dallocx(p, 0);
315 }
316 TEST_END
317 
TEST_BEGIN(test_stats_arenas_lextents)318 TEST_BEGIN(test_stats_arenas_lextents) {
319 	void *p;
320 	uint64_t epoch, nmalloc, ndalloc;
321 	size_t curlextents, sz, hsize;
322 	int expected = config_stats ? 0 : ENOENT;
323 
324 	sz = sizeof(size_t);
325 	assert_d_eq(mallctl("arenas.lextent.0.size", (void *)&hsize, &sz, NULL,
326 	    0), 0, "Unexpected mallctl() failure");
327 
328 	p = mallocx(hsize, MALLOCX_ARENA(0));
329 	assert_ptr_not_null(p, "Unexpected mallocx() failure");
330 
331 	assert_d_eq(mallctl("epoch", NULL, NULL, (void *)&epoch, sizeof(epoch)),
332 	    0, "Unexpected mallctl() failure");
333 
334 	sz = sizeof(uint64_t);
335 	assert_d_eq(mallctl("stats.arenas.0.lextents.0.nmalloc",
336 	    (void *)&nmalloc, &sz, NULL, 0), expected,
337 	    "Unexpected mallctl() result");
338 	assert_d_eq(mallctl("stats.arenas.0.lextents.0.ndalloc",
339 	    (void *)&ndalloc, &sz, NULL, 0), expected,
340 	    "Unexpected mallctl() result");
341 	sz = sizeof(size_t);
342 	assert_d_eq(mallctl("stats.arenas.0.lextents.0.curlextents",
343 	    (void *)&curlextents, &sz, NULL, 0), expected,
344 	    "Unexpected mallctl() result");
345 
346 	if (config_stats) {
347 		assert_u64_gt(nmalloc, 0,
348 		    "nmalloc should be greater than zero");
349 		assert_u64_ge(nmalloc, ndalloc,
350 		    "nmalloc should be at least as large as ndalloc");
351 		assert_u64_gt(curlextents, 0,
352 		    "At least one extent should be currently allocated");
353 	}
354 
355 	dallocx(p, 0);
356 }
357 TEST_END
358 
359 int
main(void)360 main(void) {
361 	return test_no_reentrancy(
362 	    test_stats_summary,
363 	    test_stats_large,
364 	    test_stats_arenas_summary,
365 	    test_stats_arenas_small,
366 	    test_stats_arenas_large,
367 	    test_stats_arenas_bins,
368 	    test_stats_arenas_lextents);
369 }
370