Skip to main content

rumtk_arena/
lib.rs

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        //assert!(total_arena_vec_time < vec_time, "ArenaVec is too slow. ArenaVec => {} us vs. Vec => {} us.", total_arena_vec_time, vec_time);
247    }
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}