diff options
-rw-r--r-- | components/profile/heartbeats.rs | 58 | ||||
-rw-r--r-- | components/util/opts.rs | 13 |
2 files changed, 57 insertions, 14 deletions
diff --git a/components/profile/heartbeats.rs b/components/profile/heartbeats.rs index 6eaff00e79f..0101f62e25b 100644 --- a/components/profile/heartbeats.rs +++ b/components/profile/heartbeats.rs @@ -11,6 +11,8 @@ use std::env::var_os; use std::error::Error; use std::fs::File; use std::mem; +use std::path::Path; +use util::opts; static mut HBS: Option<*mut HashMap<ProfilerCategory, Heartbeat>> = None; @@ -72,6 +74,7 @@ pub fn cleanup() { } } +/// Check if a heartbeat exists for the given category pub fn is_heartbeat_enabled(category: &ProfilerCategory) -> bool { unsafe { HBS.map_or(false, |m| (*m).contains_key(category)) @@ -93,22 +96,51 @@ pub fn maybe_heartbeat(category: &ProfilerCategory, } } -/// Create a heartbeat if the correct environment variable is set +// TODO(cimes): Android doesn't really do environment variables. Need a better way to configure dynamically. + +fn is_create_heartbeat(category: &ProfilerCategory) -> bool { + opts::get().profile_heartbeats || var_os(format!("SERVO_HEARTBEAT_ENABLE_{:?}", category)).is_some() +} + +fn open_heartbeat_log<P: AsRef<Path>>(name: P) -> Option<File> { + match File::create(name) { + Ok(f) => Some(f), + Err(e) => { + warn!("Failed to open heartbeat log: {}", Error::description(&e)); + None + }, + } +} + +#[cfg(target_os = "android")] +fn get_heartbeat_log(category: &ProfilerCategory) -> Option<File> { + open_heartbeat_log(format!("/sdcard/servo/heartbeat-{:?}.log", category)) +} + +#[cfg(not(target_os = "android"))] +fn get_heartbeat_log(category: &ProfilerCategory) -> Option<File> { + var_os(format!("SERVO_HEARTBEAT_LOG_{:?}", category)).and_then(|name| open_heartbeat_log(&name)) +} + +fn get_heartbeat_window_size(category: &ProfilerCategory) -> usize { + const WINDOW_SIZE_DEFAULT: usize = 1; + match var_os(format!("SERVO_HEARTBEAT_WINDOW_{:?}", category)) { + Some(w) => match w.into_string() { + Ok(s) => s.parse::<usize>().unwrap_or(WINDOW_SIZE_DEFAULT), + _ => WINDOW_SIZE_DEFAULT, + }, + None => WINDOW_SIZE_DEFAULT, + } +} + +/// Possibly create a heartbeat fn maybe_create_heartbeat(hbs: &mut HashMap<ProfilerCategory, Heartbeat>, category: ProfilerCategory) { - static WINDOW_SIZE_DEFAULT: usize = 20; - if let Some(_) = var_os(format!("SERVO_HEARTBEAT_ENABLE_{:?}", category)) { + if is_create_heartbeat(&category) { // get optional log file - let logfile: Option<File> = var_os(format!("SERVO_HEARTBEAT_LOG_{:?}", category)) - .and_then(|name| File::create(name).ok()); - // get window size - let window_size: usize = match var_os(format!("SERVO_HEARTBEAT_WINDOW_{:?}", category)) { - Some(w) => match w.into_string() { - Ok(s) => s.parse::<usize>().unwrap_or(WINDOW_SIZE_DEFAULT), - _ => WINDOW_SIZE_DEFAULT, - }, - None => WINDOW_SIZE_DEFAULT, - }; + let logfile: Option<File> = get_heartbeat_log(&category); + // window size + let window_size: usize = get_heartbeat_window_size(&category); // create the heartbeat match Heartbeat::new(window_size, Some(heartbeat_window_callback), logfile) { Ok(hb) => { diff --git a/components/util/opts.rs b/components/util/opts.rs index 785f5909240..9f68ffb432b 100644 --- a/components/util/opts.rs +++ b/components/util/opts.rs @@ -121,6 +121,9 @@ pub struct Opts { /// Periodically print out on which events script tasks spend their processing time. pub profile_script_events: bool, + /// Enable all heartbeats for profiling. + pub profile_heartbeats: bool, + /// `None` to disable devtools or `Some` with a port number to start a server to listen to /// remote Firefox devtools connections. pub devtools_port: Option<u16>, @@ -223,6 +226,9 @@ pub struct DebugOptions { /// Profile which events script tasks spend their time on. pub profile_script_events: bool, + /// Enable all heartbeats for profiling. + pub profile_heartbeats: bool, + /// Paint borders along layer and tile boundaries. pub show_compositor_borders: bool, @@ -286,6 +292,7 @@ impl DebugOptions { "relayout-event" => debug_options.relayout_event = true, "profile-tasks" => debug_options.profile_tasks = true, "profile-script-events" => debug_options.profile_script_events = true, + "profile-heartbeats" => debug_options.profile_heartbeats = true, "show-compositor-borders" => debug_options.show_compositor_borders = true, "show-fragment-borders" => debug_options.show_fragment_borders = true, "show-parallel-paint" => debug_options.show_parallel_paint = true, @@ -325,6 +332,8 @@ pub fn print_debug_usage(app: &str) -> ! { print_option("dump-layer-tree", "Print the layer tree whenever it changes."); print_option("relayout-event", "Print notifications when there is a relayout."); print_option("profile-tasks", "Instrument each task, writing the output to a file."); + print_option("profile-script-events", "Enable profiling of script-related events."); + print_option("profile-heartbeats", "Enable heartbeats for all task categories."); print_option("show-compositor-borders", "Paint borders along layer and tile boundaries."); print_option("show-fragment-borders", "Paint borders along fragment boundaries."); print_option("show-parallel-paint", "Overlay tiles with colors showing which thread painted them."); @@ -336,10 +345,10 @@ pub fn print_debug_usage(app: &str) -> ! { print_option("disable-share-style-cache", "Disable the style sharing cache."); print_option("parallel-display-list-building", "Build display lists in parallel."); + print_option("convert-mouse-to-touch", "Send touch events instead of mouse events"); print_option("replace-surrogates", "Replace unpaires surrogates in DOM strings with U+FFFD. \ See https://github.com/servo/servo/issues/6564"); print_option("gc-profile", "Log GC passes and their durations."); - print_option("convert-mouse-to-touch", "Send touch events instead of mouse events"); println!(""); @@ -433,6 +442,7 @@ pub fn default_opts() -> Opts { validate_display_list_geometry: false, profile_tasks: false, profile_script_events: false, + profile_heartbeats: false, sniff_mime_types: false, disable_share_style_cache: false, parallel_display_list_building: false, @@ -620,6 +630,7 @@ pub fn from_cmdline_args(args: &[String]) { bubble_inline_sizes_separately: bubble_inline_sizes_separately, profile_tasks: debug_options.profile_tasks, profile_script_events: debug_options.profile_script_events, + profile_heartbeats: debug_options.profile_heartbeats, trace_layout: debug_options.trace_layout, devtools_port: devtools_port, webdriver_port: webdriver_port, |