Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@ members = [
"primitive-types",
"ethereum-types",
"ethbloom",
"parity-util-mem/derive"
]
2 changes: 1 addition & 1 deletion parity-util-mem/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ edition = "2018"

[dependencies]
cfg-if = "0.1.10"
malloc_size_of_derive = "0.1.1"
dlmalloc = { version = "0.1.3", features = ["global"], optional = true }
wee_alloc = { version = "0.4.5", optional = true }
# from https://github.com/microsoft/mimalloc:
Expand All @@ -19,6 +18,7 @@ wee_alloc = { version = "0.4.5", optional = true }
# The performance penalty is only around 3% on average over our benchmarks.
mimallocator = { version = "0.1.3", features = ["secure"], optional = true }
mimalloc-sys = { version = "0.1.6", optional = true }
parity-util-mem-derive = { path = "derive", version = "0.1" }
Comment thread
dvdplm marked this conversation as resolved.

smallvec = { version = "1.0.0", optional = true }
ethereum-types = { version = "0.8.0", optional = true, path = "../ethereum-types" }
Expand Down
16 changes: 16 additions & 0 deletions parity-util-mem/derive/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[package]
name = "parity-util-mem-derive"
version = "0.1.0"
authors = ["Parity Technologies"]
license = "MIT"
description = "Crate for memory reporting"
repository = "https://github.com/paritytech/pariry-common/parity-util-mem/derive"

[lib]
path = "lib.rs"
proc-macro = true

[dependencies]
proc-macro2 = "1"
syn = { version = "1", features = ["full"] }
synstructure = "0.12"
65 changes: 65 additions & 0 deletions parity-util-mem/derive/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
//! A crate for deriving the MallocSizeOf trait.
Comment thread
NikVolf marked this conversation as resolved.

extern crate proc_macro2;
#[macro_use]
extern crate syn;
#[macro_use]
extern crate synstructure;

#[cfg(not(test))]
decl_derive!([MallocSizeOf, attributes(ignore_malloc_size_of)] => malloc_size_of_derive);

