Skip to content

Commit

Permalink
Add timeline markers for HTTP requests, JS evaluation, and HTML parsing.
Browse files Browse the repository at this point in the history
  • Loading branch information
jdm committed May 18, 2016
1 parent 36df00a commit 3bfd042
Show file tree
Hide file tree
Showing 16 changed files with 117 additions and 28 deletions.
1 change: 1 addition & 0 deletions components/net/Cargo.toml
Expand Up @@ -27,6 +27,7 @@ net_traits = {path = "../net_traits"}
openssl = "0.7.6"
openssl-verify = "0.1"
plugins = {path = "../plugins"}
profile_traits = {path = "../profile_traits"}
rustc-serialize = "0.3"
threadpool = "1.0"
time = "0.1.17"
Expand Down
26 changes: 18 additions & 8 deletions components/net/http_loader.rs
Expand Up @@ -31,6 +31,8 @@ use net_traits::response::HttpsState;
use net_traits::{CookieSource, IncludeSubdomains, LoadConsumer, LoadContext, LoadData};
use net_traits::{Metadata, NetworkError};
use openssl::ssl::error::{SslError, OpensslError};
use profile_traits::time::{ProfilerCategory, profile, ProfilerChan, TimerMetadata};
use profile_traits::time::{TimerMetadataReflowType, TimerMetadataFrameType};
use resource_thread::{CancellationListener, send_error, start_sending_sniffed_opt, AuthCache, AuthCacheEntry};
use std::borrow::ToOwned;
use std::boxed::FnBox;
Expand All @@ -52,21 +54,29 @@ use uuid;
pub fn factory(user_agent: String,
http_state: HttpState,
devtools_chan: Option<Sender<DevtoolsControlMsg>>,
profiler_chan: ProfilerChan,
connector: Arc<Pool<Connector>>)
-> Box<FnBox(LoadData,
LoadConsumer,
Arc<MIMEClassifier>,
CancellationListener) + Send> {
box move |load_data: LoadData, senders, classifier, cancel_listener| {
spawn_named(format!("http_loader for {}", load_data.url), move || {
load_for_consumer(load_data,
senders,
classifier,
connector,
http_state,
devtools_chan,
cancel_listener,
user_agent)
let metadata = TimerMetadata {
url: load_data.url.as_str().into(),
iframe: TimerMetadataFrameType::RootWindow,
incremental: TimerMetadataReflowType::FirstReflow,
};
profile(ProfilerCategory::NetHTTPRequestResponse, Some(metadata), profiler_chan, || {
load_for_consumer(load_data,
senders,
classifier,
connector,
http_state,
devtools_chan,
cancel_listener,
user_agent)
})
})
}
}
Expand Down
1 change: 1 addition & 0 deletions components/net/lib.rs
Expand Up @@ -31,6 +31,7 @@ extern crate msg;
extern crate net_traits;
extern crate openssl;
extern crate openssl_verify;
extern crate profile_traits;
extern crate rustc_serialize;
extern crate threadpool;
extern crate time;
Expand Down
12 changes: 9 additions & 3 deletions components/net/resource_thread.rs
Expand Up @@ -23,6 +23,7 @@ use net_traits::ProgressMsg::Done;
use net_traits::{AsyncResponseTarget, Metadata, ProgressMsg, ResourceThread, ResponseAction};
use net_traits::{ControlMsg, CookieSource, LoadConsumer, LoadData, LoadResponse, ResourceId};
use net_traits::{NetworkError, WebSocketCommunicate, WebSocketConnectData};
use profile_traits::time::ProfilerChan;
use rustc_serialize::json;
use rustc_serialize::{Decodable, Encodable};
use std::borrow::ToOwned;
Expand Down Expand Up @@ -150,13 +151,14 @@ fn start_sending_opt(start_chan: LoadConsumer, metadata: Metadata,

/// Create a ResourceThread
pub fn new_resource_thread(user_agent: String,
devtools_chan: Option<Sender<DevtoolsControlMsg>>) -> ResourceThread {
devtools_chan: Option<Sender<DevtoolsControlMsg>>,
profiler_chan: ProfilerChan) -> ResourceThread {
let hsts_preload = HstsList::from_servo_preload();
let (setup_chan, setup_port) = ipc::channel().unwrap();
let setup_chan_clone = setup_chan.clone();
spawn_named("ResourceManager".to_owned(), move || {
let resource_manager = ResourceManager::new(
user_agent, hsts_preload, devtools_chan
user_agent, hsts_preload, devtools_chan, profiler_chan
);

let mut channel_manager = ResourceChannelManager {
Expand Down Expand Up @@ -364,6 +366,7 @@ pub struct ResourceManager {
auth_cache: Arc<RwLock<AuthCache>>,
mime_classifier: Arc<MIMEClassifier>,
devtools_chan: Option<Sender<DevtoolsControlMsg>>,
profiler_chan: ProfilerChan,
hsts_list: Arc<RwLock<HstsList>>,
connector: Arc<Pool<Connector>>,
cancel_load_map: HashMap<ResourceId, Sender<()>>,
Expand All @@ -373,7 +376,8 @@ pub struct ResourceManager {
impl ResourceManager {
pub fn new(user_agent: String,
mut hsts_list: HstsList,
devtools_channel: Option<Sender<DevtoolsControlMsg>>) -> ResourceManager {
devtools_channel: Option<Sender<DevtoolsControlMsg>>,
profiler_chan: ProfilerChan) -> ResourceManager {
let mut auth_cache = AuthCache::new();
let mut cookie_jar = CookieStorage::new();
if let Some(ref profile_dir) = opts::get().profile_dir {
Expand All @@ -387,6 +391,7 @@ impl ResourceManager {
auth_cache: Arc::new(RwLock::new(auth_cache)),
mime_classifier: Arc::new(MIMEClassifier::new()),
devtools_chan: devtools_channel,
profiler_chan: profiler_chan,
hsts_list: Arc::new(RwLock::new(hsts_list)),
connector: create_http_connector(),
cancel_load_map: HashMap::new(),
Expand Down Expand Up @@ -445,6 +450,7 @@ impl ResourceManager {
http_loader::factory(self.user_agent.clone(),
http_state,
self.devtools_chan.clone(),
self.profiler_chan.clone(),
self.connector.clone())
},
"data" => from_factory(data_loader::factory),
Expand Down
3 changes: 3 additions & 0 deletions components/profile/time.rs
Expand Up @@ -122,6 +122,7 @@ impl Formattable for ProfilerCategory {
ProfilerCategory::LayoutStoreOverflow => "Store Overflow",
ProfilerCategory::LayoutParallelWarmup => "Parallel Warmup",
ProfilerCategory::LayoutDispListBuild => "Display List Construction",
ProfilerCategory::NetHTTPRequestResponse => "Network HTTP Request/Response",
ProfilerCategory::PaintingPerTile => "Painting Per Tile",
ProfilerCategory::PaintingPrepBuff => "Buffer Prep",
ProfilerCategory::Painting => "Painting",
Expand All @@ -132,10 +133,12 @@ impl Formattable for ProfilerCategory {
ProfilerCategory::ScriptDevtoolsMsg => "Script Devtools Msg",
ProfilerCategory::ScriptDocumentEvent => "Script Document Event",
ProfilerCategory::ScriptDomEvent => "Script Dom Event",
ProfilerCategory::ScriptEvaluate => "Script JS Evaluate",
ProfilerCategory::ScriptFileRead => "Script File Read",
ProfilerCategory::ScriptImageCacheMsg => "Script Image Cache Msg",
ProfilerCategory::ScriptInputEvent => "Script Input Event",
ProfilerCategory::ScriptNetworkEvent => "Script Network Event",
ProfilerCategory::ScriptParseHTML => "Script Parse HTML",
ProfilerCategory::ScriptPlannedNavigation => "Script Planned Navigation",
ProfilerCategory::ScriptResize => "Script Resize",
ProfilerCategory::ScriptEvent => "Script Event",
Expand Down
3 changes: 3 additions & 0 deletions components/profile_traits/time.rs
Expand Up @@ -53,6 +53,7 @@ pub enum ProfilerCategory {
LayoutStoreOverflow,
LayoutParallelWarmup,
LayoutDispListBuild,
NetHTTPRequestResponse,
PaintingPerTile,
PaintingPrepBuff,
Painting,
Expand All @@ -63,11 +64,13 @@ pub enum ProfilerCategory {
ScriptDevtoolsMsg,
ScriptDocumentEvent,
ScriptDomEvent,
ScriptEvaluate,
ScriptEvent,
ScriptFileRead,
ScriptImageCacheMsg,
ScriptInputEvent,
ScriptNetworkEvent,
ScriptParseHTML,
ScriptPlannedNavigation,
ScriptResize,
ScriptSetViewport,
Expand Down
10 changes: 9 additions & 1 deletion components/script/dom/bindings/global.rs
Expand Up @@ -20,7 +20,7 @@ use js::jsapi::{JSContext, JSObject, JS_GetClass, MutableHandleValue};
use js::{JSCLASS_IS_DOMJSCLASS, JSCLASS_IS_GLOBAL};
use msg::constellation_msg::{ConstellationChan, PipelineId};
use net_traits::ResourceThread;
use profile_traits::mem;
use profile_traits::{mem, time};
use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort};
use script_thread::{MainThreadScriptChan, ScriptThread};
use script_traits::{MsDuration, ScriptMsg as ConstellationMsg, TimerEventRequest};
Expand Down Expand Up @@ -81,6 +81,14 @@ impl<'a> GlobalRef<'a> {
}
}

/// Get a `time::ProfilerChan` to send messages to the time profiler thread.
pub fn time_profiler_chan(&self) -> &time::ProfilerChan {
match *self {
GlobalRef::Window(window) => window.time_profiler_chan(),
GlobalRef::Worker(worker) => worker.time_profiler_chan(),
}
}

/// Get a `ConstellationChan` to send messages to the constellation channel when available.
pub fn constellation_chan(&self) -> &ConstellationChan<ConstellationMsg> {
match *self {
Expand Down
14 changes: 14 additions & 0 deletions components/script/dom/servohtmlparser.rs
Expand Up @@ -28,6 +28,8 @@ use msg::constellation_msg::{PipelineId, SubpageId};
use net_traits::{AsyncResponseListener, Metadata, NetworkError};
use network_listener::PreInvoke;
use parse::{TrustedParser, ParserRef, Parser};
use profile_traits::time::ProfilerCategory;
use profile_traits::time::{profile, TimerMetadata, TimerMetadataReflowType, TimerMetadataFrameType};
use script_thread::ScriptThread;
use std::cell::Cell;
use std::default::Default;
Expand Down Expand Up @@ -315,6 +317,18 @@ impl ServoHTMLParser {

impl ServoHTMLParser {
pub fn parse_sync(&self) {
let metadata = TimerMetadata {
url: self.document.url().as_str().into(),
iframe: TimerMetadataFrameType::RootWindow,
incremental: TimerMetadataReflowType::FirstReflow,
};
profile(ProfilerCategory::ScriptParseHTML,
Some(metadata),
self.document.window().time_profiler_chan().clone(),
|| self.do_parse_sync())
}

fn do_parse_sync(&self) {
// This parser will continue to parse while there is either pending input or
// the parser remains unsuspended.
loop {
Expand Down
56 changes: 42 additions & 14 deletions components/script/dom/window.rs
Expand Up @@ -51,6 +51,8 @@ use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheThread};
use net_traits::storage_thread::{StorageThread, StorageType};
use num_traits::ToPrimitive;
use profile_traits::mem;
use profile_traits::time::{ProfilerCategory, TimerMetadata, TimerMetadataFrameType};
use profile_traits::time::{ProfilerChan, TimerMetadataReflowType, profile};
use reporter::CSSErrorReporter;
use rustc_serialize::base64::{FromBase64, STANDARD, ToBase64};
use script_runtime::{ScriptChan, ScriptPort};
Expand Down Expand Up @@ -165,6 +167,10 @@ pub struct Window {
#[ignore_heap_size_of = "channels are hard"]
mem_profiler_chan: mem::ProfilerChan,

/// For sending messages to the memory profiler.
#[ignore_heap_size_of = "channels are hard"]
time_profiler_chan: ProfilerChan,

/// For providing instructions to an optional devtools server.
#[ignore_heap_size_of = "channels are hard"]
devtools_chan: Option<IpcSender<ScriptToDevtoolsControlMsg>>,
Expand Down Expand Up @@ -841,21 +847,37 @@ impl<'a, T: Reflectable> ScriptHelpers for &'a T {
fn evaluate_script_on_global_with_result(self, code: &str, filename: &str,
rval: MutableHandleValue) {
let global = self.global();
let cx = global.r().get_cx();
let globalhandle = global.r().reflector().get_jsobject();
let code: Vec<u16> = code.encode_utf16().collect();
let filename = CString::new(filename).unwrap();

let _ac = JSAutoCompartment::new(cx, globalhandle.get());
let options = CompileOptionsWrapper::new(cx, filename.as_ptr(), 0);
unsafe {
if !Evaluate2(cx, options.ptr, code.as_ptr(),
code.len() as libc::size_t,
rval) {
debug!("error evaluating JS string");
report_pending_exception(cx, globalhandle.get());
let metadata = TimerMetadata {
url: if filename.is_empty() {
global.r().get_url().as_str().into()
} else {
filename.into()
},
iframe: TimerMetadataFrameType::RootWindow,
incremental: TimerMetadataReflowType::FirstReflow,
};
profile(
ProfilerCategory::ScriptEvaluate,
Some(metadata),
global.r().time_profiler_chan().clone(),
|| {
let cx = global.r().get_cx();
let globalhandle = global.r().reflector().get_jsobject();
let code: Vec<u16> = code.encode_utf16().collect();
let filename = CString::new(filename).unwrap();

let _ac = JSAutoCompartment::new(cx, globalhandle.get());
let options = CompileOptionsWrapper::new(cx, filename.as_ptr(), 0);
unsafe {
if !Evaluate2(cx, options.ptr, code.as_ptr(),
code.len() as libc::size_t,
rval) {
debug!("error evaluating JS string");
report_pending_exception(cx, globalhandle.get());
}
}
}
}
)
}
}

Expand Down Expand Up @@ -1259,6 +1281,10 @@ impl Window {
&self.mem_profiler_chan
}

pub fn time_profiler_chan(&self) -> &ProfilerChan {
&self.time_profiler_chan
}

pub fn devtools_chan(&self) -> Option<IpcSender<ScriptToDevtoolsControlMsg>> {
self.devtools_chan.clone()
}
Expand Down Expand Up @@ -1424,6 +1450,7 @@ impl Window {
bluetooth_thread: IpcSender<BluetoothMethodMsg>,
storage_thread: StorageThread,
mem_profiler_chan: mem::ProfilerChan,
time_profiler_chan: ProfilerChan,
devtools_chan: Option<IpcSender<ScriptToDevtoolsControlMsg>>,
constellation_chan: ConstellationChan<ConstellationMsg>,
control_chan: IpcSender<ConstellationControlMsg>,
Expand Down Expand Up @@ -1460,6 +1487,7 @@ impl Window {
navigator: Default::default(),
image_cache_thread: image_cache_thread,
mem_profiler_chan: mem_profiler_chan,
time_profiler_chan: time_profiler_chan,
devtools_chan: devtools_chan,
browsing_context: Default::default(),
performance: Default::default(),
Expand Down
1 change: 1 addition & 0 deletions components/script/dom/worker.rs
Expand Up @@ -102,6 +102,7 @@ impl Worker {
let init = WorkerGlobalScopeInit {
resource_thread: resource_thread,
mem_profiler_chan: global.mem_profiler_chan().clone(),
time_profiler_chan: global.time_profiler_chan().clone(),
to_devtools_sender: global.devtools_chan(),
from_devtools_sender: optional_sender,
constellation_chan: constellation_chan,
Expand Down
10 changes: 9 additions & 1 deletion components/script/dom/workerglobalscope.rs
Expand Up @@ -23,7 +23,7 @@ use js::jsval::UndefinedValue;
use js::rust::Runtime;
use msg::constellation_msg::{ConstellationChan, PipelineId};
use net_traits::{LoadContext, ResourceThread, load_whole_resource};
use profile_traits::mem;
use profile_traits::{mem, time};
use script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort};
use script_traits::ScriptMsg as ConstellationMsg;
use script_traits::{MsDuration, TimerEvent, TimerEventId, TimerEventRequest, TimerSource};
Expand All @@ -45,6 +45,7 @@ pub enum WorkerGlobalScopeTypeId {
pub struct WorkerGlobalScopeInit {
pub resource_thread: ResourceThread,
pub mem_profiler_chan: mem::ProfilerChan,
pub time_profiler_chan: time::ProfilerChan,
pub to_devtools_sender: Option<IpcSender<ScriptToDevtoolsControlMsg>>,
pub from_devtools_sender: Option<IpcSender<DevtoolScriptControlMsg>>,
pub constellation_chan: ConstellationChan<ConstellationMsg>,
Expand Down Expand Up @@ -72,6 +73,8 @@ pub struct WorkerGlobalScope {
timers: OneshotTimers,
#[ignore_heap_size_of = "Defined in std"]
mem_profiler_chan: mem::ProfilerChan,
#[ignore_heap_size_of = "Defined in std"]
time_profiler_chan: time::ProfilerChan,
#[ignore_heap_size_of = "Defined in ipc-channel"]
to_devtools_sender: Option<IpcSender<ScriptToDevtoolsControlMsg>>,

Expand Down Expand Up @@ -118,6 +121,7 @@ impl WorkerGlobalScope {
crypto: Default::default(),
timers: OneshotTimers::new(timer_event_chan, init.scheduler_chan.clone()),
mem_profiler_chan: init.mem_profiler_chan,
time_profiler_chan: init.time_profiler_chan,
to_devtools_sender: init.to_devtools_sender,
from_devtools_sender: init.from_devtools_sender,
from_devtools_receiver: from_devtools_receiver,
Expand All @@ -131,6 +135,10 @@ impl WorkerGlobalScope {
&self.mem_profiler_chan
}

pub fn time_profiler_chan(&self) -> &time::ProfilerChan {
&self.time_profiler_chan
}

pub fn devtools_chan(&self) -> Option<IpcSender<ScriptToDevtoolsControlMsg>> {
self.to_devtools_sender.clone()
}
Expand Down
1 change: 1 addition & 0 deletions components/script/script_thread.rs
Expand Up @@ -1446,6 +1446,7 @@ impl ScriptThread {
self.bluetooth_thread.clone(),
self.storage_thread.clone(),
self.mem_profiler_chan.clone(),
self.time_profiler_chan.clone(),
self.devtools_chan.clone(),
self.constellation_chan.clone(),
self.control_chan.clone(),
Expand Down
1 change: 1 addition & 0 deletions components/servo/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion components/servo/lib.rs
Expand Up @@ -210,7 +210,9 @@ fn create_constellation(opts: opts::Opts,
supports_clipboard: bool,
webrender_api_sender: Option<webrender_traits::RenderApiSender>) -> Sender<ConstellationMsg> {
let bluetooth_thread: IpcSender<BluetoothMethodMsg> = BluetoothThreadFactory::new();
let resource_thread = new_resource_thread(opts.user_agent.clone(), devtools_chan.clone());
let resource_thread = new_resource_thread(opts.user_agent.clone(),
devtools_chan.clone(),
time_profiler_chan.clone());
let image_cache_thread = new_image_cache_thread(resource_thread.clone(),
webrender_api_sender.as_ref().map(|wr| wr.create_api()));
let font_cache_thread = FontCacheThread::new(resource_thread.clone(),
Expand Down

0 comments on commit 3bfd042

Please sign in to comment.