mirror of
https://github.com/servo/servo.git
synced 2025-08-04 13:10:20 +01:00
Rename lots of profiling-related things.
------------------------------------------------------------------------ BEFORE AFTER ------------------------------------------------------------------------ util::memory util::mem - heap_size_of - heap_size_of (unchanged) - SizeOf - HeapSizeOf - size_of_excluding_self - heap_size_of_children prof::mem prof::mem - MemoryProfilerChan - ProfilerChan - MemoryReport - Report - MemoryReportsChan - ReportsChan - MemoryReporter - Reporter - MemoryProfilerMsg - ProfilerMsg - {R,UnR}egisterMemoryReporter - {R,UnR}egisterReporter - MemoryProfiler - Prof - ReportsForest - ReportsForest (unchanged) - ReportsTree - ReportsTree (unchanged) - SystemMemoryReporter - SystemReporter prof::time prof::time - TimeProfilerChan - ProfilerChan - TimerMetadata - TimerMetadata (unchanged) - Formatable - Formattable [spelling!] - TimeProfilerMsg - ProfilerMsg - TimeProfilerCategory - ProfilerCategory - TimeProfilerBuckets - ProfilerBuckets - TimeProfiler - Profiler - TimerMetadataFrameType - TimerMetadataFrameType (unchanged) - TimerMetadataReflowType - TimerMetadataReflowType (unchanged) - ProfilerMetadata - ProfilerMetadata (unchanged) In a few places both prof::time and prof::mem are used, and so module-qualification is needed to avoid overlap, e.g. time::Profiler and mem::Profiler. Likewise with std::mem and prof::mem. This is not a big deal.
This commit is contained in:
parent
7f587f6cb5
commit
ce36e574f4
19 changed files with 322 additions and 331 deletions
161
components/util/mem.rs
Normal file
161
components/util/mem.rs
Normal file
|
@ -0,0 +1,161 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
//! Data structure measurement.
|
||||
|
||||
use libc::{c_void, size_t};
|
||||
use std::collections::LinkedList;
|
||||
use std::mem::transmute;
|
||||
use std::sync::Arc;
|
||||
|
||||
extern {
|
||||
// Get the size of a heap block.
|
||||
//
|
||||
// Ideally Rust would expose a function like this in std::rt::heap, which would avoid the
|
||||
// jemalloc dependence.
|
||||
//
|
||||
// The C prototype is `je_malloc_usable_size(JEMALLOC_USABLE_SIZE_CONST void *ptr)`. On some
|
||||
// platforms `JEMALLOC_USABLE_SIZE_CONST` is `const` and on some it is empty. But in practice
|
||||
// this function doesn't modify the contents of the block that `ptr` points to, so we use
|
||||
// `*const c_void` here.
|
||||
fn je_malloc_usable_size(ptr: *const c_void) -> size_t;
|
||||
}
|
||||
|
||||
// A wrapper for je_malloc_usable_size that handles `EMPTY` and returns `usize`.
|
||||
pub fn heap_size_of(ptr: *const c_void) -> usize {
|
||||
if ptr == ::std::rt::heap::EMPTY as *const c_void {
|
||||
0
|
||||
} else {
|
||||
unsafe { je_malloc_usable_size(ptr) as usize }
|
||||
}
|
||||
}
|
||||
|
||||
// The simplest trait for measuring the size of heap data structures. More complex traits that
|
||||
// return multiple measurements -- e.g. measure text separately from images -- are also possible,
|
||||
// and should be used when appropriate.
|
||||
//
|
||||
// FIXME(njn): it would be nice to be able to derive this trait automatically, given that
|
||||
// implementations are mostly repetitive and mechanical.
|
||||
//
|
||||
pub trait HeapSizeOf {
|
||||
/// Measure the size of any heap-allocated structures that hang off this value, but not the
|
||||
/// space taken up by the value itself (i.e. what size_of::<T> measures, more or less); that
|
||||
/// space is handled by the implementation of HeapSizeOf for Box<T> below.
|
||||
fn heap_size_of_children(&self) -> usize;
|
||||
}
|
||||
|
||||
// There are two possible ways to measure the size of `self` when it's on the heap: compute it
|
||||
// (with `::std::rt::heap::usable_size(::std::mem::size_of::<T>(), 0)`) or measure it directly
|
||||
// using the heap allocator (with `heap_size_of`). We do the latter, for the following reasons.
|
||||
//
|
||||
// * The heap allocator is the true authority for the sizes of heap blocks; its measurement is
|
||||
// guaranteed to be correct. In comparison, size computations are error-prone. (For example, the
|
||||
// `rt::heap::usable_size` function used in some of Rust's non-default allocator implementations
|
||||
// underestimate the true usable size of heap blocks, which is safe in general but would cause
|
||||
// under-measurement here.)
|
||||
//
|
||||
// * If we measure something that isn't a heap block, we'll get a crash. This keeps us honest,
|
||||
// which is important because unsafe code is involved and this can be gotten wrong.
|
||||
//
|
||||
// However, in the best case, the two approaches should give the same results.
|
||||
//
|
||||
impl<T: HeapSizeOf> HeapSizeOf for Box<T> {
|
||||
fn heap_size_of_children(&self) -> usize {
|
||||
// Measure size of `self`.
|
||||
heap_size_of(&**self as *const T as *const c_void) + (**self).heap_size_of_children()
|
||||
}
|
||||
}
|
||||
|
||||
impl HeapSizeOf for String {
|
||||
fn heap_size_of_children(&self) -> usize {
|
||||
heap_size_of(self.as_ptr() as *const c_void)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: HeapSizeOf> HeapSizeOf for Option<T> {
|
||||
fn heap_size_of_children(&self) -> usize {
|
||||
match *self {
|
||||
None => 0,
|
||||
Some(ref x) => x.heap_size_of_children()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: HeapSizeOf> HeapSizeOf for Arc<T> {
|
||||
fn heap_size_of_children(&self) -> usize {
|
||||
(**self).heap_size_of_children()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: HeapSizeOf> HeapSizeOf for Vec<T> {
|
||||
fn heap_size_of_children(&self) -> usize {
|
||||
heap_size_of(self.as_ptr() as *const c_void) +
|
||||
self.iter().fold(0, |n, elem| n + elem.heap_size_of_children())
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(njn): We can't implement HeapSizeOf accurately for LinkedList because it requires access
|
||||
// to the private Node type. Eventually we'll want to add HeapSizeOf (or equivalent) to Rust
|
||||
// itself. In the meantime, we use the dirty hack of transmuting LinkedList into an identical type
|
||||
// (LinkedList2) and measuring that.
|
||||
impl<T: HeapSizeOf> HeapSizeOf for LinkedList<T> {
|
||||
fn heap_size_of_children(&self) -> usize {
|
||||
let list2: &LinkedList2<T> = unsafe { transmute(self) };
|
||||
list2.heap_size_of_children()
|
||||
}
|
||||
}
|
||||
|
||||
struct LinkedList2<T> {
|
||||
_length: usize,
|
||||
list_head: Link<T>,
|
||||
_list_tail: Rawlink<Node<T>>,
|
||||
}
|
||||
|
||||
type Link<T> = Option<Box<Node<T>>>;
|
||||
|
||||
struct Rawlink<T> {
|
||||
_p: *mut T,
|
||||
}
|
||||
|
||||
struct Node<T> {
|
||||
next: Link<T>,
|
||||
_prev: Rawlink<Node<T>>,
|
||||
value: T,
|
||||
}
|
||||
|
||||
impl<T: HeapSizeOf> HeapSizeOf for Node<T> {
|
||||
// Unlike most heap_size_of_children() functions, this one does *not* measure descendents.
|
||||
// Instead, LinkedList2<T>::heap_size_of_children() handles that, so that it can use iteration
|
||||
// instead of recursion, which avoids potentially blowing the stack.
|
||||
fn heap_size_of_children(&self) -> usize {
|
||||
self.value.heap_size_of_children()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: HeapSizeOf> HeapSizeOf for LinkedList2<T> {
|
||||
fn heap_size_of_children(&self) -> usize {
|
||||
let mut size = 0;
|
||||
let mut curr: &Link<T> = &self.list_head;
|
||||
while curr.is_some() {
|
||||
size += (*curr).heap_size_of_children();
|
||||
curr = &curr.as_ref().unwrap().next;
|
||||
}
|
||||
size
|
||||
}
|
||||
}
|
||||
|
||||
// This is a basic sanity check. If the representation of LinkedList changes such that it becomes a
|
||||
// different size to LinkedList2, this will fail at compile-time.
|
||||
#[allow(dead_code)]
|
||||
unsafe fn linked_list2_check() {
|
||||
transmute::<LinkedList<i32>, LinkedList2<i32>>(panic!());
|
||||
}
|
||||
|
||||
// Currently, types that implement the Drop type are larger than those that don't. Because
|
||||
// LinkedList implements Drop, LinkedList2 must also so that linked_list2_check() doesn't fail.
|
||||
#[unsafe_destructor]
|
||||
impl<T> Drop for LinkedList2<T> {
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue