diff options
author | Nakul Jindal <nakul02@gmail.com> | 2018-02-26 09:07:08 -0800 |
---|---|---|
committer | Nakul Jindal <nakul02@gmail.com> | 2018-03-22 11:48:27 -0700 |
commit | 7d4e2b11e940545eaa74877b75908e1e02f6eeb5 (patch) | |
tree | ca44de813d0bf3ca11c8bd2e914a4af4a373955f | |
parent | 563f0ec8245d6ff4d7d200c30655f90f5bdfed64 (diff) | |
download | servo-7d4e2b11e940545eaa74877b75908e1e02f6eeb5.tar.gz servo-7d4e2b11e940545eaa74877b75908e1e02f6eeb5.zip |
Implements profiler for blocked recv
27 files changed, 176 insertions, 58 deletions
diff --git a/Cargo.lock b/Cargo.lock index 3bd64a6ef46..0796e39564e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2258,12 +2258,14 @@ dependencies = [ "profile 0.0.1", "profile_traits 0.0.1", "servo_allocator 0.0.1", + "servo_config 0.0.1", ] [[package]] name = "profile_traits" version = "0.0.1" dependencies = [ + "bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "energy-monitor 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "energymon 0.3.0 (git+https://github.com/energymon/energymon-rust.git)", "ipc-channel 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/components/profile/time.rs b/components/profile/time.rs index c075272fbc0..6c1130345e0 100644 --- a/components/profile/time.rs +++ b/components/profile/time.rs @@ -10,7 +10,7 @@ use influent::create_client; use influent::measurement::{Measurement, Value}; use ipc_channel::ipc::{self, IpcReceiver}; use profile_traits::energy::{energy_interval_ms, read_energy_uj}; -use profile_traits::time::{ProfilerCategory, ProfilerChan, ProfilerMsg, TimerMetadata}; +use profile_traits::time::{ProfilerCategory, ProfilerChan, ProfilerMsg, ProfilerData, TimerMetadata}; use profile_traits::time::{TimerMetadataFrameType, TimerMetadataReflowType}; use servo_config::opts::OutputOptions; use std::{f64, thread, u32, u64}; @@ -158,6 +158,7 @@ impl Formattable for ProfilerCategory { ProfilerCategory::TimeToFirstPaint => "Time To First Paint", ProfilerCategory::TimeToFirstContentfulPaint => "Time To First Contentful Paint", ProfilerCategory::TimeToInteractive => "Time to Interactive", + ProfilerCategory::IpcReceiver => "Blocked at IPC Receive", ProfilerCategory::ApplicationHeartbeat => "Application Heartbeat", }; format!("{}{}", padding, name) @@ -316,6 +317,13 @@ impl Profiler { // only print if more data has arrived since the last printout self.print_buckets(); }, + ProfilerMsg::Get(k, sender) => { + let vec_option = self.buckets.get(&k); + match vec_option { + Some(vec_entry) => sender.send(ProfilerData::Record(vec_entry.to_vec())).unwrap(), + None => sender.send(ProfilerData::NoRecords).unwrap(), + }; + }, ProfilerMsg::Exit(chan) => { heartbeats::cleanup(); self.print_buckets(); diff --git a/components/profile_traits/Cargo.toml b/components/profile_traits/Cargo.toml index 2a36c9d8208..3ea12bd6cfc 100644 --- a/components/profile_traits/Cargo.toml +++ b/components/profile_traits/Cargo.toml @@ -13,6 +13,7 @@ path = "lib.rs" energy-profiling = ["energymon", "energy-monitor"] [dependencies] +bincode = "1" energy-monitor = {version = "0.2.0", optional = true} energymon = {git = "https://github.com/energymon/energymon-rust.git", optional = true} ipc-channel = "0.10" diff --git a/components/profile_traits/ipc.rs b/components/profile_traits/ipc.rs new file mode 100644 index 00000000000..fe64d54ef07 --- /dev/null +++ b/components/profile_traits/ipc.rs @@ -0,0 +1,45 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use bincode; +use ipc_channel::ipc; +use serde::{Deserialize, Serialize}; +use std::io::Error; +use time; +use time::ProfilerCategory; +use time::ProfilerChan; + +pub struct IpcReceiver<T> where T: for<'de> Deserialize<'de> + Serialize { + ipc_receiver: ipc::IpcReceiver<T>, + time_profile_chan: ProfilerChan, +} + +impl<T> IpcReceiver<T> where T: for<'de> Deserialize<'de> + Serialize { + pub fn recv(&self) -> Result<T, bincode::Error> { + time::profile( + ProfilerCategory::IpcReceiver, + None, + self.time_profile_chan.clone(), + move || self.ipc_receiver.recv(), + ) + } + + pub fn try_recv(&self) -> Result<T, bincode::Error> { + self.ipc_receiver.try_recv() + } + + pub fn to_opaque(self) -> ipc::OpaqueIpcReceiver { + self.ipc_receiver.to_opaque() + } +} + +pub fn channel<T>(time_profile_chan: ProfilerChan) -> Result<(ipc::IpcSender<T>, IpcReceiver<T>), Error> + where T: for<'de> Deserialize<'de> + Serialize, { + let (ipc_sender, ipc_receiver) = ipc::channel()?; + let profiled_ipc_receiver = IpcReceiver { + ipc_receiver, + time_profile_chan, + }; + Ok((ipc_sender, profiled_ipc_receiver)) +} diff --git a/components/profile_traits/lib.rs b/components/profile_traits/lib.rs index 5f2683adcdc..029e59a3241 100644 --- a/components/profile_traits/lib.rs +++ b/components/profile_traits/lib.rs @@ -8,6 +8,7 @@ #![deny(unsafe_code)] +extern crate bincode; extern crate ipc_channel; #[macro_use] extern crate log; @@ -17,5 +18,6 @@ extern crate signpost; #[allow(unsafe_code)] pub mod energy; +pub mod ipc; pub mod mem; pub mod time; diff --git a/components/profile_traits/time.rs b/components/profile_traits/time.rs index 3b9316f9478..2c297003b9e 100644 --- a/components/profile_traits/time.rs +++ b/components/profile_traits/time.rs @@ -29,9 +29,17 @@ impl ProfilerChan { } #[derive(Clone, Deserialize, Serialize)] +pub enum ProfilerData { + NoRecords, + Record(Vec<f64>), +} + +#[derive(Clone, Deserialize, Serialize)] pub enum ProfilerMsg { /// Normal message used for reporting time Time((ProfilerCategory, Option<TimerMetadata>), (u64, u64), (u64, u64)), + /// Message used to get time spend entries for a particular ProfilerBuckets (in nanoseconds) + Get((ProfilerCategory, Option<TimerMetadata>), IpcSender<ProfilerData>), /// Message used to force print the profiling metrics Print, /// Tells the profiler to shut down. @@ -94,6 +102,7 @@ pub enum ProfilerCategory { TimeToFirstPaint = 0x80, TimeToFirstContentfulPaint = 0x81, TimeToInteractive = 0x82, + IpcReceiver = 0x83, ApplicationHeartbeat = 0x90, } diff --git a/components/script/dom/blob.rs b/components/script/dom/blob.rs index beb7ed69df3..d8017f23ffa 100644 --- a/components/script/dom/blob.rs +++ b/components/script/dom/blob.rs @@ -12,10 +12,10 @@ use dom::bindings::root::{Dom, DomRoot}; use dom::bindings::str::DOMString; use dom::globalscope::GlobalScope; use dom_struct::dom_struct; -use ipc_channel::ipc; use net_traits::{CoreResourceMsg, IpcSend}; use net_traits::blob_url_store::{BlobBuf, get_blob_origin}; use net_traits::filemanager_thread::{FileManagerThreadMsg, ReadFileProgress, RelativePos}; +use profile_traits::ipc; use std::mem; use std::ops::Index; use std::path::PathBuf; @@ -200,7 +200,7 @@ impl Blob { BlobImpl::File(ref f) => { if set_valid { let origin = get_blob_origin(&global_url); - let (tx, rx) = ipc::channel().unwrap(); + let (tx, rx) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap(); let msg = FileManagerThreadMsg::ActivateBlobURL(f.id.clone(), tx, origin.clone()); self.send_to_file_manager(msg); @@ -227,7 +227,7 @@ impl Blob { bytes: bytes.to_vec(), }; - let (tx, rx) = ipc::channel().unwrap(); + let (tx, rx) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap(); let msg = FileManagerThreadMsg::PromoteMemory(blob_buf, set_valid, tx, origin.clone()); self.send_to_file_manager(msg); @@ -251,7 +251,7 @@ impl Blob { rel_pos: &RelativePos, parent_len: u64) -> Uuid { let origin = get_blob_origin(&self.global().get_url()); - let (tx, rx) = ipc::channel().unwrap(); + let (tx, rx) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap(); let msg = FileManagerThreadMsg::AddSlicedURLEntry(parent_id.clone(), rel_pos.clone(), tx, origin.clone()); @@ -280,7 +280,7 @@ impl Blob { if let BlobImpl::File(ref f) = *self.blob_impl.borrow() { let origin = get_blob_origin(&self.global().get_url()); - let (tx, rx) = ipc::channel().unwrap(); + let (tx, rx) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap(); let msg = FileManagerThreadMsg::DecRef(f.id.clone(), origin, tx); self.send_to_file_manager(msg); @@ -303,7 +303,7 @@ impl Drop for Blob { fn read_file(global: &GlobalScope, id: Uuid) -> Result<Vec<u8>, ()> { let resource_threads = global.resource_threads(); - let (chan, recv) = ipc::channel().map_err(|_|())?; + let (chan, recv) = ipc::channel(global.time_profiler_chan().clone()).map_err(|_|())?; let origin = get_blob_origin(&global.get_url()); let check_url_validity = false; let msg = FileManagerThreadMsg::ReadFile(chan, id, check_url_validity, origin); diff --git a/components/script/dom/bluetooth.rs b/components/script/dom/bluetooth.rs index 44cf83df5d8..e0dd0f00e10 100644 --- a/components/script/dom/bluetooth.rs +++ b/components/script/dom/bluetooth.rs @@ -34,6 +34,7 @@ use ipc_channel::router::ROUTER; use js::conversions::ConversionResult; use js::jsapi::{JSContext, JSObject}; use js::jsval::{ObjectValue, UndefinedValue}; +use profile_traits::ipc as ProfiledIpc; use std::cell::Ref; use std::collections::HashMap; use std::rc::Rc; @@ -613,7 +614,7 @@ impl PermissionAlgorithm for Bluetooth { // Step 6.2.2. // Instead of creating an internal slot we send an ipc message to the Bluetooth thread // to check if one of the filters matches. - let (sender, receiver) = ipc::channel().unwrap(); + let (sender, receiver) = ProfiledIpc::channel(global.time_profiler_chan().clone()).unwrap(); status.get_bluetooth_thread() .send(BluetoothRequest::MatchesFilter(device_id.clone(), BluetoothScanfilterSequence::new(scan_filters), diff --git a/components/script/dom/bluetoothdevice.rs b/components/script/dom/bluetoothdevice.rs index 6fcdf40f3ff..b8e08618960 100644 --- a/components/script/dom/bluetoothdevice.rs +++ b/components/script/dom/bluetoothdevice.rs @@ -24,7 +24,8 @@ use dom::eventtarget::EventTarget; use dom::globalscope::GlobalScope; use dom::promise::Promise; use dom_struct::dom_struct; -use ipc_channel::ipc::{self, IpcSender}; +use ipc_channel::ipc::IpcSender; +use profile_traits::ipc; use std::cell::Cell; use std::collections::HashMap; use std::rc::Rc; @@ -129,7 +130,7 @@ impl BluetoothDevice { } pub fn is_represented_device_null(&self) -> bool { - let (sender, receiver) = ipc::channel().unwrap(); + let (sender, receiver) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap(); self.get_bluetooth_thread().send( BluetoothRequest::IsRepresentedDeviceNull(self.Id().to_string(), sender)).unwrap(); receiver.recv().unwrap() @@ -204,7 +205,7 @@ impl BluetoothDevice { } // Step 3. - let (sender, receiver) = ipc::channel().unwrap(); + let (sender, receiver) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap(); self.get_bluetooth_thread().send( BluetoothRequest::GATTServerDisconnect(String::from(self.Id()), sender)).unwrap(); receiver.recv().unwrap().map_err(Error::from) diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 1e2278e81ca..a837fc02fd7 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -32,7 +32,7 @@ use dom::imagedata::ImageData; use dom::node::{Node, NodeDamage, window_from_node}; use dom_struct::dom_struct; use euclid::{Transform2D, Point2D, Vector2D, Rect, Size2D, vec2}; -use ipc_channel::ipc::{self, IpcSender}; +use ipc_channel::ipc::IpcSender; use net_traits::image::base::PixelFormat; use net_traits::image_cache::CanRequestImages; use net_traits::image_cache::ImageCache; @@ -41,6 +41,7 @@ use net_traits::image_cache::ImageResponse; use net_traits::image_cache::ImageState; use net_traits::image_cache::UsePlaceholder; use num_traits::ToPrimitive; +use profile_traits::ipc; use script_traits::ScriptMsg; use servo_url::ServoUrl; use std::{cmp, fmt, mem}; @@ -128,7 +129,7 @@ impl CanvasRenderingContext2D { size: Size2D<i32>) -> CanvasRenderingContext2D { debug!("Creating new canvas rendering context."); - let (sender, receiver) = ipc::channel().unwrap(); + let (sender, receiver) = ipc::channel(global.time_profiler_chan().clone()).unwrap(); let script_to_constellation_chan = global.script_to_constellation_chan(); debug!("Asking constellation to create new canvas thread."); script_to_constellation_chan.send(ScriptMsg::CreateCanvasPaintThread(size, sender)).unwrap(); @@ -371,7 +372,7 @@ impl CanvasRenderingContext2D { None => return Err(Error::InvalidState), }; - let (sender, receiver) = ipc::channel().unwrap(); + let (sender, receiver) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap(); let msg = CanvasMsg::Canvas2d(Canvas2dMsg::DrawImageInOther( self.ipc_renderer.clone(), image_size, @@ -782,7 +783,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { CanvasFillRule::Nonzero => FillRule::Nonzero, CanvasFillRule::Evenodd => FillRule::Evenodd, }; - let (sender, receiver) = ipc::channel::<bool>().unwrap(); + let (sender, receiver) = ipc::channel::<bool>(self.global().time_profiler_chan().clone()).unwrap(); self.ipc_renderer .send(CanvasMsg::Canvas2d(Canvas2dMsg::IsPointInPath(x, y, fill_rule, sender))) .unwrap(); @@ -1126,7 +1127,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { let sh = cmp::max(1, sh.to_u32().unwrap()); let sw = cmp::max(1, sw.to_u32().unwrap()); - let (sender, receiver) = ipc::channel::<Vec<u8>>().unwrap(); + let (sender, receiver) = ipc::channel::<Vec<u8>>(self.global().time_profiler_chan().clone()).unwrap(); let dest_rect = Rect::new(Point2D::new(sx.to_i32().unwrap(), sy.to_i32().unwrap()), Size2D::new(sw as i32, sh as i32)); let canvas_size = self.canvas.as_ref().map(|c| c.get_size()).unwrap_or(Size2D::zero()); diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index 6895a71fddb..b1cee370bfe 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -93,7 +93,7 @@ use fetch::FetchCanceller; use html5ever::{LocalName, Namespace, QualName}; use hyper::header::{Header, SetCookie}; use hyper_serde::Serde; -use ipc_channel::ipc::{self, IpcSender}; +use ipc_channel::ipc::IpcSender; use js::jsapi::{JSContext, JSObject, JSRuntime}; use js::jsapi::JS_GetRuntime; use metrics::{InteractiveFlag, InteractiveMetrics, InteractiveWindow, ProfilerMetadataFactory, ProgressiveWebMetric}; @@ -106,6 +106,7 @@ use net_traits::pub_domains::is_pub_domain; use net_traits::request::RequestInit; use net_traits::response::HttpsState; use num_traits::ToPrimitive; +use profile_traits::ipc; use profile_traits::time::{TimerMetadata, TimerMetadataFrameType, TimerMetadataReflowType}; use ref_slice::ref_slice; use script_layout_interface::message::{Msg, NodesFromPointQueryType, ReflowGoal}; @@ -3448,7 +3449,7 @@ impl DocumentMethods for Document { } let url = self.url(); - let (tx, rx) = ipc::channel().unwrap(); + let (tx, rx) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap(); let _ = self.window .upcast::<GlobalScope>() .resource_threads() diff --git a/components/script/dom/history.rs b/components/script/dom/history.rs index 17ee0d29cb6..d70c58963b5 100644 --- a/components/script/dom/history.rs +++ b/components/script/dom/history.rs @@ -8,17 +8,17 @@ use dom::bindings::codegen::Bindings::LocationBinding::LocationBinding::Location use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; use dom::bindings::error::{Error, ErrorResult, Fallible}; use dom::bindings::inheritance::Castable; -use dom::bindings::reflector::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object}; use dom::bindings::root::{Dom, DomRoot}; use dom::bindings::str::{DOMString, USVString}; use dom::bindings::structuredclone::StructuredCloneData; use dom::globalscope::GlobalScope; use dom::window::Window; use dom_struct::dom_struct; -use ipc_channel::ipc; use js::jsapi::{HandleValue, Heap, JSContext}; use js::jsval::{JSVal, NullValue, UndefinedValue}; use msg::constellation_msg::TraversalDirection; +use profile_traits::ipc::channel; use script_traits::ScriptMsg; enum PushOrReplace { @@ -128,7 +128,8 @@ impl HistoryMethods for History { if !self.window.Document().is_fully_active() { return Err(Error::Security); } - let (sender, recv) = ipc::channel().expect("Failed to create channel to send jsh length."); + let (sender, recv) = + channel(self.global().time_profiler_chan().clone()).expect("Failed to create channel to send jsh length."); let msg = ScriptMsg::JointSessionHistoryLength(sender); let _ = self.window.upcast::<GlobalScope>().script_to_constellation_chan().send(msg); Ok(recv.recv().unwrap()) diff --git a/components/script/dom/htmlcanvaselement.rs b/components/script/dom/htmlcanvaselement.rs index 9496670238b..c866664cbcf 100644 --- a/components/script/dom/htmlcanvaselement.rs +++ b/components/script/dom/htmlcanvaselement.rs @@ -15,6 +15,7 @@ use dom::bindings::conversions::ConversionResult; use dom::bindings::error::{Error, Fallible}; use dom::bindings::inheritance::Castable; use dom::bindings::num::Finite; +use dom::bindings::reflector::DomObject; use dom::bindings::root::{Dom, DomRoot, LayoutDom}; use dom::bindings::str::DOMString; use dom::canvasrenderingcontext2d::{CanvasRenderingContext2D, LayoutCanvasRenderingContext2DHelpers}; @@ -31,10 +32,10 @@ use euclid::Size2D; use html5ever::{LocalName, Prefix}; use image::ColorType; use image::png::PNGEncoder; -use ipc_channel::ipc; use js::error::throw_type_error; use js::jsapi::{HandleValue, JSContext}; use offscreen_gl_context::GLContextAttributes; +use profile_traits::ipc; use script_layout_interface::{HTMLCanvasData, HTMLCanvasDataSource}; use servo_config::prefs::PREFS; use std::iter::repeat; @@ -258,7 +259,7 @@ impl HTMLCanvasElement { let data = match self.context.borrow().as_ref() { Some(&CanvasContext::Context2d(ref context)) => { - let (sender, receiver) = ipc::channel().unwrap(); + let (sender, receiver) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap(); let msg = CanvasMsg::FromScript(FromScriptMsg::SendPixels(sender)); context.get_ipc_renderer().send(msg).unwrap(); diff --git a/components/script/dom/htmliframeelement.rs b/components/script/dom/htmliframeelement.rs index 41bb2a23e6a..4fcd21c6cf1 100644 --- a/components/script/dom/htmliframeelement.rs +++ b/components/script/dom/htmliframeelement.rs @@ -27,6 +27,7 @@ use dom_struct::dom_struct; use html5ever::{LocalName, Prefix}; use ipc_channel::ipc; use msg::constellation_msg::{BrowsingContextId, PipelineId, TopLevelBrowsingContextId}; +use profile_traits::ipc as ProfiledIpc; use script_layout_interface::message::ReflowGoal; use script_thread::ScriptThread; use script_traits::{IFrameLoadInfo, IFrameLoadInfoWithData, JsEvalResult, LoadData, UpdatePipelineIdReason}; @@ -559,7 +560,7 @@ impl VirtualMethods for HTMLIFrameElement { // https://html.spec.whatwg.org/multipage/#a-browsing-context-is-discarded let window = window_from_node(self); - let (sender, receiver) = ipc::channel().unwrap(); + let (sender, receiver) = ProfiledIpc::channel(self.global().time_profiler_chan().clone()).unwrap(); // Ask the constellation to remove the iframe, and tell us the // pipeline ids of the closed pipelines. diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs index 030d6278e0e..5618b366702 100755 --- a/components/script/dom/htmlinputelement.rs +++ b/components/script/dom/htmlinputelement.rs @@ -14,6 +14,7 @@ use dom::bindings::codegen::Bindings::HTMLInputElementBinding::HTMLInputElementM use dom::bindings::codegen::Bindings::KeyboardEventBinding::KeyboardEventMethods; use dom::bindings::error::{Error, ErrorResult}; use dom::bindings::inheritance::Castable; +use dom::bindings::reflector::DomObject; use dom::bindings::root::{Dom, DomRoot, LayoutDom, MutNullableDom, RootedReference}; use dom::bindings::str::DOMString; use dom::document::Document; @@ -38,11 +39,11 @@ use dom::validitystate::ValidationFlags; use dom::virtualmethods::VirtualMethods; use dom_struct::dom_struct; use html5ever::{LocalName, Prefix}; -use ipc_channel::ipc::channel; use mime_guess; use net_traits::{CoreResourceMsg, IpcSend}; use net_traits::blob_url_store::get_blob_origin; use net_traits::filemanager_thread::{FileManagerThreadMsg, FilterPattern}; +use profile_traits::ipc; use script_layout_interface::rpc::TextIndexResponse; use script_traits::ScriptToConstellationChan; use servo_atoms::Atom; @@ -974,7 +975,8 @@ impl HTMLInputElement { if self.Multiple() { let opt_test_paths = opt_test_paths.map(|paths| paths.iter().map(|p| p.to_string()).collect()); - let (chan, recv) = channel().expect("Error initializing channel"); + let (chan, recv) = + ipc::channel(self.global().time_profiler_chan().clone()).expect("Error initializing channel"); let msg = FileManagerThreadMsg::SelectFiles(filter, chan, origin, opt_test_paths); let _ = resource_threads.send(CoreResourceMsg::ToFileManager(msg)).unwrap(); @@ -998,7 +1000,8 @@ impl HTMLInputElement { None => None, }; - let (chan, recv) = channel().expect("Error initializing channel"); + let (chan, recv) = + ipc::channel(self.global().time_profiler_chan().clone()).expect("Error initializing channel"); let msg = FileManagerThreadMsg::SelectFile(filter, chan, origin, opt_test_path); let _ = resource_threads.send(CoreResourceMsg::ToFileManager(msg)).unwrap(); diff --git a/components/script/dom/paintworkletglobalscope.rs b/components/script/dom/paintworkletglobalscope.rs index eda9021e64c..3665b4af089 100644 --- a/components/script/dom/paintworkletglobalscope.rs +++ b/components/script/dom/paintworkletglobalscope.rs @@ -26,7 +26,6 @@ use dom::workletglobalscope::WorkletTask; use dom_struct::dom_struct; use euclid::TypedScale; use euclid::TypedSize2D; -use ipc_channel::ipc; use js::jsapi::Call; use js::jsapi::Construct1; use js::jsapi::HandleValue; @@ -46,6 +45,7 @@ use js::rust::Runtime; use msg::constellation_msg::PipelineId; use net_traits::image::base::PixelFormat; use net_traits::image_cache::ImageCache; +use profile_traits::ipc; use script_traits::{DrawAPaintImageResult, PaintWorkletError}; use script_traits::Painter; use servo_atoms::Atom; @@ -296,7 +296,8 @@ impl PaintWorkletGlobalScope { return self.invalid_image(size_in_dpx, missing_image_urls); } - let (sender, receiver) = ipc::channel().expect("IPC channel creation."); + let (sender, receiver) = + ipc::channel(self.global().time_profiler_chan().clone()).expect("IPC channel creation."); rendering_context.send_data(sender); let image_key = match receiver.recv() { Ok(data) => Some(data.image_key), diff --git a/components/script/dom/screen.rs b/components/script/dom/screen.rs index e83cffd93a4..193b7705a42 100644 --- a/components/script/dom/screen.rs +++ b/components/script/dom/screen.rs @@ -7,12 +7,13 @@ use dom::bindings::codegen::Bindings::ScreenBinding::ScreenMethods; use dom::bindings::inheritance::Castable; use dom::bindings::num::Finite; use dom::bindings::reflector::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::DomObject; use dom::bindings::root::{Dom, DomRoot}; use dom::globalscope::GlobalScope; use dom::window::Window; use dom_struct::dom_struct; use euclid::TypedSize2D; -use ipc_channel::ipc; +use profile_traits::ipc; use script_traits::ScriptMsg; use style_traits::CSSPixel; use webrender_api::DeviceUintSize; @@ -38,7 +39,7 @@ impl Screen { } fn screen_size(&self) -> TypedSize2D<u32, CSSPixel> { - let (send, recv) = ipc::channel::<DeviceUintSize>().unwrap(); + let (send, recv) = ipc::channel::<DeviceUintSize>(self.global().time_profiler_chan().clone()).unwrap(); self.window.upcast::<GlobalScope>() .script_to_constellation_chan().send(ScriptMsg::GetScreenSize(send)).unwrap(); let dpr = self.window.device_pixel_ratio(); @@ -47,7 +48,7 @@ impl Screen { } fn screen_avail_size(&self) -> TypedSize2D<u32, CSSPixel> { - let (send, recv) = ipc::channel::<DeviceUintSize>().unwrap(); + let (send, recv) = ipc::channel::<DeviceUintSize>(self.global().time_profiler_chan().clone()).unwrap(); self.window.upcast::<GlobalScope>() .script_to_constellation_chan().send(ScriptMsg::GetScreenAvailSize(send)).unwrap(); let dpr = self.window.device_pixel_ratio(); diff --git a/components/script/dom/storage.rs b/components/script/dom/storage.rs index 37ff6a69fe3..b2c3783c010 100644 --- a/components/script/dom/storage.rs +++ b/components/script/dom/storage.rs @@ -14,9 +14,10 @@ use dom::event::{Event, EventBubbles, EventCancelable}; use dom::storageevent::StorageEvent; use dom::window::Window; use dom_struct::dom_struct; -use ipc_channel::ipc::{self, IpcSender}; +use ipc_channel::ipc::IpcSender; use net_traits::IpcSend; use net_traits::storage_thread::{StorageThreadMsg, StorageType}; +use profile_traits::ipc; use script_traits::ScriptMsg; use servo_url::ServoUrl; use task_source::TaskSource; @@ -52,7 +53,7 @@ impl Storage { impl StorageMethods for Storage { // https://html.spec.whatwg.org/multipage/#dom-storage-length fn Length(&self) -> u32 { - let (sender, receiver) = ipc::channel().unwrap(); + let (sender, receiver) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap(); self.get_storage_thread().send(StorageThreadMsg::Length(sender, self.get_url(), self.storage_type)).unwrap(); receiver.recv().unwrap() as u32 @@ -60,7 +61,7 @@ impl StorageMethods for Storage { // https://html.spec.whatwg.org/multipage/#dom-storage-key fn Key(&self, index: u32) -> Option<DOMString> { - let (sender, receiver) = ipc::channel().unwrap(); + let (sender, receiver) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap(); self.get_storage_thread() .send(StorageThreadMsg::Key(sender, self.get_url(), self.storage_type, index)) @@ -70,7 +71,7 @@ impl StorageMethods for Storage { // https://html.spec.whatwg.org/multipage/#dom-storage-getitem fn GetItem(&self, name: DOMString) -> Option<DOMString> { - let (sender, receiver) = ipc::channel().unwrap(); + let (sender, receiver) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap(); let name = String::from(name); let msg = StorageThreadMsg::GetItem(sender, self.get_url(), self.storage_type, name); @@ -80,7 +81,7 @@ impl StorageMethods for Storage { // https://html.spec.whatwg.org/multipage/#dom-storage-setitem fn SetItem(&self, name: DOMString, value: DOMString) -> ErrorResult { - let (sender, receiver) = ipc::channel().unwrap(); + let (sender, receiver) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap(); let name = String::from(name); let value = String::from(value); @@ -99,7 +100,7 @@ impl StorageMethods for Storage { // https://html.spec.whatwg.org/multipage/#dom-storage-removeitem fn RemoveItem(&self, name: DOMString) { - let (sender, receiver) = ipc::channel().unwrap(); + let (sender, receiver) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap(); let name = String::from(name); let msg = StorageThreadMsg::RemoveItem(sender, self.get_url(), self.storage_type, name.clone()); @@ -111,7 +112,7 @@ impl StorageMethods for Storage { // https://html.spec.whatwg.org/multipage/#dom-storage-clear fn Clear(&self) { - let (sender, receiver) = ipc::channel().unwrap(); + let (sender, receiver) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap(); self.get_storage_thread().send(StorageThreadMsg::Clear(sender, self.get_url(), self.storage_type)).unwrap(); if receiver.recv().unwrap() { @@ -121,7 +122,7 @@ impl StorageMethods for Storage { // https://html.spec.whatwg.org/multipage/#the-storage-interface:supported-property-names fn SupportedPropertyNames(&self) -> Vec<DOMString> { - let (sender, receiver) = ipc::channel().unwrap(); + let (sender, receiver) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap(); self.get_storage_thread().send(StorageThreadMsg::Keys(sender, self.get_url(), self.storage_type)).unwrap(); receiver.recv() diff --git a/components/script/dom/testrunner.rs b/components/script/dom/testrunner.rs index 84a533786b8..c29b5c477d7 100644 --- a/components/script/dom/testrunner.rs +++ b/components/script/dom/testrunner.rs @@ -11,7 +11,8 @@ use dom::bindings::root::DomRoot; use dom::bindings::str::DOMString; use dom::globalscope::GlobalScope; use dom_struct::dom_struct; -use ipc_channel::ipc::{self, IpcSender}; +use ipc_channel::ipc::IpcSender; +use profile_traits::ipc; // https://webbluetoothcg.github.io/web-bluetooth/tests#test-runner #[dom_struct] @@ -40,7 +41,7 @@ impl TestRunner { impl TestRunnerMethods for TestRunner { // https://webbluetoothcg.github.io/web-bluetooth/tests#setBluetoothMockDataSet fn SetBluetoothMockDataSet(&self, dataSetName: DOMString) -> ErrorResult { - let (sender, receiver) = ipc::channel().unwrap(); + let (sender, receiver) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap(); self.get_bluetooth_thread().send(BluetoothRequest::Test(String::from(dataSetName), sender)).unwrap(); match receiver.recv().unwrap().into() { Ok(()) => { diff --git a/components/script/dom/url.rs b/components/script/dom/url.rs index f605e717bf8..0fef2e5bb5f 100644 --- a/components/script/dom/url.rs +++ b/components/script/dom/url.rs @@ -13,10 +13,10 @@ use dom::globalscope::GlobalScope; use dom::urlhelper::UrlHelper; use dom::urlsearchparams::URLSearchParams; use dom_struct::dom_struct; -use ipc_channel::ipc; use net_traits::{CoreResourceMsg, IpcSend}; use net_traits::blob_url_store::{get_blob_origin, parse_blob_url}; use net_traits::filemanager_thread::FileManagerThreadMsg; +use profile_traits::ipc; use servo_url::ServoUrl; use std::default::Default; use uuid::Uuid; @@ -118,7 +118,7 @@ impl URL { if let Ok(url) = ServoUrl::parse(&url) { if let Ok((id, _)) = parse_blob_url(&url) { let resource_threads = global.resource_threads(); - let (tx, rx) = ipc::channel().unwrap(); + let (tx, rx) = ipc::channel(global.time_profiler_chan().clone()).unwrap(); let msg = FileManagerThreadMsg::RevokeBlobURL(id, origin, tx); let _ = resource_threads.send(CoreResourceMsg::ToFileManager(msg)); diff --git a/components/script/dom/vr.rs b/components/script/dom/vr.rs index fc3bc1c05b3..3283015dd14 100644 --- a/components/script/dom/vr.rs +++ b/components/script/dom/vr.rs @@ -19,8 +19,8 @@ use dom::promise::Promise; use dom::vrdisplay::VRDisplay; use dom::vrdisplayevent::VRDisplayEvent; use dom_struct::dom_struct; -use ipc_channel::ipc; use ipc_channel::ipc::IpcSender; +use profile_traits::ipc; use std::rc::Rc; use webvr_traits::{WebVRDisplayData, WebVRDisplayEvent, WebVREvent, WebVRMsg}; use webvr_traits::{WebVRGamepadData, WebVRGamepadEvent, WebVRGamepadState}; @@ -61,7 +61,7 @@ impl VRMethods for VR { let promise = Promise::new(&self.global()); if let Some(webvr_thread) = self.webvr_thread() { - let (sender, receiver) = ipc::channel().unwrap(); + let (sender, receiver) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap(); webvr_thread.send(WebVRMsg::GetDisplays(sender)).unwrap(); match receiver.recv().unwrap() { Ok(displays) => { @@ -234,7 +234,7 @@ impl VR { // motion capture or drawing applications. pub fn get_gamepads(&self) -> Vec<DomRoot<Gamepad>> { if let Some(wevbr_sender) = self.webvr_thread() { - let (sender, receiver) = ipc::channel().unwrap(); + let (sender, receiver) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap(); let synced_ids = self.gamepads.borrow().iter().map(|g| g.gamepad_id()).collect(); wevbr_sender.send(WebVRMsg::GetGamepads(synced_ids, sender)).unwrap(); match receiver.recv().unwrap() { diff --git a/components/script/dom/vrdisplay.rs b/components/script/dom/vrdisplay.rs index 72b8e29a15c..481f10c30b5 100644 --- a/components/script/dom/vrdisplay.rs +++ b/components/script/dom/vrdisplay.rs @@ -31,7 +31,8 @@ use dom::vrpose::VRPose; use dom::vrstageparameters::VRStageParameters; use dom::webglrenderingcontext::WebGLRenderingContext; use dom_struct::dom_struct; -use ipc_channel::ipc::{self, IpcSender}; +use ipc_channel::ipc::IpcSender; +use profile_traits::ipc; use script_runtime::CommonScriptMsg; use script_runtime::ScriptThreadEventCategory::WebVREvent; use std::cell::Cell; @@ -191,7 +192,7 @@ impl VRDisplayMethods for VRDisplay { } // If not presenting we fetch inmediante VRFrameData - let (sender, receiver) = ipc::channel().unwrap(); + let (sender, receiver) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap(); self.webvr_thread().send(WebVRMsg::GetFrameData(self.global().pipeline_id(), self.DisplayId(), self.depth_near.get(), @@ -216,7 +217,7 @@ impl VRDisplayMethods for VRDisplay { // https://w3c.github.io/webvr/#dom-vrdisplay-resetpose fn ResetPose(&self) { - let (sender, receiver) = ipc::channel().unwrap(); + let (sender, receiver) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap(); self.webvr_thread().send(WebVRMsg::ResetPose(self.global().pipeline_id(), self.DisplayId(), sender)).unwrap(); @@ -324,7 +325,7 @@ impl VRDisplayMethods for VRDisplay { } // Request Present - let (sender, receiver) = ipc::channel().unwrap(); + let (sender, receiver) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap(); self.webvr_thread().send(WebVRMsg::RequestPresent(self.global().pipeline_id(), self.display.borrow().display_id, sender)) @@ -357,7 +358,7 @@ impl VRDisplayMethods for VRDisplay { } // Exit present - let (sender, receiver) = ipc::channel().unwrap(); + let (sender, receiver) = ipc::channel(self.global().time_profiler_chan().clone()).unwrap(); self.webvr_thread().send(WebVRMsg::ExitPresent(self.global().pipeline_id(), self.display.borrow().display_id, Some(sender))) diff --git a/components/script/dom/websocket.rs b/components/script/dom/websocket.rs index df67630119b..6acb82c863c 100644 --- a/components/script/dom/websocket.rs +++ b/components/script/dom/websocket.rs @@ -29,6 +29,7 @@ use net_traits::{CoreResourceMsg, FetchChannels}; use net_traits::{WebSocketDomAction, WebSocketNetworkEvent}; use net_traits::MessageData; use net_traits::request::{RequestInit, RequestMode}; +use profile_traits::ipc as ProfiledIpc; use script_runtime::CommonScriptMsg; use script_runtime::ScriptThreadEventCategory::WebSocketEvent; use servo_url::ServoUrl; @@ -181,7 +182,8 @@ impl WebSocket { IpcReceiver<WebSocketDomAction>) = ipc::channel().unwrap(); let (resource_event_sender, dom_event_receiver): (IpcSender<WebSocketNetworkEvent>, - IpcReceiver<WebSocketNetworkEvent>) = ipc::channel().unwrap(); + ProfiledIpc::IpcReceiver<WebSocketNetworkEvent>) = + ProfiledIpc::channel(global.time_profiler_chan().clone()).unwrap(); // Step 8. let request = RequestInit { diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index 37f65f774b2..327e766e7fa 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -50,7 +50,7 @@ use dom::workletglobalscope::WorkletGlobalScopeType; use dom_struct::dom_struct; use euclid::{Point2D, Vector2D, Rect, Size2D, TypedPoint2D, TypedScale, TypedSize2D}; use fetch; -use ipc_channel::ipc::{self, IpcSender}; +use ipc_channel::ipc::IpcSender; use ipc_channel::router::ROUTER; use js::jsapi::{HandleValue, JSAutoCompartment, JSContext}; use js::jsapi::{JS_GC, JS_GetRuntime}; @@ -63,6 +63,7 @@ use net_traits::image_cache::{ImageCache, ImageResponder, ImageResponse}; use net_traits::image_cache::{PendingImageId, PendingImageResponse}; use net_traits::storage_thread::StorageType; use num_traits::ToPrimitive; +use profile_traits::ipc as ProfiledIpc; use profile_traits::mem::ProfilerChan as MemProfilerChan; use profile_traits::time::ProfilerChan as TimeProfilerChan; use script_layout_interface::{TrustedNodeAddress, PendingImageState}; @@ -540,7 +541,7 @@ impl WindowMethods for Window { stderr.flush().unwrap(); } - let (sender, receiver) = ipc::channel().unwrap(); + let (sender, receiver) = ProfiledIpc::channel(self.global().time_profiler_chan().clone()).unwrap(); self.send_to_constellation(ScriptMsg::Alert(s.to_string(), sender)); let should_display_alert_dialog = receiver.recv().unwrap(); @@ -1180,7 +1181,9 @@ impl Window { } fn client_window(&self) -> (TypedSize2D<u32, CSSPixel>, TypedPoint2D<i32, CSSPixel>) { - let (send, recv) = ipc::channel::<(DeviceUintSize, DeviceIntPoint)>().unwrap(); + let timer_profile_chan = self.global().time_profiler_chan().clone(); + let (send, recv) = + ProfiledIpc::channel::<(DeviceUintSize, DeviceIntPoint)>(timer_profile_chan).unwrap(); self.send_to_constellation(ScriptMsg::GetClientWindow(send)); let (size, point) = recv.recv().unwrap_or((TypedSize2D::zero(), TypedPoint2D::zero())); let dpr = self.device_pixel_ratio(); @@ -1300,7 +1303,8 @@ impl Window { let mut images = self.pending_layout_images.borrow_mut(); let nodes = images.entry(id).or_insert(vec![]); if nodes.iter().find(|n| &***n as *const _ == &*node as *const _).is_none() { - let (responder, responder_listener) = ipc::channel().unwrap(); + let (responder, responder_listener) = + ProfiledIpc::channel(self.global().time_profiler_chan().clone()).unwrap(); let pipeline = self.upcast::<GlobalScope>().pipeline_id(); let image_cache_chan = self.image_cache_chan.clone(); ROUTER.add_route(responder_listener.to_opaque(), Box::new(move |message| { diff --git a/tests/unit/profile/Cargo.toml b/tests/unit/profile/Cargo.toml index dbb565d2b78..d3feb410884 100644 --- a/tests/unit/profile/Cargo.toml +++ b/tests/unit/profile/Cargo.toml @@ -16,3 +16,5 @@ profile_traits = {path = "../../../components/profile_traits"} # Work around https://github.com/alexcrichton/jemallocator/issues/19 servo_allocator = {path = "../../../components/allocator"} +servo_config = {path = "../../../components/config"} + diff --git a/tests/unit/profile/lib.rs b/tests/unit/profile/lib.rs index 2b97cd68cb3..a67e211ad7b 100644 --- a/tests/unit/profile/lib.rs +++ b/tests/unit/profile/lib.rs @@ -8,5 +8,6 @@ extern crate ipc_channel; extern crate profile; extern crate profile_traits; extern crate servo_allocator; +extern crate servo_config; mod time; diff --git a/tests/unit/profile/time.rs b/tests/unit/profile/time.rs index 911f1cf95c0..19d3a19ee5d 100644 --- a/tests/unit/profile/time.rs +++ b/tests/unit/profile/time.rs @@ -4,7 +4,11 @@ use ipc_channel::ipc; use profile::time; -use profile_traits::time::ProfilerMsg; +use profile_traits::ipc as ProfiledIpc; +use profile_traits::time::{ProfilerCategory, ProfilerData, ProfilerMsg}; +use servo_config::opts::OutputOptions; +use std::thread; +use std::time::Duration; #[test] fn time_profiler_smoke_test() { @@ -37,6 +41,29 @@ fn time_profiler_stats_test() { assert_eq!(13.2599, odd_max); } +#[test] +fn channel_profiler_test() { + let chan = time::Profiler::create(&Some(OutputOptions::Stdout(5.0)), None); + let (profiled_sender, profiled_receiver) = ProfiledIpc::channel(chan.clone()).unwrap(); + thread::spawn(move || { + thread::sleep(Duration::from_secs(2)); + profiled_sender.send(43).unwrap(); + }); + + let val_profile_receiver = profiled_receiver.recv().unwrap(); + assert_eq!(val_profile_receiver, 43); + + let (sender, receiver) = ipc::channel().unwrap(); + chan.send(ProfilerMsg::Get((ProfilerCategory::IpcReceiver, None), sender.clone())); + + match receiver.recv().unwrap() { + // asserts that the time spent in the sleeping thread is more than 1500 milliseconds + ProfilerData::Record(time_data) => assert!(time_data[0] > 1.5e3), + ProfilerData::NoRecords => assert!(false), + }; + +} + #[cfg(debug_assertions)] #[test] #[should_panic] |