servo: Merge #8253 - Heartbeats and energy profiling support for Android (from connorimes:android-energy-profiling); r=mbrubeck

Source-Repo: https://github.com/servo/servo
Source-Revision: f9d79600c9399c6f804cfdce4a42fc118a1bdb47
This commit is contained in:
Connor Imes 2015-10-30 11:57:10 +05:01
Родитель 741243bea5
Коммит a6521e4324
5 изменённых файлов: 70 добавлений и 23 удалений

Просмотреть файл

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

Просмотреть файл

@ -19,7 +19,7 @@ features = [ "serde_serialization" ]
[dependencies.energymon]
git = "https://github.com/energymon/energymon-rust.git"
rev = "67f74732ac"
rev = "eba1d8a"
optional = true
[dependencies.energy-monitor]

Просмотреть файл

@ -36,8 +36,8 @@ mod energymon {
static mut EM: Option<*mut EnergyMon> = None;
/// Read energy from the energy monitor, otherwise return 0.
pub fn read_energy_uj() -> u64 {
fn init() {
// can't use lazy_static macro for EM (no Sync trait for EnergyMon)
static ONCE: Once = ONCE_INIT;
ONCE.call_once(|| {
if let Ok(em) = EnergyMon::new() {
@ -47,7 +47,11 @@ mod energymon {
}
}
});
}
/// Read energy from the energy monitor, otherwise return 0.
pub fn read_energy_uj() -> u64 {
init();
unsafe {
// EnergyMon implementations of EnergyMonitor always return a value
EM.map_or(0, |em| (*em).read_uj().unwrap())
@ -55,6 +59,7 @@ mod energymon {
}
pub fn get_min_interval_ms() -> u32 {
init();
unsafe {
EM.map_or(0, |em| ((*em).interval_us() as f64 / 1000.0).ceil() as u32)
}

11
servo/components/servo/Cargo.lock сгенерированный
Просмотреть файл

@ -474,18 +474,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "energymon"
version = "0.1.0"
source = "git+https://github.com/energymon/energymon-rust.git?rev=67f74732ac#67f74732ac0acc682659f7e81836155a32188fd0"
source = "git+https://github.com/energymon/energymon-rust.git?rev=eba1d8a#eba1d8a7256b710230ea2c1b26525b88bfcb529d"
dependencies = [
"energy-monitor 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"energymon-default-sys 0.1.0 (git+https://github.com/energymon/energymon-default-sys.git)",
"energymon-sys 0.1.0 (git+https://github.com/energymon/energymon-sys.git)",
"energymon-default-sys 0.1.0 (git+https://github.com/energymon/energymon-sys.git)",
"libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "energymon-default-sys"
version = "0.1.0"
source = "git+https://github.com/energymon/energymon-default-sys.git#82dd2f6762b492ced15d8446b70569778200c287"
source = "git+https://github.com/energymon/energymon-sys.git#82756eee725db3ccb658f14857947a0260743d4d"
dependencies = [
"energymon-sys 0.1.0 (git+https://github.com/energymon/energymon-sys.git)",
"libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
@ -495,7 +494,7 @@ dependencies = [
[[package]]
name = "energymon-sys"
version = "0.1.0"
source = "git+https://github.com/energymon/energymon-sys.git#6306f70e5d5c824fa168e43521385798fd1b890b"
source = "git+https://github.com/energymon/energymon-sys.git#82756eee725db3ccb658f14857947a0260743d4d"
dependencies = [
"libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -1436,7 +1435,7 @@ name = "profile_traits"
version = "0.0.1"
dependencies = [
"energy-monitor 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"energymon 0.1.0 (git+https://github.com/energymon/energymon-rust.git?rev=67f74732ac)",
"energymon 0.1.0 (git+https://github.com/energymon/energymon-rust.git?rev=eba1d8a)",
"ipc-channel 0.1.0 (git+https://github.com/pcwalton/ipc-channel)",
"plugins 0.0.1",
"serde 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",

Просмотреть файл

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