profile: Make the time and memory profilers run over IPC.

Uses the `Router` abstraction inside `ipc-channel` to avoid spawning new
threads.
This commit is contained in:
Patrick Walton 2015-07-14 18:28:57 -07:00
parent ed1b6a3513
commit f10c076180
19 changed files with 212 additions and 168 deletions

View file

@ -22,6 +22,8 @@ use gfx::paint_task::Msg as PaintMsg;
use gfx::paint_task::PaintRequest; use gfx::paint_task::PaintRequest;
use gleam::gl::types::{GLint, GLsizei}; use gleam::gl::types::{GLint, GLsizei};
use gleam::gl; use gleam::gl;
use ipc_channel::ipc;
use ipc_channel::router::ROUTER;
use layers::geometry::{DevicePixel, LayerPixel}; use layers::geometry::{DevicePixel, LayerPixel};
use layers::layers::{BufferRequest, Layer, LayerBuffer, LayerBufferSet}; use layers::layers::{BufferRequest, Layer, LayerBuffer, LayerBufferSet};
use layers::platform::surface::NativeDisplay; 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::{Key, KeyModifiers, KeyState, LoadData};
use msg::constellation_msg::{PipelineId, WindowSizeData}; use msg::constellation_msg::{PipelineId, WindowSizeData};
use png; use png;
use profile_traits::mem; use profile_traits::mem::{self, Reporter, ReporterRequest};
use profile_traits::time::{self, ProfilerCategory, profile}; use profile_traits::time::{self, ProfilerCategory, profile};
use script_traits::{ConstellationControlMsg, LayoutControlMsg, ScriptControlChan}; use script_traits::{ConstellationControlMsg, LayoutControlMsg, ScriptControlChan};
use std::collections::HashMap; use std::collections::HashMap;
@ -257,7 +259,13 @@ impl<Window: WindowMethods> IOCompositor<Window> {
-> IOCompositor<Window> { -> IOCompositor<Window> {
// Register this thread as a memory reporter, via its own channel. // 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)); mem_profiler_chan.send(mem::ProfilerMsg::RegisterReporter(reporter_name(), reporter));
let window_size = window.framebuffer_size(); let window_size = window.framebuffer_size();
@ -1723,19 +1731,3 @@ pub enum CompositingReason {
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

@ -44,6 +44,9 @@ git = "https://github.com/servo/skia"
[dependencies.script_traits] [dependencies.script_traits]
path = "../script_traits" path = "../script_traits"
[dependencies.ipc-channel]
git = "https://github.com/pcwalton/ipc-channel"
[dependencies] [dependencies]
log = "0.3" log = "0.3"
fnv = "1.0" fnv = "1.0"

View file

@ -24,6 +24,7 @@ extern crate azure;
#[macro_use] extern crate bitflags; #[macro_use] extern crate bitflags;
extern crate fnv; extern crate fnv;
extern crate euclid; extern crate euclid;
extern crate ipc_channel;
extern crate layers; extern crate layers;
extern crate libc; extern crate libc;
#[macro_use] #[macro_use]

View file

@ -15,6 +15,8 @@ use euclid::Matrix4;
use euclid::point::Point2D; use euclid::point::Point2D;
use euclid::rect::Rect; use euclid::rect::Rect;
use euclid::size::Size2D; use euclid::size::Size2D;
use ipc_channel::ipc;
use ipc_channel::router::ROUTER;
use layers::platform::surface::{NativeDisplay, NativeSurface}; use layers::platform::surface::{NativeDisplay, NativeSurface};
use layers::layers::{BufferRequest, LayerBuffer, LayerBufferSet}; use layers::layers::{BufferRequest, LayerBuffer, LayerBufferSet};
use layers; use layers;
@ -24,7 +26,7 @@ use msg::compositor_msg::{LayerProperties, PaintListener, ScrollPolicy};
use msg::constellation_msg::Msg as ConstellationMsg; use msg::constellation_msg::Msg as ConstellationMsg;
use msg::constellation_msg::{ConstellationChan, Failure, PipelineId}; use msg::constellation_msg::{ConstellationChan, Failure, PipelineId};
use msg::constellation_msg::PipelineExitType; 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 profile_traits::time::{self, profile};
use rand::{self, Rng}; use rand::{self, Rng};
use std::borrow::ToOwned; 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> { pub struct PaintTask<C> {
id: PipelineId, id: PipelineId,
_url: Url, _url: Url,
@ -179,11 +173,20 @@ impl<C> PaintTask<C> where C: PaintListener + Send + 'static {
canvas_map: HashMap::new() canvas_map: HashMap::new()
}; };
// Register this thread as a memory reporter, via its own channel. // Register the memory reporter.
let reporter = box chan.clone();
let reporter_name = format!("paint-reporter-{}", id.0); let reporter_name = format!("paint-reporter-{}", id.0);
let msg = mem::ProfilerMsg::RegisterReporter(reporter_name.clone(), reporter); let (reporter_sender, reporter_receiver) =
mem_profiler_chan.send(msg); 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(); paint_task.start();
@ -261,8 +264,9 @@ impl<C> PaintTask<C> where C: PaintListener + Send + 'static {
Msg::PaintPermissionRevoked => { Msg::PaintPermissionRevoked => {
self.paint_permission = false; self.paint_permission = false;
} }
Msg::CollectReports(_) => { Msg::CollectReports(ref channel) => {
// FIXME(njn): should eventually measure the paint task. // FIXME(njn): should eventually measure the paint task.
channel.send(Vec::new())
} }
Msg::Exit(response_channel, _) => { Msg::Exit(response_channel, _) => {
// Ask the compositor to remove any layers it is holding for this paint task. // Ask the compositor to remove any layers it is holding for this paint task.

View file

@ -39,13 +39,14 @@ use gfx::display_list::StackingContext;
use gfx::font_cache_task::FontCacheTask; use gfx::font_cache_task::FontCacheTask;
use gfx::paint_task::Msg as PaintMsg; use gfx::paint_task::Msg as PaintMsg;
use gfx::paint_task::{PaintChan, PaintLayer}; 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 layout_traits::LayoutTaskFactory;
use log; use log;
use msg::compositor_msg::{Epoch, ScrollPolicy, LayerId}; use msg::compositor_msg::{Epoch, ScrollPolicy, LayerId};
use msg::constellation_msg::Msg as ConstellationMsg; use msg::constellation_msg::Msg as ConstellationMsg;
use msg::constellation_msg::{ConstellationChan, Failure, PipelineExitType, PipelineId}; 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::{self, ProfilerMetadata, profile};
use profile_traits::time::{TimerMetadataFrameType, TimerMetadataReflowType}; use profile_traits::time::{TimerMetadataFrameType, TimerMetadataReflowType};
use net_traits::{load_bytes_iter, PendingAsyncLoad}; use net_traits::{load_bytes_iter, PendingAsyncLoad};
@ -242,11 +243,20 @@ impl LayoutTaskFactory for LayoutTask {
time_profiler_chan, time_profiler_chan,
mem_profiler_chan.clone()); mem_profiler_chan.clone());
// Register this thread as a memory reporter, via its own channel. // Create a memory reporter thread.
let reporter = box layout_chan.clone();
let reporter_name = format!("layout-reporter-{}", id.0); let reporter_name = format!("layout-reporter-{}", id.0);
let msg = mem::ProfilerMsg::RegisterReporter(reporter_name.clone(), reporter); let (reporter_sender, reporter_receiver) =
mem_profiler_chan.send(msg); 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(); layout.start();

View file

@ -13,6 +13,9 @@ path = "../profile_traits"
[dependencies.util] [dependencies.util]
path = "../util" path = "../util"
[dependencies.ipc-channel]
git = "https://github.com/pcwalton/ipc-channel"
[dependencies] [dependencies]
log = "0.3" log = "0.3"
libc = "0.1" libc = "0.1"

View file

@ -9,6 +9,7 @@
#[macro_use] extern crate log; #[macro_use] extern crate log;
extern crate ipc_channel;
extern crate libc; extern crate libc;
#[macro_use] #[macro_use]
extern crate profile_traits; extern crate profile_traits;

View file

@ -4,26 +4,26 @@
//! Memory profiling functions. //! Memory profiling functions.
use profile_traits::mem::{ProfilerChan, ProfilerMsg, Reporter, ReportsChan}; use ipc_channel::ipc::{self, IpcReceiver};
use self::system_reporter::SystemReporter; use ipc_channel::router::ROUTER;
use profile_traits::mem::{ProfilerChan, ProfilerMsg, Reporter, ReporterRequest, ReportsChan};
use std::borrow::ToOwned; use std::borrow::ToOwned;
use std::cmp::Ordering; use std::cmp::Ordering;
use std::collections::HashMap; use std::collections::HashMap;
use std::thread::sleep_ms; use std::thread::sleep_ms;
use std::sync::mpsc::{channel, Receiver};
use util::task::spawn_named; use util::task::spawn_named;
pub struct Profiler { pub struct Profiler {
/// The port through which messages are received. /// The port through which messages are received.
pub port: Receiver<ProfilerMsg>, pub port: IpcReceiver<ProfilerMsg>,
/// Registered memory reporters. /// Registered memory reporters.
reporters: HashMap<String, Box<Reporter + Send>>, reporters: HashMap<String, Reporter>,
} }
impl Profiler { impl Profiler {
pub fn create(period: Option<f64>) -> ProfilerChan { 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. // Create the timer thread if a period was provided.
if let Some(period) = period { if let Some(period) = period {
@ -48,16 +48,21 @@ impl Profiler {
let mem_profiler_chan = ProfilerChan(chan); let mem_profiler_chan = ProfilerChan(chan);
// Register the system memory reporter, which will run on the memory profiler's own thread. // Register the system memory reporter, which will run on its own thread. It never needs to
// It never needs to be unregistered, because as long as the memory profiler is running the // be unregistered, because as long as the memory profiler is running the system memory
// system memory reporter can make measurements. // reporter can make measurements.
let system_reporter = box SystemReporter; let (system_reporter_sender, system_reporter_receiver) = ipc::channel().unwrap();
mem_profiler_chan.send(ProfilerMsg::RegisterReporter("system".to_owned(), system_reporter)); 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 mem_profiler_chan
} }
pub fn new(port: Receiver<ProfilerMsg>) -> Profiler { pub fn new(port: IpcReceiver<ProfilerMsg>) -> Profiler {
Profiler { Profiler {
port: port, port: port,
reporters: HashMap::new(), reporters: HashMap::new(),
@ -119,15 +124,14 @@ impl Profiler {
// If anything goes wrong with a reporter, we just skip it. // If anything goes wrong with a reporter, we just skip it.
let mut forest = ReportsForest::new(); let mut forest = ReportsForest::new();
for reporter in self.reporters.values() { for reporter in self.reporters.values() {
let (chan, port) = channel(); let (chan, port) = ipc::channel().unwrap();
if reporter.collect_reports(ReportsChan(chan)) { reporter.collect_reports(ReportsChan(chan));
if let Ok(reports) = port.recv() { if let Ok(reports) = port.recv() {
for report in reports.iter() { for report in reports.iter() {
forest.insert(&report.path, report.size); forest.insert(&report.path, report.size);
} }
} }
} }
}
forest.print(); forest.print();
println!("|"); println!("|");
@ -297,7 +301,7 @@ impl ReportsForest {
mod system_reporter { mod system_reporter {
use libc::{c_char, c_int, c_void, size_t}; 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::borrow::ToOwned;
use std::ffi::CString; use std::ffi::CString;
use std::mem::size_of; use std::mem::size_of;
@ -306,10 +310,7 @@ mod system_reporter {
use task_info::task_basic_info::{virtual_size, resident_size}; use task_info::task_basic_info::{virtual_size, resident_size};
/// Collects global measurements from the OS and heap allocators. /// Collects global measurements from the OS and heap allocators.
pub struct SystemReporter; pub fn collect_reports(request: ReporterRequest) {
impl Reporter for SystemReporter {
fn collect_reports(&self, reports_chan: ReportsChan) -> bool {
let mut reports = vec![]; let mut reports = vec![];
{ {
let mut report = |path, size| { let mut report = |path, size| {
@ -347,10 +348,8 @@ mod system_reporter {
// |stats.active|. This does not include inactive chunks." // |stats.active|. This does not include inactive chunks."
report(path!["jemalloc-heap-mapped"], get_jemalloc_stat("stats.mapped")); report(path!["jemalloc-heap-mapped"], get_jemalloc_stat("stats.mapped"));
} }
reports_chan.send(reports);
true request.reports_channel.send(reports);
}
} }
#[cfg(target_os="linux")] #[cfg(target_os="linux")]

View file

@ -4,12 +4,12 @@
//! Timing functions. //! Timing functions.
use ipc_channel::ipc::{self, IpcReceiver};
use profile_traits::time::{ProfilerCategory, ProfilerChan, ProfilerMsg, TimerMetadata}; use profile_traits::time::{ProfilerCategory, ProfilerChan, ProfilerMsg, TimerMetadata};
use std::borrow::ToOwned; use std::borrow::ToOwned;
use std::cmp::Ordering; use std::cmp::Ordering;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::f64; use std::f64;
use std::sync::mpsc::{channel, Receiver};
use std::thread::sleep_ms; use std::thread::sleep_ms;
use std_time::precise_time_ns; use std_time::precise_time_ns;
use util::task::spawn_named; 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 // back end of the profiler that handles data aggregation and performance metrics
pub struct Profiler { pub struct Profiler {
pub port: Receiver<ProfilerMsg>, pub port: IpcReceiver<ProfilerMsg>,
buckets: ProfilerBuckets, buckets: ProfilerBuckets,
pub last_msg: Option<ProfilerMsg>, pub last_msg: Option<ProfilerMsg>,
} }
impl Profiler { impl Profiler {
pub fn create(period: Option<f64>) -> ProfilerChan { pub fn create(period: Option<f64>) -> ProfilerChan {
let (chan, port) = channel(); let (chan, port) = ipc::channel().unwrap();
match period { match period {
Some(period) => { Some(period) => {
let period = (period * 1000.) as u32; let period = (period * 1000.) as u32;
@ -128,7 +128,7 @@ impl Profiler {
ProfilerChan(chan) ProfilerChan(chan)
} }
pub fn new(port: Receiver<ProfilerMsg>) -> Profiler { pub fn new(port: IpcReceiver<ProfilerMsg>) -> Profiler {
Profiler { Profiler {
port: port, port: port,
buckets: BTreeMap::new(), buckets: BTreeMap::new(),

View file

@ -7,7 +7,12 @@ authors = ["The Servo Project Developers"]
name = "profile_traits" name = "profile_traits"
path = "lib.rs" path = "lib.rs"
[dependencies.ipc-channel]
git = "https://github.com/pcwalton/ipc-channel"
[dependencies] [dependencies]
serde = "0.4"
serde_macros = "0.4"
time = "0.1.12" time = "0.1.12"
url = "0.2.36" url = "0.2.36"

View file

@ -6,5 +6,12 @@
//! rest of Servo. These APIs are here instead of in `profile` so that these //! rest of Servo. These APIs are here instead of in `profile` so that these
//! modules won't have to depend on `profile`. //! 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 mem;
pub mod time; pub mod time;

View file

@ -6,15 +6,15 @@
#![deny(missing_docs)] #![deny(missing_docs)]
use std::sync::mpsc::Sender; use ipc_channel::ipc::IpcSender;
/// Front-end representation of the profiler used to communicate with the /// Front-end representation of the profiler used to communicate with the
/// profiler. /// profiler.
#[derive(Clone)] #[derive(Clone)]
pub struct ProfilerChan(pub Sender<ProfilerMsg>); pub struct ProfilerChan(pub IpcSender<ProfilerMsg>);
impl ProfilerChan { impl ProfilerChan {
/// Send `msg` on this `Sender`. /// Send `msg` on this `IpcSender`.
/// ///
/// Panics if the send fails. /// Panics if the send fails.
pub fn send(&self, msg: ProfilerMsg) { pub fn send(&self, msg: ProfilerMsg) {
@ -24,6 +24,7 @@ impl ProfilerChan {
} }
/// A single memory-related measurement. /// A single memory-related measurement.
#[derive(Deserialize, Serialize)]
pub struct Report { pub struct Report {
/// The identifying path for this report. /// The identifying path for this report.
pub path: Vec<String>, pub path: Vec<String>,
@ -33,11 +34,11 @@ pub struct Report {
} }
/// A channel through which memory reports can be sent. /// A channel through which memory reports can be sent.
#[derive(Clone)] #[derive(Clone, Deserialize, Serialize)]
pub struct ReportsChan(pub Sender<Vec<Report>>); pub struct ReportsChan(pub IpcSender<Vec<Report>>);
impl ReportsChan { impl ReportsChan {
/// Send `report` on this `Sender`. /// Send `report` on this `IpcSender`.
/// ///
/// Panics if the send fails. /// Panics if the send fails.
pub fn send(&self, report: Vec<Report>) { 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 /// The protocol used to send reporter requests.
/// be passed to and registered with the Profiler, it's typically a "small" (i.e. easily cloneable) #[derive(Deserialize, Serialize)]
/// value that provides access to a "large" data structure, e.g. a channel that can inject a pub struct ReporterRequest {
/// request for measurements into the event queue associated with the "large" data structure. /// The channel on which reports are to be sent.
pub trait Reporter { 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. /// 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. /// 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. /// Messages that can be sent to the memory profiler thread.
#[derive(Deserialize, Serialize)]
pub enum ProfilerMsg { pub enum ProfilerMsg {
/// Register a Reporter with the memory profiler. The String is only used to identify the /// 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 /// 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. /// 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 /// 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 /// 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. /// Tells the memory profiler to shut down.
Exit, Exit,
} }

View file

@ -5,19 +5,19 @@
extern crate time as std_time; extern crate time as std_time;
extern crate url; extern crate url;
use ipc_channel::ipc::IpcSender;
use self::std_time::precise_time_ns; use self::std_time::precise_time_ns;
use self::url::Url; 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 struct TimerMetadata {
pub url: String, pub url: String,
pub iframe: bool, pub iframe: bool,
pub incremental: bool, pub incremental: bool,
} }
#[derive(Clone)] #[derive(Clone, Deserialize, Serialize)]
pub struct ProfilerChan(pub Sender<ProfilerMsg>); pub struct ProfilerChan(pub IpcSender<ProfilerMsg>);
impl ProfilerChan { impl ProfilerChan {
pub fn send(&self, msg: ProfilerMsg) { pub fn send(&self, msg: ProfilerMsg) {
@ -26,7 +26,7 @@ impl ProfilerChan {
} }
} }
#[derive(Clone)] #[derive(Clone, Deserialize, Serialize)]
pub enum ProfilerMsg { pub enum ProfilerMsg {
/// Normal message used for reporting time /// Normal message used for reporting time
Time((ProfilerCategory, Option<TimerMetadata>), f64), Time((ProfilerCategory, Option<TimerMetadata>), f64),
@ -37,7 +37,7 @@ pub enum ProfilerMsg {
} }
#[repr(u32)] #[repr(u32)]
#[derive(PartialEq, Clone, PartialOrd, Eq, Ord)] #[derive(PartialEq, Clone, PartialOrd, Eq, Ord, Deserialize, Serialize)]
pub enum ProfilerCategory { pub enum ProfilerCategory {
Compositing, Compositing,
LayoutPerform, LayoutPerform,

View file

@ -29,11 +29,13 @@ use msg::constellation_msg::PipelineId;
use devtools_traits::DevtoolsControlChan; use devtools_traits::DevtoolsControlChan;
use net_traits::{load_whole_resource, ResourceTask}; 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::spawn_named;
use util::task_state; use util::task_state;
use util::task_state::{SCRIPT, IN_WORKER}; 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::{JSContext, RootedValue, HandleValue};
use js::jsapi::{JSAutoRequest, JSAutoCompartment}; use js::jsapi::{JSAutoRequest, JSAutoCompartment};
use js::jsval::UndefinedValue; 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 /// 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 /// 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 /// 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 runtime = Rc::new(ScriptTask::new_rt_and_cx());
let serialized_url = url.serialize(); let serialized_url = url.serialize();
let parent_sender_for_reporter = parent_sender.clone();
let global = DedicatedWorkerGlobalScope::new( let global = DedicatedWorkerGlobalScope::new(
url, id, mem_profiler_chan.clone(), devtools_chan, runtime.clone(), resource_task, url, id, mem_profiler_chan.clone(), devtools_chan, runtime.clone(), resource_task,
parent_sender, own_sender, receiver); 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 // Register this task as a memory reporter. This needs to be done within the
// scope of `_ar` otherwise script_chan_as_reporter() will panic. // scope of `_ar` otherwise script_chan_as_reporter() will panic.
let reporter = global.script_chan_as_reporter(); let (reporter_sender, reporter_receiver) = ipc::channel().unwrap();
let msg = mem::ProfilerMsg::RegisterReporter(reporter_name.clone(), reporter); ROUTER.add_route(reporter_receiver.to_opaque(), box move |reporter_request| {
mem_profiler_chan.send(msg); // 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 { loop {
@ -230,7 +233,6 @@ impl DedicatedWorkerGlobalScope {
pub trait DedicatedWorkerGlobalScopeHelpers { pub trait DedicatedWorkerGlobalScopeHelpers {
fn script_chan(self) -> Box<ScriptChan+Send>; fn script_chan(self) -> Box<ScriptChan+Send>;
fn script_chan_as_reporter(self) -> Box<Reporter+Send>;
fn pipeline(self) -> PipelineId; fn pipeline(self) -> PipelineId;
fn new_script_pair(self) -> (Box<ScriptChan+Send>, Box<ScriptPort+Send>); fn new_script_pair(self) -> (Box<ScriptChan+Send>, Box<ScriptPort+Send>);
fn process_event(self, msg: ScriptMsg); 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 { fn pipeline(self) -> PipelineId {
self.id self.id
} }

View file

@ -18,7 +18,7 @@ use msg::constellation_msg::{WindowSizeData};
use msg::compositor_msg::Epoch; use msg::compositor_msg::Epoch;
use net_traits::image_cache_task::ImageCacheTask; use net_traits::image_cache_task::ImageCacheTask;
use net_traits::PendingAsyncLoad; use net_traits::PendingAsyncLoad;
use profile_traits::mem::{Reporter, ReportsChan}; use profile_traits::mem::ReportsChan;
use script_traits::{ConstellationControlMsg, LayoutControlMsg, ScriptControlChan}; use script_traits::{ConstellationControlMsg, LayoutControlMsg, ScriptControlChan};
use script_traits::{OpaqueScriptLayoutChannel, StylesheetLoadResponder, UntrustedNodeAddress}; use script_traits::{OpaqueScriptLayoutChannel, StylesheetLoadResponder, UntrustedNodeAddress};
use std::any::Any; 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 /// 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. /// to expose the message type to crates that don't need to know about them.
pub trait ScriptLayoutChan { pub trait ScriptLayoutChan {

View file

@ -70,7 +70,7 @@ use net_traits::{ResourceTask, LoadConsumer, ControlMsg, Metadata};
use net_traits::LoadData as NetLoadData; use net_traits::LoadData as NetLoadData;
use net_traits::image_cache_task::{ImageCacheChan, ImageCacheTask, ImageCacheResult}; use net_traits::image_cache_task::{ImageCacheChan, ImageCacheTask, ImageCacheResult};
use net_traits::storage_task::StorageTask; 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 string_cache::Atom;
use util::str::DOMString; use util::str::DOMString;
use util::task::spawn_named_with_send_on_failure; use util::task::spawn_named_with_send_on_failure;
@ -79,6 +79,8 @@ use util::task_state;
use euclid::Rect; use euclid::Rect;
use euclid::point::Point2D; use euclid::point::Point2D;
use hyper::header::{LastModified, Headers}; use hyper::header::{LastModified, Headers};
use ipc_channel::ipc;
use ipc_channel::router::ROUTER;
use js::glue::CollectServoSizes; use js::glue::CollectServoSizes;
use js::jsapi::{JS_SetWrapObjectCallbacks, JS_AddExtraGCRootsTracer, DisableIncrementalGC}; use js::jsapi::{JS_SetWrapObjectCallbacks, JS_AddExtraGCRootsTracer, DisableIncrementalGC};
use js::jsapi::{JSContext, JSRuntime, JSTracer}; use js::jsapi::{JSContext, JSRuntime, JSTracer};
@ -252,18 +254,6 @@ impl NonWorkerScriptChan {
let (chan, port) = channel(); let (chan, port) = channel();
(port, box NonWorkerScriptChan(chan)) (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; pub struct StackRootTLS;
@ -420,7 +410,7 @@ impl ScriptTaskFactory for ScriptTask {
let roots = RootCollection::new(); let roots = RootCollection::new();
let _stack_roots_tls = StackRootTLS::new(&roots); let _stack_roots_tls = StackRootTLS::new(&roots);
let chan = NonWorkerScriptChan(script_chan); let chan = NonWorkerScriptChan(script_chan);
let reporter = chan.clone_as_reporter(); let channel_for_reporter = chan.clone();
let script_task = ScriptTask::new(compositor, let script_task = ScriptTask::new(compositor,
script_port, script_port,
chan, chan,
@ -445,6 +435,14 @@ impl ScriptTaskFactory for ScriptTask {
// Register this task as a memory reporter. // Register this task as a memory reporter.
let reporter_name = format!("script-reporter-{}", id.0); 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); let msg = mem::ProfilerMsg::RegisterReporter(reporter_name.clone(), reporter);
mem_profiler_chan.send(msg); mem_profiler_chan.send(msg);

View file

@ -437,6 +437,7 @@ dependencies = [
"freetype 0.1.0 (git+https://github.com/servo/rust-freetype)", "freetype 0.1.0 (git+https://github.com/servo/rust-freetype)",
"gfx_traits 0.0.1", "gfx_traits 0.0.1",
"harfbuzz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "layers 0.1.0 (git+https://github.com/servo/rust-layers)",
"libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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" name = "profile"
version = "0.0.1" version = "0.0.1"
dependencies = [ 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)", "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)", "log 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"profile_traits 0.0.1", "profile_traits 0.0.1",
@ -1062,6 +1064,9 @@ dependencies = [
name = "profile_traits" name = "profile_traits"
version = "0.0.1" version = "0.0.1"
dependencies = [ 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)", "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)", "url 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -1221,7 +1226,7 @@ dependencies = [
[[package]] [[package]]
name = "serde_codegen" name = "serde_codegen"
version = "0.4.2" version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"aster 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "aster 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1234,7 +1239,7 @@ name = "serde_macros"
version = "0.4.1" version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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]] [[package]]

9
ports/cef/Cargo.lock generated
View file

@ -436,6 +436,7 @@ dependencies = [
"freetype 0.1.0 (git+https://github.com/servo/rust-freetype)", "freetype 0.1.0 (git+https://github.com/servo/rust-freetype)",
"gfx_traits 0.0.1", "gfx_traits 0.0.1",
"harfbuzz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "layers 0.1.0 (git+https://github.com/servo/rust-layers)",
"libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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" name = "profile"
version = "0.0.1" version = "0.0.1"
dependencies = [ 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)", "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)", "log 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"profile_traits 0.0.1", "profile_traits 0.0.1",
@ -1041,6 +1043,9 @@ dependencies = [
name = "profile_traits" name = "profile_traits"
version = "0.0.1" version = "0.0.1"
dependencies = [ 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)", "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)", "url 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -1192,7 +1197,7 @@ dependencies = [
[[package]] [[package]]
name = "serde_codegen" name = "serde_codegen"
version = "0.4.2" version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"aster 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "aster 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1205,7 +1210,7 @@ name = "serde_macros"
version = "0.4.1" version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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]] [[package]]

9
ports/gonk/Cargo.lock generated
View file

@ -415,6 +415,7 @@ dependencies = [
"freetype 0.1.0 (git+https://github.com/servo/rust-freetype)", "freetype 0.1.0 (git+https://github.com/servo/rust-freetype)",
"gfx_traits 0.0.1", "gfx_traits 0.0.1",
"harfbuzz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "layers 0.1.0 (git+https://github.com/servo/rust-layers)",
"libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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" name = "profile"
version = "0.0.1" version = "0.0.1"
dependencies = [ 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)", "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)", "log 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"profile_traits 0.0.1", "profile_traits 0.0.1",
@ -949,6 +951,9 @@ dependencies = [
name = "profile_traits" name = "profile_traits"
version = "0.0.1" version = "0.0.1"
dependencies = [ 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)", "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)", "url 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -1100,7 +1105,7 @@ dependencies = [
[[package]] [[package]]
name = "serde_codegen" name = "serde_codegen"
version = "0.4.2" version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"aster 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "aster 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1113,7 +1118,7 @@ name = "serde_macros"
version = "0.4.1" version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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]] [[package]]