]>
Commit | Line | Data |
---|---|---|
a8e16298 TL |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | ||
4 | #include <iostream> | |
5 | #include <gtest/gtest.h> | |
6 | ||
7 | #include "os/bluestore/fastbmap_allocator_impl.h" | |
8 | ||
9 | class TestAllocatorLevel01 : public AllocatorLevel01Loose | |
10 | { | |
11 | public: | |
12 | void init(uint64_t capacity, uint64_t alloc_unit) | |
13 | { | |
14 | _init(capacity, alloc_unit); | |
15 | } | |
16 | interval_t allocate_l1_cont(uint64_t length, uint64_t min_length, | |
17 | uint64_t pos_start, uint64_t pos_end) | |
18 | { | |
19 | return _allocate_l1_contiguous(length, min_length, 0, pos_start, pos_end); | |
20 | } | |
21 | void free_l1(const interval_t& r) | |
22 | { | |
23 | _free_l1(r.offset, r.length); | |
24 | } | |
25 | }; | |
26 | ||
27 | class TestAllocatorLevel02 : public AllocatorLevel02<AllocatorLevel01Loose> | |
28 | { | |
29 | public: | |
30 | void init(uint64_t capacity, uint64_t alloc_unit) | |
31 | { | |
32 | _init(capacity, alloc_unit); | |
33 | } | |
34 | void allocate_l2(uint64_t length, uint64_t min_length, | |
35 | uint64_t* allocated0, | |
36 | interval_vector_t* res) | |
37 | { | |
38 | uint64_t allocated = 0; | |
39 | uint64_t hint = 0; // trigger internal l2 hint support | |
40 | _allocate_l2(length, min_length, 0, hint, &allocated, res); | |
41 | *allocated0 += allocated; | |
42 | } | |
43 | void free_l2(const interval_vector_t& r) | |
44 | { | |
45 | _free_l2(r); | |
46 | } | |
e306af50 TL |
47 | void mark_free(uint64_t o, uint64_t len) |
48 | { | |
49 | _mark_free(o, len); | |
50 | } | |
51 | void mark_allocated(uint64_t o, uint64_t len) | |
52 | { | |
53 | _mark_allocated(o, len); | |
54 | } | |
a8e16298 TL |
55 | }; |
56 | ||
57 | const uint64_t _1m = 1024 * 1024; | |
58 | const uint64_t _2m = 2 * 1024 * 1024; | |
59 | ||
60 | TEST(TestAllocatorLevel01, test_l1) | |
61 | { | |
62 | TestAllocatorLevel01 al1; | |
63 | uint64_t num_l1_entries = 3 * 256; | |
64 | uint64_t capacity = num_l1_entries * 512 * 4096; | |
65 | al1.init(capacity, 0x1000); | |
66 | ASSERT_EQ(capacity, al1.debug_get_free()); | |
67 | ||
68 | auto i1 = al1.allocate_l1_cont(0x1000, 0x1000, 0, num_l1_entries); | |
11fdf7f2 TL |
69 | ASSERT_EQ(i1.offset, 0u); |
70 | ASSERT_EQ(i1.length, 0x1000u); | |
a8e16298 TL |
71 | ASSERT_EQ(capacity - 0x1000, al1.debug_get_free()); |
72 | ||
73 | auto i2 = al1.allocate_l1_cont(0x1000, 0x1000, 0, num_l1_entries); | |
11fdf7f2 TL |
74 | ASSERT_EQ(i2.offset, 0x1000u); |
75 | ASSERT_EQ(i2.length, 0x1000u); | |
a8e16298 TL |
76 | al1.free_l1(i2); |
77 | al1.free_l1(i1); | |
78 | i1 = al1.allocate_l1_cont(0x1000, 0x1000, 0, num_l1_entries); | |
11fdf7f2 TL |
79 | ASSERT_EQ(i1.offset, 0u); |
80 | ASSERT_EQ(i1.length, 0x1000u); | |
a8e16298 | 81 | i2 = al1.allocate_l1_cont(0x1000, 0x1000, 0, num_l1_entries); |
11fdf7f2 TL |
82 | ASSERT_EQ(i2.offset, 0x1000u); |
83 | ASSERT_EQ(i2.length, 0x1000u); | |
a8e16298 TL |
84 | al1.free_l1(i1); |
85 | al1.free_l1(i2); | |
86 | ||
87 | i1 = al1.allocate_l1_cont(0x2000, 0x1000, 0, num_l1_entries); | |
11fdf7f2 TL |
88 | ASSERT_EQ(i1.offset, 0u); |
89 | ASSERT_EQ(i1.length, 0x2000u); | |
a8e16298 TL |
90 | |
91 | i2 = al1.allocate_l1_cont(0x3000, 0x1000, 0, num_l1_entries); | |
11fdf7f2 TL |
92 | ASSERT_EQ(i2.offset, 0x2000u); |
93 | ASSERT_EQ(i2.length, 0x3000u); | |
a8e16298 TL |
94 | |
95 | al1.free_l1(i1); | |
96 | al1.free_l1(i2); | |
97 | ||
98 | i1 = al1.allocate_l1_cont(0x2000, 0x1000, 0, num_l1_entries); | |
11fdf7f2 TL |
99 | ASSERT_EQ(i1.offset, 0u); |
100 | ASSERT_EQ(i1.length, 0x2000u); | |
a8e16298 TL |
101 | |
102 | i2 = al1.allocate_l1_cont(2 * 1024 * 1024, 0x1000, 0, num_l1_entries); | |
11fdf7f2 TL |
103 | ASSERT_EQ(i2.offset, 2u * 1024u * 1024u); |
104 | ASSERT_EQ(i2.length, 2u * 1024u * 1024u); | |
a8e16298 TL |
105 | |
106 | al1.free_l1(i1); | |
107 | i1 = al1.allocate_l1_cont(1024 * 1024, 0x1000, 0, num_l1_entries); | |
11fdf7f2 TL |
108 | ASSERT_EQ(i1.offset, 0u); |
109 | ASSERT_EQ(i1.length, 1024u * 1024u); | |
a8e16298 TL |
110 | |
111 | auto i3 = al1.allocate_l1_cont(1024 * 1024 + 0x1000, 0x1000, 0, num_l1_entries); | |
11fdf7f2 TL |
112 | ASSERT_EQ(i3.offset, 2u * 2u * 1024u * 1024u); |
113 | ASSERT_EQ(i3.length, 1024u * 1024u + 0x1000u); | |
a8e16298 TL |
114 | |
115 | // here we have the following layout: | |
116 | // Alloc: 0~1M, 2M~2M, 4M~1M+4K | |
117 | // Free: 1M~1M, 4M+4K ~ 2M-4K, 6M ~... | |
118 | // | |
119 | auto i4 = al1.allocate_l1_cont(1024 * 1024, 0x1000, 0, num_l1_entries); | |
11fdf7f2 TL |
120 | ASSERT_EQ(1 * 1024 * 1024u, i4.offset); |
121 | ASSERT_EQ(1024 * 1024u, i4.length); | |
a8e16298 TL |
122 | al1.free_l1(i4); |
123 | ||
124 | i4 = al1.allocate_l1_cont(1024 * 1024 - 0x1000, 0x1000, 0, num_l1_entries); | |
11fdf7f2 TL |
125 | ASSERT_EQ(i4.offset, 5u * 1024u * 1024u + 0x1000u); |
126 | ASSERT_EQ(i4.length, 1024u * 1024u - 0x1000u); | |
a8e16298 TL |
127 | al1.free_l1(i4); |
128 | ||
129 | i4 = al1.allocate_l1_cont(1024 * 1024 + 0x1000, 0x1000, 0, num_l1_entries); | |
11fdf7f2 | 130 | ASSERT_EQ(i4.offset, 6u * 1024u * 1024u); |
a8e16298 | 131 | //ASSERT_EQ(i4.offset, 5 * 1024 * 1024 + 0x1000); |
11fdf7f2 | 132 | ASSERT_EQ(i4.length, 1024u * 1024u + 0x1000u); |
a8e16298 TL |
133 | |
134 | al1.free_l1(i1); | |
135 | al1.free_l1(i2); | |
136 | al1.free_l1(i3); | |
137 | al1.free_l1(i4); | |
138 | ||
139 | i1 = al1.allocate_l1_cont(1024 * 1024, 0x1000, 0, num_l1_entries); | |
11fdf7f2 TL |
140 | ASSERT_EQ(i1.offset, 0u); |
141 | ASSERT_EQ(i1.length, 1024u * 1024u); | |
a8e16298 TL |
142 | |
143 | i2 = al1.allocate_l1_cont(1024 * 1024, 0x1000, 0, num_l1_entries); | |
11fdf7f2 TL |
144 | ASSERT_EQ(i2.offset, 1u * 1024u * 1024u); |
145 | ASSERT_EQ(i2.length, 1024u * 1024u); | |
a8e16298 TL |
146 | |
147 | i3 = al1.allocate_l1_cont(512 * 1024, 0x1000, 0, num_l1_entries); | |
11fdf7f2 TL |
148 | ASSERT_EQ(i3.offset, 2u * 1024u * 1024u); |
149 | ASSERT_EQ(i3.length, 512u * 1024u); | |
a8e16298 TL |
150 | |
151 | i4 = al1.allocate_l1_cont(1536 * 1024, 0x1000, 0, num_l1_entries); | |
11fdf7f2 TL |
152 | ASSERT_EQ(i4.offset, (2u * 1024u + 512u) * 1024u); |
153 | ASSERT_EQ(i4.length, 1536u * 1024u); | |
a8e16298 TL |
154 | // making a hole 1.5 Mb length |
155 | al1.free_l1(i2); | |
156 | al1.free_l1(i3); | |
157 | // and trying to fill it | |
158 | i2 = al1.allocate_l1_cont(1536 * 1024, 0x1000, 0, num_l1_entries); | |
11fdf7f2 TL |
159 | ASSERT_EQ(i2.offset, 1024u * 1024u); |
160 | ASSERT_EQ(i2.length, 1536u * 1024u); | |
a8e16298 TL |
161 | |
162 | al1.free_l1(i2); | |
163 | // and trying to fill it partially | |
164 | i2 = al1.allocate_l1_cont(1528 * 1024, 0x1000, 0, num_l1_entries); | |
11fdf7f2 TL |
165 | ASSERT_EQ(i2.offset, 1024u * 1024u); |
166 | ASSERT_EQ(i2.length, 1528u * 1024u); | |
a8e16298 TL |
167 | |
168 | i3 = al1.allocate_l1_cont(8 * 1024, 0x1000, 0, num_l1_entries); | |
11fdf7f2 TL |
169 | ASSERT_EQ(i3.offset, 2552u * 1024u); |
170 | ASSERT_EQ(i3.length, 8u * 1024u); | |
a8e16298 TL |
171 | |
172 | al1.free_l1(i2); | |
173 | // here we have the following layout: | |
174 | // Alloc: 0~1M, 2552K~8K, num_l1_entries0K~1.5M | |
175 | // Free: 1M~1528K, 4M ~... | |
176 | // | |
177 | i2 = al1.allocate_l1_cont(1536 * 1024, 0x1000, 0, num_l1_entries); | |
11fdf7f2 TL |
178 | ASSERT_EQ(i2.offset, 4u * 1024u * 1024u); |
179 | ASSERT_EQ(i2.length, 1536u * 1024u); | |
a8e16298 TL |
180 | |
181 | al1.free_l1(i1); | |
182 | al1.free_l1(i2); | |
183 | al1.free_l1(i3); | |
184 | al1.free_l1(i4); | |
185 | ASSERT_EQ(capacity, al1.debug_get_free()); | |
186 | ||
187 | for (uint64_t i = 0; i < capacity; i += _2m) { | |
188 | i1 = al1.allocate_l1_cont(_2m, _2m, 0, num_l1_entries); | |
189 | ASSERT_EQ(i1.offset, i); | |
190 | ASSERT_EQ(i1.length, _2m); | |
191 | } | |
11fdf7f2 | 192 | ASSERT_EQ(0u, al1.debug_get_free()); |
a8e16298 | 193 | i2 = al1.allocate_l1_cont(_2m, _2m, 0, num_l1_entries); |
11fdf7f2 TL |
194 | ASSERT_EQ(i2.length, 0u); |
195 | ASSERT_EQ(0u, al1.debug_get_free()); | |
a8e16298 TL |
196 | |
197 | al1.free_l1(i1); | |
198 | i2 = al1.allocate_l1_cont(_2m, _2m, 0, num_l1_entries); | |
199 | ASSERT_EQ(i2, i1); | |
200 | al1.free_l1(i2); | |
201 | i2 = al1.allocate_l1_cont(_1m, _1m, 0, num_l1_entries); | |
202 | ASSERT_EQ(i2.offset, i1.offset); | |
203 | ASSERT_EQ(i2.length, _1m); | |
204 | ||
205 | i3 = al1.allocate_l1_cont(_2m, _2m, 0, num_l1_entries); | |
11fdf7f2 | 206 | ASSERT_EQ(i3.length, 0u); |
a8e16298 TL |
207 | |
208 | i3 = al1.allocate_l1_cont(_2m, _1m, 0, num_l1_entries); | |
209 | ASSERT_EQ(i3.length, _1m); | |
210 | ||
211 | i4 = al1.allocate_l1_cont(_2m, _1m, 0, num_l1_entries); | |
11fdf7f2 | 212 | ASSERT_EQ(i4.length, 0u); |
a8e16298 TL |
213 | |
214 | al1.free_l1(i2); | |
215 | i2 = al1.allocate_l1_cont(_2m, _2m, 0, num_l1_entries); | |
11fdf7f2 | 216 | ASSERT_EQ(i2.length, 0u); |
a8e16298 TL |
217 | |
218 | i2 = al1.allocate_l1_cont(_2m, 0x1000, 0, num_l1_entries); | |
219 | ASSERT_EQ(i2.length, _1m); | |
220 | ||
221 | al1.free_l1(i2); | |
222 | al1.free_l1(i3); | |
223 | ASSERT_EQ(_2m, al1.debug_get_free()); | |
224 | ||
225 | i1 = al1.allocate_l1_cont(_2m - 3 * 0x1000, 0x1000, 0, num_l1_entries); | |
226 | i2 = al1.allocate_l1_cont(0x1000, 0x1000, 0, num_l1_entries); | |
227 | i3 = al1.allocate_l1_cont(0x1000, 0x1000, 0, num_l1_entries); | |
228 | i4 = al1.allocate_l1_cont(0x1000, 0x1000, 0, num_l1_entries); | |
11fdf7f2 | 229 | ASSERT_EQ(0u, al1.debug_get_free()); |
a8e16298 TL |
230 | |
231 | al1.free_l1(i2); | |
232 | al1.free_l1(i4); | |
233 | ||
234 | i2 = al1.allocate_l1_cont(0x4000, 0x2000, 0, num_l1_entries); | |
11fdf7f2 | 235 | ASSERT_EQ(i2.length, 0u); |
a8e16298 | 236 | i2 = al1.allocate_l1_cont(0x4000, 0x1000, 0, num_l1_entries); |
11fdf7f2 | 237 | ASSERT_EQ(i2.length, 0x1000u); |
a8e16298 TL |
238 | |
239 | al1.free_l1(i3); | |
240 | i3 = al1.allocate_l1_cont(0x6000, 0x3000, 0, num_l1_entries); | |
11fdf7f2 | 241 | ASSERT_EQ(i3.length, 0u); |
a8e16298 | 242 | i3 = al1.allocate_l1_cont(0x6000, 0x1000, 0, num_l1_entries); |
11fdf7f2 TL |
243 | ASSERT_EQ(i3.length, 0x2000u); |
244 | ASSERT_EQ(0u, al1.debug_get_free()); | |
a8e16298 TL |
245 | |
246 | std::cout << "Done L1" << std::endl; | |
247 | } | |
248 | ||
249 | TEST(TestAllocatorLevel01, test_l2) | |
250 | { | |
251 | TestAllocatorLevel02 al2; | |
252 | uint64_t num_l2_entries = 64;// *512; | |
253 | uint64_t capacity = num_l2_entries * 256 * 512 * 4096; | |
254 | al2.init(capacity, 0x1000); | |
255 | std::cout << "Init L2" << std::endl; | |
256 | ||
257 | uint64_t allocated1 = 0; | |
258 | interval_vector_t a1; | |
259 | al2.allocate_l2(0x2000, 0x2000, &allocated1, &a1); | |
11fdf7f2 TL |
260 | ASSERT_EQ(allocated1, 0x2000u); |
261 | ASSERT_EQ(a1[0].offset, 0u); | |
262 | ASSERT_EQ(a1[0].length, 0x2000u); | |
a8e16298 TL |
263 | |
264 | // limit query range in debug_get_free for the sake of performance | |
11fdf7f2 TL |
265 | ASSERT_EQ(0x2000u, al2.debug_get_allocated(0, 1)); |
266 | ASSERT_EQ(0u, al2.debug_get_allocated(1, 2)); | |
a8e16298 TL |
267 | |
268 | uint64_t allocated2 = 0; | |
269 | interval_vector_t a2; | |
270 | al2.allocate_l2(0x2000, 0x2000, &allocated2, &a2); | |
11fdf7f2 TL |
271 | ASSERT_EQ(allocated2, 0x2000u); |
272 | ASSERT_EQ(a2[0].offset, 0x2000u); | |
273 | ASSERT_EQ(a2[0].length, 0x2000u); | |
a8e16298 | 274 | // limit query range in debug_get_free for the sake of performance |
11fdf7f2 TL |
275 | ASSERT_EQ(0x4000u, al2.debug_get_allocated(0, 1)); |
276 | ASSERT_EQ(0u, al2.debug_get_allocated(1, 2)); | |
a8e16298 TL |
277 | |
278 | al2.free_l2(a1); | |
279 | ||
280 | allocated2 = 0; | |
281 | a2.clear(); | |
282 | al2.allocate_l2(0x1000, 0x1000, &allocated2, &a2); | |
11fdf7f2 TL |
283 | ASSERT_EQ(allocated2, 0x1000u); |
284 | ASSERT_EQ(a2[0].offset, 0x0000u); | |
285 | ASSERT_EQ(a2[0].length, 0x1000u); | |
a8e16298 | 286 | // limit query range in debug_get_free for the sake of performance |
11fdf7f2 TL |
287 | ASSERT_EQ(0x3000u, al2.debug_get_allocated(0, 1)); |
288 | ASSERT_EQ(0u, al2.debug_get_allocated(1, 2)); | |
a8e16298 TL |
289 | |
290 | uint64_t allocated3 = 0; | |
291 | interval_vector_t a3; | |
292 | al2.allocate_l2(0x2000, 0x1000, &allocated3, &a3); | |
11fdf7f2 TL |
293 | ASSERT_EQ(allocated3, 0x2000u); |
294 | ASSERT_EQ(a3.size(), 2u); | |
295 | ASSERT_EQ(a3[0].offset, 0x1000u); | |
296 | ASSERT_EQ(a3[0].length, 0x1000u); | |
297 | ASSERT_EQ(a3[1].offset, 0x4000u); | |
298 | ASSERT_EQ(a3[1].length, 0x1000u); | |
a8e16298 | 299 | // limit query range in debug_get_free for the sake of performance |
11fdf7f2 TL |
300 | ASSERT_EQ(0x5000u, al2.debug_get_allocated(0, 1)); |
301 | ASSERT_EQ(0u, al2.debug_get_allocated(1, 2)); | |
a8e16298 TL |
302 | { |
303 | interval_vector_t r; | |
304 | r.emplace_back(0x0, 0x5000); | |
305 | al2.free_l2(r); | |
306 | } | |
307 | ||
308 | a3.clear(); | |
309 | allocated3 = 0; | |
310 | al2.allocate_l2(_1m, _1m, &allocated3, &a3); | |
11fdf7f2 TL |
311 | ASSERT_EQ(a3.size(), 1u); |
312 | ASSERT_EQ(a3[0].offset, 0u); | |
a8e16298 TL |
313 | ASSERT_EQ(a3[0].length, _1m); |
314 | ||
315 | al2.free_l2(a3); | |
316 | ||
317 | a3.clear(); | |
318 | allocated3 = 0; | |
319 | al2.allocate_l2(4 * _1m, _1m, &allocated3, &a3); | |
11fdf7f2 TL |
320 | ASSERT_EQ(a3.size(), 1u); |
321 | ASSERT_EQ(a3[0].offset, 0u); | |
a8e16298 TL |
322 | ASSERT_EQ(a3[0].length, 4 * _1m); |
323 | ||
324 | al2.free_l2(a3); | |
325 | ||
326 | #ifndef _DEBUG | |
327 | for (uint64_t i = 0; i < capacity; i += 0x1000) { | |
328 | uint64_t allocated4 = 0; | |
329 | interval_vector_t a4; | |
330 | al2.allocate_l2(0x1000, 0x1000, &allocated4, &a4); | |
11fdf7f2 | 331 | ASSERT_EQ(a4.size(), 1u); |
a8e16298 | 332 | ASSERT_EQ(a4[0].offset, i); |
11fdf7f2 | 333 | ASSERT_EQ(a4[0].length, 0x1000u); |
a8e16298 TL |
334 | if (0 == (i % (1 * 1024 * _1m))) { |
335 | std::cout << "alloc1 " << i / 1024 / 1024 << " mb of " | |
336 | << capacity / 1024 / 1024 << std::endl; | |
337 | } | |
338 | } | |
339 | #else | |
340 | for (uint64_t i = 0; i < capacity; i += _2m) { | |
341 | uint64_t allocated4 = 0; | |
342 | interval_vector_t a4; | |
343 | al2.allocate_l2(_2m, _2m, &allocated4, &a4); | |
344 | ASSERT_EQ(a4.size(), 1); | |
345 | ASSERT_EQ(a4[0].offset, i); | |
346 | ASSERT_EQ(a4[0].length, _2m); | |
347 | if (0 == (i % (1 * 1024 * _1m))) { | |
348 | std::cout << "alloc1 " << i / 1024 / 1024 << " mb of " | |
349 | << capacity / 1024 / 1024 << std::endl; | |
350 | } | |
351 | } | |
352 | #endif | |
353 | ||
11fdf7f2 | 354 | ASSERT_EQ(0u, al2.debug_get_free()); |
a8e16298 TL |
355 | for (uint64_t i = 0; i < capacity; i += _1m) { |
356 | interval_vector_t r; | |
357 | r.emplace_back(i, _1m); | |
358 | al2.free_l2(r); | |
359 | if (0 == (i % (1 * 1024 * _1m))) { | |
360 | std::cout << "free1 " << i / 1024 / 1024 << " mb of " | |
361 | << capacity / 1024 / 1024 << std::endl; | |
362 | } | |
363 | } | |
364 | ASSERT_EQ(capacity, al2.debug_get_free()); | |
365 | ||
366 | for (uint64_t i = 0; i < capacity; i += _1m) { | |
367 | uint64_t allocated4 = 0; | |
368 | interval_vector_t a4; | |
369 | al2.allocate_l2(_1m, _1m, &allocated4, &a4); | |
11fdf7f2 | 370 | ASSERT_EQ(a4.size(), 1u); |
a8e16298 TL |
371 | ASSERT_EQ(allocated4, _1m); |
372 | ASSERT_EQ(a4[0].offset, i); | |
373 | ASSERT_EQ(a4[0].length, _1m); | |
374 | if (0 == (i % (1 * 1024 * _1m))) { | |
375 | std::cout << "alloc2 " << i / 1024 / 1024 << " mb of " | |
376 | << capacity / 1024 / 1024 << std::endl; | |
377 | } | |
378 | } | |
11fdf7f2 | 379 | ASSERT_EQ(0u, al2.debug_get_free()); |
a8e16298 TL |
380 | uint64_t allocated4 = 0; |
381 | interval_vector_t a4; | |
382 | al2.allocate_l2(_1m, _1m, &allocated4, &a4); | |
11fdf7f2 | 383 | ASSERT_EQ(a4.size(), 0u); |
a8e16298 | 384 | al2.allocate_l2(0x1000, 0x1000, &allocated4, &a4); |
11fdf7f2 | 385 | ASSERT_EQ(a4.size(), 0u); |
a8e16298 TL |
386 | |
387 | for (uint64_t i = 0; i < capacity; i += 0x2000) { | |
388 | interval_vector_t r; | |
389 | r.emplace_back(i, 0x1000); | |
390 | al2.free_l2(r); | |
391 | if (0 == (i % (1 * 1024 * _1m))) { | |
392 | std::cout << "free2 " << i / 1024 / 1024 << " mb of " | |
393 | << capacity / 1024 / 1024 << std::endl; | |
394 | } | |
395 | } | |
396 | ASSERT_EQ(capacity / 2, al2.debug_get_free()); | |
397 | ||
398 | // unable to allocate due to fragmentation | |
399 | al2.allocate_l2(_1m, _1m, &allocated4, &a4); | |
11fdf7f2 | 400 | ASSERT_EQ(a4.size(), 0u); |
a8e16298 TL |
401 | |
402 | for (uint64_t i = 0; i < capacity; i += 2 * _1m) { | |
403 | a4.clear(); | |
404 | allocated4 = 0; | |
405 | al2.allocate_l2(_1m, 0x1000, &allocated4, &a4); | |
406 | ASSERT_EQ(a4.size(), _1m / 0x1000); | |
407 | ASSERT_EQ(allocated4, _1m); | |
408 | ASSERT_EQ(a4[0].offset, i); | |
11fdf7f2 | 409 | ASSERT_EQ(a4[0].length, 0x1000u); |
a8e16298 TL |
410 | if (0 == (i % (1 * 1024 * _1m))) { |
411 | std::cout << "alloc3 " << i / 1024 / 1024 << " mb of " | |
412 | << capacity / 1024 / 1024 << std::endl; | |
413 | } | |
414 | } | |
11fdf7f2 | 415 | ASSERT_EQ(0u, al2.debug_get_free()); |
a8e16298 TL |
416 | |
417 | std::cout << "Done L2" << std::endl; | |
418 | } | |
419 | ||
420 | TEST(TestAllocatorLevel01, test_l2_huge) | |
421 | { | |
422 | TestAllocatorLevel02 al2; | |
423 | uint64_t num_l2_entries = 4 * 512; | |
424 | uint64_t capacity = num_l2_entries * 256 * 512 * 4096; // 1 TB | |
425 | al2.init(capacity, 0x1000); | |
426 | std::cout << "Init L2 Huge" << std::endl; | |
427 | ||
428 | for (uint64_t i = 0; i < capacity; i += _1m) { | |
429 | uint64_t allocated4 = 0; | |
430 | interval_vector_t a4; | |
431 | al2.allocate_l2(0x1000, 0x1000, &allocated4, &a4); | |
11fdf7f2 TL |
432 | ASSERT_EQ(a4.size(), 1u); |
433 | ASSERT_EQ(allocated4, 0x1000u); | |
a8e16298 | 434 | ASSERT_EQ(a4[0].offset, i); |
11fdf7f2 | 435 | ASSERT_EQ(a4[0].length, 0x1000u); |
a8e16298 TL |
436 | |
437 | allocated4 = 0; | |
438 | a4.clear(); | |
439 | al2.allocate_l2(_1m - 0x1000, 0x1000, &allocated4, &a4); | |
11fdf7f2 | 440 | ASSERT_EQ(a4.size(), 1u); |
a8e16298 TL |
441 | ASSERT_EQ(allocated4, _1m - 0x1000); |
442 | ASSERT_EQ(a4[0].offset, i + 0x1000); | |
443 | ASSERT_EQ(a4[0].length, _1m - 0x1000); | |
444 | if (0 == (i % (1 * 1024 * _1m))) { | |
445 | std::cout << "allocH " << i / 1024 / 1024 << " mb of " | |
446 | << capacity / 1024 / 1024 << std::endl; | |
447 | } | |
448 | } | |
449 | for (uint64_t i = 0; i < capacity; i += _1m) { | |
450 | interval_vector_t a4; | |
451 | a4.emplace_back(i, 0x1000); | |
452 | al2.free_l2(a4); | |
453 | if (0 == (i % (1 * 1024 * _1m))) { | |
454 | std::cout << "freeH1 " << i / 1024 / 1024 << " mb of " | |
455 | << capacity / 1024 / 1024 << std::endl; | |
456 | } | |
457 | } | |
458 | { | |
459 | std::cout << "Try" << std::endl; | |
460 | time_t t = time(NULL); | |
461 | for (int i = 0; i < 10; ++i) { | |
462 | uint64_t allocated = 0; | |
463 | interval_vector_t a; | |
464 | al2.allocate_l2(0x2000, 0x2000, &allocated, &a); | |
11fdf7f2 | 465 | ASSERT_EQ(a.size(), 0u); |
a8e16298 TL |
466 | } |
467 | std::cout << "End try in " << time(NULL) - t << " seconds" << std::endl; | |
468 | } | |
469 | { | |
470 | std::cout << "Try" << std::endl; | |
471 | time_t t = time(NULL); | |
472 | for (int i = 0; i < 10; ++i) { | |
473 | uint64_t allocated = 0; | |
474 | interval_vector_t a; | |
475 | al2.allocate_l2(_2m, _2m, &allocated, &a); | |
11fdf7f2 | 476 | ASSERT_EQ(a.size(), 0u); |
a8e16298 TL |
477 | } |
478 | std::cout << "End try in " << time(NULL) - t << " seconds" << std::endl; | |
479 | } | |
480 | ||
481 | ASSERT_EQ((capacity / _1m) * 0x1000, al2.debug_get_free()); | |
482 | ||
483 | std::cout << "Done L2 Huge" << std::endl; | |
484 | } | |
485 | ||
486 | TEST(TestAllocatorLevel01, test_l2_unaligned) | |
487 | { | |
488 | { | |
489 | TestAllocatorLevel02 al2; | |
490 | uint64_t num_l2_entries = 3; | |
491 | uint64_t capacity = num_l2_entries * 256 * 512 * 4096; // 3x512 MB | |
492 | al2.init(capacity, 0x1000); | |
493 | std::cout << "Init L2 Unaligned" << std::endl; | |
494 | ||
495 | for (uint64_t i = 0; i < capacity; i += _1m / 2) { | |
496 | uint64_t allocated4 = 0; | |
497 | interval_vector_t a4; | |
498 | al2.allocate_l2(_1m / 2, _1m / 2, &allocated4, &a4); | |
11fdf7f2 | 499 | ASSERT_EQ(a4.size(), 1u); |
a8e16298 TL |
500 | ASSERT_EQ(allocated4, _1m / 2); |
501 | ASSERT_EQ(a4[0].offset, i); | |
502 | ASSERT_EQ(a4[0].length, _1m / 2); | |
503 | if (0 == (i % (1 * 1024 * _1m))) { | |
504 | std::cout << "allocU " << i / 1024 / 1024 << " mb of " | |
505 | << capacity / 1024 / 1024 << std::endl; | |
506 | } | |
507 | } | |
11fdf7f2 | 508 | ASSERT_EQ(0u, al2.debug_get_free()); |
a8e16298 TL |
509 | { |
510 | // no space to allocate | |
511 | uint64_t allocated4 = 0; | |
512 | interval_vector_t a4; | |
513 | al2.allocate_l2(0x1000, 0x1000, &allocated4, &a4); | |
11fdf7f2 | 514 | ASSERT_EQ(a4.size(), 0u); |
a8e16298 TL |
515 | } |
516 | } | |
517 | { | |
518 | TestAllocatorLevel02 al2; | |
519 | uint64_t capacity = 500 * 512 * 4096; // 500x2 MB | |
520 | al2.init(capacity, 0x1000); | |
521 | std::cout << ("Init L2 Unaligned2\n"); | |
522 | for (uint64_t i = 0; i < capacity; i += _1m / 2) { | |
523 | uint64_t allocated4 = 0; | |
524 | interval_vector_t a4; | |
525 | al2.allocate_l2(_1m / 2, _1m / 2, &allocated4, &a4); | |
11fdf7f2 | 526 | ASSERT_EQ(a4.size(), 1u); |
a8e16298 TL |
527 | ASSERT_EQ(allocated4, _1m / 2); |
528 | ASSERT_EQ(a4[0].offset, i); | |
529 | ASSERT_EQ(a4[0].length, _1m / 2); | |
530 | if (0 == (i % (1 * 1024 * _1m))) { | |
531 | std::cout << "allocU2 " << i / 1024 / 1024 << " mb of " | |
532 | << capacity / 1024 / 1024 << std::endl; | |
533 | } | |
534 | } | |
11fdf7f2 | 535 | ASSERT_EQ(0u, al2.debug_get_free()); |
a8e16298 TL |
536 | { |
537 | // no space to allocate | |
538 | uint64_t allocated4 = 0; | |
539 | interval_vector_t a4; | |
540 | al2.allocate_l2(0x1000, 0x1000, &allocated4, &a4); | |
11fdf7f2 | 541 | ASSERT_EQ(a4.size(), 0u); |
a8e16298 TL |
542 | } |
543 | } | |
544 | ||
545 | { | |
546 | TestAllocatorLevel02 al2; | |
547 | uint64_t capacity = 100 * 512 * 4096 + 127 * 4096; | |
548 | al2.init(capacity, 0x1000); | |
549 | std::cout << "Init L2 Unaligned2" << std::endl; | |
550 | for (uint64_t i = 0; i < capacity; i += 0x1000) { | |
551 | uint64_t allocated4 = 0; | |
552 | interval_vector_t a4; | |
553 | al2.allocate_l2(0x1000, 0x1000, &allocated4, &a4); | |
11fdf7f2 TL |
554 | ASSERT_EQ(a4.size(), 1u); |
555 | ASSERT_EQ(allocated4, 0x1000u); | |
a8e16298 | 556 | ASSERT_EQ(a4[0].offset, i); |
11fdf7f2 | 557 | ASSERT_EQ(a4[0].length, 0x1000u); |
a8e16298 | 558 | } |
11fdf7f2 | 559 | ASSERT_EQ(0u, al2.debug_get_free()); |
a8e16298 TL |
560 | { |
561 | // no space to allocate | |
562 | uint64_t allocated4 = 0; | |
563 | interval_vector_t a4; | |
564 | al2.allocate_l2(0x1000, 0x1000, &allocated4, &a4); | |
11fdf7f2 | 565 | ASSERT_EQ(a4.size(), 0u); |
a8e16298 TL |
566 | } |
567 | } | |
568 | { | |
569 | TestAllocatorLevel02 al2; | |
570 | uint64_t capacity = 3 * 4096; | |
571 | al2.init(capacity, 0x1000); | |
572 | std::cout << "Init L2 Unaligned2" << std::endl; | |
573 | for (uint64_t i = 0; i < capacity; i += 0x1000) { | |
574 | uint64_t allocated4 = 0; | |
575 | interval_vector_t a4; | |
576 | al2.allocate_l2(0x1000, 0x1000, &allocated4, &a4); | |
11fdf7f2 TL |
577 | ASSERT_EQ(a4.size(), 1u); |
578 | ASSERT_EQ(allocated4, 0x1000u); | |
a8e16298 | 579 | ASSERT_EQ(a4[0].offset, i); |
11fdf7f2 | 580 | ASSERT_EQ(a4[0].length, 0x1000u); |
a8e16298 | 581 | } |
11fdf7f2 | 582 | ASSERT_EQ(0u, al2.debug_get_free()); |
a8e16298 TL |
583 | { |
584 | // no space to allocate | |
585 | uint64_t allocated4 = 0; | |
586 | interval_vector_t a4; | |
587 | al2.allocate_l2(0x1000, 0x1000, &allocated4, &a4); | |
11fdf7f2 | 588 | ASSERT_EQ(a4.size(), 0u); |
a8e16298 TL |
589 | } |
590 | } | |
591 | ||
592 | std::cout << "Done L2 Unaligned" << std::endl; | |
593 | } | |
594 | ||
595 | TEST(TestAllocatorLevel01, test_l2_contiguous_alignment) | |
596 | { | |
597 | { | |
598 | TestAllocatorLevel02 al2; | |
599 | uint64_t num_l2_entries = 3; | |
600 | uint64_t capacity = num_l2_entries * 256 * 512 * 4096; // 3x512 MB | |
601 | uint64_t num_chunks = capacity / 4096; | |
602 | al2.init(capacity, 4096); | |
603 | std::cout << "Init L2 cont aligned" << std::endl; | |
604 | ||
605 | std::map<size_t, size_t> bins_overall; | |
606 | al2.collect_stats(bins_overall); | |
607 | ASSERT_EQ(bins_overall.size(), 1u); | |
608 | // std::cout<<bins_overall.begin()->first << std::endl; | |
609 | ASSERT_EQ(bins_overall[cbits(num_chunks) - 1], 1u); | |
610 | ||
611 | for (uint64_t i = 0; i < capacity / 2; i += _1m) { | |
612 | uint64_t allocated4 = 0; | |
613 | interval_vector_t a4; | |
614 | al2.allocate_l2(_1m, _1m, &allocated4, &a4); | |
11fdf7f2 | 615 | ASSERT_EQ(a4.size(), 1u); |
a8e16298 TL |
616 | ASSERT_EQ(allocated4, _1m); |
617 | ASSERT_EQ(a4[0].offset, i); | |
618 | ASSERT_EQ(a4[0].length, _1m); | |
619 | } | |
620 | ASSERT_EQ(capacity / 2, al2.debug_get_free()); | |
621 | ||
622 | bins_overall.clear(); | |
623 | al2.collect_stats(bins_overall); | |
624 | ASSERT_EQ(bins_overall.size(), 1u); | |
625 | ASSERT_EQ(bins_overall[cbits(num_chunks / 2) - 1], 1u); | |
626 | ||
627 | { | |
628 | size_t to_release = 2 * _1m + 0x1000; | |
629 | // release 2M + 4K at the beginning | |
630 | interval_vector_t r; | |
631 | r.emplace_back(0, to_release); | |
632 | al2.free_l2(r); | |
633 | bins_overall.clear(); | |
634 | al2.collect_stats(bins_overall); | |
635 | ASSERT_EQ(bins_overall.size(), 2u); | |
636 | ASSERT_EQ(bins_overall[cbits(to_release / 0x1000) - 1], 1u); | |
637 | ASSERT_EQ(bins_overall[cbits(num_chunks / 2) - 1], 1u); | |
638 | } | |
639 | { | |
640 | // allocate 4K within the deallocated range | |
641 | uint64_t allocated4 = 0; | |
642 | interval_vector_t a4; | |
643 | al2.allocate_l2(0x1000, 0x1000, &allocated4, &a4); | |
644 | ASSERT_EQ(a4.size(), 1u); | |
645 | ASSERT_EQ(allocated4, 0x1000u); | |
646 | ASSERT_EQ(a4[0].offset, 0u); | |
647 | ASSERT_EQ(a4[0].length, 0x1000u); | |
648 | bins_overall.clear(); | |
649 | al2.collect_stats(bins_overall); | |
650 | ASSERT_EQ(bins_overall.size(), 2u); | |
651 | ASSERT_EQ(bins_overall[cbits(2 * _1m / 0x1000) - 1], 1u); | |
652 | ASSERT_EQ(bins_overall[cbits(num_chunks / 2) - 1], 1u); | |
653 | } | |
654 | { | |
655 | // allocate 1M - should go to the second 1M chunk | |
656 | uint64_t allocated4 = 0; | |
657 | interval_vector_t a4; | |
658 | al2.allocate_l2(_1m, _1m, &allocated4, &a4); | |
11fdf7f2 | 659 | ASSERT_EQ(a4.size(), 1u); |
a8e16298 TL |
660 | ASSERT_EQ(allocated4, _1m); |
661 | ASSERT_EQ(a4[0].offset, _1m); | |
662 | ASSERT_EQ(a4[0].length, _1m); | |
663 | bins_overall.clear(); | |
664 | al2.collect_stats(bins_overall); | |
665 | ASSERT_EQ(bins_overall.size(), 3u); | |
666 | ASSERT_EQ(bins_overall[0], 1u); | |
667 | ASSERT_EQ(bins_overall[cbits((_1m - 0x1000) / 0x1000) - 1], 1u); | |
668 | ASSERT_EQ(bins_overall[cbits(num_chunks / 2) - 1], 1u); | |
669 | } | |
670 | { | |
671 | // and allocate yet another 8K within the deallocated range | |
672 | uint64_t allocated4 = 0; | |
673 | interval_vector_t a4; | |
674 | al2.allocate_l2(0x2000, 0x1000, &allocated4, &a4); | |
675 | ASSERT_EQ(a4.size(), 1u); | |
676 | ASSERT_EQ(allocated4, 0x2000u); | |
677 | ASSERT_EQ(a4[0].offset, 0x1000u); | |
678 | ASSERT_EQ(a4[0].length, 0x2000u); | |
679 | bins_overall.clear(); | |
680 | al2.collect_stats(bins_overall); | |
681 | ASSERT_EQ(bins_overall[0], 1u); | |
682 | ASSERT_EQ(bins_overall[cbits((_1m - 0x3000) / 0x1000) - 1], 1u); | |
683 | ASSERT_EQ(bins_overall[cbits(num_chunks / 2) - 1], 1u); | |
684 | } | |
685 | { | |
686 | // release just allocated 1M | |
687 | interval_vector_t r; | |
688 | r.emplace_back(_1m, _1m); | |
689 | al2.free_l2(r); | |
690 | bins_overall.clear(); | |
691 | al2.collect_stats(bins_overall); | |
692 | ASSERT_EQ(bins_overall.size(), 2u); | |
693 | ASSERT_EQ(bins_overall[cbits((2 * _1m - 0x3000) / 0x1000) - 1], 1u); | |
694 | ASSERT_EQ(bins_overall[cbits(num_chunks / 2) - 1], 1u); | |
695 | } | |
696 | { | |
697 | // allocate 3M - should go to the second 1M chunk and @capacity/2 | |
698 | uint64_t allocated4 = 0; | |
699 | interval_vector_t a4; | |
700 | al2.allocate_l2(3 * _1m, _1m, &allocated4, &a4); | |
11fdf7f2 | 701 | ASSERT_EQ(a4.size(), 2u); |
a8e16298 TL |
702 | ASSERT_EQ(allocated4, 3 * _1m); |
703 | ASSERT_EQ(a4[0].offset, _1m); | |
704 | ASSERT_EQ(a4[0].length, _1m); | |
705 | ASSERT_EQ(a4[1].offset, capacity / 2); | |
706 | ASSERT_EQ(a4[1].length, 2 * _1m); | |
707 | bins_overall.clear(); | |
708 | al2.collect_stats(bins_overall); | |
709 | ASSERT_EQ(bins_overall.size(), 3u); | |
710 | ASSERT_EQ(bins_overall[0], 1u); | |
711 | ASSERT_EQ(bins_overall[cbits((_1m - 0x3000) / 0x1000) - 1], 1u); | |
712 | ASSERT_EQ(bins_overall[cbits((num_chunks - 512) / 2) - 1], 1u); | |
713 | } | |
714 | { | |
715 | // release allocated 1M in the second meg chunk except | |
716 | // the first 4K chunk | |
717 | interval_vector_t r; | |
718 | r.emplace_back(_1m + 0x1000, _1m); | |
719 | al2.free_l2(r); | |
720 | bins_overall.clear(); | |
721 | al2.collect_stats(bins_overall); | |
722 | ASSERT_EQ(bins_overall.size(), 3u); | |
723 | ASSERT_EQ(bins_overall[cbits(_1m / 0x1000) - 1], 1u); | |
724 | ASSERT_EQ(bins_overall[cbits((_1m - 0x3000) / 0x1000) - 1], 1u); | |
725 | ASSERT_EQ(bins_overall[cbits((num_chunks - 512) / 2) - 1], 1u); | |
726 | } | |
727 | { | |
728 | // release 2M @(capacity / 2) | |
729 | interval_vector_t r; | |
730 | r.emplace_back(capacity / 2, 2 * _1m); | |
731 | al2.free_l2(r); | |
732 | bins_overall.clear(); | |
733 | al2.collect_stats(bins_overall); | |
734 | ASSERT_EQ(bins_overall.size(), 3u); | |
735 | ASSERT_EQ(bins_overall[cbits(_1m / 0x1000) - 1], 1u); | |
736 | ASSERT_EQ(bins_overall[cbits((_1m - 0x3000) / 0x1000) - 1], 1u); | |
737 | ASSERT_EQ(bins_overall[cbits((num_chunks) / 2) - 1], 1u); | |
738 | } | |
739 | { | |
740 | // allocate 4x512K - should go to the second halves of | |
741 | // the first and second 1M chunks and @(capacity / 2) | |
742 | uint64_t allocated4 = 0; | |
743 | interval_vector_t a4; | |
744 | al2.allocate_l2(2 * _1m, _1m / 2, &allocated4, &a4); | |
11fdf7f2 | 745 | ASSERT_EQ(a4.size(), 3u); |
a8e16298 TL |
746 | ASSERT_EQ(allocated4, 2 * _1m); |
747 | ASSERT_EQ(a4[0].offset, _1m / 2); | |
748 | ASSERT_EQ(a4[0].length, _1m / 2); | |
749 | ASSERT_EQ(a4[1].offset, _1m + _1m / 2); | |
750 | ASSERT_EQ(a4[1].length, _1m / 2); | |
751 | ASSERT_EQ(a4[2].offset, capacity / 2); | |
752 | ASSERT_EQ(a4[2].length, _1m); | |
753 | ||
754 | bins_overall.clear(); | |
755 | al2.collect_stats(bins_overall); | |
756 | ASSERT_EQ(bins_overall.size(), 3u); | |
757 | ASSERT_EQ(bins_overall[0], 1u); | |
758 | // below we have 512K - 4K & 512K - 12K chunks which both fit into | |
759 | // the same bin = 6 | |
760 | ASSERT_EQ(bins_overall[6], 2u); | |
761 | ASSERT_EQ(bins_overall[cbits((num_chunks - 256) / 2) - 1], 1u); | |
762 | ||
763 | } | |
764 | { | |
765 | // cleanup first 2M except except the last 4K chunk | |
766 | interval_vector_t r; | |
767 | r.emplace_back(0, 2 * _1m - 0x1000); | |
768 | al2.free_l2(r); | |
769 | bins_overall.clear(); | |
770 | al2.collect_stats(bins_overall); | |
771 | ||
772 | ASSERT_EQ(bins_overall.size(), 3u); | |
773 | ASSERT_EQ(bins_overall[0], 1u); | |
774 | ASSERT_EQ(bins_overall[cbits((_2m - 0x1000) / 0x1000) - 1], 1u); | |
775 | ASSERT_EQ(bins_overall[cbits((num_chunks - 256) / 2) - 1], 1u); | |
776 | } | |
777 | { | |
778 | // release 2M @(capacity / 2) | |
779 | interval_vector_t r; | |
780 | r.emplace_back(capacity / 2, 2 * _1m); | |
781 | al2.free_l2(r); | |
782 | bins_overall.clear(); | |
783 | al2.collect_stats(bins_overall); | |
784 | ||
785 | ASSERT_EQ(bins_overall.size(), 3u); | |
786 | ASSERT_EQ(bins_overall[0], 1u); | |
787 | ASSERT_EQ(bins_overall[cbits((_2m - 0x1000) / 0x1000) - 1], 1u); | |
788 | ASSERT_EQ(bins_overall[cbits(num_chunks / 2) - 1], 1u); | |
789 | } | |
790 | { | |
791 | // allocate 132M using 4M granularity should go to (capacity / 2) | |
792 | uint64_t allocated4 = 0; | |
793 | interval_vector_t a4; | |
794 | al2.allocate_l2(132 * _1m, 4 * _1m , &allocated4, &a4); | |
11fdf7f2 | 795 | ASSERT_EQ(a4.size(), 1u); |
a8e16298 TL |
796 | ASSERT_EQ(a4[0].offset, capacity / 2); |
797 | ASSERT_EQ(a4[0].length, 132 * _1m); | |
798 | ||
799 | bins_overall.clear(); | |
800 | al2.collect_stats(bins_overall); | |
801 | ASSERT_EQ(bins_overall.size(), 3u); | |
802 | } | |
803 | { | |
804 | // cleanup left 4K chunk in the first 2M | |
805 | interval_vector_t r; | |
806 | r.emplace_back(2 * _1m - 0x1000, 0x1000); | |
807 | al2.free_l2(r); | |
808 | bins_overall.clear(); | |
809 | al2.collect_stats(bins_overall); | |
810 | ||
811 | ASSERT_EQ(bins_overall.size(), 2u); | |
812 | } | |
813 | { | |
814 | // release 132M @(capacity / 2) | |
815 | interval_vector_t r; | |
816 | r.emplace_back(capacity / 2, 132 * _1m); | |
817 | al2.free_l2(r); | |
818 | } | |
819 | { | |
820 | // allocate 132M using 2M granularity should go to the first chunk and to | |
821 | // (capacity / 2) | |
822 | uint64_t allocated4 = 0; | |
823 | interval_vector_t a4; | |
824 | al2.allocate_l2(132 * _1m, 2 * _1m , &allocated4, &a4); | |
11fdf7f2 TL |
825 | ASSERT_EQ(a4.size(), 2u); |
826 | ASSERT_EQ(a4[0].offset, 0u); | |
a8e16298 TL |
827 | ASSERT_EQ(a4[0].length, 2 * _1m); |
828 | ASSERT_EQ(a4[1].offset, capacity / 2); | |
829 | ASSERT_EQ(a4[1].length, 130 * _1m); | |
830 | } | |
831 | { | |
832 | // release 130M @(capacity / 2) | |
833 | interval_vector_t r; | |
834 | r.emplace_back(capacity / 2, 132 * _1m); | |
835 | al2.free_l2(r); | |
836 | } | |
837 | { | |
838 | // release 4K~16K | |
839 | // release 28K~32K | |
840 | // release 68K~24K | |
841 | interval_vector_t r; | |
842 | r.emplace_back(0x1000, 0x4000); | |
843 | r.emplace_back(0x7000, 0x8000); | |
844 | r.emplace_back(0x11000, 0x6000); | |
845 | al2.free_l2(r); | |
846 | } | |
847 | { | |
848 | // allocate 32K using 16K granularity - should bypass the first | |
849 | // unaligned extent, use the second free extent partially given | |
850 | // the 16K alignment and then fallback to capacity / 2 | |
851 | uint64_t allocated4 = 0; | |
852 | interval_vector_t a4; | |
853 | al2.allocate_l2(0x8000, 0x4000, &allocated4, &a4); | |
11fdf7f2 TL |
854 | ASSERT_EQ(a4.size(), 2u); |
855 | ASSERT_EQ(a4[0].offset, 0x8000u); | |
856 | ASSERT_EQ(a4[0].length, 0x4000u); | |
a8e16298 | 857 | ASSERT_EQ(a4[1].offset, capacity / 2); |
11fdf7f2 | 858 | ASSERT_EQ(a4[1].length, 0x4000u); |
a8e16298 TL |
859 | } |
860 | ||
861 | } | |
862 | std::cout << "Done L2 cont aligned" << std::endl; | |
863 | } | |
864 | ||
865 | TEST(TestAllocatorLevel01, test_4G_alloc_bug) | |
866 | { | |
867 | { | |
868 | TestAllocatorLevel02 al2; | |
869 | uint64_t capacity = 0x8000 * _1m; // = 32GB | |
870 | al2.init(capacity, 0x10000); | |
871 | std::cout << "Init L2 cont aligned" << std::endl; | |
872 | ||
873 | uint64_t allocated4 = 0; | |
874 | interval_vector_t a4; | |
875 | al2.allocate_l2(_1m, _1m, &allocated4, &a4); | |
876 | ASSERT_EQ(a4.size(), 1u); // the bug caused no allocations here | |
877 | ASSERT_EQ(allocated4, _1m); | |
878 | ASSERT_EQ(a4[0].offset, 0u); | |
879 | ASSERT_EQ(a4[0].length, _1m); | |
880 | } | |
881 | } | |
882 | ||
883 | TEST(TestAllocatorLevel01, test_4G_alloc_bug2) | |
884 | { | |
885 | { | |
886 | TestAllocatorLevel02 al2; | |
887 | uint64_t capacity = 0x8000 * _1m; // = 32GB | |
888 | al2.init(capacity, 0x10000); | |
889 | ||
890 | for (uint64_t i = 0; i < capacity; i += _1m) { | |
891 | uint64_t allocated4 = 0; | |
892 | interval_vector_t a4; | |
893 | al2.allocate_l2(_1m, _1m, &allocated4, &a4); | |
894 | ASSERT_EQ(a4.size(), 1u); | |
895 | ASSERT_EQ(allocated4, _1m); | |
896 | ASSERT_EQ(a4[0].offset, i); | |
897 | ASSERT_EQ(a4[0].length, _1m); | |
898 | } | |
899 | ASSERT_EQ(0u , al2.debug_get_free()); | |
900 | ||
901 | interval_vector_t r; | |
902 | r.emplace_back(0x5fec30000, 0x13d0000); | |
903 | r.emplace_back(0x628000000, 0x80000000); | |
904 | r.emplace_back(0x6a8000000, 0x80000000); | |
905 | r.emplace_back(0x728100000, 0x70000); | |
906 | al2.free_l2(r); | |
907 | ||
908 | std::map<size_t, size_t> bins_overall; | |
909 | al2.collect_stats(bins_overall); | |
910 | ||
911 | uint64_t allocated4 = 0; | |
912 | interval_vector_t a4; | |
913 | al2.allocate_l2(0x3e000000, _1m, &allocated4, &a4); | |
914 | ASSERT_EQ(a4.size(), 2u); | |
915 | ASSERT_EQ(allocated4, 0x3e000000u); | |
916 | ASSERT_EQ(a4[0].offset, 0x5fed00000u); | |
917 | ASSERT_EQ(a4[0].length, 0x1300000u); | |
918 | ASSERT_EQ(a4[1].offset, 0x628000000u); | |
919 | ASSERT_EQ(a4[1].length, 0x3cd00000u); | |
920 | } | |
921 | } | |
922 | ||
923 | TEST(TestAllocatorLevel01, test_4G_alloc_bug3) | |
924 | { | |
925 | { | |
926 | TestAllocatorLevel02 al2; | |
927 | uint64_t capacity = 0x8000 * _1m; // = 32GB | |
928 | al2.init(capacity, 0x10000); | |
929 | std::cout << "Init L2 cont aligned" << std::endl; | |
930 | ||
931 | uint64_t allocated4 = 0; | |
932 | interval_vector_t a4; | |
933 | al2.allocate_l2(4096ull * _1m, _1m, &allocated4, &a4); | |
934 | ASSERT_EQ(a4.size(), 2u); // allocator has to split into 2 allocations | |
935 | ASSERT_EQ(allocated4, 4096ull * _1m); | |
936 | ASSERT_EQ(a4[0].offset, 0u); | |
937 | ASSERT_EQ(a4[0].length, 2048ull * _1m); | |
938 | ASSERT_EQ(a4[1].offset, 2048ull * _1m); | |
939 | ASSERT_EQ(a4[1].length, 2048ull * _1m); | |
940 | } | |
941 | } | |
e306af50 TL |
942 | |
943 | TEST(TestAllocatorLevel01, test_claim_free_l2) | |
944 | { | |
945 | TestAllocatorLevel02 al2; | |
946 | uint64_t num_l2_entries = 64;// *512; | |
947 | uint64_t capacity = num_l2_entries * 256 * 512 * 4096; | |
948 | al2.init(capacity, 0x1000); | |
949 | std::cout << "Init L2" << std::endl; | |
950 | ||
951 | uint64_t max_available = 0x20000; | |
952 | al2.mark_allocated(max_available, capacity - max_available); | |
953 | ||
954 | uint64_t allocated1 = 0; | |
955 | interval_vector_t a1; | |
956 | al2.allocate_l2(0x2000, 0x2000, &allocated1, &a1); | |
957 | ASSERT_EQ(allocated1, 0x2000u); | |
958 | ASSERT_EQ(a1[0].offset, 0u); | |
959 | ASSERT_EQ(a1[0].length, 0x2000u); | |
960 | ||
961 | uint64_t allocated2 = 0; | |
962 | interval_vector_t a2; | |
963 | al2.allocate_l2(0x2000, 0x2000, &allocated2, &a2); | |
964 | ASSERT_EQ(allocated2, 0x2000u); | |
965 | ASSERT_EQ(a2[0].offset, 0x2000u); | |
966 | ASSERT_EQ(a2[0].length, 0x2000u); | |
967 | ||
968 | uint64_t allocated3 = 0; | |
969 | interval_vector_t a3; | |
970 | al2.allocate_l2(0x3000, 0x3000, &allocated3, &a3); | |
971 | ASSERT_EQ(allocated3, 0x3000u); | |
972 | ASSERT_EQ(a3[0].offset, 0x4000u); | |
973 | ASSERT_EQ(a3[0].length, 0x3000u); | |
974 | ||
975 | al2.free_l2(a1); | |
976 | al2.free_l2(a3); | |
977 | ASSERT_EQ(max_available - 0x2000, al2.debug_get_free()); | |
978 | ||
979 | auto claimed = al2.claim_free_to_right(0x4000); | |
980 | ASSERT_EQ(max_available - 0x4000u, claimed); | |
981 | ASSERT_EQ(0x2000, al2.debug_get_free()); | |
982 | ||
983 | claimed = al2.claim_free_to_right(0x4000); | |
984 | ASSERT_EQ(0, claimed); | |
985 | ASSERT_EQ(0x2000, al2.debug_get_free()); | |
986 | ||
987 | claimed = al2.claim_free_to_left(0x2000); | |
988 | ASSERT_EQ(0x2000u, claimed); | |
989 | ASSERT_EQ(0, al2.debug_get_free()); | |
990 | ||
991 | claimed = al2.claim_free_to_left(0x2000); | |
992 | ASSERT_EQ(0, claimed); | |
993 | ASSERT_EQ(0, al2.debug_get_free()); | |
994 | ||
995 | ||
996 | al2.mark_free(0x3000, 0x4000); | |
997 | ASSERT_EQ(0x4000, al2.debug_get_free()); | |
998 | ||
999 | claimed = al2.claim_free_to_right(0x7000); | |
1000 | ASSERT_EQ(0, claimed); | |
1001 | ASSERT_EQ(0x4000, al2.debug_get_free()); | |
1002 | ||
1003 | claimed = al2.claim_free_to_right(0x6000); | |
1004 | ASSERT_EQ(0x1000, claimed); | |
1005 | ASSERT_EQ(0x3000, al2.debug_get_free()); | |
1006 | ||
1007 | claimed = al2.claim_free_to_right(0x6000); | |
1008 | ASSERT_EQ(0, claimed); | |
1009 | ASSERT_EQ(0x3000, al2.debug_get_free()); | |
1010 | ||
1011 | claimed = al2.claim_free_to_left(0x3000); | |
1012 | ASSERT_EQ(0u, claimed); | |
1013 | ASSERT_EQ(0x3000, al2.debug_get_free()); | |
1014 | ||
1015 | claimed = al2.claim_free_to_left(0x4000); | |
1016 | ASSERT_EQ(0x1000, claimed); | |
1017 | ASSERT_EQ(0x2000, al2.debug_get_free()); | |
1018 | ||
adb31ebb TL |
1019 | // claiming on the right boundary |
1020 | claimed = al2.claim_free_to_right(capacity); | |
1021 | ASSERT_EQ(0x0, claimed); | |
1022 | ASSERT_EQ(0x2000, al2.debug_get_free()); | |
1023 | ||
e306af50 TL |
1024 | // extend allocator space up to 64M |
1025 | auto max_available2 = 64 * 1024 * 1024; | |
1026 | al2.mark_free(max_available, max_available2 - max_available); | |
1027 | ASSERT_EQ(max_available2 - max_available + 0x2000, al2.debug_get_free()); | |
1028 | ||
1029 | // pin some allocations | |
1030 | al2.mark_allocated(0x400000 + 0x2000, 1000); | |
1031 | al2.mark_allocated(0x400000 + 0x5000, 1000); | |
1032 | al2.mark_allocated(0x400000 + 0x20000, 1000); | |
1033 | ASSERT_EQ(max_available2 - max_available - 0x1000, al2.debug_get_free()); | |
1034 | ||
1035 | claimed = al2.claim_free_to_left(0x403000); | |
1036 | ASSERT_EQ(0x0, claimed); | |
1037 | ||
1038 | claimed = al2.claim_free_to_left(0x404000); | |
1039 | ASSERT_EQ(0x1000, claimed); | |
1040 | ASSERT_EQ(max_available2 - max_available - 0x2000, al2.debug_get_free()); | |
1041 | ||
1042 | claimed = al2.claim_free_to_left(max_available); | |
1043 | ASSERT_EQ(0, claimed); | |
1044 | ||
1045 | claimed = al2.claim_free_to_left(0x400000); | |
1046 | ASSERT_EQ(0x3e0000, claimed); | |
1047 | ASSERT_EQ(max_available2 - max_available - 0x3e2000, al2.get_available()); | |
1048 | ASSERT_EQ(max_available2 - max_available - 0x3e2000, al2.debug_get_free()); | |
1049 | ||
1050 | claimed = al2.claim_free_to_right(0x407000); | |
1051 | ASSERT_EQ(0x19000, claimed); | |
1052 | ASSERT_EQ(max_available2 - max_available - 0x3e2000 - 0x19000, | |
1053 | al2.get_available()); | |
1054 | ASSERT_EQ(max_available2 - max_available - 0x3e2000 - 0x19000, | |
1055 | al2.debug_get_free()); | |
1056 | ||
1057 | claimed = al2.claim_free_to_right(0x407000); | |
1058 | ASSERT_EQ(0, claimed); | |
1059 | ||
1060 | claimed = al2.claim_free_to_right(0x430000); | |
1061 | ASSERT_EQ(max_available2 - 0x430000, claimed); | |
1062 | ASSERT_EQ(0x15000, | |
1063 | al2.get_available()); | |
1064 | ASSERT_EQ(0x15000, | |
1065 | al2.debug_get_free()); | |
1066 | } |