mirror of
https://github.com/servo/servo.git
synced 2025-08-07 14:35:33 +01:00
auto merge of #808 : tikue/servo/master, r=metajack
* Use ProfilerBucket structs instead of (ProfilerCategory, ~[Float]) tuples * Simplify the order check of bucket categories
This commit is contained in:
commit
65c6435902
1 changed files with 50 additions and 58 deletions
|
@ -8,6 +8,7 @@ use std::cell::Cell;
|
||||||
use std::comm::{Port, SharedChan};
|
use std::comm::{Port, SharedChan};
|
||||||
use extra::sort::tim_sort;
|
use extra::sort::tim_sort;
|
||||||
use std::iterator::AdditiveIterator;
|
use std::iterator::AdditiveIterator;
|
||||||
|
use extra::treemap::TreeMap;
|
||||||
|
|
||||||
// front-end representation of the profiler used to communicate with the profiler
|
// front-end representation of the profiler used to communicate with the profiler
|
||||||
#[deriving(Clone)]
|
#[deriving(Clone)]
|
||||||
|
@ -26,7 +27,14 @@ impl ProfilerChan {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deriving(Eq, Clone)]
|
pub enum ProfilerMsg {
|
||||||
|
// Normal message used for reporting time
|
||||||
|
TimeMsg(ProfilerCategory, float),
|
||||||
|
// Message used to force print the profiling metrics
|
||||||
|
PrintMsg,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[deriving(Eq, Clone, TotalEq, TotalOrd)]
|
||||||
pub enum ProfilerCategory {
|
pub enum ProfilerCategory {
|
||||||
CompositingCategory,
|
CompositingCategory,
|
||||||
LayoutQueryCategory,
|
LayoutQueryCategory,
|
||||||
|
@ -41,65 +49,36 @@ pub enum ProfilerCategory {
|
||||||
RenderingDrawingCategory,
|
RenderingDrawingCategory,
|
||||||
RenderingPrepBuffCategory,
|
RenderingPrepBuffCategory,
|
||||||
RenderingCategory,
|
RenderingCategory,
|
||||||
// hackish but helps prevent errors when adding new categories
|
// FIXME(rust#8803): workaround for lack of CTFE function on enum types to return length
|
||||||
NUM_BUCKETS,
|
NumBuckets,
|
||||||
}
|
|
||||||
// FIXME(#5873) this should be initialized by a NUM_BUCKETS cast,
|
|
||||||
static BUCKETS: uint = 13;
|
|
||||||
type ProfilerBuckets = [(ProfilerCategory, ~[float]), ..BUCKETS];
|
|
||||||
|
|
||||||
pub enum ProfilerMsg {
|
|
||||||
// Normal message used for reporting time
|
|
||||||
TimeMsg(ProfilerCategory, float),
|
|
||||||
// Message used to force print the profiling metrics
|
|
||||||
PrintMsg,
|
|
||||||
}
|
|
||||||
|
|
||||||
// back end of the profiler that handles data aggregation and performance metrics
|
|
||||||
pub struct Profiler {
|
|
||||||
port: Port<ProfilerMsg>,
|
|
||||||
buckets: ProfilerBuckets,
|
|
||||||
last_msg: Option<ProfilerMsg>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ProfilerCategory {
|
impl ProfilerCategory {
|
||||||
// convenience function to not have to cast every time
|
// convenience function to not have to cast every time
|
||||||
pub fn num_buckets() -> uint {
|
pub fn num_buckets() -> uint {
|
||||||
NUM_BUCKETS as uint
|
NumBuckets as uint
|
||||||
}
|
}
|
||||||
|
|
||||||
// enumeration of all ProfilerCategory types
|
// enumeration of all ProfilerCategory types
|
||||||
// TODO(tkuehn): is there a better way to ensure proper order of categories?
|
|
||||||
fn empty_buckets() -> ProfilerBuckets {
|
fn empty_buckets() -> ProfilerBuckets {
|
||||||
let buckets = [
|
let mut buckets = TreeMap::new();
|
||||||
(CompositingCategory, ~[]),
|
buckets.insert(CompositingCategory, ~[]);
|
||||||
(LayoutQueryCategory, ~[]),
|
buckets.insert(LayoutQueryCategory, ~[]);
|
||||||
(LayoutPerformCategory, ~[]),
|
buckets.insert(LayoutPerformCategory, ~[]);
|
||||||
(LayoutAuxInitCategory, ~[]),
|
buckets.insert(LayoutAuxInitCategory, ~[]);
|
||||||
(LayoutSelectorMatchCategory, ~[]),
|
buckets.insert(LayoutSelectorMatchCategory, ~[]);
|
||||||
(LayoutTreeBuilderCategory, ~[]),
|
buckets.insert(LayoutTreeBuilderCategory, ~[]);
|
||||||
(LayoutMainCategory, ~[]),
|
buckets.insert(LayoutMainCategory, ~[]);
|
||||||
(LayoutShapingCategory, ~[]),
|
buckets.insert(LayoutShapingCategory, ~[]);
|
||||||
(LayoutDispListBuildCategory, ~[]),
|
buckets.insert(LayoutDispListBuildCategory, ~[]);
|
||||||
(GfxRegenAvailableFontsCategory, ~[]),
|
buckets.insert(GfxRegenAvailableFontsCategory, ~[]);
|
||||||
(RenderingDrawingCategory, ~[]),
|
buckets.insert(RenderingDrawingCategory, ~[]);
|
||||||
(RenderingPrepBuffCategory, ~[]),
|
buckets.insert(RenderingPrepBuffCategory, ~[]);
|
||||||
(RenderingCategory, ~[]),
|
buckets.insert(RenderingCategory, ~[]);
|
||||||
];
|
|
||||||
|
|
||||||
ProfilerCategory::check_order(&buckets);
|
|
||||||
buckets
|
buckets
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensure that the order of the buckets matches the order of the enum categories
|
|
||||||
fn check_order(vec: &ProfilerBuckets) {
|
|
||||||
for &(category, _) in vec.iter() {
|
|
||||||
if category != vec[category as uint].first() {
|
|
||||||
fail!("Enum category does not match bucket index. This is a bug.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// some categories are subcategories of LayoutPerformCategory
|
// some categories are subcategories of LayoutPerformCategory
|
||||||
// and should be printed to indicate this
|
// and should be printed to indicate this
|
||||||
pub fn format(self) -> ~str {
|
pub fn format(self) -> ~str {
|
||||||
|
@ -112,6 +91,15 @@ impl ProfilerCategory {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ProfilerBuckets = TreeMap<ProfilerCategory, ~[float]>;
|
||||||
|
|
||||||
|
// back end of the profiler that handles data aggregation and performance metrics
|
||||||
|
pub struct Profiler {
|
||||||
|
port: Port<ProfilerMsg>,
|
||||||
|
buckets: ProfilerBuckets,
|
||||||
|
last_msg: Option<ProfilerMsg>,
|
||||||
|
}
|
||||||
|
|
||||||
impl Profiler {
|
impl Profiler {
|
||||||
pub fn create(port: Port<ProfilerMsg>) {
|
pub fn create(port: Port<ProfilerMsg>) {
|
||||||
let port = Cell::new(port);
|
let port = Cell::new(port);
|
||||||
|
@ -141,14 +129,11 @@ impl Profiler {
|
||||||
|
|
||||||
fn handle_msg(&mut self, msg: ProfilerMsg) {
|
fn handle_msg(&mut self, msg: ProfilerMsg) {
|
||||||
match msg {
|
match msg {
|
||||||
TimeMsg(category, t) => match self.buckets[category as uint] {
|
TimeMsg(category, t) => self.buckets.find_mut(&category).unwrap().push(t),
|
||||||
//TODO(tkuehn): would be nice to have tuple.second_mut()
|
|
||||||
(_, ref mut data) => data.push(t),
|
|
||||||
},
|
|
||||||
PrintMsg => match self.last_msg {
|
PrintMsg => match self.last_msg {
|
||||||
// only print if more data has arrived since the last printout
|
// only print if more data has arrived since the last printout
|
||||||
Some(TimeMsg(*)) => self.print_buckets(),
|
Some(TimeMsg(*)) => self.print_buckets(),
|
||||||
_ => {}
|
_ => ()
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
self.last_msg = Some(msg);
|
self.last_msg = Some(msg);
|
||||||
|
@ -158,11 +143,10 @@ impl Profiler {
|
||||||
println(fmt!("%31s %15s %15s %15s %15s %15s",
|
println(fmt!("%31s %15s %15s %15s %15s %15s",
|
||||||
"_category_", "_mean (ms)_", "_median (ms)_",
|
"_category_", "_mean (ms)_", "_median (ms)_",
|
||||||
"_min (ms)_", "_max (ms)_", "_bucket size_"));
|
"_min (ms)_", "_max (ms)_", "_bucket size_"));
|
||||||
for bucket in self.buckets.mut_iter() {
|
for (category, data) in self.buckets.iter() {
|
||||||
let (category, data) = match *bucket {
|
// FIXME(XXX): TreeMap currently lacks mut_iter()
|
||||||
(category, ref mut data) => (category, data),
|
let mut data = data.clone();
|
||||||
};
|
tim_sort(data);
|
||||||
tim_sort(*data);
|
|
||||||
let data_len = data.len();
|
let data_len = data.len();
|
||||||
if data_len > 0 {
|
if data_len > 0 {
|
||||||
let (mean, median, &min, &max) =
|
let (mean, median, &min, &max) =
|
||||||
|
@ -202,4 +186,12 @@ pub fn time<T>(msg: &str, callback: &fn() -> T) -> T{
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
// ensure that the order of the buckets matches the order of the enum categories
|
||||||
|
#[test]
|
||||||
|
fn check_order() {
|
||||||
|
let buckets = ProfilerCategory::empty_buckets();
|
||||||
|
assert!(buckets.len() == NumBuckets as uint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue