Skip to content

Commit d389f3a

Browse files
author
bors-servo
authored
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 -->
2 parents 855f85c + 010df90 commit d389f3a

File tree

4 files changed

+80
-1
lines changed

4 files changed

+80
-1
lines changed

.travis.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ rust:
55
- stable
66
script: |
77
cargo build --verbose &&
8+
cargo build --features=heapsizeof --verbose &&
89
cargo test --verbose &&
10+
cargo test --features=heapsizeof --verbose &&
911
([ $TRAVIS_RUST_VERSION != nightly ] || cargo bench --verbose bench)
1012
notifications:
1113
webhooks: http://build.servo.org:54856/travis

Cargo.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@ keywords = ["small", "vec", "vector", "stack"]
99
readme = "README.md"
1010
documentation = "http://doc.servo.org/smallvec/"
1111

12+
[features]
13+
heapsizeof = ["heapsize"]
14+
1215
[lib]
1316
name = "smallvec"
1417
path = "lib.rs"
18+
19+
[dependencies]
20+
heapsize = { version = "0.3", optional = true }

benches/bench.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,15 @@ fn bench_extend(b: &mut Bencher) {
6363
});
6464
}
6565

66+
#[bench]
67+
fn bench_from_slice(b: &mut Bencher) {
68+
let v: Vec<u64> = (0..100).collect();
69+
b.iter(|| {
70+
let vec: SmallVec<[u64; 16]> = SmallVec::from_slice(&v);
71+
vec
72+
});
73+
}
74+
6675
#[bench]
6776
fn bench_extend_from_slice(b: &mut Bencher) {
6877
let v: Vec<u64> = (0..100).collect();

lib.rs

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
//! to the heap for larger allocations. This can be a useful optimization for improving cache
77
//! locality and reducing allocator traffic for workloads that fit within the inline buffer.
88
9+
#[cfg(feature="heapsizeof")]
10+
extern crate heapsize;
11+
912
use std::borrow::{Borrow, BorrowMut};
1013
use std::cmp;
1114
use std::fmt;
@@ -15,7 +18,11 @@ use std::mem;
1518
use std::ops;
1619
use std::ptr;
1720
use std::slice;
21+
#[cfg(feature="heapsizeof")]
22+
use std::os::raw::c_void;
1823

24+
#[cfg(feature="heapsizeof")]
25+
use heapsize::{HeapSizeOf, heap_size_of};
1926
use SmallVecData::{Inline, Heap};
2027

2128
/// Common operations implemented by both `Vec` and `SmallVec`.
@@ -478,6 +485,12 @@ impl<A: Array> SmallVec<A> {
478485
}
479486

480487
impl<A: Array> SmallVec<A> where A::Item: Copy {
488+
pub fn from_slice(slice: &[A::Item]) -> Self {
489+
let mut vec = Self::new();
490+
vec.extend_from_slice(slice);
491+
vec
492+
}
493+
481494
pub fn insert_from_slice(&mut self, index: usize, slice: &[A::Item]) {
482495
self.reserve(slice.len());
483496

@@ -500,6 +513,20 @@ impl<A: Array> SmallVec<A> where A::Item: Copy {
500513
}
501514
}
502515

516+
#[cfg(feature="heapsizeof")]
517+
impl<A: Array> HeapSizeOf for SmallVec<A> where A::Item: HeapSizeOf {
518+
fn heap_size_of_children(&self) -> usize {
519+
match self.data {
520+
Inline { .. } => 0,
521+
Heap { ptr, .. } => {
522+
self.iter().fold(
523+
unsafe { heap_size_of(ptr as *const c_void) },
524+
|n, elem| n + elem.heap_size_of_children())
525+
},
526+
}
527+
}
528+
}
529+
503530
impl<A: Array> ops::Deref for SmallVec<A> {
504531
type Target = [A::Item];
505532
#[inline]
@@ -823,7 +850,7 @@ macro_rules! impl_array(
823850
}
824851
);
825852

826-
impl_array!(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20, 24, 32,
853+
impl_array!(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20, 24, 32, 36,
827854
0x40, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000,
828855
0x10000, 0x20000, 0x40000, 0x80000, 0x100000);
829856

@@ -833,6 +860,11 @@ pub mod tests {
833860
use std::borrow::ToOwned;
834861
use std::iter::FromIterator;
835862

863+
#[cfg(feature="heapsizeof")]
864+
use heapsize::HeapSizeOf;
865+
#[cfg(feature="heapsizeof")]
866+
use std::mem::size_of;
867+
836868
// We heap allocate all these strings so that double frees will show up under valgrind.
837869

838870
#[test]
@@ -1248,6 +1280,36 @@ pub mod tests {
12481280
assert_eq!(&SmallVec::<[u32; 2]>::from(&[1, 2, 3][..])[..], [1, 2, 3]);
12491281
}
12501282

1283+
#[test]
1284+
fn test_from_slice() {
1285+
assert_eq!(&SmallVec::<[u32; 2]>::from_slice(&[1][..])[..], [1]);
1286+
assert_eq!(&SmallVec::<[u32; 2]>::from_slice(&[1, 2, 3][..])[..], [1, 2, 3]);
1287+
}
1288+
1289+
#[cfg(feature="heapsizeof")]
1290+
#[test]
1291+
fn test_heap_size_of_children() {
1292+
let mut vec = SmallVec::<[u32; 2]>::new();
1293+
assert_eq!(vec.heap_size_of_children(), 0);
1294+
vec.push(1);
1295+
vec.push(2);
1296+
assert_eq!(vec.heap_size_of_children(), 0);
1297+
vec.push(3);
1298+
assert_eq!(vec.heap_size_of_children(), 16);
1299+
1300+
// Now check with reserved space
1301+
let mut vec = SmallVec::<[u32; 2]>::new();
1302+
vec.reserve(10); // Rounds up to 16
1303+
assert_eq!(vec.heap_size_of_children(), 64);
1304+
1305+
// Check with nested heap structures
1306+
let mut vec = SmallVec::<[Vec<u32>; 2]>::new();
1307+
vec.reserve(10);
1308+
vec.push(vec![2, 3, 4]);
1309+
assert_eq!(vec.heap_size_of_children(),
1310+
vec![2, 3, 4].heap_size_of_children() + 16 * size_of::<Vec<u32>>());
1311+
}
1312+
12511313
#[test]
12521314
fn test_exact_size_iterator() {
12531315
let mut vec = SmallVec::<[u32; 2]>::from(&[1, 2, 3][..]);

0 commit comments

Comments
 (0)