malloc_best_effort/
lib.rs1#![no_std]
2#![cfg_attr(docsrs, feature(doc_cfg))]
3
4#![doc = document_features::document_features!()]
56
57#[cfg(not(all(
58 target_os = "linux",
59 any(
60 target_arch = "x86_64",
61 target_arch = "aarch64",
62 target_arch = "powerpc64"
63 ),
64 target_endian = "little"
65)))]
66mod mimalloc {
67 pub(crate) use mimalloc::MiMalloc as BEMallocImpl;
68
69 #[inline]
70 pub(crate) fn init_impl() {}
71}
72#[cfg(all(
73 target_os = "linux",
74 any(
75 target_arch = "x86_64",
76 target_arch = "aarch64",
77 target_arch = "powerpc64"
78 ),
79 target_endian = "little"
80))]
81mod tcmalloc {
82 pub(crate) use tcmalloc_better::TCMalloc as BEMallocImpl;
83
84 #[cfg(feature = "std")]
85 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
86 #[inline]
87 pub(crate) fn init_impl() {
88 BEMallocImpl::process_background_actions_thread();
89 }
90
91 #[cfg(not(feature = "std"))]
92 #[cfg_attr(docsrs, doc(cfg(not(feature = "std"))))]
93 #[inline]
94 pub(crate) fn init_impl() {}
95}
96
97#[cfg(not(all(
98 target_os = "linux",
99 any(
100 target_arch = "x86_64",
101 target_arch = "aarch64",
102 target_arch = "powerpc64"
103 ),
104 target_endian = "little"
105)))]
106use crate::mimalloc::BEMallocImpl;
107#[cfg(not(all(
108 target_os = "linux",
109 any(
110 target_arch = "x86_64",
111 target_arch = "aarch64",
112 target_arch = "powerpc64"
113 ),
114 target_endian = "little"
115)))]
116use crate::mimalloc::init_impl;
117#[cfg(all(
118 target_os = "linux",
119 any(
120 target_arch = "x86_64",
121 target_arch = "aarch64",
122 target_arch = "powerpc64"
123 ),
124 target_endian = "little"
125))]
126use crate::tcmalloc::BEMallocImpl;
127#[cfg(all(
128 target_os = "linux",
129 any(
130 target_arch = "x86_64",
131 target_arch = "aarch64",
132 target_arch = "powerpc64"
133 ),
134 target_endian = "little"
135))]
136use crate::tcmalloc::init_impl;
137use core::alloc::{GlobalAlloc, Layout};
138
139pub struct BEMalloc {
142 alloc_impl: BEMallocImpl,
143}
144
145unsafe impl GlobalAlloc for BEMalloc {
146 #[inline]
147 unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
148 unsafe { self.alloc_impl.alloc(layout) }
149 }
150
151 #[inline]
152 unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
153 unsafe { self.alloc_impl.dealloc(ptr, layout) }
154 }
155
156 #[inline]
157 unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
158 unsafe { self.alloc_impl.alloc_zeroed(layout) }
159 }
160
161 #[inline]
162 unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
163 unsafe { self.alloc_impl.realloc(ptr, layout, new_size) }
164 }
165}
166
167impl Default for BEMalloc {
168 #[inline]
169 fn default() -> Self {
170 Self::new()
171 }
172}
173
174impl BEMalloc {
175 #[inline]
177 pub const fn new() -> Self {
178 Self {
179 alloc_impl: BEMallocImpl,
180 }
181 }
182 #[inline]
184 pub fn init() {
185 init_impl();
186 }
187}
188
189#[cfg(test)]
190mod tests {
191 use super::*;
192
193 #[test]
194 fn it_frees_allocated_memory() {
195 unsafe {
196 let layout = Layout::from_size_align(8, 8).unwrap();
197 let alloc = BEMalloc::new();
198
199 let ptr = alloc.alloc(layout);
200 alloc.dealloc(ptr, layout);
201 }
202 }
203
204 #[test]
205 fn it_frees_allocated_memory_with_init() {
206 unsafe {
207 let layout = Layout::from_size_align(8, 8).unwrap();
208 let alloc = BEMalloc::new();
209 BEMalloc::init();
210
211 let ptr = alloc.alloc(layout);
212 alloc.dealloc(ptr, layout);
213 }
214 }
215
216 #[test]
217 fn it_frees_allocated_big_memory() {
218 unsafe {
219 let layout = Layout::from_size_align(1 << 20, 32).unwrap();
220 let alloc = BEMalloc::new();
221
222 let ptr = alloc.alloc(layout);
223 alloc.dealloc(ptr, layout);
224 }
225 }
226
227 #[test]
228 fn it_frees_zero_allocated_memory() {
229 unsafe {
230 let layout = Layout::from_size_align(8, 8).unwrap();
231 let alloc = BEMalloc::new();
232
233 let ptr = alloc.alloc_zeroed(layout);
234 alloc.dealloc(ptr, layout);
235 }
236 }
237
238 #[test]
239 fn it_frees_zero_allocated_big_memory() {
240 unsafe {
241 let layout = Layout::from_size_align(1 << 20, 32).unwrap();
242 let alloc = BEMalloc::new();
243
244 let ptr = alloc.alloc_zeroed(layout);
245 alloc.dealloc(ptr, layout);
246 }
247 }
248
249 #[test]
250 fn it_frees_reallocated_memory() {
251 unsafe {
252 let layout = Layout::from_size_align(8, 8).unwrap();
253 let new_size = 16;
254 let new_layout = Layout::from_size_align(new_size, layout.align()).unwrap();
255 let alloc = BEMalloc::new();
256
257 let ptr = alloc.alloc(layout);
258 let ptr = alloc.realloc(ptr, layout, new_size);
259 alloc.dealloc(ptr, new_layout);
260 }
261 }
262
263 #[test]
264 fn it_frees_reallocated_big_memory() {
265 unsafe {
266 let layout = Layout::from_size_align(1 << 20, 32).unwrap();
267 let new_size = 2 << 20;
268 let new_layout = Layout::from_size_align(new_size, layout.align()).unwrap();
269 let alloc = BEMalloc::new();
270
271 let ptr = alloc.alloc(layout);
272 let ptr = alloc.realloc(ptr, layout, new_size);
273 alloc.dealloc(ptr, new_layout);
274 }
275 }
276}