mirror of
https://github.com/servo/servo.git
synced 2025-06-10 17:43:16 +00:00
Auto merge of #6334 - nnethercote:report-local-contexts, r=pcwalton
Passing a function that measures TLS to WorkQueue is a bit weird, but I can't see how else to measure that data. <!-- Reviewable:start --> [<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/6334) <!-- Reviewable:end -->
This commit is contained in:
commit
f03f584895
5 changed files with 70 additions and 3 deletions
|
@ -29,6 +29,7 @@ use std::sync::mpsc::{channel, Sender};
|
|||
use style::selector_matching::Stylist;
|
||||
use url::Url;
|
||||
use util::geometry::Au;
|
||||
use util::mem::HeapSizeOf;
|
||||
use util::opts;
|
||||
|
||||
struct LocalLayoutContext {
|
||||
|
@ -37,8 +38,21 @@ struct LocalLayoutContext {
|
|||
style_sharing_candidate_cache: RefCell<StyleSharingCandidateCache>,
|
||||
}
|
||||
|
||||
impl HeapSizeOf for LocalLayoutContext {
|
||||
// FIXME(njn): measure other fields eventually.
|
||||
fn heap_size_of_children(&self) -> usize {
|
||||
self.font_context.heap_size_of_children()
|
||||
}
|
||||
}
|
||||
|
||||
thread_local!(static LOCAL_CONTEXT_KEY: RefCell<Option<Rc<LocalLayoutContext>>> = RefCell::new(None));
|
||||
|
||||
pub fn heap_size_of_local_context() -> usize {
|
||||
LOCAL_CONTEXT_KEY.with(|r| {
|
||||
r.borrow().clone().map_or(0, |context| context.heap_size_of_children())
|
||||
})
|
||||
}
|
||||
|
||||
fn create_or_get_local_context(shared_layout_context: &SharedLayoutContext)
|
||||
-> Rc<LocalLayoutContext> {
|
||||
LOCAL_CONTEXT_KEY.with(|r| {
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
use animation;
|
||||
use construct::ConstructionResult;
|
||||
use context::{SharedLayoutContext, SharedLayoutContextWrapper};
|
||||
use context::{SharedLayoutContext, SharedLayoutContextWrapper, heap_size_of_local_context};
|
||||
use css::node_style::StyledNode;
|
||||
use data::{LayoutDataAccess, LayoutDataWrapper};
|
||||
use display_list_builder::ToGfxColor;
|
||||
|
@ -575,10 +575,28 @@ impl LayoutTask {
|
|||
let rw_data = self.lock_rw_data(possibly_locked_rw_data);
|
||||
let stacking_context = rw_data.stacking_context.as_ref();
|
||||
reports.push(Report {
|
||||
path: path!["pages", format!("url({})", self.url), "display-list"],
|
||||
path: path!["pages", format!("url({})", self.url), "layout-task", "display-list"],
|
||||
size: stacking_context.map_or(0, |sc| sc.heap_size_of_children()),
|
||||
});
|
||||
|
||||
// The LayoutTask has a context in TLS...
|
||||
reports.push(Report {
|
||||
path: path!["pages", format!("url({})", self.url), "layout-task", "local-context"],
|
||||
size: heap_size_of_local_context(),
|
||||
});
|
||||
|
||||
// ... as do each of the LayoutWorkers, if present.
|
||||
if let Some(ref traversal) = rw_data.parallel_traversal {
|
||||
let sizes = traversal.heap_size_of_tls(heap_size_of_local_context);
|
||||
for (i, size) in sizes.iter().enumerate() {
|
||||
reports.push(Report {
|
||||
path: path!["pages", format!("url({})", self.url),
|
||||
format!("layout-worker-{}-local-context", i)],
|
||||
size: *size
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
reports_chan.send(reports);
|
||||
}
|
||||
|
||||
|
|
|
@ -224,7 +224,7 @@ impl ReportsTree {
|
|||
}
|
||||
|
||||
let mebi = 1024f64 * 1024f64;
|
||||
let count_str = if self.count > 1 { format!(" {}", self.count) } else { "".to_owned() };
|
||||
let count_str = if self.count > 1 { format!(" [{}]", self.count) } else { "".to_owned() };
|
||||
println!("|{}{:8.2} MiB -- {}{}",
|
||||
indent_str, (self.size as f64) / mebi, self.path_seg, count_str);
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
//! Data structure measurement.
|
||||
|
||||
use libc::{c_void, size_t};
|
||||
use std::cell::RefCell;
|
||||
use std::collections::LinkedList;
|
||||
use std::mem::transmute;
|
||||
use std::sync::Arc;
|
||||
|
@ -92,6 +93,12 @@ impl<T: HeapSizeOf> HeapSizeOf for Arc<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: HeapSizeOf> HeapSizeOf for RefCell<T> {
|
||||
fn heap_size_of_children(&self) -> usize {
|
||||
self.borrow().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) +
|
||||
|
|
|
@ -36,6 +36,8 @@ enum WorkerMsg<QueueData: 'static, WorkData: 'static> {
|
|||
Start(Worker<WorkUnit<QueueData, WorkData>>, *mut AtomicUsize, *const QueueData),
|
||||
/// Tells the worker to stop. It can be restarted again with a `WorkerMsg::Start`.
|
||||
Stop,
|
||||
/// Tells the worker to measure the heap size of its TLS using the supplied function.
|
||||
HeapSizeOfTLS(fn() -> usize),
|
||||
/// Tells the worker thread to terminate.
|
||||
Exit,
|
||||
}
|
||||
|
@ -45,6 +47,7 @@ unsafe impl<QueueData: 'static, WorkData: 'static> Send for WorkerMsg<QueueData,
|
|||
/// Messages to the supervisor.
|
||||
enum SupervisorMsg<QueueData: 'static, WorkData: 'static> {
|
||||
Finished,
|
||||
HeapSizeOfTLS(usize),
|
||||
ReturnDeque(usize, Worker<WorkUnit<QueueData, WorkData>>),
|
||||
}
|
||||
|
||||
|
@ -102,6 +105,10 @@ impl<QueueData: Send, WorkData: Send> WorkerThread<QueueData, WorkData> {
|
|||
WorkerMsg::Start(deque, ref_count, queue_data) => (deque, ref_count, queue_data),
|
||||
WorkerMsg::Stop => panic!("unexpected stop message"),
|
||||
WorkerMsg::Exit => return,
|
||||
WorkerMsg::HeapSizeOfTLS(f) => {
|
||||
self.chan.send(SupervisorMsg::HeapSizeOfTLS(f())).unwrap();
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
let mut back_off_sleep = 0 as u32;
|
||||
|
@ -335,11 +342,32 @@ impl<QueueData: Send, WorkData: Send> WorkQueue<QueueData, WorkData> {
|
|||
for _ in 0..self.workers.len() {
|
||||
match self.port.recv().unwrap() {
|
||||
SupervisorMsg::ReturnDeque(index, deque) => self.workers[index].deque = Some(deque),
|
||||
SupervisorMsg::HeapSizeOfTLS(_) => panic!("unexpected HeapSizeOfTLS message"),
|
||||
SupervisorMsg::Finished => panic!("unexpected finished message!"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Synchronously measure memory usage of any thread-local storage.
|
||||
pub fn heap_size_of_tls(&self, f: fn() -> usize) -> Vec<usize> {
|
||||
// Tell the workers to measure themselves.
|
||||
for worker in self.workers.iter() {
|
||||
worker.chan.send(WorkerMsg::HeapSizeOfTLS(f)).unwrap()
|
||||
}
|
||||
|
||||
// Wait for the workers to finish measuring themselves.
|
||||
let mut sizes = vec![];
|
||||
for _ in 0..self.workers.len() {
|
||||
match self.port.recv().unwrap() {
|
||||
SupervisorMsg::HeapSizeOfTLS(size) => {
|
||||
sizes.push(size);
|
||||
}
|
||||
_ => panic!("unexpected message!"),
|
||||
}
|
||||
}
|
||||
sizes
|
||||
}
|
||||
|
||||
pub fn shutdown(&mut self) {
|
||||
for worker in self.workers.iter() {
|
||||
worker.chan.send(WorkerMsg::Exit).unwrap()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue