diff options
Diffstat (limited to 'deps/jemalloc/test/stress')
-rw-r--r-- | deps/jemalloc/test/stress/batch_alloc.c | 198 | ||||
-rw-r--r-- | deps/jemalloc/test/stress/fill_flush.c | 76 | ||||
-rw-r--r-- | deps/jemalloc/test/stress/large_microbench.c | 33 | ||||
-rw-r--r-- | deps/jemalloc/test/stress/mallctl.c | 74 | ||||
-rw-r--r-- | deps/jemalloc/test/stress/microbench.c | 43 |
5 files changed, 383 insertions, 41 deletions
diff --git a/deps/jemalloc/test/stress/batch_alloc.c b/deps/jemalloc/test/stress/batch_alloc.c new file mode 100644 index 000000000..427e1cba8 --- /dev/null +++ b/deps/jemalloc/test/stress/batch_alloc.c @@ -0,0 +1,198 @@ +#include "test/jemalloc_test.h" +#include "test/bench.h" + +#define MIBLEN 8 +static size_t mib[MIBLEN]; +static size_t miblen = MIBLEN; + +#define TINY_BATCH 10 +#define TINY_BATCH_ITER (10 * 1000 * 1000) +#define HUGE_BATCH (1000 * 1000) +#define HUGE_BATCH_ITER 100 +#define LEN (100 * 1000 * 1000) +static void *batch_ptrs[LEN]; +static size_t batch_ptrs_next = 0; +static void *item_ptrs[LEN]; +static size_t item_ptrs_next = 0; + +#define SIZE 7 + +typedef struct batch_alloc_packet_s batch_alloc_packet_t; +struct batch_alloc_packet_s { + void **ptrs; + size_t num; + size_t size; + int flags; +}; + +static void +batch_alloc_wrapper(size_t batch) { + batch_alloc_packet_t batch_alloc_packet = + {batch_ptrs + batch_ptrs_next, batch, SIZE, 0}; + size_t filled; + size_t len = sizeof(size_t); + assert_d_eq(mallctlbymib(mib, miblen, &filled, &len, + &batch_alloc_packet, sizeof(batch_alloc_packet)), 0, ""); + assert_zu_eq(filled, batch, ""); +} + +static void +item_alloc_wrapper(size_t batch) { + for (size_t i = item_ptrs_next, end = i + batch; i < end; ++i) { + item_ptrs[i] = malloc(SIZE); + } +} + +static void +release_and_clear(void **ptrs, size_t len) { + for (size_t i = 0; i < len; ++i) { + void *p = ptrs[i]; + assert_ptr_not_null(p, "allocation failed"); + sdallocx(p, SIZE, 0); + ptrs[i] = NULL; + } +} + +static void +batch_alloc_without_free(size_t batch) { + batch_alloc_wrapper(batch); + batch_ptrs_next += batch; +} + +static void +item_alloc_without_free(size_t batch) { + item_alloc_wrapper(batch); + item_ptrs_next += batch; +} + +static void +batch_alloc_with_free(size_t batch) { + batch_alloc_wrapper(batch); + release_and_clear(batch_ptrs + batch_ptrs_next, batch); + batch_ptrs_next += batch; +} + +static void +item_alloc_with_free(size_t batch) { + item_alloc_wrapper(batch); + release_and_clear(item_ptrs + item_ptrs_next, batch); + item_ptrs_next += batch; +} + +static void +compare_without_free(size_t batch, size_t iter, + void (*batch_alloc_without_free_func)(void), + void (*item_alloc_without_free_func)(void)) { + assert(batch_ptrs_next == 0); + assert(item_ptrs_next == 0); + assert(batch * iter <= LEN); + for (size_t i = 0; i < iter; ++i) { + batch_alloc_without_free_func(); + item_alloc_without_free_func(); + } + release_and_clear(batch_ptrs, batch_ptrs_next); + batch_ptrs_next = 0; + release_and_clear(item_ptrs, item_ptrs_next); + item_ptrs_next = 0; + compare_funcs(0, iter, + "batch allocation", batch_alloc_without_free_func, + "item allocation", item_alloc_without_free_func); + release_and_clear(batch_ptrs, batch_ptrs_next); + batch_ptrs_next = 0; + release_and_clear(item_ptrs, item_ptrs_next); + item_ptrs_next = 0; +} + +static void +compare_with_free(size_t batch, size_t iter, + void (*batch_alloc_with_free_func)(void), + void (*item_alloc_with_free_func)(void)) { + assert(batch_ptrs_next == 0); + assert(item_ptrs_next == 0); + assert(batch * iter <= LEN); + for (size_t i = 0; i < iter; ++i) { + batch_alloc_with_free_func(); + item_alloc_with_free_func(); + } + batch_ptrs_next = 0; + item_ptrs_next = 0; + compare_funcs(0, iter, + "batch allocation", batch_alloc_with_free_func, + "item allocation", item_alloc_with_free_func); + batch_ptrs_next = 0; + item_ptrs_next = 0; +} + +static void +batch_alloc_without_free_tiny() { + batch_alloc_without_free(TINY_BATCH); +} + +static void +item_alloc_without_free_tiny() { + item_alloc_without_free(TINY_BATCH); +} + +TEST_BEGIN(test_tiny_batch_without_free) { + compare_without_free(TINY_BATCH, TINY_BATCH_ITER, + batch_alloc_without_free_tiny, item_alloc_without_free_tiny); +} +TEST_END + +static void +batch_alloc_with_free_tiny() { + batch_alloc_with_free(TINY_BATCH); +} + +static void +item_alloc_with_free_tiny() { + item_alloc_with_free(TINY_BATCH); +} + +TEST_BEGIN(test_tiny_batch_with_free) { + compare_with_free(TINY_BATCH, TINY_BATCH_ITER, + batch_alloc_with_free_tiny, item_alloc_with_free_tiny); +} +TEST_END + +static void +batch_alloc_without_free_huge() { + batch_alloc_without_free(HUGE_BATCH); +} + +static void +item_alloc_without_free_huge() { + item_alloc_without_free(HUGE_BATCH); +} + +TEST_BEGIN(test_huge_batch_without_free) { + compare_without_free(HUGE_BATCH, HUGE_BATCH_ITER, + batch_alloc_without_free_huge, item_alloc_without_free_huge); +} +TEST_END + +static void +batch_alloc_with_free_huge() { + batch_alloc_with_free(HUGE_BATCH); +} + +static void +item_alloc_with_free_huge() { + item_alloc_with_free(HUGE_BATCH); +} + +TEST_BEGIN(test_huge_batch_with_free) { + compare_with_free(HUGE_BATCH, HUGE_BATCH_ITER, + batch_alloc_with_free_huge, item_alloc_with_free_huge); +} +TEST_END + +int main(void) { + assert_d_eq(mallctlnametomib("experimental.batch_alloc", mib, &miblen), + 0, ""); + return test_no_reentrancy( + test_tiny_batch_without_free, + test_tiny_batch_with_free, + test_huge_batch_without_free, + test_huge_batch_with_free); +} diff --git a/deps/jemalloc/test/stress/fill_flush.c b/deps/jemalloc/test/stress/fill_flush.c new file mode 100644 index 000000000..a2db044dd --- /dev/null +++ b/deps/jemalloc/test/stress/fill_flush.c @@ -0,0 +1,76 @@ +#include "test/jemalloc_test.h" +#include "test/bench.h" + +#define SMALL_ALLOC_SIZE 128 +#define LARGE_ALLOC_SIZE SC_LARGE_MINCLASS +#define NALLOCS 1000 + +/* + * We make this volatile so the 1-at-a-time variants can't leave the allocation + * in a register, just to try to get the cache behavior closer. + */ +void *volatile allocs[NALLOCS]; + +static void +array_alloc_dalloc_small(void) { + for (int i = 0; i < NALLOCS; i++) { + void *p = mallocx(SMALL_ALLOC_SIZE, 0); + assert_ptr_not_null(p, "mallocx shouldn't fail"); + allocs[i] = p; + } + for (int i = 0; i < NALLOCS; i++) { + sdallocx(allocs[i], SMALL_ALLOC_SIZE, 0); + } +} + +static void +item_alloc_dalloc_small(void) { + for (int i = 0; i < NALLOCS; i++) { + void *p = mallocx(SMALL_ALLOC_SIZE, 0); + assert_ptr_not_null(p, "mallocx shouldn't fail"); + allocs[i] = p; + sdallocx(allocs[i], SMALL_ALLOC_SIZE, 0); + } +} + +TEST_BEGIN(test_array_vs_item_small) { + compare_funcs(1 * 1000, 10 * 1000, + "array of small allocations", array_alloc_dalloc_small, + "small item allocation", item_alloc_dalloc_small); +} +TEST_END + +static void +array_alloc_dalloc_large(void) { + for (int i = 0; i < NALLOCS; i++) { + void *p = mallocx(LARGE_ALLOC_SIZE, 0); + assert_ptr_not_null(p, "mallocx shouldn't fail"); + allocs[i] = p; + } + for (int i = 0; i < NALLOCS; i++) { + sdallocx(allocs[i], LARGE_ALLOC_SIZE, 0); + } +} + +static void +item_alloc_dalloc_large(void) { + for (int i = 0; i < NALLOCS; i++) { + void *p = mallocx(LARGE_ALLOC_SIZE, 0); + assert_ptr_not_null(p, "mallocx shouldn't fail"); + allocs[i] = p; + sdallocx(allocs[i], LARGE_ALLOC_SIZE, 0); + } +} + +TEST_BEGIN(test_array_vs_item_large) { + compare_funcs(100, 1000, + "array of large allocations", array_alloc_dalloc_large, + "large item allocation", item_alloc_dalloc_large); +} +TEST_END + +int main(void) { + return test_no_reentrancy( + test_array_vs_item_small, + test_array_vs_item_large); +} diff --git a/deps/jemalloc/test/stress/large_microbench.c b/deps/jemalloc/test/stress/large_microbench.c new file mode 100644 index 000000000..c66b33a1c --- /dev/null +++ b/deps/jemalloc/test/stress/large_microbench.c @@ -0,0 +1,33 @@ +#include "test/jemalloc_test.h" +#include "test/bench.h" + +static void +large_mallocx_free(void) { + /* + * We go a bit larger than the large minclass on its own to better + * expose costs from things like zeroing. + */ + void *p = mallocx(SC_LARGE_MINCLASS, MALLOCX_TCACHE_NONE); + assert_ptr_not_null(p, "mallocx shouldn't fail"); + free(p); +} + +static void +small_mallocx_free(void) { + void *p = mallocx(16, 0); + assert_ptr_not_null(p, "mallocx shouldn't fail"); + free(p); +} + +TEST_BEGIN(test_large_vs_small) { + compare_funcs(100*1000, 1*1000*1000, "large mallocx", + large_mallocx_free, "small mallocx", small_mallocx_free); +} +TEST_END + +int +main(void) { + return test_no_reentrancy( + test_large_vs_small); +} + diff --git a/deps/jemalloc/test/stress/mallctl.c b/deps/jemalloc/test/stress/mallctl.c new file mode 100644 index 000000000..d29b31184 --- /dev/null +++ b/deps/jemalloc/test/stress/mallctl.c @@ -0,0 +1,74 @@ +#include "test/jemalloc_test.h" +#include "test/bench.h" + +static void +mallctl_short(void) { + const char *version; + size_t sz = sizeof(version); + int err = mallctl("version", &version, &sz, NULL, 0); + assert_d_eq(err, 0, "mallctl failure"); +} + +size_t mib_short[1]; + +static void +mallctlbymib_short(void) { + size_t miblen = sizeof(mib_short)/sizeof(mib_short[0]); + const char *version; + size_t sz = sizeof(version); + int err = mallctlbymib(mib_short, miblen, &version, &sz, NULL, 0); + assert_d_eq(err, 0, "mallctlbymib failure"); +} + +TEST_BEGIN(test_mallctl_vs_mallctlbymib_short) { + size_t miblen = sizeof(mib_short)/sizeof(mib_short[0]); + + int err = mallctlnametomib("version", mib_short, &miblen); + assert_d_eq(err, 0, "mallctlnametomib failure"); + compare_funcs(10*1000*1000, 10*1000*1000, "mallctl_short", + mallctl_short, "mallctlbymib_short", mallctlbymib_short); +} +TEST_END + +static void +mallctl_long(void) { + uint64_t nmalloc; + size_t sz = sizeof(nmalloc); + int err = mallctl("stats.arenas.0.bins.0.nmalloc", &nmalloc, &sz, NULL, + 0); + assert_d_eq(err, 0, "mallctl failure"); +} + +size_t mib_long[6]; + +static void +mallctlbymib_long(void) { + size_t miblen = sizeof(mib_long)/sizeof(mib_long[0]); + uint64_t nmalloc; + size_t sz = sizeof(nmalloc); + int err = mallctlbymib(mib_long, miblen, &nmalloc, &sz, NULL, 0); + assert_d_eq(err, 0, "mallctlbymib failure"); +} + +TEST_BEGIN(test_mallctl_vs_mallctlbymib_long) { + /* + * We want to use the longest mallctl we have; that needs stats support + * to be allowed. + */ + test_skip_if(!config_stats); + + size_t miblen = sizeof(mib_long)/sizeof(mib_long[0]); + int err = mallctlnametomib("stats.arenas.0.bins.0.nmalloc", mib_long, + &miblen); + assert_d_eq(err, 0, "mallctlnametomib failure"); + compare_funcs(10*1000*1000, 10*1000*1000, "mallctl_long", + mallctl_long, "mallctlbymib_long", mallctlbymib_long); +} +TEST_END + +int +main(void) { + return test_no_reentrancy( + test_mallctl_vs_mallctlbymib_short, + test_mallctl_vs_mallctlbymib_long); +} diff --git a/deps/jemalloc/test/stress/microbench.c b/deps/jemalloc/test/stress/microbench.c index 988b7938f..062e32fde 100644 --- a/deps/jemalloc/test/stress/microbench.c +++ b/deps/jemalloc/test/stress/microbench.c @@ -1,44 +1,5 @@ #include "test/jemalloc_test.h" - -static inline void -time_func(timedelta_t *timer, uint64_t nwarmup, uint64_t niter, - void (*func)(void)) { - uint64_t i; - - for (i = 0; i < nwarmup; i++) { - func(); - } - timer_start(timer); - for (i = 0; i < niter; i++) { - func(); - } - timer_stop(timer); -} - -void -compare_funcs(uint64_t nwarmup, uint64_t niter, const char *name_a, - void (*func_a), const char *name_b, void (*func_b)) { - timedelta_t timer_a, timer_b; - char ratio_buf[6]; - void *p; - - p = mallocx(1, 0); - if (p == NULL) { - test_fail("Unexpected mallocx() failure"); - return; - } - - time_func(&timer_a, nwarmup, niter, func_a); - time_func(&timer_b, nwarmup, niter, func_b); - - timer_ratio(&timer_a, &timer_b, ratio_buf, sizeof(ratio_buf)); - malloc_printf("%"FMTu64" iterations, %s=%"FMTu64"us, " - "%s=%"FMTu64"us, ratio=1:%s\n", - niter, name_a, timer_usec(&timer_a), name_b, timer_usec(&timer_b), - ratio_buf); - - dallocx(p, 0); -} +#include "test/bench.h" static void malloc_free(void) { @@ -108,7 +69,7 @@ malloc_mus_free(void) { test_fail("Unexpected malloc() failure"); return; } - malloc_usable_size(p); + TEST_MALLOC_SIZE(p); free(p); } |