From 900337e3d1c8ee3d50c42fc37bdc1196b919046d Mon Sep 17 00:00:00 2001 From: Martin Robinson Date: Wed, 15 Jul 2015 12:16:46 -0700 Subject: [PATCH 1/2] 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. --- components/compositing/compositor.rs | 42 ++++++++++++++++++++--- components/compositing/compositor_task.rs | 7 ++-- components/compositing/headless.rs | 1 + components/compositing/lib.rs | 1 + ports/cef/window.rs | 2 +- ports/glutin/window.rs | 2 +- ports/gonk/src/window.rs | 2 +- 7 files changed, 48 insertions(+), 9 deletions(-) diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index 0f397a7d4f7..75bd9a3f6ca 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -243,6 +243,10 @@ fn initialize_png(width: usize, height: usize) -> (Vec, Vec String { + "compositor-reporter".to_string() +} + impl IOCompositor { fn new(window: Rc, sender: Box, @@ -251,10 +255,11 @@ impl IOCompositor { time_profiler_chan: time::ProfilerChan, mem_profiler_chan: mem::ProfilerChan) -> IOCompositor { - // Create an initial layer tree. - // - // TODO: There should be no initial layer tree until the painter creates one from the - // display list. This is only here because we don't have that logic in the painter yet. + + // Register this thread as a memory reporter, via its own channel. + let reporter = box CompositorMemoryReporter(sender.clone_compositor_proxy()); + mem_profiler_chan.send(mem::ProfilerMsg::RegisterReporter(reporter_name(), reporter)); + let window_size = window.framebuffer_size(); let hidpi_factor = window.hidpi_factor(); let composite_target = match opts::get().output_file { @@ -333,6 +338,9 @@ impl IOCompositor { let ConstellationChan(ref con_chan) = self.constellation_chan; con_chan.send(ConstellationMsg::Exit).unwrap(); chan.send(()).unwrap(); + + self.mem_profiler_chan.send(mem::ProfilerMsg::UnregisterReporter(reporter_name())); + self.shutdown_state = ShutdownState::ShuttingDown; } @@ -482,6 +490,15 @@ impl IOCompositor { self.window.head_parsed(); } + (Msg::CollectMemoryReports(reports_chan), ShutdownState::NotShuttingDown) => { + let mut reports = vec![]; + reports.push(mem::Report { + path: path!["compositor-task", "buffer-map"], + size: self.buffer_map.mem(), + }); + reports_chan.send(reports); + } + // When we are shutting_down, we need to avoid performing operations // such as Paint that may crash because we have begun tearing down // the rest of our resources. @@ -1696,3 +1713,20 @@ pub enum CompositingReason { /// The window has been zoomed. Zoom, } + +struct CompositorMemoryReporter(Box); + +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 + } +} diff --git a/components/compositing/compositor_task.rs b/components/compositing/compositor_task.rs index d8ada04bbdf..07777992541 100644 --- a/components/compositing/compositor_task.rs +++ b/components/compositing/compositor_task.rs @@ -35,7 +35,7 @@ use util::cursor::Cursor; /// process, and so forth. pub trait CompositorProxy : 'static + Send { /// Sends a message to the compositor. - fn send(&mut self, msg: Msg); + fn send(&self, msg: Msg); /// Clones the compositor proxy. fn clone_compositor_proxy(&self) -> Box; } @@ -62,7 +62,7 @@ impl CompositorReceiver for Receiver { } } -pub fn run_script_listener_thread(mut compositor_proxy: Box, +pub fn run_script_listener_thread(compositor_proxy: Box, receiver: IpcReceiver) { while let Ok(msg) = receiver.recv() { match msg { @@ -197,6 +197,8 @@ pub enum Msg { /// 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. ReturnUnusedLayerBuffers(Vec>), + /// Collect memory reports and send them back to the given mem::ReportsChan. + CollectMemoryReports(mem::ReportsChan), } impl Debug for Msg { @@ -226,6 +228,7 @@ impl Debug for Msg { Msg::NewFavicon(..) => write!(f, "NewFavicon"), Msg::HeadParsed => write!(f, "HeadParsed"), Msg::ReturnUnusedLayerBuffers(..) => write!(f, "ReturnUnusedLayerBuffers"), + Msg::CollectMemoryReports(..) => write!(f, "CollectMemoryReports"), } } } diff --git a/components/compositing/headless.rs b/components/compositing/headless.rs index c4a4368d49b..6d2da22da43 100644 --- a/components/compositing/headless.rs +++ b/components/compositing/headless.rs @@ -112,6 +112,7 @@ impl CompositorEventListener for NullCompositor { Msg::NewFavicon(..) => {} Msg::HeadParsed => {} Msg::ReturnUnusedLayerBuffers(..) => {} + Msg::CollectMemoryReports(..) => {} } true } diff --git a/components/compositing/lib.rs b/components/compositing/lib.rs index a9cb24eeb8d..ef27074c96d 100644 --- a/components/compositing/lib.rs +++ b/components/compositing/lib.rs @@ -22,6 +22,7 @@ extern crate script_traits; extern crate msg; extern crate net; extern crate num; +#[macro_use] extern crate profile_traits; extern crate net_traits; extern crate gfx_traits; diff --git a/ports/cef/window.rs b/ports/cef/window.rs index d12770e29b9..29177022469 100644 --- a/ports/cef/window.rs +++ b/ports/cef/window.rs @@ -474,7 +474,7 @@ struct 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(); app_wakeup(); } diff --git a/ports/glutin/window.rs b/ports/glutin/window.rs index 6397abb1d1f..20af32e8781 100644 --- a/ports/glutin/window.rs +++ b/ports/glutin/window.rs @@ -805,7 +805,7 @@ struct GlutinCompositorProxy { unsafe impl Send 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. self.sender.send(msg).unwrap(); if let Some(ref window_proxy) = self.window_proxy { diff --git a/ports/gonk/src/window.rs b/ports/gonk/src/window.rs index 1e1b0965163..0d94ddaa7a4 100644 --- a/ports/gonk/src/window.rs +++ b/ports/gonk/src/window.rs @@ -857,7 +857,7 @@ struct 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. self.sender.send(msg).ok().unwrap(); self.event_sender.send(WindowEvent::Idle).ok().unwrap(); From 5d93f9d5fa92c9d352df8f94c8302c996b0a71f4 Mon Sep 17 00:00:00 2001 From: Martin Robinson Date: Wed, 15 Jul 2015 18:24:32 -0700 Subject: [PATCH 2/2] Report layer tree memory usage rust-layers can now deliver the memory usage of a layer tree, so include that in the reports. --- components/compositing/compositor.rs | 7 +++++-- components/servo/Cargo.lock | 2 +- ports/cef/Cargo.lock | 2 +- ports/gonk/Cargo.lock | 2 +- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index 75bd9a3f6ca..bf19468781f 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -492,9 +492,12 @@ impl IOCompositor { (Msg::CollectMemoryReports(reports_chan), ShutdownState::NotShuttingDown) => { let mut reports = vec![]; + let name = "compositor-task"; reports.push(mem::Report { - path: path!["compositor-task", "buffer-map"], - size: self.buffer_map.mem(), + 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); } diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock index 94b8ada8efd..d0b917ad040 100644 --- a/components/servo/Cargo.lock +++ b/components/servo/Cargo.lock @@ -678,7 +678,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "layers" version = "0.1.0" -source = "git+https://github.com/servo/rust-layers#abc4f3803dde8d818343984a28d2e3d1fdad11a3" +source = "git+https://github.com/servo/rust-layers#1c9628618803c161753fd9f00f5ef781660ce11e" dependencies = [ "azure 0.1.0 (git+https://github.com/servo/rust-azure)", "cgl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/ports/cef/Cargo.lock b/ports/cef/Cargo.lock index b27e8cc7490..984b5d50660 100644 --- a/ports/cef/Cargo.lock +++ b/ports/cef/Cargo.lock @@ -670,7 +670,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "layers" version = "0.1.0" -source = "git+https://github.com/servo/rust-layers#abc4f3803dde8d818343984a28d2e3d1fdad11a3" +source = "git+https://github.com/servo/rust-layers#1c9628618803c161753fd9f00f5ef781660ce11e" dependencies = [ "azure 0.1.0 (git+https://github.com/servo/rust-azure)", "cgl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/ports/gonk/Cargo.lock b/ports/gonk/Cargo.lock index 7cac84c7df3..90b28852d44 100644 --- a/ports/gonk/Cargo.lock +++ b/ports/gonk/Cargo.lock @@ -604,7 +604,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "layers" version = "0.1.0" -source = "git+https://github.com/servo/rust-layers#abc4f3803dde8d818343984a28d2e3d1fdad11a3" +source = "git+https://github.com/servo/rust-layers#1c9628618803c161753fd9f00f5ef781660ce11e" dependencies = [ "azure 0.1.0 (git+https://github.com/servo/rust-azure)", "cgl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",