fn malloc_size_of_derive(s: synstructure::Structure) -> proc_macro2::TokenStream {
let match_body = s.each(|binding| {
let ignore = binding.ast().attrs.iter().any(|attr| match attr.parse_meta().unwrap() {
syn::Meta::Path(ref path) | syn::Meta::List(syn::MetaList { ref path, .. })
if path.is_ident("ignore_malloc_size_of") =>
{
panic!(
"#[ignore_malloc_size_of] should have an explanation, \
e.g. #[ignore_malloc_size_of = \"because reasons\"]"
);
}
syn::Meta::NameValue(syn::MetaNameValue { ref path, .. }) if path.is_ident("ignore_malloc_size_of") => true,
_ => false,
});
if ignore {
None
} else if let syn::Type::Array(..) = binding.ast().ty {
Some(quote! {
for item in #binding.iter() {
sum += parity_util_mem::MallocSizeOf::size_of(item, ops);
}
})
} else {
Some(quote! {
sum += parity_util_mem::MallocSizeOf::size_of(#binding, ops);
})
}
});

let ast = s.ast();
let name = &ast.ident;
let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
let mut where_clause = where_clause.unwrap_or(&parse_quote!(where)).clone();
for param in ast.generics.type_params() {
let ident = &param.ident;
where_clause.predicates.push(parse_quote!(#ident: parity_util_mem::MallocSizeOf));
}

let tokens = quote! {
impl #impl_generics parity_util_mem::MallocSizeOf for #name #ty_generics #where_clause {
#[inline]
#[allow(unused_variables, unused_mut, unreachable_code)]
fn size_of(&self, ops: &mut parity_util_mem::MallocSizeOfOps) -> usize {
let mut sum = 0;
match *self {
#match_body
}
sum
}
}
};

tokens
}
6 changes: 6 additions & 0 deletions parity-util-mem/src/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ malloc_size_of_is_0!(std::time::Duration);

malloc_size_of_is_0!(U64, U128, U256, U512, H32, H64, H128, H160, H256, H264, H512, H520, Bloom);

malloc_size_of_is_0!(
[u8; 1], [u8; 2], [u8; 3], [u8; 4], [u8; 5], [u8; 6], [u8; 7], [u8; 8], [u8; 9], [u8; 10], [u8; 11], [u8; 12],
[u8; 13], [u8; 14], [u8; 15], [u8; 16], [u8; 17], [u8; 18], [u8; 19], [u8; 20], [u8; 21], [u8; 22], [u8; 23],
[u8; 24], [u8; 25], [u8; 26], [u8; 27], [u8; 28], [u8; 29], [u8; 30], [u8; 31], [u8; 32]
);

macro_rules! impl_smallvec {
($size: expr) => {
impl<T> MallocSizeOf for SmallVec<[T; $size]>
Expand Down
5 changes: 2 additions & 3 deletions parity-util-mem/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@
#[cfg(not(feature = "std"))]
extern crate alloc;

use malloc_size_of_derive as malloc_size_derive;

cfg_if::cfg_if! {
if #[cfg(all(
feature = "jemalloc-global",
Expand Down Expand Up @@ -72,7 +70,8 @@ pub mod impls;

pub use allocators::MallocSizeOfExt;
pub use malloc_size::{MallocSizeOf, MallocSizeOfOps};
pub use malloc_size_derive::*;

pub use parity_util_mem_derive::*;

#[cfg(feature = "std")]
#[cfg(test)]
Expand Down
20 changes: 6 additions & 14 deletions parity-util-mem/src/malloc_size.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@
//! measured as well as the thing it points to. E.g.
//! `<Box<_> as MallocSizeOf>::size_of(field, ops)`.

//! This is an extended (for own internal needs) version of the Servo internal malloc_size crate.
//! We should occasionally track the upstream changes/fixes and reintroduce them here, be they applicable.
//! This is an extended version of the Servo internal malloc_size crate.
//! We should occasionally track the upstream changes/fixes and reintroduce them here, whenever applicable.

#[cfg(not(feature = "std"))]
use alloc::vec::Vec;
Expand Down Expand Up @@ -426,11 +426,7 @@ where
}

#[cfg(feature = "std")]
impl<K, V, S> MallocShallowSizeOf for std::collections::HashMap<K, V, S>
where
K: Eq + Hash,
S: BuildHasher,
{
impl<K, V, S> MallocShallowSizeOf for std::collections::HashMap<K, V, S> {
fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
// See the implementation for std::collections::HashSet for details.
if ops.has_malloc_enclosing_size_of() {
Expand All @@ -444,9 +440,8 @@ where
#[cfg(feature = "std")]
impl<K, V, S> MallocSizeOf for std::collections::HashMap<K, V, S>
where
K: Eq + Hash + MallocSizeOf,
K: MallocSizeOf,
V: MallocSizeOf,
S: BuildHasher,
{
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
let mut n = self.shallow_size_of(ops);
Expand All @@ -458,10 +453,7 @@ where
}
}

impl<K, V> MallocShallowSizeOf for rstd::collections::BTreeMap<K, V>
where
K: Eq + Hash,
{
impl<K, V> MallocShallowSizeOf for rstd::collections::BTreeMap<K, V> {
fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
if ops.has_malloc_enclosing_size_of() {
self.values().next().map_or(0, |v| unsafe { ops.malloc_enclosing_size_of(v) })
Expand All @@ -473,7 +465,7 @@ where

impl<K, V> MallocSizeOf for rstd::collections::BTreeMap<K, V>
where
K: Eq + Hash + MallocSizeOf,
K: MallocSizeOf,
V: MallocSizeOf,
{
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
Expand Down
47 changes: 47 additions & 0 deletions parity-util-mem/tests/derive.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
use parity_util_mem::{MallocSizeOf, MallocSizeOfExt};
Comment thread
NikVolf marked this conversation as resolved.

#[test]
#[cfg(feature = "std")]
fn derive_vec() {
#[derive(MallocSizeOf)]
struct Trivia {
v: Vec<u8>,
}

let t = Trivia { v: vec![0u8; 1024] };

assert!(t.malloc_size_of() > 1000);
}

Comment thread
dvdplm marked this conversation as resolved.
#[test]
#[cfg(feature = "std")]
fn derive_hashmap() {
#[derive(MallocSizeOf, Default)]
struct Trivia {
hm: std::collections::HashMap<u64, Vec<u8>>,
}

let mut t = Trivia::default();

t.hm.insert(1, vec![0u8; 2048]);

assert!(t.malloc_size_of() > 2000);
}

#[test]
#[cfg(feature = "std")]
fn derive_ignore() {
#[derive(MallocSizeOf, Default)]
struct Trivia {
hm: std::collections::HashMap<u64, Vec<u8>>,
#[ignore_malloc_size_of = "I don't like vectors"]
v: Vec<u8>,
}

let mut t = Trivia::default();

t.hm.insert(1, vec![0u8; 2048]);
t.v = vec![0u8; 1024];

assert!(t.malloc_size_of() < 3000);
}