Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove support for energy and heartbeats profiling #26788

Merged
merged 2 commits into from Jun 5, 2020
Merged
Changes from 1 commit
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Next

Remove support for energy profiling

  • Loading branch information
SimonSapin committed Jun 4, 2020
commit 0abe90647f4548d0e35c8d9107b81e45ea739226

Some generated files are not rendered by default. Learn more.

@@ -1456,8 +1456,6 @@ impl LayoutThread {
&self.time_profiler_chan,
0,
text_shaping_time as u64,
0,
0,
);

// Retrieve the (possibly rebuilt) root flow.
@@ -81,8 +81,6 @@ fn set_metric<U: ProgressiveWebMetric>(
&pwm.get_time_profiler_chan(),
time,
time,
0,
0,
);

// Print the metric to console if the print-pwm option was given.
@@ -62,31 +62,3 @@ Time is measured in nanoseconds and energy is measured in microjoules.
`Work`, `Time`, and `Energy` also have `Global` and `Window` values which are the summed over the entire runtime and sliding window period, respectively.

`Perf` (performance) and `Pwr` (power) have `Global`, `Window`, and `Instant` values as described above.


# Energy Profiling

Energy monitoring is hardware and platform-specific, so it is only enabled with the `energy-profiling` feature.

To use energy profiling, you must have a compatible `energymon-default` implementation installed to your system as `energymon-default-static` when building Servo.
Otherwise a default dummy implementation is used.
The library is linked through a chain of dependencies:

* servo::profile_traits
* energymon - Rust abstractions
* energymon-default-sys - Rust bindings to `energymon-default.h`
* energymon-default-static: A statically linked C library installed to the system that implements `energymon.h` and `energymon-default.h`

