]>
git.proxmox.com Git - rustc.git/blob - src/jemalloc/test/unit/decay.c
1 #include "test/jemalloc_test.h"
3 static nstime_monotonic_t
*nstime_monotonic_orig
;
4 static nstime_update_t
*nstime_update_orig
;
6 static unsigned nupdates_mock
;
7 static nstime_t time_mock
;
8 static bool monotonic_mock
;
11 nstime_monotonic_mock(void)
14 return (monotonic_mock
);
18 nstime_update_mock(nstime_t
*time
)
23 nstime_copy(time
, &time_mock
);
24 return (!monotonic_mock
);
27 TEST_BEGIN(test_decay_ticks
)
29 ticker_t
*decay_ticker
;
30 unsigned tick0
, tick1
;
31 size_t sz
, huge0
, large0
;
34 test_skip_if(opt_purge
!= purge_mode_decay
);
36 decay_ticker
= decay_ticker_get(tsd_fetch(), 0);
37 assert_ptr_not_null(decay_ticker
,
38 "Unexpected failure getting decay ticker");
41 assert_d_eq(mallctl("arenas.hchunk.0.size", (void *)&huge0
, &sz
, NULL
,
42 0), 0, "Unexpected mallctl failure");
43 assert_d_eq(mallctl("arenas.lrun.0.size", (void *)&large0
, &sz
, NULL
,
44 0), 0, "Unexpected mallctl failure");
47 * Test the standard APIs using a huge size class, since we can't
48 * control tcache interactions (except by completely disabling tcache
49 * for the entire test program).
53 tick0
= ticker_read(decay_ticker
);
55 assert_ptr_not_null(p
, "Unexpected malloc() failure");
56 tick1
= ticker_read(decay_ticker
);
57 assert_u32_ne(tick1
, tick0
, "Expected ticker to tick during malloc()");
59 tick0
= ticker_read(decay_ticker
);
61 tick1
= ticker_read(decay_ticker
);
62 assert_u32_ne(tick1
, tick0
, "Expected ticker to tick during free()");
65 tick0
= ticker_read(decay_ticker
);
67 assert_ptr_not_null(p
, "Unexpected calloc() failure");
68 tick1
= ticker_read(decay_ticker
);
69 assert_u32_ne(tick1
, tick0
, "Expected ticker to tick during calloc()");
72 /* posix_memalign(). */
73 tick0
= ticker_read(decay_ticker
);
74 assert_d_eq(posix_memalign(&p
, sizeof(size_t), huge0
), 0,
75 "Unexpected posix_memalign() failure");
76 tick1
= ticker_read(decay_ticker
);
77 assert_u32_ne(tick1
, tick0
,
78 "Expected ticker to tick during posix_memalign()");
81 /* aligned_alloc(). */
82 tick0
= ticker_read(decay_ticker
);
83 p
= aligned_alloc(sizeof(size_t), huge0
);
84 assert_ptr_not_null(p
, "Unexpected aligned_alloc() failure");
85 tick1
= ticker_read(decay_ticker
);
86 assert_u32_ne(tick1
, tick0
,
87 "Expected ticker to tick during aligned_alloc()");
92 tick0
= ticker_read(decay_ticker
);
93 p
= realloc(NULL
, huge0
);
94 assert_ptr_not_null(p
, "Unexpected realloc() failure");
95 tick1
= ticker_read(decay_ticker
);
96 assert_u32_ne(tick1
, tick0
, "Expected ticker to tick during realloc()");
98 tick0
= ticker_read(decay_ticker
);
99 p
= realloc(p
, huge0
);
100 assert_ptr_not_null(p
, "Unexpected realloc() failure");
101 tick1
= ticker_read(decay_ticker
);
102 assert_u32_ne(tick1
, tick0
, "Expected ticker to tick during realloc()");
104 tick0
= ticker_read(decay_ticker
);
106 tick1
= ticker_read(decay_ticker
);
107 assert_u32_ne(tick1
, tick0
, "Expected ticker to tick during realloc()");
110 * Test the *allocx() APIs using huge, large, and small size classes,
111 * with tcache explicitly disabled.
115 size_t allocx_sizes
[3];
116 allocx_sizes
[0] = huge0
;
117 allocx_sizes
[1] = large0
;
120 for (i
= 0; i
< sizeof(allocx_sizes
) / sizeof(size_t); i
++) {
121 sz
= allocx_sizes
[i
];
124 tick0
= ticker_read(decay_ticker
);
125 p
= mallocx(sz
, MALLOCX_TCACHE_NONE
);
126 assert_ptr_not_null(p
, "Unexpected mallocx() failure");
127 tick1
= ticker_read(decay_ticker
);
128 assert_u32_ne(tick1
, tick0
,
129 "Expected ticker to tick during mallocx() (sz=%zu)",
132 tick0
= ticker_read(decay_ticker
);
133 p
= rallocx(p
, sz
, MALLOCX_TCACHE_NONE
);
134 assert_ptr_not_null(p
, "Unexpected rallocx() failure");
135 tick1
= ticker_read(decay_ticker
);
136 assert_u32_ne(tick1
, tick0
,
137 "Expected ticker to tick during rallocx() (sz=%zu)",
140 tick0
= ticker_read(decay_ticker
);
141 xallocx(p
, sz
, 0, MALLOCX_TCACHE_NONE
);
142 tick1
= ticker_read(decay_ticker
);
143 assert_u32_ne(tick1
, tick0
,
144 "Expected ticker to tick during xallocx() (sz=%zu)",
147 tick0
= ticker_read(decay_ticker
);
148 dallocx(p
, MALLOCX_TCACHE_NONE
);
149 tick1
= ticker_read(decay_ticker
);
150 assert_u32_ne(tick1
, tick0
,
151 "Expected ticker to tick during dallocx() (sz=%zu)",
154 p
= mallocx(sz
, MALLOCX_TCACHE_NONE
);
155 assert_ptr_not_null(p
, "Unexpected mallocx() failure");
156 tick0
= ticker_read(decay_ticker
);
157 sdallocx(p
, sz
, MALLOCX_TCACHE_NONE
);
158 tick1
= ticker_read(decay_ticker
);
159 assert_u32_ne(tick1
, tick0
,
160 "Expected ticker to tick during sdallocx() "
166 * Test tcache fill/flush interactions for large and small size classes,
167 * using an explicit tcache.
170 unsigned tcache_ind
, i
;
171 size_t tcache_sizes
[2];
172 tcache_sizes
[0] = large0
;
175 sz
= sizeof(unsigned);
176 assert_d_eq(mallctl("tcache.create", (void *)&tcache_ind
, &sz
,
177 NULL
, 0), 0, "Unexpected mallctl failure");
179 for (i
= 0; i
< sizeof(tcache_sizes
) / sizeof(size_t); i
++) {
180 sz
= tcache_sizes
[i
];
183 tick0
= ticker_read(decay_ticker
);
184 p
= mallocx(sz
, MALLOCX_TCACHE(tcache_ind
));
185 assert_ptr_not_null(p
, "Unexpected mallocx() failure");
186 tick1
= ticker_read(decay_ticker
);
187 assert_u32_ne(tick1
, tick0
,
188 "Expected ticker to tick during tcache fill "
191 dallocx(p
, MALLOCX_TCACHE(tcache_ind
));
192 tick0
= ticker_read(decay_ticker
);
193 assert_d_eq(mallctl("tcache.flush", NULL
, NULL
,
194 (void *)&tcache_ind
, sizeof(unsigned)), 0,
195 "Unexpected mallctl failure");
196 tick1
= ticker_read(decay_ticker
);
197 assert_u32_ne(tick1
, tick0
,
198 "Expected ticker to tick during tcache flush "
205 TEST_BEGIN(test_decay_ticker
)
208 int flags
= (MALLOCX_ARENA(0) | MALLOCX_TCACHE_NONE
);
211 uint64_t npurge0
= 0;
212 uint64_t npurge1
= 0;
214 unsigned i
, nupdates0
;
215 nstime_t time
, decay_time
, deadline
;
217 test_skip_if(opt_purge
!= purge_mode_decay
);
220 * Allocate a bunch of large objects, pause the clock, deallocate the
221 * objects, restore the clock, then [md]allocx() in a tight loop to
222 * verify the ticker triggers purging.
229 assert_d_eq(mallctl("arenas.tcache_max", (void *)&tcache_max
,
230 &sz
, NULL
, 0), 0, "Unexpected mallctl failure");
231 large
= nallocx(tcache_max
+ 1, flags
);
234 assert_d_eq(mallctl("arenas.lrun.0.size", (void *)&large
, &sz
,
235 NULL
, 0), 0, "Unexpected mallctl failure");
238 assert_d_eq(mallctl("arena.0.purge", NULL
, NULL
, NULL
, 0), 0,
239 "Unexpected mallctl failure");
240 assert_d_eq(mallctl("epoch", NULL
, NULL
, (void *)&epoch
,
241 sizeof(uint64_t)), 0, "Unexpected mallctl failure");
242 sz
= sizeof(uint64_t);
243 assert_d_eq(mallctl("stats.arenas.0.npurge", (void *)&npurge0
, &sz
,
244 NULL
, 0), config_stats
? 0 : ENOENT
, "Unexpected mallctl result");
246 for (i
= 0; i
< NPS
; i
++) {
247 ps
[i
] = mallocx(large
, flags
);
248 assert_ptr_not_null(ps
[i
], "Unexpected mallocx() failure");
252 nstime_init(&time_mock
, 0);
253 nstime_update(&time_mock
);
254 monotonic_mock
= true;
256 nstime_monotonic_orig
= nstime_monotonic
;
257 nstime_update_orig
= nstime_update
;
258 nstime_monotonic
= nstime_monotonic_mock
;
259 nstime_update
= nstime_update_mock
;
261 for (i
= 0; i
< NPS
; i
++) {
262 dallocx(ps
[i
], flags
);
263 nupdates0
= nupdates_mock
;
264 assert_d_eq(mallctl("arena.0.decay", NULL
, NULL
, NULL
, 0), 0,
265 "Unexpected arena.0.decay failure");
266 assert_u_gt(nupdates_mock
, nupdates0
,
267 "Expected nstime_update() to be called");
270 nstime_monotonic
= nstime_monotonic_orig
;
271 nstime_update
= nstime_update_orig
;
273 nstime_init(&time
, 0);
274 nstime_update(&time
);
275 nstime_init2(&decay_time
, opt_decay_time
, 0);
276 nstime_copy(&deadline
, &time
);
277 nstime_add(&deadline
, &decay_time
);
279 for (i
= 0; i
< DECAY_NTICKS_PER_UPDATE
/ 2; i
++) {
280 void *p
= mallocx(1, flags
);
281 assert_ptr_not_null(p
, "Unexpected mallocx() failure");
284 assert_d_eq(mallctl("epoch", NULL
, NULL
, (void *)&epoch
,
285 sizeof(uint64_t)), 0, "Unexpected mallctl failure");
286 sz
= sizeof(uint64_t);
287 assert_d_eq(mallctl("stats.arenas.0.npurge", (void *)&npurge1
,
288 &sz
, NULL
, 0), config_stats
? 0 : ENOENT
,
289 "Unexpected mallctl result");
291 nstime_update(&time
);
292 } while (nstime_compare(&time
, &deadline
) <= 0 && npurge1
== npurge0
);
295 assert_u64_gt(npurge1
, npurge0
, "Expected purging to occur");
300 TEST_BEGIN(test_decay_nonmonotonic
)
302 #define NPS (SMOOTHSTEP_NSTEPS + 1)
303 int flags
= (MALLOCX_ARENA(0) | MALLOCX_TCACHE_NONE
);
306 uint64_t npurge0
= 0;
307 uint64_t npurge1
= 0;
309 unsigned i
, nupdates0
;
311 test_skip_if(opt_purge
!= purge_mode_decay
);
314 assert_d_eq(mallctl("arenas.lrun.0.size", (void *)&large0
, &sz
, NULL
,
315 0), 0, "Unexpected mallctl failure");
317 assert_d_eq(mallctl("arena.0.purge", NULL
, NULL
, NULL
, 0), 0,
318 "Unexpected mallctl failure");
319 assert_d_eq(mallctl("epoch", NULL
, NULL
, (void *)&epoch
,
320 sizeof(uint64_t)), 0, "Unexpected mallctl failure");
321 sz
= sizeof(uint64_t);
322 assert_d_eq(mallctl("stats.arenas.0.npurge", (void *)&npurge0
, &sz
,
323 NULL
, 0), config_stats
? 0 : ENOENT
, "Unexpected mallctl result");
326 nstime_init(&time_mock
, 0);
327 nstime_update(&time_mock
);
328 monotonic_mock
= false;
330 nstime_monotonic_orig
= nstime_monotonic
;
331 nstime_update_orig
= nstime_update
;
332 nstime_monotonic
= nstime_monotonic_mock
;
333 nstime_update
= nstime_update_mock
;
335 for (i
= 0; i
< NPS
; i
++) {
336 ps
[i
] = mallocx(large0
, flags
);
337 assert_ptr_not_null(ps
[i
], "Unexpected mallocx() failure");
340 for (i
= 0; i
< NPS
; i
++) {
341 dallocx(ps
[i
], flags
);
342 nupdates0
= nupdates_mock
;
343 assert_d_eq(mallctl("arena.0.decay", NULL
, NULL
, NULL
, 0), 0,
344 "Unexpected arena.0.decay failure");
345 assert_u_gt(nupdates_mock
, nupdates0
,
346 "Expected nstime_update() to be called");
349 assert_d_eq(mallctl("epoch", NULL
, NULL
, (void *)&epoch
,
350 sizeof(uint64_t)), 0, "Unexpected mallctl failure");
351 sz
= sizeof(uint64_t);
352 assert_d_eq(mallctl("stats.arenas.0.npurge", (void *)&npurge1
, &sz
,
353 NULL
, 0), config_stats
? 0 : ENOENT
, "Unexpected mallctl result");
356 assert_u64_eq(npurge0
, npurge1
, "Unexpected purging occurred");
358 nstime_monotonic
= nstime_monotonic_orig
;
359 nstime_update
= nstime_update_orig
;
371 test_decay_nonmonotonic
));