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::RUMBuffer;
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_arena_direct_allocation() {
86
87 let (r, time) = rumtk_benchmark_snippet!(|| {
88 unsafe { as_slice_mut(direct_alloc(DEFAULT_GLOBAL_MB_ALLOCATION_LAYOUT), DEFAULT_GLOBAL_MB_ALLOCATION) }
89 });
90
91 assert_eq!(r.len(), DEFAULT_GLOBAL_MB_ALLOCATION);
92 assert!(time < 500, "Allocation took long! => {}us", time)
93
94 }
95
96 #[test]
97 fn test_arena_basic_allocation() {
98 let (r, time) = rumtk_benchmark_snippet!(|| {
99 unsafe { as_slice_mut(alloc(DEFAULT_GLOBAL_MB_ALLOCATION_LAYOUT), DEFAULT_GLOBAL_MB_ALLOCATION) }
100 });
101
102 assert_eq!(r.len(), DEFAULT_GLOBAL_MB_ALLOCATION);
103 assert!(time < 310, "Allocation took long! => {}us", time)
104
105 }
106
107 #[test]
108 fn test_arena_allocate_and_use() {
109 let (r, time) = rumtk_benchmark_snippet!(|| {
110 let slice = unsafe { as_slice_mut(alloc(DEFAULT_GLOBAL_MB_ALLOCATION_LAYOUT), DEFAULT_GLOBAL_MB_ALLOCATION) };
111 let v = slice.to_vec();
112 let mut buffer = RUMBuffer::from(v);
113 let mut chunk = buffer.freeze();
114
115 for _ in 0..(DEFAULT_GLOBAL_MB_ALLOCATION/5) {
116 chunk.split_to(5);
117 }
118
119 chunk
120 });
121
122 assert_eq!(r.len(), 0);
123 assert!(time < 200000, "Allocation took long!")
124
125 }
126
127 #[test]
128 fn test_arena_simple_vec_allocation() {
129 let arena = Arena::with_capacity(1024);
130 let mut v = Vec::<usize>::with_capacity(10);
131
132 v.push(10);
133 v.push(10);
134
135 assert_eq!(v, [10, 10], "Failed to allocate and fill a small vector!");
136 }
137
138 #[test]
139 fn test_arena_simple_vec_reallocation() {
140 let arena = Arena::with_capacity(1024);
141 let mut v = Vec::<usize>::with_capacity(1);
142
143 v.push(10);
144 v.push(10);
145
146 assert_eq!(v, [10, 10], "Failed to reallocate and fill a small vector!");
147 }
148
149 #[test]
150 fn test_arena_allocate_more_than_allowed() {
151 let mut arena = Arena::with_capacity(5);
152 let v = arena.commit(10);
153
154 assert!(v.is_err(), "Arena did not emit error upon allocation of byte count higher than current capacity.");
155 }
156
157 #[test]
158 fn test_arena_create_vec_with_macro() {
159 let arena = Arena::with_capacity(5);
160 let v: Vec<String> = vec![];
161
162 assert!(v.is_empty(), "Failed to create vector with arena allocation enabled.");
163 }
164
165 #[test]
166 fn test_arena_benchmark_arenavec_vs_vec() {
167 struct ptr {
168 data: usize,
169 len: usize,
170 index: usize,
171 bad: usize,
172 }
173
174 impl ptr {
175 pub fn new() -> Self {
176 Self {
177 data: 0,
178 len: 0,
179 index: 0,
180 bad: 0,
181 }
182 }
183 }
184
185 let total_items = 20000;
186
187 let (arena, arena_time) = rumtk_benchmark_snippet!(|| {
188 let total_bytes = (total_items * size_of::<ptr>()) + size_of::<Vec<ptr>>();
189 Arena::with_capacity(total_bytes)
190 });
191
192 let (arena_vec_r, arena_vec_time) = rumtk_benchmark_snippet!(|| {
193 let mut v: Vec<ptr> = vec![];
194
195 for _ in 0..total_items {
196 v.push(ptr::new());
197 }
198
199 v
200 });
201
202 let (vec_r, vec_time) = rumtk_benchmark_snippet!(|| {
203 let mut v = Vec::<ptr>::with_capacity(total_items);
204
205 for _ in 0..total_items {
206 v.push(ptr::new());
207 }
208
209 v
210 });
211
212 let total_arena_vec_time = arena_time + arena_vec_time;
213 println!("ArenaVec => {} us vs. Vec => {} us.", total_arena_vec_time, vec_time);
214
215 }
217
218 #[test]
219 fn test_arena_create_vec_with_macro_with_items() {
220 let arena = Arena::with_capacity(50);
221 let expected = &["Hello", "World", "!"];
222 let v: Vec<&str> = vec!["Hello", "World", "!"];
223
224 assert_eq!(v.as_slice(), expected, "Failed to create vector with arena allocation enabled and item slice.");
225 }
226
227 #[test]
228 fn test_arena_create_vecdeque_with_macro() {
229 let arena = Arena::with_capacity(5);
230 let v: VecDeque<String> = VecDeque::new();
231
232 assert!(v.is_empty(), "Failed to create vector with arena allocation enabled.");
233 }
234
235 #[test]
236 fn test_arena_create_vecdeque_with_macro_with_items() {
237 let arena = Arena::with_capacity(50);
238 let expected = ["Hello", "World", "!"];
239 let mut v: VecDeque<&str> = VecDeque::from(expected.clone());
240
241 assert_eq!(v.pop_front(), Some(expected[0]), "Failed to create queue with arena allocation enabled and item slice.");
242 }
243
244 #[test]
245 fn test_arena_create_hashmap_with_macro() {
246 let arena = Arena::with_capacity(5);
247 let v: HashMap<&str, &str> = HashMap::new();
248
249 assert!(v.is_empty(), "Failed to create vector with arena allocation enabled.");
250 }
251
252 #[test]
253 fn test_arena_create_hashmap_with_macro_with_items() {
254 let arena = Arena::with_capacity(120);
255 let expected = [(0, "Hello"), (1, "World"), (2, "!")];
256 let v: HashMap<usize, &str> = HashMap::from_iter(expected.clone());
257
258 assert_eq!(v[&0], expected[0].1, "Failed to create hashmap with arena allocation enabled and item slice.");
259 }
260
261 #[test]
262 fn test_arena_vec_debug_print() {
263 let arena = rumtk_arena_new!(500);
264 let mut test_vec = Vec::new();
265 let expected = ["Hello", "World", "!"];
266
267 for s in expected.iter() {
268 test_vec.push(s);
269 }
270
271 println!("{:?}", &test_vec);
272 }
273
274 #[test]
275 fn test_arena_map_debug_print() {
276 let expected = [(5, "Hello"), (1, "World"), (3, "!")];
277
278
279 let m = HashMap::<usize, &str>::from_iter(expected.clone());
280
281 for (k, v) in expected.iter() {
282 assert!(m.contains_key(k), "Key missing!");
283 assert_eq!(v, &m[k], "Contents mismatch!");
284 }
285 }
286}