1 #include "test/jemalloc_test.h" 2 #include "test/bench.h" 3 4 #define MIBLEN 8 5 static size_t mib[MIBLEN]; 6 static size_t miblen = MIBLEN; 7 8 #define TINY_BATCH 10 9 #define TINY_BATCH_ITER (10 * 1000 * 1000) 10 #define HUGE_BATCH (1000 * 1000) 11 #define HUGE_BATCH_ITER 100 12 #define LEN (100 * 1000 * 1000) 13 static void *batch_ptrs[LEN]; 14 static size_t batch_ptrs_next = 0; 15 static void *item_ptrs[LEN]; 16 static size_t item_ptrs_next = 0; 17 18 #define SIZE 7 19 20 typedef struct batch_alloc_packet_s batch_alloc_packet_t; 21 struct batch_alloc_packet_s { 22 void **ptrs; 23 size_t num; 24 size_t size; 25 int flags; 26 }; 27 28 static void 29 batch_alloc_wrapper(size_t batch) { 30 batch_alloc_packet_t batch_alloc_packet = 31 {batch_ptrs + batch_ptrs_next, batch, SIZE, 0}; 32 size_t filled; 33 size_t len = sizeof(size_t); 34 assert_d_eq(mallctlbymib(mib, miblen, &filled, &len, 35 &batch_alloc_packet, sizeof(batch_alloc_packet)), 0, ""); 36 assert_zu_eq(filled, batch, ""); 37 } 38 39 static void 40 item_alloc_wrapper(size_t batch) { 41 for (size_t i = item_ptrs_next, end = i + batch; i < end; ++i) { 42 item_ptrs[i] = malloc(SIZE); 43 } 44 } 45 46 static void 47 release_and_clear(void **ptrs, size_t len) { 48 for (size_t i = 0; i < len; ++i) { 49 void *p = ptrs[i]; 50 assert_ptr_not_null(p, "allocation failed"); 51 sdallocx(p, SIZE, 0); 52 ptrs[i] = NULL; 53 } 54 } 55 56 static void 57 batch_alloc_without_free(size_t batch) { 58 batch_alloc_wrapper(batch); 59 batch_ptrs_next += batch; 60 } 61 62 static void 63 item_alloc_without_free(size_t batch) { 64 item_alloc_wrapper(batch); 65 item_ptrs_next += batch; 66 } 67 68 static void 69 batch_alloc_with_free(size_t batch) { 70 batch_alloc_wrapper(batch); 71 release_and_clear(batch_ptrs + batch_ptrs_next, batch); 72 batch_ptrs_next += batch; 73 } 74 75 static void 76 item_alloc_with_free(size_t batch) { 77 item_alloc_wrapper(batch); 78 release_and_clear(item_ptrs + item_ptrs_next, batch); 79 item_ptrs_next += batch; 80 } 81 82 static void 83 compare_without_free(size_t batch, size_t iter, 84 void (*batch_alloc_without_free_func)(void), 85 void (*item_alloc_without_free_func)(void)) { 86 assert(batch_ptrs_next == 0); 87 assert(item_ptrs_next == 0); 88 assert(batch * iter <= LEN); 89 for (size_t i = 0; i < iter; ++i) { 90 batch_alloc_without_free_func(); 91 item_alloc_without_free_func(); 92 } 93 release_and_clear(batch_ptrs, batch_ptrs_next); 94 batch_ptrs_next = 0; 95 release_and_clear(item_ptrs, item_ptrs_next); 96 item_ptrs_next = 0; 97 compare_funcs(0, iter, 98 "batch allocation", batch_alloc_without_free_func, 99 "item allocation", item_alloc_without_free_func); 100 release_and_clear(batch_ptrs, batch_ptrs_next); 101 batch_ptrs_next = 0; 102 release_and_clear(item_ptrs, item_ptrs_next); 103 item_ptrs_next = 0; 104 } 105 106 static void 107 compare_with_free(size_t batch, size_t iter, 108 void (*batch_alloc_with_free_func)(void), 109 void (*item_alloc_with_free_func)(void)) { 110 assert(batch_ptrs_next == 0); 111 assert(item_ptrs_next == 0); 112 assert(batch * iter <= LEN); 113 for (size_t i = 0; i < iter; ++i) { 114 batch_alloc_with_free_func(); 115 item_alloc_with_free_func(); 116 } 117 batch_ptrs_next = 0; 118 item_ptrs_next = 0; 119 compare_funcs(0, iter, 120 "batch allocation", batch_alloc_with_free_func, 121 "item allocation", item_alloc_with_free_func); 122 batch_ptrs_next = 0; 123 item_ptrs_next = 0; 124 } 125 126 static void 127 batch_alloc_without_free_tiny() { 128 batch_alloc_without_free(TINY_BATCH); 129 } 130 131 static void 132 item_alloc_without_free_tiny() { 133 item_alloc_without_free(TINY_BATCH); 134 } 135 136 TEST_BEGIN(test_tiny_batch_without_free) { 137 compare_without_free(TINY_BATCH, TINY_BATCH_ITER, 138 batch_alloc_without_free_tiny, item_alloc_without_free_tiny); 139 } 140 TEST_END 141 142 static void 143 batch_alloc_with_free_tiny() { 144 batch_alloc_with_free(TINY_BATCH); 145 } 146 147 static void 148 item_alloc_with_free_tiny() { 149 item_alloc_with_free(TINY_BATCH); 150 } 151 152 TEST_BEGIN(test_tiny_batch_with_free) { 153 compare_with_free(TINY_BATCH, TINY_BATCH_ITER, 154 batch_alloc_with_free_tiny, item_alloc_with_free_tiny); 155 } 156 TEST_END 157 158 static void 159 batch_alloc_without_free_huge() { 160 batch_alloc_without_free(HUGE_BATCH); 161 } 162 163 static void 164 item_alloc_without_free_huge() { 165 item_alloc_without_free(HUGE_BATCH); 166 } 167 168 TEST_BEGIN(test_huge_batch_without_free) { 169 compare_without_free(HUGE_BATCH, HUGE_BATCH_ITER, 170 batch_alloc_without_free_huge, item_alloc_without_free_huge); 171 } 172 TEST_END 173 174 static void 175 batch_alloc_with_free_huge() { 176 batch_alloc_with_free(HUGE_BATCH); 177 } 178 179 static void 180 item_alloc_with_free_huge() { 181 item_alloc_with_free(HUGE_BATCH); 182 } 183 184 TEST_BEGIN(test_huge_batch_with_free) { 185 compare_with_free(HUGE_BATCH, HUGE_BATCH_ITER, 186 batch_alloc_with_free_huge, item_alloc_with_free_huge); 187 } 188 TEST_END 189 190 int main(void) { 191 assert_d_eq(mallctlnametomib("experimental.batch_alloc", mib, &miblen), 192 0, ""); 193 return test_no_reentrancy( 194 test_tiny_batch_without_free, 195 test_tiny_batch_with_free, 196 test_huge_batch_without_free, 197 test_huge_batch_with_free); 198 } 199