1use cfg_if::cfg_if;
14use cfx_types::{
15 AddressWithSpace, AllChainID, Space, SpaceMap, H160, H256, H512, U256, U512,
16};
17use hashbrown::HashMap as FastHashMap;
18use slab::Slab;
19use std::{
20 cmp::Reverse,
21 collections::{BinaryHeap, HashSet, VecDeque},
22 hash::{BuildHasher, Hash},
23 mem::{self, size_of},
24 ops::Range,
25 os::raw::c_void,
26 sync::Arc,
27};
28
29type VoidPtrToSizeFn = unsafe extern "C" fn(ptr: *const c_void) -> usize;
31
32pub struct MallocSizeOfOps {
34 pub size_of_op: VoidPtrToSizeFn,
36
37 pub enclosing_size_of_op: Option<VoidPtrToSizeFn>,
42
43 pub visited: HashSet<usize>,
44}
45
46impl MallocSizeOfOps {
47 pub fn new(
48 size_of: VoidPtrToSizeFn,
49 malloc_enclosing_size_of: Option<VoidPtrToSizeFn>,
50 ) -> Self {
51 MallocSizeOfOps {
52 size_of_op: size_of,
53 enclosing_size_of_op: malloc_enclosing_size_of,
54 visited: HashSet::new(),
55 }
56 }
57
58 fn is_empty<T: ?Sized>(ptr: *const T) -> bool {
61 ptr as *const usize as usize <= 256
69 }
70
71 pub unsafe fn malloc_size_of<T: ?Sized>(&self, ptr: *const T) -> usize {
74 if MallocSizeOfOps::is_empty(ptr) {
75 0
76 } else {
77 (self.size_of_op)(ptr as *const c_void)
78 }
79 }
80
81 pub fn has_malloc_enclosing_size_of(&self) -> bool {
83 self.enclosing_size_of_op.is_some()
84 }
85
86 pub unsafe fn malloc_enclosing_size_of<T>(&self, ptr: *const T) -> usize {
89 assert!(!MallocSizeOfOps::is_empty(ptr));
90 (self.enclosing_size_of_op.unwrap())(ptr as *const c_void)
91 }
92}
93
94pub trait MallocSizeOf {
97 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize;
100}
101
102pub trait MallocShallowSizeOf {
104 fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize;
109}
110
111impl MallocSizeOf for String {
112 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
113 unsafe { ops.malloc_size_of(self.as_ptr()) }
114 }
115}
116
117impl<T: MallocSizeOf> MallocSizeOf for SpaceMap<T> {
118 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
119 self.map_sum(|x| x.size_of(ops))
120 }
121}
122
123impl<T: ?Sized> MallocShallowSizeOf for Box<T> {
124 fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
125 unsafe { ops.malloc_size_of(&**self) }
126 }
127}
128
129impl<T: MallocSizeOf + ?Sized> MallocSizeOf for Box<T> {
130 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
131 self.shallow_size_of(ops) + (**self).size_of(ops)
132 }
133}
134
135impl MallocSizeOf for () {
136 fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize { 0 }
137}
138
139impl<T1, T2> MallocSizeOf for (T1, T2)
140where
141 T1: MallocSizeOf,
142 T2: MallocSizeOf,
143{
144 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
145 self.0.size_of(ops) + self.1.size_of(ops)
146 }
147}
148
149impl<T1, T2, T3> MallocSizeOf for (T1, T2, T3)
150where
151 T1: MallocSizeOf,
152 T2: MallocSizeOf,
153 T3: MallocSizeOf,
154{
155 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
156 self.0.size_of(ops) + self.1.size_of(ops) + self.2.size_of(ops)
157 }
158}
159
160impl<T1, T2, T3, T4> MallocSizeOf for (T1, T2, T3, T4)
161where
162 T1: MallocSizeOf,
163 T2: MallocSizeOf,
164 T3: MallocSizeOf,
165 T4: MallocSizeOf,
166{
167 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
168 self.0.size_of(ops)
169 + self.1.size_of(ops)
170 + self.2.size_of(ops)
171 + self.3.size_of(ops)
172 }
173}
174
175impl<T: MallocSizeOf> MallocSizeOf for Option<T> {
176 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
177 if let Some(val) = self.as_ref() {
178 val.size_of(ops)
179 } else {
180 0
181 }
182 }
183}
184
185impl<T: MallocSizeOf, E: MallocSizeOf> MallocSizeOf for Result<T, E> {
186 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
187 match *self {
188 Ok(ref x) => x.size_of(ops),
189 Err(ref e) => e.size_of(ops),
190 }
191 }
192}
193
194impl<T: MallocSizeOf + Copy> MallocSizeOf for std::cell::Cell<T> {
195 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
196 self.get().size_of(ops)
197 }
198}
199
200impl<T: MallocSizeOf> MallocSizeOf for std::cell::RefCell<T> {
201 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
202 self.borrow().size_of(ops)
203 }
204}
205
206impl<T: MallocSizeOf> MallocSizeOf for std::cell::UnsafeCell<T> {
207 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
208 unsafe { &*self.get() }.size_of(ops)
209 }
210}
211
212impl<'a, B: ?Sized + ToOwned> MallocSizeOf for std::borrow::Cow<'a, B>
213where B::Owned: MallocSizeOf
214{
215 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
216 match *self {
217 std::borrow::Cow::Borrowed(_) => 0,
218 std::borrow::Cow::Owned(ref b) => b.size_of(ops),
219 }
220 }
221}
222
223impl<T: MallocSizeOf> MallocSizeOf for [T] {
224 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
225 let mut n = 0;
226 for elem in self.iter() {
227 n += elem.size_of(ops);
228 }
229 n
230 }
231}
232
233impl<T> MallocShallowSizeOf for Vec<T> {
234 fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
235 unsafe { ops.malloc_size_of(self.as_ptr()) }
236 }
237}
238
239impl<T: MallocSizeOf> MallocSizeOf for Vec<T> {
240 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
241 let mut n = self.shallow_size_of(ops);
242 for elem in self.iter() {
243 n += elem.size_of(ops);
244 }
245 n
246 }
247}
248
249#[allow(dead_code)]
250#[derive(Clone)]
251enum Entry<T> {
252 Vacant(usize),
253 Occupied(T),
254}
255
256impl<T> MallocShallowSizeOf for Slab<T> {
257 fn shallow_size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
258 mem::size_of::<Entry<T>>() * self.capacity()
259 }
260}
261
262impl<T: MallocSizeOf> MallocSizeOf for Slab<T> {
263 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
264 let mut n = self.shallow_size_of(ops);
265 for (_, elem) in self.iter() {
266 n += elem.size_of(ops);
267 }
268 n
269 }
270}
271
272impl<T> MallocShallowSizeOf for BinaryHeap<T> {
273 fn shallow_size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
274 mem::size_of::<T>() * self.capacity()
275 }
276}
277
278impl<T: MallocSizeOf> MallocSizeOf for BinaryHeap<T> {
279 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
280 let mut n = self.shallow_size_of(ops);
281 for elem in self.iter() {
282 n += elem.size_of(ops);
283 }
284 n
285 }
286}
287
288impl<T> MallocShallowSizeOf for VecDeque<T> {
289 fn shallow_size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
290 mem::size_of::<T>() * self.capacity()
291 }
292}
293
294impl<T: MallocSizeOf> MallocSizeOf for VecDeque<T> {
295 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
296 let mut n = self.shallow_size_of(ops);
297 for elem in self.iter() {
298 n += elem.size_of(ops);
299 }
300 n
301 }
302}
303
304impl<T: MallocSizeOf> MallocSizeOf for Arc<T> {
306 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
307 let ptr = self.as_ref() as *const T as usize;
308 if ops.visited.contains(&ptr) {
309 return 0;
310 }
311 ops.visited.insert(ptr);
312 mem::size_of::<T>() + self.as_ref().size_of(ops)
313 }
314}
315
316macro_rules! malloc_size_of_hash_set {
317 ($ty:ty) => {
318 impl<T, S> MallocShallowSizeOf for $ty
319 where
320 T: Eq + Hash,
321 S: BuildHasher,
322 {
323 fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
324 if ops.has_malloc_enclosing_size_of() {
325 self.iter().next().map_or(0, |t| unsafe {
331 ops.malloc_enclosing_size_of(t)
332 })
333 } else {
334 self.capacity() * (size_of::<T>() + size_of::<usize>())
336 }
337 }
338 }
339
340 impl<T, S> MallocSizeOf for $ty
341 where
342 T: Eq + Hash + MallocSizeOf,
343 S: BuildHasher,
344 {
345 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
346 let mut n = self.shallow_size_of(ops);
347 for t in self.iter() {
348 n += t.size_of(ops);
349 }
350 n
351 }
352 }
353 };
354}
355
356malloc_size_of_hash_set!(std::collections::HashSet<T, S>);
357
358macro_rules! malloc_size_of_hash_map {
359 ($ty:ty) => {
360 impl<K, V, S> MallocShallowSizeOf for $ty
361 where
362 K: Eq + Hash,
363 S: BuildHasher,
364 {
365 fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
366 if ops.has_malloc_enclosing_size_of() {
369 self.values().next().map_or(0, |v| unsafe {
370 ops.malloc_enclosing_size_of(v)
371 })
372 } else {
373 self.capacity()
374 * (size_of::<V>() + size_of::<K>() + size_of::<usize>())
375 }
376 }
377 }
378
379 impl<K, V, S> MallocSizeOf for $ty
380 where
381 K: Eq + Hash + MallocSizeOf,
382 V: MallocSizeOf,
383 S: BuildHasher,
384 {
385 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
386 let mut n = self.shallow_size_of(ops);
387 for (k, v) in self.iter() {
388 n += k.size_of(ops);
389 n += v.size_of(ops);
390 }
391 n
392 }
393 }
394 };
395}
396
397malloc_size_of_hash_map!(std::collections::HashMap<K, V, S>);
398malloc_size_of_hash_map!(FastHashMap<K, V, S>);
399
400impl<T> MallocSizeOf for std::marker::PhantomData<T> {
402 fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize { 0 }
403}
404
405impl<T: MallocSizeOf> MallocSizeOf for std::sync::Mutex<T> {
406 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
407 self.lock().unwrap().size_of(ops)
408 }
409}
410
411impl<T: MallocSizeOf> MallocSizeOf for parking_lot::Mutex<T> {
412 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
413 self.lock().size_of(ops)
414 }
415}
416
417impl<T: MallocSizeOf> MallocSizeOf for std::sync::RwLock<T> {
418 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
419 self.read().unwrap().size_of(ops)
420 }
421}
422
423impl<T: MallocSizeOf> MallocSizeOf for parking_lot::RwLock<T> {
424 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
425 self.read().size_of(ops)
426 }
427}
428
429impl<T: MallocSizeOf> MallocSizeOf for Reverse<T> {
430 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
431 self.0.size_of(ops)
432 }
433}
434
435macro_rules! impl_smallvec {
436 ($size:expr) => {
437 impl<T> MallocSizeOf for smallvec::SmallVec<[T; $size]>
438 where T: MallocSizeOf
439 {
440 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
441 let mut n = if self.spilled() {
442 self.capacity() * core::mem::size_of::<T>()
443 } else {
444 0
445 };
446 for elem in self.iter() {
447 n += elem.size_of(ops);
448 }
449 n
450 }
451 }
452 };
453}
454
455impl_smallvec!(32); #[macro_export]
459macro_rules! malloc_size_of_is_0(
460 ($($ty:ty),+) => (
461 $(
462 impl $crate::MallocSizeOf for $ty {
463 #[inline(always)]
464 fn size_of(&self, _: &mut $crate::MallocSizeOfOps) -> usize {
465 0
466 }
467 }
468 )+
469 );
470 ($($ty:ident<$($gen:ident),+>),+) => (
471 $(
472 impl<$($gen: $crate::MallocSizeOf),+> $crate::MallocSizeOf for $ty<$($gen),+> {
473 #[inline(always)]
474 fn size_of(&self, _: &mut $crate::MallocSizeOfOps) -> usize {
475 0
476 }
477 }
478 )+
479 );
480);
481
482malloc_size_of_is_0!(bool, char, str);
483malloc_size_of_is_0!(u8, u16, u32, u64, u128, usize);
484malloc_size_of_is_0!(i8, i16, i32, i64, i128, isize);
485malloc_size_of_is_0!(f32, f64);
486
487malloc_size_of_is_0!(std::sync::atomic::AtomicBool);
488malloc_size_of_is_0!(std::sync::atomic::AtomicIsize);
489malloc_size_of_is_0!(std::sync::atomic::AtomicUsize);
490
491malloc_size_of_is_0!(std::num::NonZeroUsize);
492malloc_size_of_is_0!(std::num::NonZeroU32);
493
494malloc_size_of_is_0!(std::time::Duration);
495malloc_size_of_is_0!(std::time::Instant);
496malloc_size_of_is_0!(std::time::SystemTime);
497
498malloc_size_of_is_0!(
499 Range<u8>,
500 Range<u16>,
501 Range<u32>,
502 Range<u64>,
503 Range<usize>
504);
505malloc_size_of_is_0!(
506 Range<i8>,
507 Range<i16>,
508 Range<i32>,
509 Range<i64>,
510 Range<isize>
511);
512malloc_size_of_is_0!(Range<f32>, Range<f64>);
513
514malloc_size_of_is_0!(
515 H256,
516 U256,
517 H512,
518 H160,
519 U512,
520 AddressWithSpace,
521 AllChainID,
522 Space
523);
524
525mod usable_size {
526
527 use super::*;
528
529 cfg_if! {
530 if #[cfg(target_os = "windows")] {
531
532 extern crate winapi;
534
535 use self::winapi::um::heapapi::{GetProcessHeap, HeapSize, HeapValidate};
536
537 pub unsafe extern "C" fn malloc_usable_size(mut ptr: *const c_void) -> usize {
540
541 let heap = GetProcessHeap();
542
543 if HeapValidate(heap, 0, ptr) == 0 {
544 ptr = *(ptr as *const *const c_void).offset(-1);
545 }
546
547 HeapSize(heap, 0, ptr) as usize
548 }
549
550 } else if #[cfg(feature = "jemalloc")] {
551
552 pub unsafe extern "C" fn malloc_usable_size(ptr: *const c_void) -> usize {
554 tikv_jemallocator::usable_size(ptr)
555 }
556
557 } else if #[cfg(target_os = "linux")] {
558
559 extern "C" {
561 pub fn malloc_usable_size(ptr: *const c_void) -> usize;
562 }
563
564 } else if #[cfg(target_os = "macos")] {
565
566 extern "C" {
568 #[link_name = "malloc_size"]
569 pub fn malloc_usable_size(ptr: *const c_void) -> usize;
570 }
571
572
573 } else {
574 pub unsafe extern "C" fn malloc_usable_size(_ptr: *const c_void) -> usize {
575 unreachable!("estimate heapsize or feature allocator needed")
576 }
577
578 }
579
580 }
581
582 #[inline]
584 pub fn new_enclosing_size_fn() -> Option<VoidPtrToSizeFn> { None }
585}
586
587pub fn new_malloc_size_ops() -> MallocSizeOfOps {
589 MallocSizeOfOps::new(
590 usable_size::malloc_usable_size,
591 usable_size::new_enclosing_size_fn(),
592 )
593}