Auto merge of #6640 - mrobinson:memory-profiling-for-compositor, r=nnethercote

Add memory profiling for the compositor task

Currently only the BufferMap is recorded, but a later change will also
measure the memory usage of the compositor tree.

<!-- Reviewable:start -->
[<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/6640)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2015-07-22 11:44:30 -06:00
commit 3f69eadc0d
10 changed files with 54 additions and 12 deletions

View file

@ -243,6 +243,10 @@ fn initialize_png(width: usize, height: usize) -> (Vec<gl::GLuint>, Vec<gl::GLui
(framebuffer_ids, texture_ids) (framebuffer_ids, texture_ids)
} }
pub fn reporter_name() -> String {
"compositor-reporter".to_string()
}
impl<Window: WindowMethods> IOCompositor<Window> { impl<Window: WindowMethods> IOCompositor<Window> {
fn new(window: Rc<Window>, fn new(window: Rc<Window>,
sender: Box<CompositorProxy+Send>, sender: Box<CompositorProxy+Send>,
@ -251,10 +255,11 @@ impl<Window: WindowMethods> IOCompositor<Window> {
time_profiler_chan: time::ProfilerChan, time_profiler_chan: time::ProfilerChan,
mem_profiler_chan: mem::ProfilerChan) mem_profiler_chan: mem::ProfilerChan)
-> IOCompositor<Window> { -> IOCompositor<Window> {
// Create an initial layer tree.
// // Register this thread as a memory reporter, via its own channel.
// TODO: There should be no initial layer tree until the painter creates one from the let reporter = box CompositorMemoryReporter(sender.clone_compositor_proxy());
// display list. This is only here because we don't have that logic in the painter yet. mem_profiler_chan.send(mem::ProfilerMsg::RegisterReporter(reporter_name(), reporter));
let window_size = window.framebuffer_size(); let window_size = window.framebuffer_size();
let hidpi_factor = window.hidpi_factor(); let hidpi_factor = window.hidpi_factor();
let composite_target = match opts::get().output_file { let composite_target = match opts::get().output_file {
@ -333,6 +338,9 @@ impl<Window: WindowMethods> IOCompositor<Window> {
let ConstellationChan(ref con_chan) = self.constellation_chan; let ConstellationChan(ref con_chan) = self.constellation_chan;
con_chan.send(ConstellationMsg::Exit).unwrap(); con_chan.send(ConstellationMsg::Exit).unwrap();
chan.send(()).unwrap(); chan.send(()).unwrap();
self.mem_profiler_chan.send(mem::ProfilerMsg::UnregisterReporter(reporter_name()));
self.shutdown_state = ShutdownState::ShuttingDown; self.shutdown_state = ShutdownState::ShuttingDown;
} }
@ -482,6 +490,18 @@ impl<Window: WindowMethods> IOCompositor<Window> {
self.window.head_parsed(); self.window.head_parsed();
} }
(Msg::CollectMemoryReports(reports_chan), ShutdownState::NotShuttingDown) => {
let mut reports = vec![];
let name = "compositor-task";
reports.push(mem::Report {
path: path![name, "buffer-map"], size: self.buffer_map.mem(),
});
reports.push(mem::Report {
path: path![name, "layer-tree"], size: self.scene.get_memory_usage(),
});
reports_chan.send(reports);
}
// When we are shutting_down, we need to avoid performing operations // When we are shutting_down, we need to avoid performing operations
// such as Paint that may crash because we have begun tearing down // such as Paint that may crash because we have begun tearing down
// the rest of our resources. // the rest of our resources.
@ -1702,3 +1722,20 @@ pub enum CompositingReason {
/// The window has been zoomed. /// The window has been zoomed.
Zoom, Zoom,
} }
struct CompositorMemoryReporter(Box<CompositorProxy+'static+Send>);
impl CompositorMemoryReporter {
pub fn send(&self, message: Msg) {
let CompositorMemoryReporter(ref proxy) = *self;
proxy.send(message);
}
}
impl mem::Reporter for CompositorMemoryReporter {
fn collect_reports(&self, reports_chan: mem::ReportsChan) -> bool {
// FIXME(mrobinson): The port should probably return the success of the message here.
self.send(Msg::CollectMemoryReports(reports_chan));
true
}
}

View file

@ -35,7 +35,7 @@ use util::cursor::Cursor;
/// process, and so forth. /// process, and so forth.
pub trait CompositorProxy : 'static + Send { pub trait CompositorProxy : 'static + Send {
/// Sends a message to the compositor. /// Sends a message to the compositor.
fn send(&mut self, msg: Msg); fn send(&self, msg: Msg);
/// Clones the compositor proxy. /// Clones the compositor proxy.
fn clone_compositor_proxy(&self) -> Box<CompositorProxy+'static+Send>; fn clone_compositor_proxy(&self) -> Box<CompositorProxy+'static+Send>;
} }
@ -62,7 +62,7 @@ impl CompositorReceiver for Receiver<Msg> {
} }
} }
pub fn run_script_listener_thread(mut compositor_proxy: Box<CompositorProxy + 'static + Send>, pub fn run_script_listener_thread(compositor_proxy: Box<CompositorProxy + 'static + Send>,
receiver: IpcReceiver<ScriptToCompositorMsg>) { receiver: IpcReceiver<ScriptToCompositorMsg>) {
while let Ok(msg) = receiver.recv() { while let Ok(msg) = receiver.recv() {
match msg { match msg {
@ -197,6 +197,8 @@ pub enum Msg {
/// Signal that the paint task ignored the paint requests that carried /// Signal that the paint task ignored the paint requests that carried
/// these layer buffers, so that they can be re-added to the surface cache. /// these layer buffers, so that they can be re-added to the surface cache.
ReturnUnusedLayerBuffers(Vec<Box<LayerBuffer>>), ReturnUnusedLayerBuffers(Vec<Box<LayerBuffer>>),
/// Collect memory reports and send them back to the given mem::ReportsChan.
CollectMemoryReports(mem::ReportsChan),
} }
impl Debug for Msg { impl Debug for Msg {
@ -226,6 +228,7 @@ impl Debug for Msg {
Msg::NewFavicon(..) => write!(f, "NewFavicon"), Msg::NewFavicon(..) => write!(f, "NewFavicon"),
Msg::HeadParsed => write!(f, "HeadParsed"), Msg::HeadParsed => write!(f, "HeadParsed"),
Msg::ReturnUnusedLayerBuffers(..) => write!(f, "ReturnUnusedLayerBuffers"), Msg::ReturnUnusedLayerBuffers(..) => write!(f, "ReturnUnusedLayerBuffers"),
Msg::CollectMemoryReports(..) => write!(f, "CollectMemoryReports"),
} }
} }
} }

View file

@ -112,6 +112,7 @@ impl CompositorEventListener for NullCompositor {
Msg::NewFavicon(..) => {} Msg::NewFavicon(..) => {}
Msg::HeadParsed => {} Msg::HeadParsed => {}
Msg::ReturnUnusedLayerBuffers(..) => {} Msg::ReturnUnusedLayerBuffers(..) => {}
Msg::CollectMemoryReports(..) => {}
} }
true true
} }

