diff --git a/.travis.yml b/.travis.yml index 913ebf5..0790f90 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,7 +13,7 @@ notifications: webhooks: http://build.servo.org:54856/travis script: - - cargo test - - "[ $TRAVIS_RUST_VERSION != nightly ] || cargo test --features unstable" + - cargo test --features jemalloc + - "[ $TRAVIS_RUST_VERSION != nightly ] || cargo test --features unstable,jemalloc" - "[[ $TRAVIS_RUST_VERSION != nightly && $TRAVIS_RUST_VERSION != beta ]] || cargo test --manifest-path derive/Cargo.toml" diff --git a/Cargo.toml b/Cargo.toml index 63be860..7c07bbe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "heapsize" -version = "0.4.0" +version = "0.5.0" authors = [ "The Servo Project Developers" ] description = "Infrastructure for measuring the total runtime size of an object on the heap" license = "MIT/Apache-2.0" @@ -12,6 +12,7 @@ kernel32-sys = "0.2.1" [features] unstable = [] +jemalloc = [] # https://github.com/servo/heapsize/issues/74 flexible-tests = [] diff --git a/derive/Cargo.toml b/derive/Cargo.toml index 92c8eaa..8573486 100644 --- a/derive/Cargo.toml +++ b/derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "heapsize_derive" -version = "0.1.4" +version = "0.2.0" authors = ["The Servo Project Developers"] description = "Automatically generating infrastructure for measuring the total runtime size of an object on the heap" license = "MIT/Apache-2.0" diff --git a/derive/lib.rs b/derive/lib.rs index 766e9e5..5b53f9f 100644 --- a/derive/lib.rs +++ b/derive/lib.rs @@ -30,12 +30,12 @@ fn expand_string(input: &str) -> String { } else if let syn::Ty::Array(..) = binding.field.ty { Some(quote! { for item in #binding.iter() { - sum += ::heapsize::HeapSizeOf::heap_size_of_children(item); + sum += ::heapsize::HeapSizeOf::heap_size_of_children(item, heap_size); } }) } else { Some(quote! { - sum += ::heapsize::HeapSizeOf::heap_size_of_children(#binding); + sum += ::heapsize::HeapSizeOf::heap_size_of_children(#binding, heap_size); }) } }); @@ -61,7 +61,7 @@ fn expand_string(input: &str) -> String { impl #impl_generics ::heapsize::HeapSizeOf for #name #ty_generics #where_clause { #[inline] #[allow(unused_variables, unused_mut, unreachable_code)] - fn heap_size_of_children(&self) -> usize { + fn heap_size_of_children(&self, heap_size: ::heapsize::HeapSizeOfFn) -> usize { let mut sum = 0; match *self { #match_body diff --git a/derive/test.rs b/derive/test.rs index 0fbb4a5..3042449 100644 --- a/derive/test.rs +++ b/derive/test.rs @@ -1,12 +1,14 @@ #[macro_use] extern crate heapsize_derive; mod heapsize { + pub type HeapSizeOfFn = unsafe fn(ptr: *const ()) -> usize; + pub trait HeapSizeOf { - fn heap_size_of_children(&self) -> usize; + fn heap_size_of_children(&self, heap_size: HeapSizeOfFn) -> usize; } impl HeapSizeOf for Box { - fn heap_size_of_children(&self) -> usize { + fn heap_size_of_children(&self, _heap_size: HeapSizeOfFn) -> usize { ::std::mem::size_of::() } } @@ -19,5 +21,8 @@ struct Foo([Box; 2], Box); #[test] fn test() { use heapsize::HeapSizeOf; - assert_eq!(Foo([Box::new(1), Box::new(2)], Box::new(3)).heap_size_of_children(), 9); + unsafe fn test_heap_size(_ptr: *const ()) -> usize { + unreachable!() + } + assert_eq!(Foo([Box::new(1), Box::new(2)], Box::new(3)).heap_size_of_children(test_heap_size), 9); } diff --git a/src/lib.rs b/src/lib.rs index a761b53..6b47d72 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,43 +18,49 @@ use std::sync::Arc; use std::sync::atomic::{AtomicBool, AtomicIsize, AtomicUsize}; use std::rc::Rc; +pub type HeapSizeOfFn = unsafe fn(ptr: *const c_void) -> usize; + /// Get the size of a heap block. /// /// Ideally Rust would expose a function like this in std::rt::heap. /// -/// `unsafe` because the caller must ensure that the pointer is from jemalloc. -/// FIXME: This probably interacts badly with custom allocators: -/// https://doc.rust-lang.org/book/custom-allocators.html -pub unsafe fn heap_size_of(ptr: *const T) -> usize { +/// `unsafe` because the caller must ensure that the pointer is from the allocator +/// associated with the `heap_size_of` callback. +pub unsafe fn do_heap_size_of(heap_size_of: HeapSizeOfFn, ptr: *const T) -> usize { if ptr as usize <= align_of::() { 0 } else { - heap_size_of_impl(ptr as *const c_void) + heap_size_of(ptr as *const c_void) } } -#[cfg(not(target_os = "windows"))] -unsafe fn heap_size_of_impl(ptr: *const c_void) -> usize { - // The C prototype is `je_malloc_usable_size(JEMALLOC_USABLE_SIZE_CONST void *ptr)`. On some - // platforms `JEMALLOC_USABLE_SIZE_CONST` is `const` and on some it is empty. But in practice - // this function doesn't modify the contents of the block that `ptr` points to, so we use - // `*const c_void` here. - extern "C" { - #[cfg_attr(any(prefixed_jemalloc, target_os = "macos", target_os = "android"), link_name = "je_malloc_usable_size")] - fn malloc_usable_size(ptr: *const c_void) -> usize; +#[cfg(feature = "jemalloc")] +pub mod jemalloc { + use std::os::raw::c_void; + + #[cfg(not(target_os = "windows"))] + pub unsafe fn heap_size_of(ptr: *const c_void) -> usize { + // The C prototype is `je_malloc_usable_size(JEMALLOC_USABLE_SIZE_CONST void *ptr)`. On some + // platforms `JEMALLOC_USABLE_SIZE_CONST` is `const` and on some it is empty. But in practice + // this function doesn't modify the contents of the block that `ptr` points to, so we use + // `*const c_void` here. + extern "C" { + #[cfg_attr(any(prefixed_jemalloc, target_os = "macos", target_os = "android"), link_name = "je_malloc_usable_size")] + fn malloc_usable_size(ptr: *const c_void) -> usize; + } + malloc_usable_size(ptr) } - malloc_usable_size(ptr) -} -#[cfg(target_os = "windows")] -unsafe fn heap_size_of_impl(mut ptr: *const c_void) -> usize { - let heap = GetProcessHeap(); + #[cfg(target_os = "windows")] + pub unsafe fn heap_size_of(mut ptr: *const c_void) -> usize { + let heap = GetProcessHeap(); - if HeapValidate(heap, 0, ptr) == 0 { - ptr = *(ptr as *const *const c_void).offset(-1); - } + if HeapValidate(heap, 0, ptr) == 0 { + ptr = *(ptr as *const *const c_void).offset(-1); + } - HeapSize(heap, 0, ptr) as usize + HeapSize(heap, 0, ptr) as usize + } } // The simplest trait for measuring the size of heap data structures. More complex traits that @@ -65,7 +71,7 @@ pub trait HeapSizeOf { /// Measure the size of any heap-allocated structures that hang off this value, but not the /// space taken up by the value itself (i.e. what size_of:: measures, more or less); that /// space is handled by the implementation of HeapSizeOf for Box below. - fn heap_size_of_children(&self) -> usize; + fn heap_size_of_children(&self, heap_size_of: HeapSizeOfFn) -> usize; } // There are two possible ways to measure the size of `self` when it's on the heap: compute it @@ -84,30 +90,30 @@ pub trait HeapSizeOf { // However, in the best case, the two approaches should give the same results. // impl HeapSizeOf for Box { - fn heap_size_of_children(&self) -> usize { + fn heap_size_of_children(&self, heap_size: HeapSizeOfFn) -> usize { // Measure size of `self`. unsafe { - heap_size_of(&**self as *const T as *const c_void) + (**self).heap_size_of_children() + do_heap_size_of(heap_size, &**self as *const T as *const c_void) + (**self).heap_size_of_children(heap_size) } } } impl HeapSizeOf for [T] { - fn heap_size_of_children(&self) -> usize { - self.iter().fold(0, |size, item| size + item.heap_size_of_children()) + fn heap_size_of_children(&self, heap_size: HeapSizeOfFn) -> usize { + self.iter().fold(0, |size, item| size + item.heap_size_of_children(heap_size)) } } impl HeapSizeOf for String { - fn heap_size_of_children(&self) -> usize { + fn heap_size_of_children(&self, heap_size: HeapSizeOfFn) -> usize { unsafe { - heap_size_of(self.as_ptr()) + do_heap_size_of(heap_size, self.as_ptr()) } } } impl<'a, T: ?Sized> HeapSizeOf for &'a T { - fn heap_size_of_children(&self) -> usize { + fn heap_size_of_children(&self, _heap_size: HeapSizeOfFn) -> usize { 0 } } @@ -120,46 +126,46 @@ impl<'a, T: ?Sized> HeapSizeOf for &'a T { // These have to return 0 since we don't know if the pointer is pointing to a heap allocation or // even valid memory. impl HeapSizeOf for *mut T { - fn heap_size_of_children(&self) -> usize { + fn heap_size_of_children(&self, _heap_size: HeapSizeOfFn) -> usize { 0 } } impl HeapSizeOf for *const T { - fn heap_size_of_children(&self) -> usize { + fn heap_size_of_children(&self, _heap_size: HeapSizeOfFn) -> usize { 0 } } impl HeapSizeOf for Option { - fn heap_size_of_children(&self) -> usize { + fn heap_size_of_children(&self, heap_size: HeapSizeOfFn) -> usize { match *self { None => 0, - Some(ref x) => x.heap_size_of_children() + Some(ref x) => x.heap_size_of_children(heap_size) } } } impl HeapSizeOf for Result { - fn heap_size_of_children(&self) -> usize { + fn heap_size_of_children(&self, heap_size: HeapSizeOfFn) -> usize { match *self { - Ok(ref x) => x.heap_size_of_children(), - Err(ref e) => e.heap_size_of_children(), + Ok(ref x) => x.heap_size_of_children(heap_size), + Err(ref e) => e.heap_size_of_children(heap_size), } } } impl<'a, B: ?Sized + ToOwned> HeapSizeOf for Cow<'a, B> where B::Owned: HeapSizeOf { - fn heap_size_of_children(&self) -> usize { + fn heap_size_of_children(&self, heap_size: HeapSizeOfFn) -> usize { match *self { Cow::Borrowed(_) => 0, - Cow::Owned(ref b) => b.heap_size_of_children(), + Cow::Owned(ref b) => b.heap_size_of_children(heap_size), } } } impl HeapSizeOf for () { - fn heap_size_of_children(&self) -> usize { + fn heap_size_of_children(&self, _heap_size: HeapSizeOfFn) -> usize { 0 } } @@ -167,125 +173,125 @@ impl HeapSizeOf for () { impl HeapSizeOf for (T1, T2) where T1: HeapSizeOf, T2 :HeapSizeOf { - fn heap_size_of_children(&self) -> usize { - self.0.heap_size_of_children() + - self.1.heap_size_of_children() + fn heap_size_of_children(&self, heap_size: HeapSizeOfFn) -> usize { + self.0.heap_size_of_children(heap_size) + + self.1.heap_size_of_children(heap_size) } } impl HeapSizeOf for (T1, T2, T3) where T1: HeapSizeOf, T2 :HeapSizeOf, T3: HeapSizeOf { - fn heap_size_of_children(&self) -> usize { - self.0.heap_size_of_children() + - self.1.heap_size_of_children() + - self.2.heap_size_of_children() + fn heap_size_of_children(&self, heap_size: HeapSizeOfFn) -> usize { + self.0.heap_size_of_children(heap_size) + + self.1.heap_size_of_children(heap_size) + + self.2.heap_size_of_children(heap_size) } } impl HeapSizeOf for (T1, T2, T3, T4) where T1: HeapSizeOf, T2 :HeapSizeOf, T3: HeapSizeOf, T4: HeapSizeOf { - fn heap_size_of_children(&self) -> usize { - self.0.heap_size_of_children() + - self.1.heap_size_of_children() + - self.2.heap_size_of_children() + - self.3.heap_size_of_children() + fn heap_size_of_children(&self, heap_size: HeapSizeOfFn) -> usize { + self.0.heap_size_of_children(heap_size) + + self.1.heap_size_of_children(heap_size) + + self.2.heap_size_of_children(heap_size) + + self.3.heap_size_of_children(heap_size) } } impl HeapSizeOf for (T1, T2, T3, T4, T5) where T1: HeapSizeOf, T2 :HeapSizeOf, T3: HeapSizeOf, T4: HeapSizeOf, T5: HeapSizeOf { - fn heap_size_of_children(&self) -> usize { - self.0.heap_size_of_children() + - self.1.heap_size_of_children() + - self.2.heap_size_of_children() + - self.3.heap_size_of_children() + - self.4.heap_size_of_children() + fn heap_size_of_children(&self, heap_size: HeapSizeOfFn) -> usize { + self.0.heap_size_of_children(heap_size) + + self.1.heap_size_of_children(heap_size) + + self.2.heap_size_of_children(heap_size) + + self.3.heap_size_of_children(heap_size) + + self.4.heap_size_of_children(heap_size) } } impl HeapSizeOf for Arc { - fn heap_size_of_children(&self) -> usize { - (**self).heap_size_of_children() + fn heap_size_of_children(&self, heap_size: HeapSizeOfFn) -> usize { + (**self).heap_size_of_children(heap_size) } } impl HeapSizeOf for RefCell { - fn heap_size_of_children(&self) -> usize { - self.borrow().heap_size_of_children() + fn heap_size_of_children(&self, heap_size: HeapSizeOfFn) -> usize { + self.borrow().heap_size_of_children(heap_size) } } impl HeapSizeOf for Cell { - fn heap_size_of_children(&self) -> usize { - self.get().heap_size_of_children() + fn heap_size_of_children(&self, heap_size: HeapSizeOfFn) -> usize { + self.get().heap_size_of_children(heap_size) } } impl HeapSizeOf for Vec { - fn heap_size_of_children(&self) -> usize { + fn heap_size_of_children(&self, heap_size: HeapSizeOfFn) -> usize { self.iter().fold( - unsafe { heap_size_of(self.as_ptr()) }, - |n, elem| n + elem.heap_size_of_children()) + unsafe { do_heap_size_of(heap_size, self.as_ptr()) }, + |n, elem| n + elem.heap_size_of_children(heap_size)) } } impl HeapSizeOf for VecDeque { - fn heap_size_of_children(&self) -> usize { + fn heap_size_of_children(&self, heap_size: HeapSizeOfFn) -> usize { self.iter().fold( - // FIXME: get the buffer pointer for heap_size_of(), capacity() is a lower bound: + // FIXME: get the buffer pointer for do_heap_size_of(), capacity() is a lower bound: self.capacity() * size_of::(), - |n, elem| n + elem.heap_size_of_children()) + |n, elem| n + elem.heap_size_of_children(heap_size)) } } impl HeapSizeOf for Vec> { - fn heap_size_of_children(&self) -> usize { + fn heap_size_of_children(&self, heap_size: HeapSizeOfFn) -> usize { // The fate of measuring Rc is still undecided, but we still want to measure // the space used for storing them. unsafe { - heap_size_of(self.as_ptr()) + do_heap_size_of(heap_size, self.as_ptr()) } } } impl HeapSizeOf for HashSet where T: Eq + Hash, S: BuildHasher { - fn heap_size_of_children(&self) -> usize { + fn heap_size_of_children(&self, heap_size: HeapSizeOfFn) -> usize { //TODO(#6908) measure actual bucket memory usage instead of approximating let size = self.capacity() * (size_of::() + size_of::()); self.iter().fold(size, |n, value| { - n + value.heap_size_of_children() + n + value.heap_size_of_children(heap_size) }) } } impl HeapSizeOf for HashMap where K: Eq + Hash, S: BuildHasher { - fn heap_size_of_children(&self) -> usize { + fn heap_size_of_children(&self, heap_size: HeapSizeOfFn) -> usize { //TODO(#6908) measure actual bucket memory usage instead of approximating let size = self.capacity() * (size_of::() + size_of::() + size_of::()); self.iter().fold(size, |n, (key, value)| { - n + key.heap_size_of_children() + value.heap_size_of_children() + n + key.heap_size_of_children(heap_size) + value.heap_size_of_children(heap_size) }) } } // PhantomData is always 0. impl HeapSizeOf for PhantomData { - fn heap_size_of_children(&self) -> usize { + fn heap_size_of_children(&self, _heap_size: HeapSizeOfFn) -> usize { 0 } } // A linked list has an overhead of two words per item. impl HeapSizeOf for LinkedList { - fn heap_size_of_children(&self) -> usize { + fn heap_size_of_children(&self, heap_size: HeapSizeOfFn) -> usize { let mut size = 0; for item in self { - size += 2 * size_of::() + size_of::() + item.heap_size_of_children(); + size += 2 * size_of::() + size_of::() + item.heap_size_of_children(heap_size); } size } @@ -293,12 +299,12 @@ impl HeapSizeOf for LinkedList { // FIXME: Overhead for the BTreeMap nodes is not accounted for. impl HeapSizeOf for BTreeMap { - fn heap_size_of_children(&self) -> usize { + fn heap_size_of_children(&self, heap_size: HeapSizeOfFn) -> usize { let mut size = 0; for (key, value) in self.iter() { size += size_of::<(K, V)>() + - key.heap_size_of_children() + - value.heap_size_of_children(); + key.heap_size_of_children(heap_size) + + value.heap_size_of_children(heap_size); } size } @@ -312,7 +318,7 @@ macro_rules! known_heap_size( $( impl $crate::HeapSizeOf for $ty { #[inline(always)] - fn heap_size_of_children(&self) -> usize { + fn heap_size_of_children(&self, _heap_size: HeapSizeOfFn) -> usize { $size } } @@ -322,7 +328,7 @@ macro_rules! known_heap_size( $( impl<$($gen: $crate::HeapSizeOf),+> $crate::HeapSizeOf for $ty<$($gen),+> { #[inline(always)] - fn heap_size_of_children(&self) -> usize { + fn heap_size_of_children(&self, _heap_size: HeapSizeOfFn) -> usize { $size } } diff --git a/tests/tests.rs b/tests/tests.rs index f9cca0c..5ddf23e 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -1,8 +1,9 @@ #![cfg_attr(feature= "unstable", feature(alloc, heap_api, repr_simd))] +#![cfg(feature = "jemalloc")] extern crate heapsize; -use heapsize::{HeapSizeOf, heap_size_of}; +use heapsize::{HeapSizeOf, do_heap_size_of, jemalloc}; use std::os::raw::c_void; const EMPTY: *mut () = 0x1 as *mut (); @@ -30,7 +31,7 @@ macro_rules! assert_size { mod unstable { extern crate alloc; - use heapsize::heap_size_of; + use heapsize::{do_heap_size_of, jemalloc}; use std::os::raw::c_void; #[repr(C, simd)] @@ -47,22 +48,22 @@ mod unstable { unsafe { // A 64 byte request is allocated exactly. let x = alloc::heap::allocate(64, 0); - assert_size!(heap_size_of(x as *const c_void), 64); + assert_size!(do_heap_size_of(jemalloc::heap_size_of, x as *const c_void), 64); alloc::heap::deallocate(x, 64, 0); // A 255 byte request is rounded up to 256 bytes. let x = alloc::heap::allocate(255, 0); - assert_size!(heap_size_of(x as *const c_void), 256); + assert_size!(do_heap_size_of(jemalloc::heap_size_of, x as *const c_void), 256); alloc::heap::deallocate(x, 255, 0); // A 1MiB request is allocated exactly. let x = alloc::heap::allocate(1024 * 1024, 0); - assert_size!(heap_size_of(x as *const c_void), 1024 * 1024); + assert_size!(do_heap_size_of(jemalloc::heap_size_of, x as *const c_void), 1024 * 1024); alloc::heap::deallocate(x, 1024 * 1024, 0); // An overaligned 1MiB request is allocated exactly. let x = alloc::heap::allocate(1024 * 1024, 32); - assert_size!(heap_size_of(x as *const c_void), 1024 * 1024); + assert_size!(do_heap_size_of(jemalloc::heap_size_of, x as *const c_void), 1024 * 1024); alloc::heap::deallocate(x, 1024 * 1024, 32); } } @@ -73,22 +74,22 @@ mod unstable { unsafe { // A 64 byte request is allocated exactly. let x = alloc::heap::allocate(64, 0); - assert_size!(heap_size_of(x as *const c_void), 64); + assert_size!(do_heap_size_of(jemalloc::heap_size_of, x as *const c_void), 64); alloc::heap::deallocate(x, 64, 0); // A 255 byte request is allocated exactly. let x = alloc::heap::allocate(255, 0); - assert_size!(heap_size_of(x as *const c_void), 255); + assert_size!(do_heap_size_of(jemalloc::heap_size_of, x as *const c_void), 255); alloc::heap::deallocate(x, 255, 0); // A 1MiB request is allocated exactly. let x = alloc::heap::allocate(1024 * 1024, 0); - assert_size!(heap_size_of(x as *const c_void), 1024 * 1024); + assert_size!(do_heap_size_of(jemalloc::heap_size_of, x as *const c_void), 1024 * 1024); alloc::heap::deallocate(x, 1024 * 1024, 0); // An overaligned 1MiB request is over-allocated. let x = alloc::heap::allocate(1024 * 1024, 32); - assert_size!(heap_size_of(x as *const c_void), 1024 * 1024 + 32); + assert_size!(do_heap_size_of(jemalloc::heap_size_of, x as *const c_void), 1024 * 1024 + 32); alloc::heap::deallocate(x, 1024 * 1024, 32); } } @@ -97,21 +98,21 @@ mod unstable { #[test] fn test_simd() { let x = Box::new(OverAligned(0, 0, 0, 0)); - assert_size!(unsafe { heap_size_of(&*x as *const _ as *const c_void) }, 32); + assert_size!(unsafe { do_heap_size_of(jemalloc::heap_size_of, &*x as *const _ as *const c_void) }, 32); } #[cfg(target_os = "windows")] #[test] fn test_simd() { let x = Box::new(OverAligned(0, 0, 0, 0)); - assert_size!(unsafe { heap_size_of(&*x as *const _ as *const c_void) }, 32 + 32); + assert_size!(unsafe { do_heap_size_of(jemalloc::heap_size_of, &*x as *const _ as *const c_void) }, 32 + 32); } } #[test] fn test_boxed_str() { let x = "raclette".to_owned().into_boxed_str(); - assert_size!(x.heap_size_of_children(), 8); + assert_size!(x.heap_size_of_children(jemalloc::heap_size_of), 8); } #[test] @@ -126,7 +127,7 @@ fn test_heap_size() { unsafe { // EMPTY is the special non-null address used to represent zero-size allocations. - assert_size!(heap_size_of(EMPTY as *const c_void), 0); + assert_size!(do_heap_size_of(jemalloc::heap_size_of, EMPTY as *const c_void), 0); } //----------------------------------------------------------------------- @@ -134,53 +135,53 @@ fn test_heap_size() { // Not on the heap; 0 bytes. let x = 0i64; - assert_size!(x.heap_size_of_children(), 0); + assert_size!(x.heap_size_of_children(jemalloc::heap_size_of), 0); // An i64 is 8 bytes. let x = Box::new(0i64); - assert_size!(x.heap_size_of_children(), 8); + assert_size!(x.heap_size_of_children(jemalloc::heap_size_of), 8); // An ascii string with 16 chars is 16 bytes in UTF-8. let string = String::from("0123456789abcdef"); - assert_size!(string.heap_size_of_children(), 16); + assert_size!(string.heap_size_of_children(jemalloc::heap_size_of), 16); let string_ref: (&String, ()) = (&string, ()); - assert_size!(string_ref.heap_size_of_children(), 0); + assert_size!(string_ref.heap_size_of_children(jemalloc::heap_size_of), 0); let slice: &str = &*string; - assert_size!(slice.heap_size_of_children(), 0); + assert_size!(slice.heap_size_of_children(jemalloc::heap_size_of), 0); // Not on the heap. let x: Option = None; - assert_size!(x.heap_size_of_children(), 0); + assert_size!(x.heap_size_of_children(jemalloc::heap_size_of), 0); // Not on the heap. let x = Some(0i64); - assert_size!(x.heap_size_of_children(), 0); + assert_size!(x.heap_size_of_children(jemalloc::heap_size_of), 0); // The `Some` is not on the heap, but the Box is. let x = Some(Box::new(0i64)); - assert_size!(x.heap_size_of_children(), 8); + assert_size!(x.heap_size_of_children(jemalloc::heap_size_of), 8); // Not on the heap. let x = ::std::sync::Arc::new(0i64); - assert_size!(x.heap_size_of_children(), 0); + assert_size!(x.heap_size_of_children(jemalloc::heap_size_of), 0); // The `Arc` is not on the heap, but the Box is. let x = ::std::sync::Arc::new(Box::new(0i64)); - assert_size!(x.heap_size_of_children(), 8); + assert_size!(x.heap_size_of_children(jemalloc::heap_size_of), 8); // Zero elements, no heap storage. let x: Vec = vec![]; - assert_size!(x.heap_size_of_children(), 0); + assert_size!(x.heap_size_of_children(jemalloc::heap_size_of), 0); // Four elements, 8 bytes per element. let x = vec![0i64, 1i64, 2i64, 3i64]; - assert_size!(x.heap_size_of_children(), 32); + assert_size!(x.heap_size_of_children(jemalloc::heap_size_of), 32); } #[test] fn test_boxed_slice() { let x = vec![1i64, 2i64].into_boxed_slice(); - assert_size!(x.heap_size_of_children(), 16) + assert_size!(x.heap_size_of_children(jemalloc::heap_size_of), 16) }