// Copyright 2016-2017 The Servo Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms.
//! A reduced fork of Firefox's malloc_size_of crate, for bundling with WebRender.
externcrate app_units; externcrate euclid;
use std::hash::{BuildHasher, Hash}; use std::mem::size_of; use std::ops::Range; use std::os::raw::c_void; use std::path::PathBuf;
/// A C function that takes a pointer to a heap allocation and returns its size. type VoidPtrToSizeFn = unsafeextern"C"fn(ptr: *const c_void) -> usize;
/// Operations used when measuring heap usage of data structures. pubstruct MallocSizeOfOps { /// A function that returns the size of a heap allocation. pub size_of_op: VoidPtrToSizeFn,
/// Like `size_of_op`, but can take an interior pointer. Optional because /// not all allocators support this operation. If it's not provided, some /// memory measurements will actually be computed estimates rather than /// real and accurate measurements. pub enclosing_size_of_op: Option<VoidPtrToSizeFn>,
}
/// Check if an allocation is empty. This relies on knowledge of how Rust /// handles empty allocations, which may change in the future. fn is_empty<T: ?Sized>(ptr: *const T) -> bool { // The correct condition is this: // `ptr as usize <= ::std::mem::align_of::<T>()` // But we can't call align_of() on a ?Sized T. So we approximate it // with the following. 256 is large enough that it should always be // larger than the required alignment, but small enough that it is // always in the first page of memory and therefore not a legitimate // address.
ptr as *const usize as usize <= 256
}
/// Call `size_of_op` on `ptr`, first checking that the allocation isn't /// empty, because some types (such as `Vec`) utilize empty allocations. pubunsafefn malloc_size_of<T: ?Sized>(&self, ptr: *const T) -> usize { if MallocSizeOfOps::is_empty(ptr) { 0
} else {
(self.size_of_op)(ptr as *const c_void)
}
}
/// Is an `enclosing_size_of_op` available? pubfn has_malloc_enclosing_size_of(&self) -> bool { self.enclosing_size_of_op.is_some()
}
/// Call `enclosing_size_of_op`, which must be available, on `ptr`, which /// must not be empty. pubunsafefn malloc_enclosing_size_of<T>(&self, ptr: *const T) -> usize {
assert!(!MallocSizeOfOps::is_empty(ptr));
(self.enclosing_size_of_op.unwrap())(ptr as *const c_void)
}
}
/// Trait for measuring the "deep" heap usage of a data structure. This is the /// most commonly-used of the traits. pubtrait MallocSizeOf { /// Measure the heap usage of all descendant heap-allocated structures, but /// not the space taken up by the value itself. fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize;
}
/// Trait for measuring the "shallow" heap usage of a container. pubtrait MallocShallowSizeOf { /// Measure the heap usage of immediate heap-allocated descendant /// structures, but not the space taken up by the value itself. Anything /// beyond the immediate descendants must be measured separately, using /// iteration. fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize;
}
impl<T: MallocSizeOf> MallocSizeOf for Vec<T> { fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { letmut n = self.shallow_size_of(ops); for elem inself.iter() {
n += elem.size_of(ops);
}
n
}
}
macro_rules! malloc_size_of_hash_set {
($ty:ty) => { impl<T, S> MallocShallowSizeOf for $ty where
T: Eq + Hash,
S: BuildHasher,
{ fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize { if ops.has_malloc_enclosing_size_of() { // The first value from the iterator gives us an interior pointer. // `ops.malloc_enclosing_size_of()` then gives us the storage size. // This assumes that the `HashSet`'s contents (values and hashes) // are all stored in a single contiguous heap allocation. self.iter()
.next()
.map_or(0, |t| unsafe { ops.malloc_enclosing_size_of(t) })
} else { // An estimate. self.capacity() * (size_of::<T>() + size_of::<usize>())
}
}
}
impl<T, S> MallocSizeOf for $ty where
T: Eq + Hash + MallocSizeOf,
S: BuildHasher,
{ fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { letmut n = self.shallow_size_of(ops); for t inself.iter() {
n += t.size_of(ops);
}
n
}
}
};
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.