For instructions on building existing native libraries, visit the [energymon project source](https://github.com/energymon/energymon).
You may also write your own implementation of `energymon.h` and `energymon-default.h` and install it as `energymon-default-static` where pkg-config can find it.

Once you install the proper library, you will need to rebuild the `energymon-default-sys` crate.
The most straightforward way to do this is to do a clean build of Servo.

To build Servo with the `energy-profiling` feature enabled, pass `--features "energy-profiling"` to the `mach` command, e.g.:

```sh
./mach build -r --features "energy-profiling"
```

When running Servo, you will want to enable the desired Heartbeats to record the results.
@@ -7,14 +7,12 @@
use crate::heartbeats;
use crate::trace_dump::TraceDump;
use ipc_channel::ipc::{self, IpcReceiver};
use profile_traits::energy::{energy_interval_ms, read_energy_uj};
use profile_traits::time::{
ProfilerCategory, ProfilerChan, ProfilerData, ProfilerMsg, TimerMetadata,
};
use profile_traits::time::{TimerMetadataFrameType, TimerMetadataReflowType};
use servo_config::opts::OutputOptions;
use std::borrow::ToOwned;
use std::cmp::Ordering;
use std::collections::{BTreeMap, HashMap};
use std::fs::File;
use std::io::{self, Write};
@@ -253,22 +251,15 @@ impl Profiler {
};
if run_ap_thread() {
let profiler_chan = profiler_chan.clone();
// min of 1 heartbeat/sec, max of 20 should provide accurate enough power/energy readings
// min of 1 heartbeat/sec, max of 20 should provide accurate enough readings
// waking up more frequently allows the thread to end faster on exit
const SLEEP_MS: u32 = 10;
const MIN_ENERGY_INTERVAL_MS: u32 = 50;
const MAX_ENERGY_INTERVAL_MS: u32 = 1000;
let interval_ms = enforce_range(
MIN_ENERGY_INTERVAL_MS,
MAX_ENERGY_INTERVAL_MS,
energy_interval_ms(),
);
let interval_ms = 200;
let loop_count: u32 = (interval_ms as f32 / SLEEP_MS as f32).ceil() as u32;
thread::Builder::new()
.name("Application heartbeat profiler".to_owned())
.spawn(move || {
let mut start_time = precise_time_ns();
let mut start_energy = read_energy_uj();
loop {
for _ in 0..loop_count {
if run_ap_thread() {
@@ -278,20 +269,17 @@ impl Profiler {
}
}
let end_time = precise_time_ns();
let end_energy = read_energy_uj();
// send using the inner channel
// (using ProfilerChan.send() forces an unwrap
// and sometimes panics for this background profiler)
let ProfilerChan(ref c) = profiler_chan;
if let Err(_) = c.send(ProfilerMsg::Time(
(ProfilerCategory::ApplicationHeartbeat, None),
(start_time, end_time),
(start_energy, end_energy),
)) {
return;
}
start_time = end_time;
start_energy = end_energy;
}
})
.expect("Thread spawning failed");
@@ -331,10 +319,10 @@ impl Profiler {

fn handle_msg(&mut self, msg: ProfilerMsg) -> bool {
match msg.clone() {
ProfilerMsg::Time(k, t, e) => {
heartbeats::maybe_heartbeat(&k.0, t.0, t.1, e.0, e.1, self.profile_heartbeats);
ProfilerMsg::Time(k, t) => {
heartbeats::maybe_heartbeat(&k.0, t.0, t.1, 0, 0, self.profile_heartbeats);
if let Some(ref mut trace) = self.trace {
trace.write_one(&k, t, e);
trace.write_one(&k, t);
}
let ms = (t.1 - t.0) as f64 / 1000000f64;
self.find_or_insert(k, ms);
@@ -475,20 +463,6 @@ impl Profiler {
}
}

fn enforce_range<T>(min: T, max: T, value: T) -> T
where
T: Ord,
{
assert!(min <= max);
match value.cmp(&max) {
Ordering::Equal | Ordering::Greater => max,
Ordering::Less => match value.cmp(&min) {
Ordering::Equal | Ordering::Less => min,
Ordering::Greater => value,
},
}
}

pub fn duration_from_seconds(secs: f64) -> Duration {
pub const NANOS_PER_SEC: u32 = 1_000_000_000;

@@ -25,12 +25,6 @@ struct TraceEntry {

#[serde(rename = "endTime")]
end_time: u64,

#[serde(rename = "startEnergy")]
start_energy: u64,

#[serde(rename = "endEnergy")]
end_energy: u64,
}

impl TraceDump {
@@ -50,15 +44,12 @@ impl TraceDump {
&mut self,
category: &(ProfilerCategory, Option<TimerMetadata>),
time: (u64, u64),
energy: (u64, u64),
) {
let entry = TraceEntry {
category: category.0,
metadata: category.1.clone(),
start_time: time.0,
end_time: time.1,
start_energy: energy.0,
end_energy: energy.1,
};
serde_json::to_writer(&mut self.file, &entry).unwrap();
writeln!(&mut self.file, ",").unwrap();
@@ -10,13 +10,8 @@ publish = false
name = "profile_traits"
path = "lib.rs"

[features]
energy-profiling = ["energy-monitor", "energymon"]

[dependencies]
crossbeam-channel = "0.4"
energy-monitor = { version = "0.2.0", optional = true }
energymon = { git = "https://github.com/energymon/energymon-rust.git", optional = true }
ipc-channel = "0.14"
log = "0.4"
serde = "1.0"

This file was deleted.

@@ -13,8 +13,6 @@ extern crate log;
#[macro_use]
extern crate serde;

#[allow(unsafe_code)]
pub mod energy;
pub mod ipc;
pub mod mem;
pub mod time;
@@ -2,7 +2,6 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */

use crate::energy::read_energy_uj;
use ipc_channel::ipc::IpcSender;
use servo_config::opts;
use time::precise_time_ns;
@@ -34,11 +33,7 @@ pub enum ProfilerData {
#[derive(Clone, Debug, Deserialize, Serialize)]
pub enum ProfilerMsg {
/// Normal message used for reporting time
Time(
(ProfilerCategory, Option<TimerMetadata>),
(u64, u64),
(u64, u64),
),
Time((ProfilerCategory, Option<TimerMetadata>), (u64, u64)),
/// Message used to get time spend entries for a particular ProfilerBuckets (in nanoseconds)
Get(
(ProfilerCategory, Option<TimerMetadata>),
@@ -142,26 +137,16 @@ where
if opts::get().signpost {
signpost::start(category as u32, &[0, 0, 0, (category as usize) >> 4]);
}
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();
if opts::get().signpost {
signpost::end(category as u32, &[0, 0, 0, (category as usize) >> 4]);
}

send_profile_data(
category,
meta,
&profiler_chan,
start_time,
end_time,
start_energy,
end_energy,
);
send_profile_data(category, meta, &profiler_chan, start_time, end_time);
val
}

@@ -171,12 +156,6 @@ pub fn send_profile_data(
profiler_chan: &ProfilerChan,
start_time: u64,
end_time: u64,
start_energy: u64,
end_energy: u64,
) {
profiler_chan.send(ProfilerMsg::Time(
(category, meta),
(start_time, end_time),
(start_energy, end_energy),
));
profiler_chan.send(ProfilerMsg::Time((category, meta), (start_time, end_time)));
}
@@ -14,7 +14,6 @@ crate-type = ["rlib"]
[features]
debugmozjs = ["script/debugmozjs"]
egl = ["mozangle/egl"]
energy-profiling = ["profile_traits/energy-profiling"]
googlevr = ["webxr/googlevr"]
jitspew = ["script/jitspew"]
js_backtrace = ["script/js_backtrace"]
@@ -35,7 +35,6 @@ gl_generator = "0.14"
debugmozjs = ["libservo/debugmozjs"]
default = ["webdriver", "max_log_level"]
egl = ["libservo/egl"]
energy-profiling = ["libservo/energy-profiling"]
googlevr = ["libservo/googlevr"]
jitspew = ["libservo/jitspew"]
js_backtrace = ["libservo/js_backtrace"]
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.