alloc_tester/
alloc-tester.rs

1extern crate std;
2
3use std::alloc::Layout;
4use std::ffi::c_char as char;
5
6use ialloc::*;
7use ialloc::allocator::*;
8
9
10
11struct Test<A> {
12    pub name:   &'static str,
13    pub create: fn()->A,
14    pub thin:   Option<AlignmentRange>,
15    pub fat:    Option<AlignmentRange>,
16}
17
18#[derive(Clone, Copy, Debug)] struct AlignmentRange {
19    pub min: Alignment,
20    pub max: Alignment,
21}
22
23impl<A> Test<A> {
24    pub fn new(name: &'static str, create: fn()->A) -> Self {
25        Self { name, create, thin: None, fat: None }
26    }
27
28    pub fn thin(&mut self) -> &mut Self where A : thin::Alloc + thin::Free {
29        let mut thin = AlignmentRange { min: Alignment::MAX, max: Alignment::MAX };
30        for (dst, min_size) in [(&mut thin.min, 1), (&mut thin.max, 4096)] {
31            for _ in 0 .. 100 {
32                let alloc = (self.create)();
33                let addrs = [(); 4096].into_iter().enumerate().map(|(i, _)| alloc.alloc_uninit(i%16+min_size).unwrap()).collect::<Vec<_>>();
34                let addrbits = addrs[..].iter().copied().map(|addr| addr.as_ptr() as usize).reduce(|x,y| x|y).unwrap();
35                addrs.iter().copied().for_each(|addr| unsafe { alloc.free(addr) });
36                let align = Alignment::new(1 << addrbits.trailing_zeros()).unwrap();
37                *dst = align.min(*dst);
38            }
39        }
40        self.thin = Some(thin);
41        self
42    }
43
44    pub fn fat(&mut self) -> &mut Self where A : fat::Alloc + fat::Free {
45        let mut fat = AlignmentRange { min: Alignment::MAX, max: ALIGN_1 };
46
47        for _ in 0 .. 100 {
48            let layout = Layout::new::<u8>(); // 1B
49            let alloc = (self.create)();
50            let addrs = [(); 4096].map(|_| alloc.alloc_uninit(layout).unwrap());
51            let addrbits = addrs[..].iter().copied().map(|addr| addr.as_ptr() as usize).reduce(|x,y| x|y).unwrap();
52            addrs.iter().copied().for_each(|addr| unsafe { alloc.free(addr, layout) });
53            let align = Alignment::new(1 << addrbits.trailing_zeros()).unwrap();
54            fat.min = align.min(fat.min);
55        }
56
57        fat.max = fat.min;
58        let alloc = (self.create)();
59        while let Some(next) = fat.max.as_usize().checked_shl(1) {
60            let Some(align) = Alignment::new(next) else { break };
61            let Ok(layout) = Layout::from_size_align(next, next) else { break };
62            let Ok(addr) = alloc.alloc_uninit(layout) else { break };
63            fat.max = align;
64            unsafe { alloc.free(addr, layout) };
65        }
66
67        self.fat = Some(fat);
68        self
69    }
70
71    pub fn print(&self) {
72        let name = self.name;
73        let thin = self.thin.map_or_else(|| format!(""), |t| if t.min == t.max { format!("{:?}", t.min) } else { format!("{:?} ..= {:?}", t.min, t.max) });
74        let fat  = self.fat .map_or_else(|| format!(""), |t| if t.min == t.max { format!("{:?}", t.min) } else { format!("{:?} ..= {:?}", t.min, t.max) });
75        println!("{name: <25}{thin: <20}{fat: <20}");
76    }
77}
78
79fn main() {
80    println!("{: <25}{: <20}{: <20}", "",          "thin::Alloc",   "fat::Alloc",   );
81    println!("{: <25}{: <20}{: <20}", "Allocator", "Alignment",     "Alignment",    );
82    println!("{:=<65}", "");
83    #[cfg(feature = "alloc")]   Test::new("Global",                 || alloc::Global                    )       .fat().print();
84    #[cfg(c89)]                 Test::new("Malloc",                 || c::Malloc                        ).thin().fat().print();
85    #[cfg(c89)]                 Test::new("AlignedMalloc",          || c::AlignedMalloc                 )       .fat().print();
86    #[cfg(cpp98)]               Test::new("NewDelete",              || cpp::NewDelete                   ).thin().fat().print();
87    #[cfg(cpp98)]               Test::new("NewDeleteArray",         || cpp::NewDeleteArray              ).thin().fat().print();
88    #[cfg(cpp17)]               Test::new("NewDeleteAligned",       || cpp::NewDeleteAligned            )       .fat().print();
89    #[cfg(cpp17)]               Test::new("NewDeleteArrayAligned",  || cpp::NewDeleteArrayAligned       )       .fat().print();
90    #[cfg(cpp98)]               Test::new("StdAllocator<char>",     || cpp::StdAllocator::<char>::new() )       .fat().print();
91    #[cfg(all(windows, feature = "win32"))] {
92        println!();
93        println!("win32:");
94        Test::new("ProcessHeap",        || win32::ProcessHeap               ).thin().fat().print();
95        Test::new("Global",             || win32::Global                    ).thin().fat().print();
96        Test::new("Local",              || win32::Local                     ).thin().fat().print();
97        Test::new("CryptMem",           || win32::CryptMem                  ).thin().fat().print();
98        Test::new("CoTaskMem",          || win32::CoTaskMem                 ).thin().fat().print();
99        Test::new("VirtualCommit",      || win32::VirtualCommit             ).thin().fat().print();
100    }
101}