Add energy monitoring and characterization scripts

This commit is contained in:
Connor Imes 2015-07-28 15:23:57 -05:00
parent 0d37e8f96b
commit 3c25f47dbc
11 changed files with 834 additions and 5 deletions

View file

@ -7,6 +7,9 @@ authors = ["The Servo Project Developers"]
name = "profile_traits"
path = "lib.rs"
[features]
energy-profiling = ["energymon", "energy-monitor"]
[dependencies.ipc-channel]
git = "https://github.com/pcwalton/ipc-channel"
@ -14,6 +17,15 @@ git = "https://github.com/pcwalton/ipc-channel"
version = "0.2"
features = [ "serde_serialization" ]
[dependencies.energymon]
git = "https://github.com/energymon/energymon-rust.git"
rev = "67f74732ac"
optional = true
[dependencies.energy-monitor]
version = "0.1.0"
optional = true
[dependencies]
serde = "0.5"
serde_macros = "0.5"

View file

@ -0,0 +1,63 @@
/* 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/. */
#[cfg(feature = "energy-profiling")]
pub fn read_energy_uj() -> u64 {
energymon::read_energy_uj()
}
#[cfg(not(feature = "energy-profiling"))]
pub fn read_energy_uj() -> u64 {
0
}
#[cfg(feature = "energy-profiling")]
pub fn energy_interval_ms() -> u32 {
energymon::get_min_interval_ms()
}
#[cfg(not(feature = "energy-profiling"))]
pub fn energy_interval_ms() -> u32 {
1000
}
#[cfg(feature = "energy-profiling")]
mod energymon {
extern crate energymon;
extern crate energy_monitor;
use self::energy_monitor::EnergyMonitor;
use self::energymon::EnergyMon;
use std::mem;
use std::sync::{Once, ONCE_INIT};
static mut EM: Option<*mut EnergyMon> = None;
/// Read energy from the energy monitor, otherwise return 0.
pub fn read_energy_uj() -> u64 {
static ONCE: Once = ONCE_INIT;
ONCE.call_once(|| {
if let Ok(em) = EnergyMon::new() {
println!("Started energy monitoring from: {}", em.source());
unsafe {
EM = Some(mem::transmute(Box::new(em)));
}
}
});
unsafe {
// EnergyMon implementations of EnergyMonitor always return a value
EM.map_or(0, |em| (*em).read_uj().unwrap())
}
}
pub fn get_min_interval_ms() -> u32 {
unsafe {
EM.map_or(0, |em| ((*em).interval_us() as f64 / 1000.0).ceil() as u32)
}
}
}

View file

@ -13,6 +13,7 @@
extern crate ipc_channel;
extern crate serde;
pub mod energy;
pub mod mem;
pub mod time;

View file

@ -5,6 +5,7 @@
extern crate time as std_time;
extern crate url;
use energy::read_energy_uj;
use ipc_channel::ipc::IpcSender;
use self::std_time::precise_time_ns;
use self::url::Url;
@ -29,7 +30,7 @@ impl ProfilerChan {
#[derive(Clone, Deserialize, Serialize)]
pub enum ProfilerMsg {
/// Normal message used for reporting time
Time((ProfilerCategory, Option<TimerMetadata>), (u64, u64)),
Time((ProfilerCategory, Option<TimerMetadata>), (u64, u64), (u64, u64)),
/// Message used to force print the profiling metrics
Print,
/// Tells the profiler to shut down.
@ -72,6 +73,7 @@ pub enum ProfilerCategory {
ScriptWebSocketEvent,
ScriptWorkerEvent,
ScriptXhrEvent,
ApplicationHeartbeat,
}
#[derive(Eq, PartialEq)]
@ -96,15 +98,19 @@ pub fn profile<T, F>(category: ProfilerCategory,
-> T
where F: FnOnce() -> T
{
let start_energy = read_energy_uj();
let start_time = precise_time_ns();
let val = callback();
let end_time = precise_time_ns();
let end_energy = read_energy_uj();
let meta = meta.map(|(url, iframe, reflow_type)|
TimerMetadata {
url: url.serialize(),
iframe: iframe == TimerMetadataFrameType::IFrame,
incremental: reflow_type == TimerMetadataReflowType::Incremental,
});
profiler_chan.send(ProfilerMsg::Time((category, meta), (start_time, end_time)));
profiler_chan.send(ProfilerMsg::Time((category, meta),
(start_time, end_time),
(start_energy, end_energy)));
return val;
}