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