summaryrefslogtreecommitdiff
path: root/deps/jemalloc/test/stress
diff options
context:
space:
mode:
Diffstat (limited to 'deps/jemalloc/test/stress')
-rw-r--r--deps/jemalloc/test/stress/batch_alloc.c198
-rw-r--r--deps/jemalloc/test/stress/fill_flush.c76
-rw-r--r--deps/jemalloc/test/stress/large_microbench.c33
-rw-r--r--deps/jemalloc/test/stress/mallctl.c74
-rw-r--r--deps/jemalloc/test/stress/microbench.c43
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);
}