View file

@ -22,6 +22,7 @@ extern crate script_traits;
extern crate msg; extern crate msg;
extern crate net; extern crate net;
extern crate num; extern crate num;
#[macro_use]
extern crate profile_traits; extern crate profile_traits;
extern crate net_traits; extern crate net_traits;
extern crate gfx_traits; extern crate gfx_traits;

View file

@ -679,7 +679,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "layers" name = "layers"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/servo/rust-layers#abc4f3803dde8d818343984a28d2e3d1fdad11a3" source = "git+https://github.com/servo/rust-layers#1c9628618803c161753fd9f00f5ef781660ce11e"
dependencies = [ dependencies = [
"azure 0.1.0 (git+https://github.com/servo/rust-azure)", "azure 0.1.0 (git+https://github.com/servo/rust-azure)",
"cgl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "cgl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",

2
ports/cef/Cargo.lock generated
View file

@ -671,7 +671,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "layers" name = "layers"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/servo/rust-layers#abc4f3803dde8d818343984a28d2e3d1fdad11a3" source = "git+https://github.com/servo/rust-layers#1c9628618803c161753fd9f00f5ef781660ce11e"
dependencies = [ dependencies = [
"azure 0.1.0 (git+https://github.com/servo/rust-azure)", "azure 0.1.0 (git+https://github.com/servo/rust-azure)",
"cgl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "cgl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",

View file

@ -474,7 +474,7 @@ struct CefCompositorProxy {
} }
impl CompositorProxy for CefCompositorProxy { impl CompositorProxy for CefCompositorProxy {
fn send(&mut self, msg: compositor_task::Msg) { fn send(&self, msg: compositor_task::Msg) {
self.sender.send(msg).unwrap(); self.sender.send(msg).unwrap();
app_wakeup(); app_wakeup();
} }

View file

@ -805,7 +805,7 @@ struct GlutinCompositorProxy {
unsafe impl Send for GlutinCompositorProxy {} unsafe impl Send for GlutinCompositorProxy {}
impl CompositorProxy for GlutinCompositorProxy { impl CompositorProxy for GlutinCompositorProxy {
fn send(&mut self, msg: compositor_task::Msg) { fn send(&self, msg: compositor_task::Msg) {
// Send a message and kick the OS event loop awake. // Send a message and kick the OS event loop awake.
self.sender.send(msg).unwrap(); self.sender.send(msg).unwrap();
if let Some(ref window_proxy) = self.window_proxy { if let Some(ref window_proxy) = self.window_proxy {

2
ports/gonk/Cargo.lock generated
View file

@ -605,7 +605,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "layers" name = "layers"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/servo/rust-layers#abc4f3803dde8d818343984a28d2e3d1fdad11a3" source = "git+https://github.com/servo/rust-layers#1c9628618803c161753fd9f00f5ef781660ce11e"
dependencies = [ dependencies = [
"azure 0.1.0 (git+https://github.com/servo/rust-azure)", "azure 0.1.0 (git+https://github.com/servo/rust-azure)",
"cgl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "cgl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",

View file

@ -857,7 +857,7 @@ struct GonkCompositorProxy {
} }
impl CompositorProxy for GonkCompositorProxy { impl CompositorProxy for GonkCompositorProxy {
fn send(&mut self, msg: compositor_task::Msg) { fn send(&self, msg: compositor_task::Msg) {
// Send a message and kick the OS event loop awake. // Send a message and kick the OS event loop awake.
self.sender.send(msg).ok().unwrap(); self.sender.send(msg).ok().unwrap();
self.event_sender.send(WindowEvent::Idle).ok().unwrap(); self.event_sender.send(WindowEvent::Idle).ok().unwrap();