Add a profile_traits crate to reduce compile times.

A rebuild after touching components/profile/mem.rs now takes 48 seconds (and
only rebuilds `profile` and `servo`) which is much lower than it used to be.
In comparison, a rebuild after touching components/profile_traits/mem.rs takes
294 seconds and rebuilds many more crates.

This change also removes some unnecessary crate dependencies in `net` and
`net_traits`.
This commit is contained in:
Nicholas Nethercote 2015-04-29 21:36:03 -07:00
parent 826b722202
commit 092507d23c
37 changed files with 269 additions and 225 deletions

View file

@ -0,0 +1,13 @@
[package]
name = "profile_traits"
version = "0.0.1"
authors = ["The Servo Project Developers"]
[lib]
name = "profile_traits"
path = "lib.rs"
[dependencies]
time = "0.1.12"
url = "0.2.16"

View file

@ -0,0 +1,6 @@
/* 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/. */
pub mod mem;
pub mod time;

View file

@ -0,0 +1,72 @@
/* 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/. */
use std::sync::mpsc::Sender;
#[derive(Clone)]
pub struct ProfilerChan(pub Sender<ProfilerMsg>);
impl ProfilerChan {
pub fn send(&self, msg: ProfilerMsg) {
let ProfilerChan(ref c) = *self;
c.send(msg).unwrap();
}
}
/// A single memory-related measurement.
pub struct Report {
/// The identifying path for this report.
pub path: Vec<String>,
/// The size, in bytes.
pub size: usize,
}
/// A channel through which memory reports can be sent.
#[derive(Clone)]
pub struct ReportsChan(pub Sender<Vec<Report>>);
impl ReportsChan {
pub fn send(&self, report: Vec<Report>) {
let ReportsChan(ref c) = *self;
c.send(report).unwrap();
}
}
/// A memory reporter is capable of measuring some data structure of interest. Because it needs to
/// be passed to and registered with the Profiler, it's typically a "small" (i.e. easily cloneable)
/// value that provides access to a "large" data structure, e.g. a channel that can inject a
/// request for measurements into the event queue associated with the "large" data structure.
pub trait Reporter {
/// Collect one or more memory reports. Returns true on success, and false on failure.
fn collect_reports(&self, reports_chan: ReportsChan) -> bool;
}
/// An easy way to build a path for a report.
#[macro_export]
macro_rules! path {
($($x:expr),*) => {{
use std::borrow::ToOwned;
vec![$( $x.to_owned() ),*]
}}
}
/// Messages that can be sent to the memory profiler thread.
pub enum ProfilerMsg {
/// Register a Reporter with the memory profiler. The String is only used to identify the
/// reporter so it can be unregistered later. The String must be distinct from that used by any
/// other registered reporter otherwise a panic will occur.
RegisterReporter(String, Box<Reporter + Send>),
/// Unregister a Reporter with the memory profiler. The String must match the name given when
/// the reporter was registered. If the String does not match the name of a registered reporter
/// a panic will occur.
UnregisterReporter(String),
/// Triggers printing of the memory profiling metrics.
Print,
/// Tells the memory profiler to shut down.
Exit,
}

View file

@ -0,0 +1,95 @@
/* 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/. */
extern crate "time" as std_time;
extern crate url;
use self::std_time::precise_time_ns;
use self::url::Url;
use std::sync::mpsc::Sender;
#[derive(PartialEq, Clone, PartialOrd, Eq, Ord)]
pub struct TimerMetadata {
pub url: String,
pub iframe: bool,
pub incremental: bool,
}
#[derive(Clone)]
pub struct ProfilerChan(pub Sender<ProfilerMsg>);
impl ProfilerChan {
pub fn send(&self, msg: ProfilerMsg) {
let ProfilerChan(ref c) = *self;
c.send(msg).unwrap();
}
}
#[derive(Clone)]
pub enum ProfilerMsg {
/// Normal message used for reporting time
Time((ProfilerCategory, Option<TimerMetadata>), f64),
/// Message used to force print the profiling metrics
Print,
/// Tells the profiler to shut down.
Exit,
}
#[repr(u32)]
#[derive(PartialEq, Clone, PartialOrd, Eq, Ord)]
pub enum ProfilerCategory {
Compositing,
LayoutPerform,
LayoutStyleRecalc,
LayoutRestyleDamagePropagation,
LayoutNonIncrementalReset,
LayoutSelectorMatch,
LayoutTreeBuilder,
LayoutDamagePropagate,
LayoutGeneratedContent,
LayoutMain,
LayoutParallelWarmup,
LayoutShaping,
LayoutDispListBuild,
PaintingPerTile,
PaintingPrepBuff,
Painting,
ImageDecoding,
}
#[derive(Eq, PartialEq)]
pub enum TimerMetadataFrameType {
RootWindow,
IFrame,
}
#[derive(Eq, PartialEq)]
pub enum TimerMetadataReflowType {
Incremental,
FirstReflow,
}
pub type ProfilerMetadata<'a> =
Option<(&'a Url, TimerMetadataFrameType, TimerMetadataReflowType)>;
pub fn profile<T, F>(category: ProfilerCategory,
meta: ProfilerMetadata,
profiler_chan: ProfilerChan,
callback: F)
-> T
where F: FnOnce() -> T
{
let start_time = precise_time_ns();
let val = callback();
let end_time = precise_time_ns();
let ms = (end_time - start_time) as f64 / 1000000f64;
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), ms));
return val;
}