Auto merge of #42 - nipunn1313:heapsize, r=jdm

Add HeapSizeOf trait and from_slice method

Also added some tests for the new methods. The rationale
- from_slice is an ergonomic way to convert a Copy-able slice to a SmallVec (instead of using the From<'a slice> which uses an iterator)
- HeapSizeOf is handy for measuring heap allocations. Especially useful for monitoring something like this. Seems to be part of the servo project anyway.
- Added size 36 to smallvec sizes (was useful to us)

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/rust-smallvec/42)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo
2017-03-16 14:58:45 -07:00
committed by GitHub
4 changed files with 80 additions and 1 deletions
+2
View File
@@ -5,7 +5,9 @@ rust:
- stable
script: |
cargo build --verbose &&
cargo build --features=heapsizeof --verbose &&
cargo test --verbose &&
cargo test --features=heapsizeof --verbose &&
([ $TRAVIS_RUST_VERSION != nightly ] || cargo bench --verbose bench)
notifications:
webhooks: http://build.servo.org:54856/travis
+6
View File
@@ -9,6 +9,12 @@ keywords = ["small", "vec", "vector", "stack"]
readme = "README.md"
documentation = "http://doc.servo.org/smallvec/"
[features]
heapsizeof = ["heapsize"]
[lib]
name = "smallvec"
path = "lib.rs"
[dependencies]
heapsize = { version = "0.3", optional = true }
+9
View File
@@ -63,6 +63,15 @@ fn bench_extend(b: &mut Bencher) {
});
}
#[bench]
fn bench_from_slice(b: &mut Bencher) {
let v: Vec<u64> = (0..100).collect();
b.iter(|| {
let vec: SmallVec<[u64; 16]> = SmallVec::from_slice(&v);
vec
});
}
#[bench]
fn bench_extend_from_slice(b: &mut Bencher) {
let v: Vec<u64> = (0..100).collect();
+63 -1
View File
@@ -6,6 +6,9 @@
//! to the heap for larger allocations. This can be a useful optimization for improving cache
//! locality and reducing allocator traffic for workloads that fit within the inline buffer.
#[cfg(feature="heapsizeof")]
extern crate heapsize;
use std::borrow::{Borrow, BorrowMut};
use std::cmp;
use std::fmt;
@@ -15,7 +18,11 @@ use std::mem;
use std::ops;
use std::ptr;
use std::slice;
#[cfg(feature="heapsizeof")]
use std::os::raw::c_void;
#[cfg(feature="heapsizeof")]
use heapsize::{HeapSizeOf, heap_size_of};
use SmallVecData::{Inline, Heap};
/// Common operations implemented by both `Vec` and `SmallVec`.
@@ -478,6 +485,12 @@ impl<A: Array> SmallVec<A> {
}
impl<A: Array> SmallVec<A> where A::Item: Copy {
pub fn from_slice(slice: &[A::Item]) -> Self {
let mut vec = Self::new();
vec.extend_from_slice(slice);
vec
}
pub fn insert_from_slice(&mut self, index: usize, slice: &[A::Item]) {
self.reserve(slice.len());
@@ -500,6 +513,20 @@ impl<A: Array> SmallVec<A> where A::Item: Copy {
}
}
#[cfg(feature="heapsizeof")]
impl<A: Array> HeapSizeOf for SmallVec<A> where A::Item: HeapSizeOf {
fn heap_size_of_children(&self) -> usize {
match self.data {
Inline { .. } => 0,
Heap { ptr, .. } => {
self.iter().fold(
unsafe { heap_size_of(ptr as *const c_void) },
|n, elem| n + elem.heap_size_of_children())
},
}
}
}
impl<A: Array> ops::Deref for SmallVec<A> {
type Target = [A::Item];
#[inline]
@@ -823,7 +850,7 @@ macro_rules! impl_array(
}
);
impl_array!(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20, 24, 32,
impl_array!(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20, 24, 32, 36,
0x40, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000,
0x10000, 0x20000, 0x40000, 0x80000, 0x100000);
@@ -833,6 +860,11 @@ pub mod tests {
use std::borrow::ToOwned;
use std::iter::FromIterator;
#[cfg(feature="heapsizeof")]
use heapsize::HeapSizeOf;
#[cfg(feature="heapsizeof")]
use std::mem::size_of;
// We heap allocate all these strings so that double frees will show up under valgrind.
#[test]
@@ -1248,6 +1280,36 @@ pub mod tests {
assert_eq!(&SmallVec::<[u32; 2]>::from(&[1, 2, 3][..])[..], [1, 2, 3]);
}
#[test]
fn test_from_slice() {
assert_eq!(&SmallVec::<[u32; 2]>::from_slice(&[1][..])[..], [1]);
assert_eq!(&SmallVec::<[u32; 2]>::from_slice(&[1, 2, 3][..])[..], [1, 2, 3]);
}
#[cfg(feature="heapsizeof")]
#[test]
fn test_heap_size_of_children() {
let mut vec = SmallVec::<[u32; 2]>::new();
assert_eq!(vec.heap_size_of_children(), 0);
vec.push(1);
vec.push(2);
assert_eq!(vec.heap_size_of_children(), 0);
vec.push(3);
assert_eq!(vec.heap_size_of_children(), 16);
// Now check with reserved space
let mut vec = SmallVec::<[u32; 2]>::new();
vec.reserve(10); // Rounds up to 16
assert_eq!(vec.heap_size_of_children(), 64);
// Check with nested heap structures
let mut vec = SmallVec::<[Vec<u32>; 2]>::new();
vec.reserve(10);
vec.push(vec![2, 3, 4]);
assert_eq!(vec.heap_size_of_children(),
vec![2, 3, 4].heap_size_of_children() + 16 * size_of::<Vec<u32>>());
}
#[test]
fn test_exact_size_iterator() {
let mut vec = SmallVec::<[u32; 2]>::from(&[1, 2, 3][..]);