xref: /netbsd-src/external/bsd/jemalloc/dist/test/stress/batch_alloc.c (revision f8cf1a9151c7af1cb0bd8b09c13c66bca599c027)
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