diff --git a/kvdb-memorydb/Cargo.toml b/kvdb-memorydb/Cargo.toml index 74c81818c..2ba57bbc4 100644 --- a/kvdb-memorydb/Cargo.toml +++ b/kvdb-memorydb/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "kvdb-memorydb" -version = "0.3.0" +version = "0.3.1" authors = ["Parity Technologies "] repository = "https://github.com/paritytech/parity-common" description = "A key-value in-memory database that implements the `KeyValueDB` trait" @@ -8,7 +8,7 @@ license = "GPL-3.0" edition = "2018" [dependencies] -parity-util-mem = { path = "../parity-util-mem", version = "0.4" } +parity-util-mem = { path = "../parity-util-mem", version = "0.4", default-features = false, features = ["std"] } parking_lot = "0.9.0" kvdb = { version = "0.3", path = "../kvdb" } diff --git a/kvdb-rocksdb/Cargo.toml b/kvdb-rocksdb/Cargo.toml index 778bc0736..657c0392c 100644 --- a/kvdb-rocksdb/Cargo.toml +++ b/kvdb-rocksdb/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "kvdb-rocksdb" -version = "0.4.0" +version = "0.4.1" authors = ["Parity Technologies "] repository = "https://github.com/paritytech/parity-common" description = "kvdb implementation backed by RocksDB" @@ -22,7 +22,7 @@ parking_lot = "0.9.0" regex = "1.3.1" rocksdb = { version = "0.13", features = ["snappy"], default-features = false } owning_ref = "0.4.0" -parity-util-mem = { path = "../parity-util-mem", version = "0.4" } +parity-util-mem = { path = "../parity-util-mem", version = "0.4", default-features = false, features = ["std", "smallvec"] } [dev-dependencies] alloc_counter = "0.0.4" diff --git a/kvdb-web/Cargo.toml b/kvdb-web/Cargo.toml index 985e453c2..ea77e5855 100644 --- a/kvdb-web/Cargo.toml +++ b/kvdb-web/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "kvdb-web" -version = "0.3.0" +version = "0.3.1" authors = ["Parity Technologies "] repository = "https://github.com/paritytech/parity-common" description = "A key-value database for use in browsers" @@ -16,7 +16,7 @@ kvdb-memorydb = { version = "0.3", path = "../kvdb-memorydb" } futures = "0.3" log = "0.4.8" send_wrapper = "0.3.0" -parity-util-mem = { path = "../parity-util-mem", version = "0.4" } +parity-util-mem = { path = "../parity-util-mem", version = "0.4", default-features = false } [dependencies.web-sys] version = "0.3.31" diff --git a/kvdb/Cargo.toml b/kvdb/Cargo.toml index 46aad54c6..c176644ac 100644 --- a/kvdb/Cargo.toml +++ b/kvdb/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "kvdb" -version = "0.3.0" +version = "0.3.1" authors = ["Parity Technologies "] repository = "https://github.com/paritytech/parity-common" description = "Generic key-value trait" @@ -10,4 +10,4 @@ edition = "2018" [dependencies] smallvec = "1.0.0" bytes = { package = "parity-bytes", version = "0.1", path = "../parity-bytes" } -parity-util-mem = { path = "../parity-util-mem", version = "0.4" } +parity-util-mem = { path = "../parity-util-mem", version = "0.4", default-features = false } diff --git a/parity-util-mem/Cargo.toml b/parity-util-mem/Cargo.toml index b9dc68913..9aee6db3e 100644 --- a/parity-util-mem/Cargo.toml +++ b/parity-util-mem/Cargo.toml @@ -35,7 +35,7 @@ version = "0.3.2" optional = true [features] -default = ["std", "ethereum-impls", "lru", "hashbrown"] +default = ["std", "ethereum-impls", "lru", "hashbrown", "smallvec"] std = ["parking_lot"] # use dlmalloc as global allocator dlmalloc-global = ["dlmalloc", "estimate-heapsize"] @@ -46,6 +46,6 @@ jemalloc-global = ["jemallocator"] # use mimalloc as global allocator mimalloc-global = ["mimallocator", "mimalloc-sys"] # implement additional types -ethereum-impls = ["ethereum-types", "smallvec"] +ethereum-impls = ["ethereum-types"] # Full estimate: no call to allocator estimate-heapsize = [] diff --git a/parity-util-mem/src/ethereum_impls.rs b/parity-util-mem/src/ethereum_impls.rs new file mode 100644 index 000000000..243230106 --- /dev/null +++ b/parity-util-mem/src/ethereum_impls.rs @@ -0,0 +1,22 @@ +// Copyright 2015-2019 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Implementation of `MallocSize` for common ethereum types: fixed hashes +//! and uints. + +use ethereum_types::{Bloom, H128, H160, H256, H264, H32, H512, H520, H64, U128, U256, U512, U64}; + +malloc_size_of_is_0!(U64, U128, U256, U512, H32, H64, H128, H160, H256, H264, H512, H520, Bloom); diff --git a/parity-util-mem/src/impls.rs b/parity-util-mem/src/impls.rs deleted file mode 100644 index 4124b132a..000000000 --- a/parity-util-mem/src/impls.rs +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright 2015-2019 Parity Technologies (UK) Ltd. -// This file is part of Parity. - -// Parity is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity. If not, see . - -//! Implementation of `MallocSize` for common types : -//! - ethereum types uint and fixed hash. -//! - smallvec arrays of sizes 32, 36 - -use super::{MallocSizeOf, MallocSizeOfOps}; - -use ethereum_types::{Bloom, H128, H160, H256, H264, H32, H512, H520, H64, U128, U256, U512, U64}; -use smallvec::SmallVec; - -#[cfg(not(feature = "std"))] -use core as std; - -#[cfg(feature = "std")] -malloc_size_of_is_0!(std::time::Instant); -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 MallocSizeOf for SmallVec<[T; $size]> - where - T: MallocSizeOf, - { - fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { - let mut n = if self.spilled() { self.capacity() * core::mem::size_of::() } else { 0 }; - for elem in self.iter() { - n += elem.size_of(ops); - } - n - } - } - }; -} - -impl_smallvec!(32); // kvdb uses this -impl_smallvec!(36); // trie-db uses this - -#[cfg(test)] -mod tests { - use crate::{allocators::new_malloc_size_ops, MallocSizeOf, MallocSizeOfOps}; - use smallvec::SmallVec; - use std::mem; - impl_smallvec!(3); - - #[test] - fn test_smallvec_stack_allocated_type() { - let mut v: SmallVec<[u8; 3]> = SmallVec::new(); - let mut ops = new_malloc_size_ops(); - assert_eq!(v.size_of(&mut ops), 0); - v.push(1); - v.push(2); - v.push(3); - assert_eq!(v.size_of(&mut ops), 0); - assert!(!v.spilled()); - v.push(4); - assert!(v.spilled(), "SmallVec spills when going beyond the capacity of the inner backing array"); - assert_eq!(v.size_of(&mut ops), 4); // 4 u8s on the heap - } - - #[test] - fn test_smallvec_boxed_stack_allocated_type() { - let mut v: SmallVec<[Box; 3]> = SmallVec::new(); - let mut ops = new_malloc_size_ops(); - assert_eq!(v.size_of(&mut ops), 0); - v.push(Box::new(1u8)); - v.push(Box::new(2u8)); - v.push(Box::new(3u8)); - assert!(v.size_of(&mut ops) >= 3); - assert!(!v.spilled()); - v.push(Box::new(4u8)); - assert!(v.spilled(), "SmallVec spills when going beyond the capacity of the inner backing array"); - let mut ops = new_malloc_size_ops(); - let expected_min_allocs = mem::size_of::>() * 4 + 4; - assert!(v.size_of(&mut ops) >= expected_min_allocs); - } - - #[test] - fn test_smallvec_heap_allocated_type() { - let mut v: SmallVec<[String; 3]> = SmallVec::new(); - let mut ops = new_malloc_size_ops(); - assert_eq!(v.size_of(&mut ops), 0); - v.push("COW".into()); - v.push("PIG".into()); - v.push("DUCK".into()); - assert!(!v.spilled()); - assert!(v.size_of(&mut ops) >= "COW".len() + "PIG".len() + "DUCK".len()); - v.push("ÖWL".into()); - assert!(v.spilled()); - let mut ops = new_malloc_size_ops(); - let expected_min_allocs = mem::size_of::() * 4 + "ÖWL".len() + "COW".len() + "PIG".len() + "DUCK".len(); - assert!(v.size_of(&mut ops) >= expected_min_allocs); - } -} diff --git a/parity-util-mem/src/lib.rs b/parity-util-mem/src/lib.rs index 2d45cf9b4..ddd8f1fd5 100644 --- a/parity-util-mem/src/lib.rs +++ b/parity-util-mem/src/lib.rs @@ -66,7 +66,7 @@ pub mod sizeof; mod malloc_size; #[cfg(feature = "ethereum-impls")] -pub mod impls; +pub mod ethereum_impls; pub use allocators::MallocSizeOfExt; pub use malloc_size::{MallocSizeOf, MallocSizeOfOps}; diff --git a/parity-util-mem/src/malloc_size.rs b/parity-util-mem/src/malloc_size.rs index b9761527f..2f180a676 100644 --- a/parity-util-mem/src/malloc_size.rs +++ b/parity-util-mem/src/malloc_size.rs @@ -639,3 +639,92 @@ where n } } + +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) => { + #[cfg(feature = "smallvec")] + impl MallocSizeOf for smallvec::SmallVec<[T; $size]> + where + T: MallocSizeOf, + { + fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { + let mut n = if self.spilled() { self.capacity() * core::mem::size_of::() } else { 0 }; + for elem in self.iter() { + n += elem.size_of(ops); + } + n + } + } + }; +} + +impl_smallvec!(32); // kvdb uses this +impl_smallvec!(36); // trie-db uses this + +#[cfg(feature = "std")] +malloc_size_of_is_0!(std::time::Instant); +#[cfg(feature = "std")] +malloc_size_of_is_0!(std::time::Duration); + +#[cfg(all(test, feature = "std"))] // tests are using std implementations +mod tests { + use crate::{allocators::new_malloc_size_ops, MallocSizeOf, MallocSizeOfOps}; + use smallvec::SmallVec; + use std::mem; + impl_smallvec!(3); + + #[test] + fn test_smallvec_stack_allocated_type() { + let mut v: SmallVec<[u8; 3]> = SmallVec::new(); + let mut ops = new_malloc_size_ops(); + assert_eq!(v.size_of(&mut ops), 0); + v.push(1); + v.push(2); + v.push(3); + assert_eq!(v.size_of(&mut ops), 0); + assert!(!v.spilled()); + v.push(4); + assert!(v.spilled(), "SmallVec spills when going beyond the capacity of the inner backing array"); + assert_eq!(v.size_of(&mut ops), 4); // 4 u8s on the heap + } + + #[test] + fn test_smallvec_boxed_stack_allocated_type() { + let mut v: SmallVec<[Box; 3]> = SmallVec::new(); + let mut ops = new_malloc_size_ops(); + assert_eq!(v.size_of(&mut ops), 0); + v.push(Box::new(1u8)); + v.push(Box::new(2u8)); + v.push(Box::new(3u8)); + assert!(v.size_of(&mut ops) >= 3); + assert!(!v.spilled()); + v.push(Box::new(4u8)); + assert!(v.spilled(), "SmallVec spills when going beyond the capacity of the inner backing array"); + let mut ops = new_malloc_size_ops(); + let expected_min_allocs = mem::size_of::>() * 4 + 4; + assert!(v.size_of(&mut ops) >= expected_min_allocs); + } + + #[test] + fn test_smallvec_heap_allocated_type() { + let mut v: SmallVec<[String; 3]> = SmallVec::new(); + let mut ops = new_malloc_size_ops(); + assert_eq!(v.size_of(&mut ops), 0); + v.push("COW".into()); + v.push("PIG".into()); + v.push("DUCK".into()); + assert!(!v.spilled()); + assert!(v.size_of(&mut ops) >= "COW".len() + "PIG".len() + "DUCK".len()); + v.push("ÖWL".into()); + assert!(v.spilled()); + let mut ops = new_malloc_size_ops(); + let expected_min_allocs = mem::size_of::() * 4 + "ÖWL".len() + "COW".len() + "PIG".len() + "DUCK".len(); + assert!(v.size_of(&mut ops) >= expected_min_allocs); + } +}