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

@ -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
}

View file

@ -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 {

View file

@ -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);