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