mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
Split TraversalStatistics into two parts.
This commit is contained in:
parent
afa377acfd
commit
d700fa16a1
2 changed files with 64 additions and 62 deletions
|
@ -296,7 +296,7 @@ impl ElementCascadeInputs {
|
||||||
/// thread and then combine them after the threads join via the Add
|
/// thread and then combine them after the threads join via the Add
|
||||||
/// implementation below.
|
/// implementation below.
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct TraversalStatistics {
|
pub struct PerThreadTraversalStatistics {
|
||||||
/// The total number of elements traversed.
|
/// The total number of elements traversed.
|
||||||
pub elements_traversed: u32,
|
pub elements_traversed: u32,
|
||||||
/// The number of elements where has_styles() went from false to true.
|
/// The number of elements where has_styles() went from false to true.
|
||||||
|
@ -308,6 +308,28 @@ pub struct TraversalStatistics {
|
||||||
/// The number of styles reused via rule node comparison from the
|
/// The number of styles reused via rule node comparison from the
|
||||||
/// StyleSharingCache.
|
/// StyleSharingCache.
|
||||||
pub styles_reused: u32,
|
pub styles_reused: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Implementation of Add to aggregate statistics across different threads.
|
||||||
|
impl<'a> ops::Add for &'a PerThreadTraversalStatistics {
|
||||||
|
type Output = PerThreadTraversalStatistics;
|
||||||
|
fn add(self, other: Self) -> PerThreadTraversalStatistics {
|
||||||
|
PerThreadTraversalStatistics {
|
||||||
|
elements_traversed: self.elements_traversed + other.elements_traversed,
|
||||||
|
elements_styled: self.elements_styled + other.elements_styled,
|
||||||
|
elements_matched: self.elements_matched + other.elements_matched,
|
||||||
|
styles_shared: self.styles_shared + other.styles_shared,
|
||||||
|
styles_reused: self.styles_reused + other.styles_reused,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Statistics gathered during the traversal plus some information from
|
||||||
|
/// other sources including stylist.
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct TraversalStatistics {
|
||||||
|
/// Aggregated statistics gathered during the traversal.
|
||||||
|
pub aggregated: PerThreadTraversalStatistics,
|
||||||
/// The number of selectors in the stylist.
|
/// The number of selectors in the stylist.
|
||||||
pub selectors: u32,
|
pub selectors: u32,
|
||||||
/// The number of revalidation selectors.
|
/// The number of revalidation selectors.
|
||||||
|
@ -321,38 +343,9 @@ pub struct TraversalStatistics {
|
||||||
/// Time spent in the traversal, in milliseconds.
|
/// Time spent in the traversal, in milliseconds.
|
||||||
pub traversal_time_ms: f64,
|
pub traversal_time_ms: f64,
|
||||||
/// Whether this was a parallel traversal.
|
/// Whether this was a parallel traversal.
|
||||||
pub is_parallel: Option<bool>,
|
pub is_parallel: bool,
|
||||||
/// Whether this is a "large" traversal.
|
/// Whether this is a "large" traversal.
|
||||||
pub is_large: Option<bool>,
|
pub is_large: bool,
|
||||||
}
|
|
||||||
|
|
||||||
/// Implementation of Add to aggregate statistics across different threads.
|
|
||||||
impl<'a> ops::Add for &'a TraversalStatistics {
|
|
||||||
type Output = TraversalStatistics;
|
|
||||||
fn add(self, other: Self) -> TraversalStatistics {
|
|
||||||
debug_assert!(self.traversal_time_ms == 0.0 && other.traversal_time_ms == 0.0,
|
|
||||||
"traversal_time_ms should be set at the end by the caller");
|
|
||||||
debug_assert!(self.selectors == 0, "set at the end");
|
|
||||||
debug_assert!(self.revalidation_selectors == 0, "set at the end");
|
|
||||||
debug_assert!(self.dependency_selectors == 0, "set at the end");
|
|
||||||
debug_assert!(self.declarations == 0, "set at the end");
|
|
||||||
debug_assert!(self.stylist_rebuilds == 0, "set at the end");
|
|
||||||
TraversalStatistics {
|
|
||||||
elements_traversed: self.elements_traversed + other.elements_traversed,
|
|
||||||
elements_styled: self.elements_styled + other.elements_styled,
|
|
||||||
elements_matched: self.elements_matched + other.elements_matched,
|
|
||||||
styles_shared: self.styles_shared + other.styles_shared,
|
|
||||||
styles_reused: self.styles_reused + other.styles_reused,
|
|
||||||
selectors: 0,
|
|
||||||
revalidation_selectors: 0,
|
|
||||||
dependency_selectors: 0,
|
|
||||||
declarations: 0,
|
|
||||||
stylist_rebuilds: 0,
|
|
||||||
traversal_time_ms: 0.0,
|
|
||||||
is_parallel: None,
|
|
||||||
is_large: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Format the statistics in a way that the performance test harness understands.
|
/// Format the statistics in a way that the performance test harness understands.
|
||||||
|
@ -361,16 +354,16 @@ impl fmt::Display for TraversalStatistics {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
debug_assert!(self.traversal_time_ms != 0.0, "should have set traversal time");
|
debug_assert!(self.traversal_time_ms != 0.0, "should have set traversal time");
|
||||||
writeln!(f, "[PERF] perf block start")?;
|
writeln!(f, "[PERF] perf block start")?;
|
||||||
writeln!(f, "[PERF],traversal,{}", if self.is_parallel.unwrap() {
|
writeln!(f, "[PERF],traversal,{}", if self.is_parallel {
|
||||||
"parallel"
|
"parallel"
|
||||||
} else {
|
} else {
|
||||||
"sequential"
|
"sequential"
|
||||||
})?;
|
})?;
|
||||||
writeln!(f, "[PERF],elements_traversed,{}", self.elements_traversed)?;
|
writeln!(f, "[PERF],elements_traversed,{}", self.aggregated.elements_traversed)?;
|
||||||
writeln!(f, "[PERF],elements_styled,{}", self.elements_styled)?;
|
writeln!(f, "[PERF],elements_styled,{}", self.aggregated.elements_styled)?;
|
||||||
writeln!(f, "[PERF],elements_matched,{}", self.elements_matched)?;
|
writeln!(f, "[PERF],elements_matched,{}", self.aggregated.elements_matched)?;
|
||||||
writeln!(f, "[PERF],styles_shared,{}", self.styles_shared)?;
|
writeln!(f, "[PERF],styles_shared,{}", self.aggregated.styles_shared)?;
|
||||||
writeln!(f, "[PERF],styles_reused,{}", self.styles_reused)?;
|
writeln!(f, "[PERF],styles_reused,{}", self.aggregated.styles_reused)?;
|
||||||
writeln!(f, "[PERF],selectors,{}", self.selectors)?;
|
writeln!(f, "[PERF],selectors,{}", self.selectors)?;
|
||||||
writeln!(f, "[PERF],revalidation_selectors,{}", self.revalidation_selectors)?;
|
writeln!(f, "[PERF],revalidation_selectors,{}", self.revalidation_selectors)?;
|
||||||
writeln!(f, "[PERF],dependency_selectors,{}", self.dependency_selectors)?;
|
writeln!(f, "[PERF],dependency_selectors,{}", self.dependency_selectors)?;
|
||||||
|
@ -382,29 +375,33 @@ impl fmt::Display for TraversalStatistics {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TraversalStatistics {
|
impl TraversalStatistics {
|
||||||
/// Computes the traversal time given the start time in seconds.
|
/// Generate complete traversal statistics.
|
||||||
pub fn finish<E, D>(&mut self, traversal: &D, parallel: bool, start: f64)
|
///
|
||||||
|
/// The traversal time is computed given the start time in seconds.
|
||||||
|
pub fn new<E, D>(
|
||||||
|
aggregated: PerThreadTraversalStatistics,
|
||||||
|
traversal: &D,
|
||||||
|
parallel: bool,
|
||||||
|
start: f64
|
||||||
|
) -> TraversalStatistics
|
||||||
where
|
where
|
||||||
E: TElement,
|
E: TElement,
|
||||||
D: DomTraversal<E>,
|
D: DomTraversal<E>,
|
||||||
{
|
{
|
||||||
let threshold = traversal.shared_context().options.style_statistics_threshold;
|
let threshold = traversal.shared_context().options.style_statistics_threshold;
|
||||||
let stylist = traversal.shared_context().stylist;
|
let stylist = traversal.shared_context().stylist;
|
||||||
|
let is_large = aggregated.elements_traversed as usize >= threshold;
|
||||||
self.is_parallel = Some(parallel);
|
TraversalStatistics {
|
||||||
self.is_large = Some(self.elements_traversed as usize >= threshold);
|
aggregated,
|
||||||
self.traversal_time_ms = (time::precise_time_s() - start) * 1000.0;
|
selectors: stylist.num_selectors() as u32,
|
||||||
self.selectors = stylist.num_selectors() as u32;
|
revalidation_selectors: stylist.num_revalidation_selectors() as u32,
|
||||||
self.revalidation_selectors = stylist.num_revalidation_selectors() as u32;
|
dependency_selectors: stylist.num_invalidations() as u32,
|
||||||
self.dependency_selectors = stylist.num_invalidations() as u32;
|
declarations: stylist.num_declarations() as u32,
|
||||||
self.declarations = stylist.num_declarations() as u32;
|
stylist_rebuilds: stylist.num_rebuilds() as u32,
|
||||||
self.stylist_rebuilds = stylist.num_rebuilds() as u32;
|
traversal_time_ms: (time::precise_time_s() - start) * 1000.0,
|
||||||
}
|
is_parallel: parallel,
|
||||||
|
is_large
|
||||||
/// Returns whether this traversal is 'large' in order to avoid console spam
|
}
|
||||||
/// from lots of tiny traversals.
|
|
||||||
pub fn is_large_traversal(&self) -> bool {
|
|
||||||
self.is_large.unwrap()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -714,7 +711,7 @@ pub struct ThreadLocalStyleContext<E: TElement> {
|
||||||
/// than the current element).
|
/// than the current element).
|
||||||
pub selector_flags: SelectorFlagsMap<E>,
|
pub selector_flags: SelectorFlagsMap<E>,
|
||||||
/// Statistics about the traversal.
|
/// Statistics about the traversal.
|
||||||
pub statistics: TraversalStatistics,
|
pub statistics: PerThreadTraversalStatistics,
|
||||||
/// The struct used to compute and cache font metrics from style
|
/// The struct used to compute and cache font metrics from style
|
||||||
/// for evaluation of the font-relative em/ch units and font-size
|
/// for evaluation of the font-relative em/ch units and font-size
|
||||||
pub font_metrics_provider: E::FontMetricsProvider,
|
pub font_metrics_provider: E::FontMetricsProvider,
|
||||||
|
@ -736,7 +733,7 @@ impl<E: TElement> ThreadLocalStyleContext<E> {
|
||||||
new_animations_sender: shared.local_context_creation_data.lock().unwrap().new_animations_sender.clone(),
|
new_animations_sender: shared.local_context_creation_data.lock().unwrap().new_animations_sender.clone(),
|
||||||
tasks: SequentialTaskList(Vec::new()),
|
tasks: SequentialTaskList(Vec::new()),
|
||||||
selector_flags: SelectorFlagsMap::new(),
|
selector_flags: SelectorFlagsMap::new(),
|
||||||
statistics: TraversalStatistics::default(),
|
statistics: PerThreadTraversalStatistics::default(),
|
||||||
font_metrics_provider: E::FontMetricsProvider::create_from(shared),
|
font_metrics_provider: E::FontMetricsProvider::create_from(shared),
|
||||||
stack_limit_checker: StackLimitChecker::new(
|
stack_limit_checker: StackLimitChecker::new(
|
||||||
(STYLE_THREAD_STACK_SIZE_KB - STACK_SAFETY_MARGIN_KB) * 1024),
|
(STYLE_THREAD_STACK_SIZE_KB - STACK_SAFETY_MARGIN_KB) * 1024),
|
||||||
|
@ -753,7 +750,7 @@ impl<E: TElement> ThreadLocalStyleContext<E> {
|
||||||
bloom_filter: StyleBloom::new(),
|
bloom_filter: StyleBloom::new(),
|
||||||
tasks: SequentialTaskList(Vec::new()),
|
tasks: SequentialTaskList(Vec::new()),
|
||||||
selector_flags: SelectorFlagsMap::new(),
|
selector_flags: SelectorFlagsMap::new(),
|
||||||
statistics: TraversalStatistics::default(),
|
statistics: PerThreadTraversalStatistics::default(),
|
||||||
font_metrics_provider: E::FontMetricsProvider::create_from(shared),
|
font_metrics_provider: E::FontMetricsProvider::create_from(shared),
|
||||||
stack_limit_checker: StackLimitChecker::new(
|
stack_limit_checker: StackLimitChecker::new(
|
||||||
(STYLE_THREAD_STACK_SIZE_KB - STACK_SAFETY_MARGIN_KB) * 1024),
|
(STYLE_THREAD_STACK_SIZE_KB - STACK_SAFETY_MARGIN_KB) * 1024),
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
#![deny(missing_docs)]
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
use context::{StyleContext, ThreadLocalStyleContext};
|
use context::{StyleContext, ThreadLocalStyleContext, TraversalStatistics};
|
||||||
use dom::{SendNode, TElement, TNode};
|
use dom::{SendNode, TElement, TNode};
|
||||||
use parallel;
|
use parallel;
|
||||||
use parallel::{DispatchMode, WORK_UNIT_MAX};
|
use parallel::{DispatchMode, WORK_UNIT_MAX};
|
||||||
|
@ -128,9 +128,14 @@ where
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
aggregate.finish(traversal, parallel, start_time.unwrap());
|
let stats = TraversalStatistics::new(
|
||||||
if aggregate.is_large_traversal() {
|
aggregate,
|
||||||
println!("{}", aggregate);
|
traversal,
|
||||||
|
parallel,
|
||||||
|
start_time.unwrap()
|
||||||
|
);
|
||||||
|
if stats.is_large {
|
||||||
|
println!("{}", stats);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue