diff options
author | Patrick Walton <pcwalton@mimiga.net> | 2015-07-14 18:28:57 -0700 |
---|---|---|
committer | Patrick Walton <pcwalton@mimiga.net> | 2015-07-24 17:02:17 -0700 |
commit | f10c0761802ed0f77e21d410124ef54239beb48a (patch) | |
tree | c17f2bb6b6ee77c246802a88a5b7acaa40e1f57e | |
parent | ed1b6a3513e7546b580693f554a081bc0c7c478a (diff) | |
download | servo-f10c0761802ed0f77e21d410124ef54239beb48a.tar.gz servo-f10c0761802ed0f77e21d410124ef54239beb48a.zip |
profile: Make the time and memory profilers run over IPC.
Uses the `Router` abstraction inside `ipc-channel` to avoid spawning new
threads.
-rw-r--r-- | components/compositing/compositor.rs | 28 | ||||
-rw-r--r-- | components/gfx/Cargo.toml | 3 | ||||
-rw-r--r-- | components/gfx/lib.rs | 1 | ||||
-rw-r--r-- | components/gfx/paint_task.rs | 32 | ||||
-rw-r--r-- | components/layout/layout_task.rs | 22 | ||||
-rw-r--r-- | components/profile/Cargo.toml | 3 | ||||
-rw-r--r-- | components/profile/lib.rs | 1 | ||||
-rw-r--r-- | components/profile/mem.rs | 111 | ||||
-rw-r--r-- | components/profile/time.rs | 8 | ||||
-rw-r--r-- | components/profile_traits/Cargo.toml | 5 | ||||
-rw-r--r-- | components/profile_traits/lib.rs | 7 | ||||
-rw-r--r-- | components/profile_traits/mem.rs | 46 | ||||
-rw-r--r-- | components/profile_traits/time.rs | 12 | ||||
-rw-r--r-- | components/script/dom/dedicatedworkerglobalscope.rs | 34 | ||||
-rw-r--r-- | components/script/layout_interface.rs | 10 | ||||
-rw-r--r-- | components/script/script_task.rs | 26 | ||||
-rw-r--r-- | components/servo/Cargo.lock | 9 | ||||
-rw-r--r-- | ports/cef/Cargo.lock | 9 | ||||
-rw-r--r-- | ports/gonk/Cargo.lock | 9 |
19 files changed, 210 insertions, 166 deletions
diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index 79a0f08b150..834d1ff8bd1 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -22,6 +22,8 @@ use gfx::paint_task::Msg as PaintMsg; use gfx::paint_task::PaintRequest; use gleam::gl::types::{GLint, GLsizei}; use gleam::gl; +use ipc_channel::ipc; +use ipc_channel::router::ROUTER; use layers::geometry::{DevicePixel, LayerPixel}; use layers::layers::{BufferRequest, Layer, LayerBuffer, LayerBufferSet}; use layers::platform::surface::NativeDisplay; @@ -37,7 +39,7 @@ use msg::constellation_msg::{ConstellationChan, NavigationDirection}; use msg::constellation_msg::{Key, KeyModifiers, KeyState, LoadData}; use msg::constellation_msg::{PipelineId, WindowSizeData}; use png; -use profile_traits::mem; +use profile_traits::mem::{self, Reporter, ReporterRequest}; use profile_traits::time::{self, ProfilerCategory, profile}; use script_traits::{ConstellationControlMsg, LayoutControlMsg, ScriptControlChan}; use std::collections::HashMap; @@ -257,7 +259,13 @@ impl<Window: WindowMethods> IOCompositor<Window> { -> IOCompositor<Window> { // Register this thread as a memory reporter, via its own channel. - let reporter = box CompositorMemoryReporter(sender.clone_compositor_proxy()); + let (reporter_sender, reporter_receiver) = ipc::channel().unwrap(); + let compositor_proxy_for_memory_reporter = sender.clone_compositor_proxy(); + ROUTER.add_route(reporter_receiver.to_opaque(), box move |reporter_request| { + let reporter_request: ReporterRequest = reporter_request.to().unwrap(); + compositor_proxy_for_memory_reporter.send(Msg::CollectMemoryReports(reporter_request.reports_channel)); + }); + let reporter = Reporter(reporter_sender); mem_profiler_chan.send(mem::ProfilerMsg::RegisterReporter(reporter_name(), reporter)); let window_size = window.framebuffer_size(); @@ -1723,19 +1731,3 @@ pub enum CompositingReason { 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 - } -} diff --git a/components/gfx/Cargo.toml b/components/gfx/Cargo.toml index ed91b98dc87..1e7894b86b0 100644 --- a/components/gfx/Cargo.toml +++ b/components/gfx/Cargo.toml @@ -44,6 +44,9 @@ git = "https://github.com/servo/skia" [dependencies.script_traits] path = "../script_traits" +[dependencies.ipc-channel] +git = "https://github.com/pcwalton/ipc-channel" + [dependencies] log = "0.3" fnv = "1.0" diff --git a/components/gfx/lib.rs b/components/gfx/lib.rs index c711ae1fc9a..abeaea80b0e 100644 --- a/components/gfx/lib.rs +++ b/components/gfx/lib.rs @@ -24,6 +24,7 @@ extern crate azure; #[macro_use] extern crate bitflags; extern crate fnv; extern crate euclid; +extern crate ipc_channel; extern crate layers; extern crate libc; #[macro_use] diff --git a/components/gfx/paint_task.rs b/components/gfx/paint_task.rs index 4083fd05aa2..4f6a907841e 100644 --- a/components/gfx/paint_task.rs +++ b/components/gfx/paint_task.rs @@ -15,6 +15,8 @@ use euclid::Matrix4; use euclid::point::Point2D; use euclid::rect::Rect; use euclid::size::Size2D; +use ipc_channel::ipc; +use ipc_channel::router::ROUTER; use layers::platform::surface::{NativeDisplay, NativeSurface}; use layers::layers::{BufferRequest, LayerBuffer, LayerBufferSet}; use layers; @@ -24,7 +26,7 @@ use msg::compositor_msg::{LayerProperties, PaintListener, ScrollPolicy}; use msg::constellation_msg::Msg as ConstellationMsg; use msg::constellation_msg::{ConstellationChan, Failure, PipelineId}; use msg::constellation_msg::PipelineExitType; -use profile_traits::mem::{self, Reporter, ReportsChan}; +use profile_traits::mem::{self, Reporter, ReporterRequest, ReportsChan}; use profile_traits::time::{self, profile}; use rand::{self, Rng}; use std::borrow::ToOwned; @@ -98,14 +100,6 @@ impl PaintChan { } } -impl Reporter for PaintChan { - // Just injects an appropriate event into the paint task's queue. - fn collect_reports(&self, reports_chan: ReportsChan) -> bool { - let PaintChan(ref c) = *self; - c.send(Msg::CollectReports(reports_chan)).is_ok() - } -} - pub struct PaintTask<C> { id: PipelineId, _url: Url, @@ -179,11 +173,20 @@ impl<C> PaintTask<C> where C: PaintListener + Send + 'static { canvas_map: HashMap::new() }; - // Register this thread as a memory reporter, via its own channel. - let reporter = box chan.clone(); + // Register the memory reporter. let reporter_name = format!("paint-reporter-{}", id.0); - let msg = mem::ProfilerMsg::RegisterReporter(reporter_name.clone(), reporter); - mem_profiler_chan.send(msg); + let (reporter_sender, reporter_receiver) = + ipc::channel::<ReporterRequest>().unwrap(); + let paint_chan_for_reporter = chan.clone(); + ROUTER.add_route(reporter_receiver.to_opaque(), box move |message| { + // Just injects an appropriate event into the paint task's queue. + let request: ReporterRequest = message.to().unwrap(); + paint_chan_for_reporter.0.send(Msg::CollectReports(request.reports_channel)) + .unwrap(); + }); + mem_profiler_chan.send(mem::ProfilerMsg::RegisterReporter( + reporter_name.clone(), + Reporter(reporter_sender))); paint_task.start(); @@ -261,8 +264,9 @@ impl<C> PaintTask<C> where C: PaintListener + Send + 'static { Msg::PaintPermissionRevoked => { self.paint_permission = false; } - Msg::CollectReports(_) => { + Msg::CollectReports(ref channel) => { // FIXME(njn): should eventually measure the paint task. + channel.send(Vec::new()) } Msg::Exit(response_channel, _) => { // Ask the compositor to remove any layers it is holding for this paint task. diff --git a/components/layout/layout_task.rs b/components/layout/layout_task.rs index 36fbaa88383..6adb14a4c68 100644 --- a/components/layout/layout_task.rs +++ b/components/layout/layout_task.rs @@ -39,13 +39,14 @@ use gfx::display_list::StackingContext; use gfx::font_cache_task::FontCacheTask; use gfx::paint_task::Msg as PaintMsg; use gfx::paint_task::{PaintChan, PaintLayer}; -use ipc_channel::ipc::IpcReceiver; +use ipc_channel::ipc::{self, IpcReceiver}; +use ipc_channel::router::ROUTER; use layout_traits::LayoutTaskFactory; use log; use msg::compositor_msg::{Epoch, ScrollPolicy, LayerId}; use msg::constellation_msg::Msg as ConstellationMsg; use msg::constellation_msg::{ConstellationChan, Failure, PipelineExitType, PipelineId}; -use profile_traits::mem::{self, Report, ReportsChan}; +use profile_traits::mem::{self, Report, Reporter, ReporterRequest, ReportsChan}; use profile_traits::time::{self, ProfilerMetadata, profile}; use profile_traits::time::{TimerMetadataFrameType, TimerMetadataReflowType}; use net_traits::{load_bytes_iter, PendingAsyncLoad}; @@ -242,11 +243,20 @@ impl LayoutTaskFactory for LayoutTask { time_profiler_chan, mem_profiler_chan.clone()); - // Register this thread as a memory reporter, via its own channel. - let reporter = box layout_chan.clone(); + // Create a memory reporter thread. let reporter_name = format!("layout-reporter-{}", id.0); - let msg = mem::ProfilerMsg::RegisterReporter(reporter_name.clone(), reporter); - mem_profiler_chan.send(msg); + let (reporter_sender, reporter_receiver) = + ipc::channel::<ReporterRequest>().unwrap(); + let layout_chan_for_reporter = layout_chan.clone(); + ROUTER.add_route(reporter_receiver.to_opaque(), box move |message| { + // Just injects an appropriate event into the layout task's queue. + let request: ReporterRequest = message.to().unwrap(); + layout_chan_for_reporter.0.send(Msg::CollectReports(request.reports_channel)) + .unwrap(); + }); + mem_profiler_chan.send(mem::ProfilerMsg::RegisterReporter( + reporter_name.clone(), + Reporter(reporter_sender))); layout.start(); diff --git a/components/profile/Cargo.toml b/components/profile/Cargo.toml index 58a6726f4d6..4ec2abfcb87 100644 --- a/components/profile/Cargo.toml +++ b/components/profile/Cargo.toml @@ -13,6 +13,9 @@ path = "../profile_traits" [dependencies.util] path = "../util" +[dependencies.ipc-channel] +git = "https://github.com/pcwalton/ipc-channel" + [dependencies] log = "0.3" libc = "0.1" diff --git a/components/profile/lib.rs b/components/profile/lib.rs index a874ed233bb..f736d408ff1 100644 --- a/components/profile/lib.rs +++ b/components/profile/lib.rs @@ -9,6 +9,7 @@ #[macro_use] extern crate log; +extern crate ipc_channel; extern crate libc; #[macro_use] extern crate profile_traits; diff --git a/components/profile/mem.rs b/components/profile/mem.rs index 00a5c51f14b..9c4a5ac710f 100644 --- a/components/profile/mem.rs +++ b/components/profile/mem.rs @@ -4,26 +4,26 @@ //! Memory profiling functions. -use profile_traits::mem::{ProfilerChan, ProfilerMsg, Reporter, ReportsChan}; -use self::system_reporter::SystemReporter; +use ipc_channel::ipc::{self, IpcReceiver}; +use ipc_channel::router::ROUTER; +use profile_traits::mem::{ProfilerChan, ProfilerMsg, Reporter, ReporterRequest, ReportsChan}; use std::borrow::ToOwned; use std::cmp::Ordering; use std::collections::HashMap; use std::thread::sleep_ms; -use std::sync::mpsc::{channel, Receiver}; use util::task::spawn_named; pub struct Profiler { /// The port through which messages are received. - pub port: Receiver<ProfilerMsg>, + pub port: IpcReceiver<ProfilerMsg>, /// Registered memory reporters. - reporters: HashMap<String, Box<Reporter + Send>>, + reporters: HashMap<String, Reporter>, } impl Profiler { pub fn create(period: Option<f64>) -> ProfilerChan { - let (chan, port) = channel(); + let (chan, port) = ipc::channel().unwrap(); // Create the timer thread if a period was provided. if let Some(period) = period { @@ -48,16 +48,21 @@ impl Profiler { let mem_profiler_chan = ProfilerChan(chan); - // Register the system memory reporter, which will run on the memory profiler's own thread. - // It never needs to be unregistered, because as long as the memory profiler is running the - // system memory reporter can make measurements. - let system_reporter = box SystemReporter; - mem_profiler_chan.send(ProfilerMsg::RegisterReporter("system".to_owned(), system_reporter)); + // Register the system memory reporter, which will run on its own thread. It never needs to + // be unregistered, because as long as the memory profiler is running the system memory + // reporter can make measurements. + let (system_reporter_sender, system_reporter_receiver) = ipc::channel().unwrap(); + ROUTER.add_route(system_reporter_receiver.to_opaque(), box |message| { + let request: ReporterRequest = message.to().unwrap(); + system_reporter::collect_reports(request) + }); + mem_profiler_chan.send(ProfilerMsg::RegisterReporter("system".to_owned(), + Reporter(system_reporter_sender))); mem_profiler_chan } - pub fn new(port: Receiver<ProfilerMsg>) -> Profiler { + pub fn new(port: IpcReceiver<ProfilerMsg>) -> Profiler { Profiler { port: port, reporters: HashMap::new(), @@ -119,12 +124,11 @@ impl Profiler { // If anything goes wrong with a reporter, we just skip it. let mut forest = ReportsForest::new(); for reporter in self.reporters.values() { - let (chan, port) = channel(); - if reporter.collect_reports(ReportsChan(chan)) { - if let Ok(reports) = port.recv() { - for report in reports.iter() { - forest.insert(&report.path, report.size); - } + let (chan, port) = ipc::channel().unwrap(); + reporter.collect_reports(ReportsChan(chan)); + if let Ok(reports) = port.recv() { + for report in reports.iter() { + forest.insert(&report.path, report.size); } } } @@ -297,7 +301,7 @@ impl ReportsForest { mod system_reporter { use libc::{c_char, c_int, c_void, size_t}; - use profile_traits::mem::{Report, Reporter, ReportsChan}; + use profile_traits::mem::{Report, ReporterRequest}; use std::borrow::ToOwned; use std::ffi::CString; use std::mem::size_of; @@ -306,51 +310,46 @@ mod system_reporter { use task_info::task_basic_info::{virtual_size, resident_size}; /// Collects global measurements from the OS and heap allocators. - pub struct SystemReporter; - - impl Reporter for SystemReporter { - fn collect_reports(&self, reports_chan: ReportsChan) -> bool { - let mut reports = vec![]; - { - let mut report = |path, size| { - if let Some(size) = size { - reports.push(Report { path: path, size: size }); - } - }; - - // Virtual and physical memory usage, as reported by the OS. - report(path!["vsize"], get_vsize()); - report(path!["resident"], get_resident()); - - // Memory segments, as reported by the OS. - for seg in get_resident_segments().iter() { - report(path!["resident-according-to-smaps", seg.0], Some(seg.1)); + pub fn collect_reports(request: ReporterRequest) { + let mut reports = vec![]; + { + let mut report = |path, size| { + if let Some(size) = size { + reports.push(Report { path: path, size: size }); } + }; - // Total number of bytes allocated by the application on the system - // heap. - report(path!["system-heap-allocated"], get_system_heap_allocated()); + // Virtual and physical memory usage, as reported by the OS. + report(path!["vsize"], get_vsize()); + report(path!["resident"], get_resident()); - // The descriptions of the following jemalloc measurements are taken - // directly from the jemalloc documentation. + // Memory segments, as reported by the OS. + for seg in get_resident_segments().iter() { + report(path!["resident-according-to-smaps", seg.0], Some(seg.1)); + } - // "Total number of bytes allocated by the application." - report(path!["jemalloc-heap-allocated"], get_jemalloc_stat("stats.allocated")); + // Total number of bytes allocated by the application on the system + // heap. + report(path!["system-heap-allocated"], get_system_heap_allocated()); - // "Total number of bytes in active pages allocated by the application. - // This is a multiple of the page size, and greater than or equal to - // |stats.allocated|." - report(path!["jemalloc-heap-active"], get_jemalloc_stat("stats.active")); + // The descriptions of the following jemalloc measurements are taken + // directly from the jemalloc documentation. - // "Total number of bytes in chunks mapped on behalf of the application. - // This is a multiple of the chunk size, and is at least as large as - // |stats.active|. This does not include inactive chunks." - report(path!["jemalloc-heap-mapped"], get_jemalloc_stat("stats.mapped")); - } - reports_chan.send(reports); + // "Total number of bytes allocated by the application." + report(path!["jemalloc-heap-allocated"], get_jemalloc_stat("stats.allocated")); - true + // "Total number of bytes in active pages allocated by the application. + // This is a multiple of the page size, and greater than or equal to + // |stats.allocated|." + report(path!["jemalloc-heap-active"], get_jemalloc_stat("stats.active")); + + // "Total number of bytes in chunks mapped on behalf of the application. + // This is a multiple of the chunk size, and is at least as large as + // |stats.active|. This does not include inactive chunks." + report(path!["jemalloc-heap-mapped"], get_jemalloc_stat("stats.mapped")); } + + request.reports_channel.send(reports); } #[cfg(target_os="linux")] diff --git a/components/profile/time.rs b/components/profile/time.rs index 133b48c09c1..02e9f44c294 100644 --- a/components/profile/time.rs +++ b/components/profile/time.rs @@ -4,12 +4,12 @@ //! Timing functions. +use ipc_channel::ipc::{self, IpcReceiver}; use profile_traits::time::{ProfilerCategory, ProfilerChan, ProfilerMsg, TimerMetadata}; use std::borrow::ToOwned; use std::cmp::Ordering; use std::collections::BTreeMap; use std::f64; -use std::sync::mpsc::{channel, Receiver}; use std::thread::sleep_ms; use std_time::precise_time_ns; use util::task::spawn_named; @@ -86,14 +86,14 @@ type ProfilerBuckets = BTreeMap<(ProfilerCategory, Option<TimerMetadata>), Vec<f // back end of the profiler that handles data aggregation and performance metrics pub struct Profiler { - pub port: Receiver<ProfilerMsg>, + pub port: IpcReceiver<ProfilerMsg>, buckets: ProfilerBuckets, pub last_msg: Option<ProfilerMsg>, } impl Profiler { pub fn create(period: Option<f64>) -> ProfilerChan { - let (chan, port) = channel(); + let (chan, port) = ipc::channel().unwrap(); match period { Some(period) => { let period = (period * 1000.) as u32; @@ -128,7 +128,7 @@ impl Profiler { ProfilerChan(chan) } - pub fn new(port: Receiver<ProfilerMsg>) -> Profiler { + pub fn new(port: IpcReceiver<ProfilerMsg>) -> Profiler { Profiler { port: port, buckets: BTreeMap::new(), diff --git a/components/profile_traits/Cargo.toml b/components/profile_traits/Cargo.toml index 509565deb4b..f85223c99ee 100644 --- a/components/profile_traits/Cargo.toml +++ b/components/profile_traits/Cargo.toml @@ -7,7 +7,12 @@ authors = ["The Servo Project Developers"] name = "profile_traits" path = "lib.rs" +[dependencies.ipc-channel] +git = "https://github.com/pcwalton/ipc-channel" + [dependencies] +serde = "0.4" +serde_macros = "0.4" time = "0.1.12" url = "0.2.36" diff --git a/components/profile_traits/lib.rs b/components/profile_traits/lib.rs index 1a20a02c234..74b356092df 100644 --- a/components/profile_traits/lib.rs +++ b/components/profile_traits/lib.rs @@ -6,5 +6,12 @@ //! rest of Servo. These APIs are here instead of in `profile` so that these //! modules won't have to depend on `profile`. +#![feature(custom_derive, plugin)] +#![plugin(serde_macros)] + +extern crate ipc_channel; +extern crate serde; + pub mod mem; pub mod time; + diff --git a/components/profile_traits/mem.rs b/components/profile_traits/mem.rs index 4b4bd2a59f9..0269e8f29d7 100644 --- a/components/profile_traits/mem.rs +++ b/components/profile_traits/mem.rs @@ -6,15 +6,15 @@ #![deny(missing_docs)] -use std::sync::mpsc::Sender; +use ipc_channel::ipc::IpcSender; /// Front-end representation of the profiler used to communicate with the /// profiler. #[derive(Clone)] -pub struct ProfilerChan(pub Sender<ProfilerMsg>); +pub struct ProfilerChan(pub IpcSender<ProfilerMsg>); impl ProfilerChan { - /// Send `msg` on this `Sender`. + /// Send `msg` on this `IpcSender`. /// /// Panics if the send fails. pub fn send(&self, msg: ProfilerMsg) { @@ -24,6 +24,7 @@ impl ProfilerChan { } /// A single memory-related measurement. +#[derive(Deserialize, Serialize)] pub struct Report { /// The identifying path for this report. pub path: Vec<String>, @@ -33,11 +34,11 @@ pub struct Report { } /// A channel through which memory reports can be sent. -#[derive(Clone)] -pub struct ReportsChan(pub Sender<Vec<Report>>); +#[derive(Clone, Deserialize, Serialize)] +pub struct ReportsChan(pub IpcSender<Vec<Report>>); impl ReportsChan { - /// Send `report` on this `Sender`. + /// Send `report` on this `IpcSender`. /// /// Panics if the send fails. pub fn send(&self, report: Vec<Report>) { @@ -46,13 +47,30 @@ impl ReportsChan { } } -/// A memory reporter is capable of measuring some data structure of interest. Because it needs to -/// be passed to and registered with the Profiler, it's typically a "small" (i.e. easily cloneable) -/// value that provides access to a "large" data structure, e.g. a channel that can inject a -/// request for measurements into the event queue associated with the "large" data structure. -pub trait Reporter { +/// The protocol used to send reporter requests. +#[derive(Deserialize, Serialize)] +pub struct ReporterRequest { + /// The channel on which reports are to be sent. + pub reports_channel: ReportsChan, +} + +/// A memory reporter is capable of measuring some data structure of interest. It's structured as +/// an IPC sender that a `ReporterRequest` in transmitted over. `ReporterRequest` objects in turn +/// encapsulate the channel on which the memory profiling information is to be sent. +/// +/// In many cases, clients construct `Reporter` objects by creating an IPC sender/receiver pair and +/// registering the receiving end with the router so that messages from the memory profiler end up +/// injected into the client's event loop. +#[derive(Deserialize, Serialize)] +pub struct Reporter(pub IpcSender<ReporterRequest>); + +impl Reporter { /// Collect one or more memory reports. Returns true on success, and false on failure. - fn collect_reports(&self, reports_chan: ReportsChan) -> bool; + pub fn collect_reports(&self, reports_chan: ReportsChan) { + self.0.send(ReporterRequest { + reports_channel: reports_chan, + }).unwrap() + } } /// An easy way to build a path for a report. @@ -65,11 +83,12 @@ macro_rules! path { } /// Messages that can be sent to the memory profiler thread. +#[derive(Deserialize, Serialize)] pub enum ProfilerMsg { /// Register a Reporter with the memory profiler. The String is only used to identify the /// reporter so it can be unregistered later. The String must be distinct from that used by any /// other registered reporter otherwise a panic will occur. - RegisterReporter(String, Box<Reporter + Send>), + RegisterReporter(String, Reporter), /// Unregister a Reporter with the memory profiler. The String must match the name given when /// the reporter was registered. If the String does not match the name of a registered reporter @@ -82,3 +101,4 @@ pub enum ProfilerMsg { /// Tells the memory profiler to shut down. Exit, } + diff --git a/components/profile_traits/time.rs b/components/profile_traits/time.rs index f49940a168f..ef38acc6c5f 100644 --- a/components/profile_traits/time.rs +++ b/components/profile_traits/time.rs @@ -5,19 +5,19 @@ extern crate time as std_time; extern crate url; +use ipc_channel::ipc::IpcSender; use self::std_time::precise_time_ns; use self::url::Url; -use std::sync::mpsc::Sender; -#[derive(PartialEq, Clone, PartialOrd, Eq, Ord)] +#[derive(PartialEq, Clone, PartialOrd, Eq, Ord, Deserialize, Serialize)] pub struct TimerMetadata { pub url: String, pub iframe: bool, pub incremental: bool, } -#[derive(Clone)] -pub struct ProfilerChan(pub Sender<ProfilerMsg>); +#[derive(Clone, Deserialize, Serialize)] +pub struct ProfilerChan(pub IpcSender<ProfilerMsg>); impl ProfilerChan { pub fn send(&self, msg: ProfilerMsg) { @@ -26,7 +26,7 @@ impl ProfilerChan { } } -#[derive(Clone)] +#[derive(Clone, Deserialize, Serialize)] pub enum ProfilerMsg { /// Normal message used for reporting time Time((ProfilerCategory, Option<TimerMetadata>), f64), @@ -37,7 +37,7 @@ pub enum ProfilerMsg { } #[repr(u32)] -#[derive(PartialEq, Clone, PartialOrd, Eq, Ord)] +#[derive(PartialEq, Clone, PartialOrd, Eq, Ord, Deserialize, Serialize)] pub enum ProfilerCategory { Compositing, LayoutPerform, diff --git a/components/script/dom/dedicatedworkerglobalscope.rs b/components/script/dom/dedicatedworkerglobalscope.rs index b298f37bee1..cf8c22f81d7 100644 --- a/components/script/dom/dedicatedworkerglobalscope.rs +++ b/components/script/dom/dedicatedworkerglobalscope.rs @@ -29,11 +29,13 @@ use msg::constellation_msg::PipelineId; use devtools_traits::DevtoolsControlChan; use net_traits::{load_whole_resource, ResourceTask}; -use profile_traits::mem::{self, Reporter, ReportsChan}; +use profile_traits::mem::{self, Reporter, ReporterRequest}; use util::task::spawn_named; use util::task_state; use util::task_state::{SCRIPT, IN_WORKER}; +use ipc_channel::ipc; +use ipc_channel::router::ROUTER; use js::jsapi::{JSContext, RootedValue, HandleValue}; use js::jsapi::{JSAutoRequest, JSAutoCompartment}; use js::jsval::UndefinedValue; @@ -66,13 +68,6 @@ impl ScriptChan for SendableWorkerScriptChan { } } -impl Reporter for SendableWorkerScriptChan { - // Just injects an appropriate event into the worker task's queue. - fn collect_reports(&self, reports_chan: ReportsChan) -> bool { - self.send(ScriptMsg::CollectReports(reports_chan)).is_ok() - } -} - /// Set the `worker` field of a related DedicatedWorkerGlobalScope object to a particular /// value for the duration of this object's lifetime. This ensures that the related Worker /// object only lives as long as necessary (ie. while events are being executed), while @@ -182,6 +177,7 @@ impl DedicatedWorkerGlobalScope { let runtime = Rc::new(ScriptTask::new_rt_and_cx()); let serialized_url = url.serialize(); + let parent_sender_for_reporter = parent_sender.clone(); let global = DedicatedWorkerGlobalScope::new( url, id, mem_profiler_chan.clone(), devtools_chan, runtime.clone(), resource_task, parent_sender, own_sender, receiver); @@ -206,9 +202,16 @@ impl DedicatedWorkerGlobalScope { // Register this task as a memory reporter. This needs to be done within the // scope of `_ar` otherwise script_chan_as_reporter() will panic. - let reporter = global.script_chan_as_reporter(); - let msg = mem::ProfilerMsg::RegisterReporter(reporter_name.clone(), reporter); - mem_profiler_chan.send(msg); + let (reporter_sender, reporter_receiver) = ipc::channel().unwrap(); + ROUTER.add_route(reporter_receiver.to_opaque(), box move |reporter_request| { + // Just injects an appropriate event into the worker task's queue. + let reporter_request: ReporterRequest = reporter_request.to().unwrap(); + parent_sender_for_reporter.send(ScriptMsg::CollectReports( + reporter_request.reports_channel)).unwrap() + }); + mem_profiler_chan.send(mem::ProfilerMsg::RegisterReporter( + reporter_name.clone(), + Reporter(reporter_sender))); } loop { @@ -230,7 +233,6 @@ impl DedicatedWorkerGlobalScope { pub trait DedicatedWorkerGlobalScopeHelpers { fn script_chan(self) -> Box<ScriptChan+Send>; - fn script_chan_as_reporter(self) -> Box<Reporter+Send>; fn pipeline(self) -> PipelineId; fn new_script_pair(self) -> (Box<ScriptChan+Send>, Box<ScriptPort+Send>); fn process_event(self, msg: ScriptMsg); @@ -244,14 +246,6 @@ impl<'a> DedicatedWorkerGlobalScopeHelpers for &'a DedicatedWorkerGlobalScope { } } - fn script_chan_as_reporter(self) -> Box<Reporter+Send> { - box SendableWorkerScriptChan { - sender: self.own_sender.clone(), - worker: self.worker.borrow().as_ref().unwrap().clone(), - } - } - - fn pipeline(self) -> PipelineId { self.id } diff --git a/components/script/layout_interface.rs b/components/script/layout_interface.rs index 3c26f062214..b94758f56b7 100644 --- a/components/script/layout_interface.rs +++ b/components/script/layout_interface.rs @@ -18,7 +18,7 @@ use msg::constellation_msg::{WindowSizeData}; use msg::compositor_msg::Epoch; use net_traits::image_cache_task::ImageCacheTask; use net_traits::PendingAsyncLoad; -use profile_traits::mem::{Reporter, ReportsChan}; +use profile_traits::mem::ReportsChan; use script_traits::{ConstellationControlMsg, LayoutControlMsg, ScriptControlChan}; use script_traits::{OpaqueScriptLayoutChannel, StylesheetLoadResponder, UntrustedNodeAddress}; use std::any::Any; @@ -159,14 +159,6 @@ impl LayoutChan { } } -impl Reporter for LayoutChan { - // Just injects an appropriate event into the layout task's queue. - fn collect_reports(&self, reports_chan: ReportsChan) -> bool { - let LayoutChan(ref c) = *self; - c.send(Msg::CollectReports(reports_chan)).is_ok() - } -} - /// A trait to manage opaque references to script<->layout channels without needing /// to expose the message type to crates that don't need to know about them. pub trait ScriptLayoutChan { diff --git a/components/script/script_task.rs b/components/script/script_task.rs index 480514b36b2..a352414689d 100644 --- a/components/script/script_task.rs +++ b/components/script/script_task.rs @@ -70,7 +70,7 @@ use net_traits::{ResourceTask, LoadConsumer, ControlMsg, Metadata}; use net_traits::LoadData as NetLoadData; use net_traits::image_cache_task::{ImageCacheChan, ImageCacheTask, ImageCacheResult}; use net_traits::storage_task::StorageTask; -use profile_traits::mem::{self, Report, Reporter, ReportsChan}; +use profile_traits::mem::{self, Report, Reporter, ReporterRequest, ReportsChan}; use string_cache::Atom; use util::str::DOMString; use util::task::spawn_named_with_send_on_failure; @@ -79,6 +79,8 @@ use util::task_state; use euclid::Rect; use euclid::point::Point2D; use hyper::header::{LastModified, Headers}; +use ipc_channel::ipc; +use ipc_channel::router::ROUTER; use js::glue::CollectServoSizes; use js::jsapi::{JS_SetWrapObjectCallbacks, JS_AddExtraGCRootsTracer, DisableIncrementalGC}; use js::jsapi::{JSContext, JSRuntime, JSTracer}; @@ -252,18 +254,6 @@ impl NonWorkerScriptChan { let (chan, port) = channel(); (port, box NonWorkerScriptChan(chan)) } - - fn clone_as_reporter(&self) -> Box<Reporter+Send> { - let NonWorkerScriptChan(ref chan) = *self; - box NonWorkerScriptChan((*chan).clone()) - } -} - -impl Reporter for NonWorkerScriptChan { - // Just injects an appropriate event into the script task's queue. - fn collect_reports(&self, reports_chan: ReportsChan) -> bool { - self.send(ScriptMsg::CollectReports(reports_chan)).is_ok() - } } pub struct StackRootTLS; @@ -420,7 +410,7 @@ impl ScriptTaskFactory for ScriptTask { let roots = RootCollection::new(); let _stack_roots_tls = StackRootTLS::new(&roots); let chan = NonWorkerScriptChan(script_chan); - let reporter = chan.clone_as_reporter(); + let channel_for_reporter = chan.clone(); let script_task = ScriptTask::new(compositor, script_port, chan, @@ -445,6 +435,14 @@ impl ScriptTaskFactory for ScriptTask { // Register this task as a memory reporter. let reporter_name = format!("script-reporter-{}", id.0); + let (reporter_sender, reporter_receiver) = ipc::channel().unwrap(); + ROUTER.add_route(reporter_receiver.to_opaque(), box move |reporter_request| { + // Just injects an appropriate event into the worker task's queue. + let reporter_request: ReporterRequest = reporter_request.to().unwrap(); + channel_for_reporter.send(ScriptMsg::CollectReports( + reporter_request.reports_channel)).unwrap() + }); + let reporter = Reporter(reporter_sender); let msg = mem::ProfilerMsg::RegisterReporter(reporter_name.clone(), reporter); mem_profiler_chan.send(msg); diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock index e3289f453ca..050832d4881 100644 --- a/components/servo/Cargo.lock +++ b/components/servo/Cargo.lock @@ -437,6 +437,7 @@ dependencies = [ "freetype 0.1.0 (git+https://github.com/servo/rust-freetype)", "gfx_traits 0.0.1", "harfbuzz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ipc-channel 0.1.0 (git+https://github.com/pcwalton/ipc-channel)", "layers 0.1.0 (git+https://github.com/servo/rust-layers)", "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1049,6 +1050,7 @@ source = "git+https://github.com/servo/rust-png#3c3105672622c76fbb079a96384f78e4 name = "profile" version = "0.0.1" dependencies = [ + "ipc-channel 0.1.0 (git+https://github.com/pcwalton/ipc-channel)", "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "profile_traits 0.0.1", @@ -1062,6 +1064,9 @@ dependencies = [ name = "profile_traits" version = "0.0.1" dependencies = [ + "ipc-channel 0.1.0 (git+https://github.com/pcwalton/ipc-channel)", + "serde 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_macros 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", "url 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1221,7 +1226,7 @@ dependencies = [ [[package]] name = "serde_codegen" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aster 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1234,7 +1239,7 @@ name = "serde_macros" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_codegen 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] diff --git a/ports/cef/Cargo.lock b/ports/cef/Cargo.lock index 58eaf628956..0693ddc70d5 100644 --- a/ports/cef/Cargo.lock +++ b/ports/cef/Cargo.lock @@ -436,6 +436,7 @@ dependencies = [ "freetype 0.1.0 (git+https://github.com/servo/rust-freetype)", "gfx_traits 0.0.1", "harfbuzz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ipc-channel 0.1.0 (git+https://github.com/pcwalton/ipc-channel)", "layers 0.1.0 (git+https://github.com/servo/rust-layers)", "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1028,6 +1029,7 @@ source = "git+https://github.com/servo/rust-png#653902184ce95d2dc44cd4674c8b273f name = "profile" version = "0.0.1" dependencies = [ + "ipc-channel 0.1.0 (git+https://github.com/pcwalton/ipc-channel)", "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "profile_traits 0.0.1", @@ -1041,6 +1043,9 @@ dependencies = [ name = "profile_traits" version = "0.0.1" dependencies = [ + "ipc-channel 0.1.0 (git+https://github.com/pcwalton/ipc-channel)", + "serde 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_macros 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", "url 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1192,7 +1197,7 @@ dependencies = [ [[package]] name = "serde_codegen" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aster 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1205,7 +1210,7 @@ name = "serde_macros" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_codegen 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] diff --git a/ports/gonk/Cargo.lock b/ports/gonk/Cargo.lock index 8938b748c62..7a2368baa1d 100644 --- a/ports/gonk/Cargo.lock +++ b/ports/gonk/Cargo.lock @@ -415,6 +415,7 @@ dependencies = [ "freetype 0.1.0 (git+https://github.com/servo/rust-freetype)", "gfx_traits 0.0.1", "harfbuzz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ipc-channel 0.1.0 (git+https://github.com/pcwalton/ipc-channel)", "layers 0.1.0 (git+https://github.com/servo/rust-layers)", "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -936,6 +937,7 @@ source = "git+https://github.com/servo/rust-png#3c3105672622c76fbb079a96384f78e4 name = "profile" version = "0.0.1" dependencies = [ + "ipc-channel 0.1.0 (git+https://github.com/pcwalton/ipc-channel)", "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "profile_traits 0.0.1", @@ -949,6 +951,9 @@ dependencies = [ name = "profile_traits" version = "0.0.1" dependencies = [ + "ipc-channel 0.1.0 (git+https://github.com/pcwalton/ipc-channel)", + "serde 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_macros 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", "url 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1100,7 +1105,7 @@ dependencies = [ [[package]] name = "serde_codegen" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aster 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1113,7 +1118,7 @@ name = "serde_macros" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_codegen 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] |