1#![feature(allocator_api)]
2#![feature(slice_ptr_get)]
3#![feature(linked_list_retain)]
4#![feature(linked_list_cursors)]
5#![feature(portable_simd)]
6#![feature(str_as_str)]
7
8extern crate alloc;
9extern crate core;
10
11pub mod arena;
12pub mod buffers;
13pub mod cpu;
14pub mod mem;
15pub mod dune;
16pub mod base;
17pub mod serde;
18
19pub use arena::Arena;
20pub use mem::*;
21
22#[cfg(test)]
23mod tests {
24 use crate::buffers::{buffer_find, RUMBuffer, RUMBufferIteratorExt};
25 use crate::cpu::{cpu_find, cpu_slice_to_array_padded};
26 use crate::mem::constants::*;
27 use crate::{as_slice_mut, direct_alloc, rumtk_arena_new, Arena};
28 use std::alloc::alloc;
29 use std::collections::{HashMap, VecDeque};
30
31 macro_rules! rumtk_benchmark_snippet {
32 ( $closure:expr ) => {{
33 use std::time::Instant;
34
35 let start = Instant::now();
36 let r = $closure();
37 let end = Instant::now();
38
39 let time = end - start;
40 let micros = time.as_micros();
41
42 (r, micros)
43 }};
44 }
45
46 #[test]
47 fn test_cpu_slice_to_array_padded() {
48 let expected = b"Hello World\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
49 let result = cpu_slice_to_array_padded::<32, 0>(b"Hello World");
50 assert_eq!(&result, expected, "Stack array was not properly padded!");
51 }
52
53 #[test]
54 fn test_cpu_slice_to_array_padded_newline() {
55 let expected = b"Hello World\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n";
56 let result = cpu_slice_to_array_padded::<32, b'\n'>(b"Hello World");
57 assert_eq!(&result, expected, "Stack array was not properly padded!");
58 }
59
60 #[test]
61 fn test_cpu_find_simd_aligned() {
62 let input = b"Hello World\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n00000000000000000000000000000000";
63 let expected = 6;
64 let result = cpu_find(input, b'W').unwrap();
65 assert_eq!(result, expected, "Failed to find needle in haystack!");
66 }
67
68 #[test]
69 fn test_cpu_find_simd_unaligned() {
70 let input = b"Hello World\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n";
71 let expected = 6;
72 let result = cpu_find(input, b'W').unwrap();
73 assert_eq!(result, expected, "Failed to find needle in haystack!");
74 }
75
76 #[test]
77 fn test_cpu_find_simd_unaligned_none() {
78 let input = b"Hello World\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n";
79 let expected = 6;
80 let result = cpu_find(input, b'\0');
81 assert!(result.is_none() || (result.unwrap() -1) < input.len(), "Succeeded to find needle in haystack when the search character is not part of the haystack!");
82 }
83
84 #[test]
85 fn test_buffer_find() {
86 let input = b"Hello World\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n";
87 let expected = 9;
88 let result = buffer_find(input, b"ld\n");
89
90 assert_eq!(result, expected, "Succeeded to find needle in haystack when the search character is not part of the haystack!");
91 }
92
93 #[test]
94 fn test_buffer_find2() {
95 let input = b"Hello World\n\n\n\n\n\n\nasdjklfkasjwaoia poaw ml;,\n\n\n\n\n\n\n\n\n\n\n\n\n";
96 let expected = 40;
97 let result = buffer_find(input, b"ml;");
98
99 assert_eq!(result, expected, "Succeeded to find needle in haystack when the search character is not part of the haystack!");
100 }
101
102 #[test]
103 fn test_buffer_split() {
104 let input = RUMBuffer::from(b"Hello World\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
105 let expected = 20;
106 let mut result = 0;
107
108 for _ in input.split_fast(b'\n') {
109 result += 1;
110 }
111
112 assert_eq!(result, expected, "Succeeded to find needle in haystack when the search character is not part of the haystack!");
113 }
114
115 #[test]
116 fn test_arena_direct_allocation() {
117
118 let (r, time) = rumtk_benchmark_snippet!(|| {
119 unsafe { as_slice_mut(direct_alloc(DEFAULT_GLOBAL_MB_ALLOCATION_LAYOUT), DEFAULT_GLOBAL_MB_ALLOCATION) }
120 });
121
122 assert_eq!(r.len(), DEFAULT_GLOBAL_MB_ALLOCATION);
123 assert!(time < 1000, "Allocation took long! => {}us", time)
124
125 }
126
127 #[test]
128 fn test_arena_basic_allocation() {
129 let (r, time) = rumtk_benchmark_snippet!(|| {
130 unsafe { as_slice_mut(alloc(DEFAULT_GLOBAL_MB_ALLOCATION_LAYOUT), DEFAULT_GLOBAL_MB_ALLOCATION) }
131 });
132
133 assert_eq!(r.len(), DEFAULT_GLOBAL_MB_ALLOCATION);
134 assert!(time < 310, "Allocation took long! => {}us", time)
135
136 }
137
138 #[test]
139 fn test_arena_allocate_and_use() {
140 let (r, time) = rumtk_benchmark_snippet!(|| {
141 let slice = unsafe { as_slice_mut(alloc(DEFAULT_GLOBAL_MB_ALLOCATION_LAYOUT), DEFAULT_GLOBAL_MB_ALLOCATION) };
142 let v = slice.to_vec();
143 let mut buffer = RUMBuffer::from(v);
144 let mut chunk = buffer.freeze();
145
146 for _ in 0..(DEFAULT_GLOBAL_MB_ALLOCATION/5) {
147 chunk.split_to(5);
148 }
149
150 chunk
151 });
152
153 assert_eq!(r.len(), 0);
154 assert!(time < 200000, "Allocation took long!")
155
156 }
157
158 #[test]
159 fn test_arena_simple_vec_allocation() {
160 let arena = Arena::with_capacity(1024);
161 let mut v = Vec::<usize>::with_capacity(10);
162
163 v.push(10);
164 v.push(10);
165
166 assert_eq!(v, [10, 10], "Failed to allocate and fill a small vector!");
167 }
168
169 #[test]
170 fn test_arena_simple_vec_reallocation() {
171 let arena = Arena::with_capacity(1024);
172 let mut v = Vec::<usize>::with_capacity(1);
173
174 v.push(10);
175 v.push(10);
176
177 assert_eq!(v, [10, 10], "Failed to reallocate and fill a small vector!");
178 }
179
180 #[test]
181 fn test_arena_allocate_more_than_allowed() {
182 let mut arena = Arena::with_capacity(5);
183 let v = arena.commit(10);
184
185 assert!(v.is_err(), "Arena did not emit error upon allocation of byte count higher than current capacity.");
186 }
187
188 #[test]
189 fn test_arena_create_vec_with_macro() {
190 let arena = Arena::with_capacity(5);
191 let v: Vec<String> = vec![];
192
193 assert!(v.is_empty(), "Failed to create vector with arena allocation enabled.");
194 }
195
196 #[test]
197 fn test_arena_benchmark_arenavec_vs_vec() {
198 struct ptr {
199 data: usize,
200 len: usize,
201 index: usize,
202 bad: usize,
203 }
204
205 impl ptr {
206 pub fn new() -> Self {
207 Self {
208 data: 0,
209 len: 0,
210 index: 0,
211 bad: 0,
212 }
213 }
214 }
215
216 let total_items = 20000;
217
218 let (arena, arena_time) = rumtk_benchmark_snippet!(|| {
219 let total_bytes = (total_items * size_of::<ptr>()) + size_of::<Vec<ptr>>();
220 Arena::with_capacity(total_bytes)
221 });
222
223 let (arena_vec_r, arena_vec_time) = rumtk_benchmark_snippet!(|| {
224 let mut v: Vec<ptr> = vec![];
225
226 for _ in 0..total_items {
227 v.push(ptr::new());
228 }
229
230 v
231 });
232
233 let (vec_r, vec_time) = rumtk_benchmark_snippet!(|| {
234 let mut v = Vec::<ptr>::with_capacity(total_items);
235
236 for _ in 0..total_items {
237 v.push(ptr::new());
238 }
239
240 v
241 });
242
243 let total_arena_vec_time = arena_time + arena_vec_time;
244 println!("ArenaVec => {} us vs. Vec => {} us.", total_arena_vec_time, vec_time);
245
246 }
248
249 #[test]
250 fn test_arena_create_vec_with_macro_with_items() {
251 let arena = Arena::with_capacity(50);
252 let expected = &["Hello", "World", "!"];
253 let v: Vec<&str> = vec!["Hello", "World", "!"];
254
255 assert_eq!(v.as_slice(), expected, "Failed to create vector with arena allocation enabled and item slice.");
256 }
257
258 #[test]
259 fn test_arena_create_vecdeque_with_macro() {
260 let arena = Arena::with_capacity(5);
261 let v: VecDeque<String> = VecDeque::new();
262
263 assert!(v.is_empty(), "Failed to create vector with arena allocation enabled.");
264 }
265
266 #[test]
267 fn test_arena_create_vecdeque_with_macro_with_items() {
268 let arena = Arena::with_capacity(50);
269 let expected = ["Hello", "World", "!"];
270 let mut v: VecDeque<&str> = VecDeque::from(expected.clone());
271
272 assert_eq!(v.pop_front(), Some(expected[0]), "Failed to create queue with arena allocation enabled and item slice.");
273 }
274
275 #[test]
276 fn test_arena_create_hashmap_with_macro() {
277 let arena = Arena::with_capacity(5);
278 let v: HashMap<&str, &str> = HashMap::new();
279
280 assert!(v.is_empty(), "Failed to create vector with arena allocation enabled.");
281 }
282
283 #[test]
284 fn test_arena_create_hashmap_with_macro_with_items() {
285 let arena = Arena::with_capacity(120);
286 let expected = [(0, "Hello"), (1, "World"), (2, "!")];
287 let v: HashMap<usize, &str> = HashMap::from_iter(expected.clone());
288
289 assert_eq!(v[&0], expected[0].1, "Failed to create hashmap with arena allocation enabled and item slice.");
290 }
291
292 #[test]
293 fn test_arena_vec_debug_print() {
294 let arena = rumtk_arena_new!(500);
295 let mut test_vec = Vec::new();
296 let expected = ["Hello", "World", "!"];
297
298 for s in expected.iter() {
299 test_vec.push(s);
300 }
301
302 println!("{:?}", &test_vec);
303 }
304
305 #[test]
306 fn test_arena_map_debug_print() {
307 let expected = [(5, "Hello"), (1, "World"), (3, "!")];
308
309
310 let m = HashMap::<usize, &str>::from_iter(expected.clone());
311
312 for (k, v) in expected.iter() {
313 assert!(m.contains_key(k), "Key missing!");
314 assert_eq!(v, &m[k], "Contents mismatch!");
315 }
316 }
317}