Have servo report traversal statistics to gecko.

This commit is contained in:
Xidorn Quan 2018-03-15 10:46:27 +11:00
parent d700fa16a1
commit 368fb574f8
2 changed files with 150 additions and 11 deletions

View file

@ -7,7 +7,8 @@
#![deny(missing_docs)]
use context::{StyleContext, ThreadLocalStyleContext, TraversalStatistics};
use context::{StyleContext, PerThreadTraversalStatistics};
use context::{ThreadLocalStyleContext, TraversalStatistics};
use dom::{SendNode, TElement, TNode};
use parallel;
use parallel::{DispatchMode, WORK_UNIT_MAX};
@ -18,6 +19,36 @@ use std::mem;
use time;
use traversal::{DomTraversal, PerLevelTraversalData, PreTraverseToken};
#[cfg(feature = "servo")]
fn should_report_statistics() -> bool {
false
}
#[cfg(feature = "gecko")]
fn should_report_statistics() -> bool {
unsafe { ::gecko_bindings::structs::ServoTraversalStatistics_sActive }
}
#[cfg(feature = "servo")]
fn report_statistics(_stats: &PerThreadTraversalStatistics) {
unreachable!("Servo never report stats");
}
#[cfg(feature = "gecko")]
fn report_statistics(stats: &PerThreadTraversalStatistics) {
// This should only be called in the main thread, or it may be racy
// to update the statistics in a global variable.
debug_assert!(unsafe { ::gecko_bindings::bindings::Gecko_IsMainThread() });
let gecko_stats = unsafe {
&mut ::gecko_bindings::structs::ServoTraversalStatistics_sSingleton
};
gecko_stats.mElementsTraversed += stats.elements_traversed;
gecko_stats.mElementsStyled += stats.elements_styled;
gecko_stats.mElementsMatched += stats.elements_matched;
gecko_stats.mStylesShared += stats.styles_shared;
gecko_stats.mStylesReused += stats.styles_reused;
}
/// Do a DOM traversal for top-down and (optionally) bottom-up processing,
/// generic over `D`.
///
@ -41,6 +72,7 @@ where
let root =
token.traversal_root().expect("Should've ensured we needed to traverse");
let report_stats = should_report_statistics();
let dump_stats = traversal.shared_context().options.dump_style_statistics;
let start_time = if dump_stats { Some(time::precise_time_s()) } else { None };
@ -113,8 +145,8 @@ where
}
}
// dump statistics to stdout if requested
if dump_stats {
// Collect statistics from thread-locals if requested.
if dump_stats || report_stats {
let mut aggregate =
mem::replace(&mut context.thread_local.statistics, Default::default());
let parallel = maybe_tls.is_some();
@ -128,14 +160,20 @@ where
});
}
let stats = TraversalStatistics::new(
aggregate,
traversal,
parallel,
start_time.unwrap()
);
if stats.is_large {
println!("{}", stats);
if report_stats {
report_statistics(&aggregate);
}
// dump statistics to stdout if requested
if dump_stats {
let stats = TraversalStatistics::new(
aggregate,
traversal,
parallel,
start_time.unwrap()
);
if stats.is_large {
println!("{}", stats);
}
}
}
}

View file

@ -13634,6 +13634,107 @@ pub mod root {
);
}
#[repr(C)]
#[derive(Debug, Copy)]
pub struct ServoTraversalStatistics {
pub mElementsTraversed: u32,
pub mElementsStyled: u32,
pub mElementsMatched: u32,
pub mStylesShared: u32,
pub mStylesReused: u32,
}
extern "C" {
#[link_name = "\u{1}_ZN7mozilla24ServoTraversalStatistics7sActiveE"]
pub static mut ServoTraversalStatistics_sActive: bool;
}
extern "C" {
#[link_name = "\u{1}_ZN7mozilla24ServoTraversalStatistics10sSingletonE"]
pub static mut ServoTraversalStatistics_sSingleton:
root::mozilla::ServoTraversalStatistics;
}
#[test]
fn bindgen_test_layout_ServoTraversalStatistics() {
assert_eq!(
::std::mem::size_of::<ServoTraversalStatistics>(),
20usize,
concat!("Size of: ", stringify!(ServoTraversalStatistics))
);
assert_eq!(
::std::mem::align_of::<ServoTraversalStatistics>(),
4usize,
concat!("Alignment of ", stringify!(ServoTraversalStatistics))
);
assert_eq!(
unsafe {
&(*(::std::ptr::null::<ServoTraversalStatistics>())).mElementsTraversed
as *const _ as usize
},
0usize,
concat!(
"Offset of field: ",
stringify!(ServoTraversalStatistics),
"::",
stringify!(mElementsTraversed)
)
);
assert_eq!(
unsafe {
&(*(::std::ptr::null::<ServoTraversalStatistics>())).mElementsStyled as *const _
as usize
},
4usize,
concat!(
"Offset of field: ",
stringify!(ServoTraversalStatistics),
"::",
stringify!(mElementsStyled)
)
);
assert_eq!(
unsafe {
&(*(::std::ptr::null::<ServoTraversalStatistics>())).mElementsMatched
as *const _ as usize
},
8usize,
concat!(
"Offset of field: ",
stringify!(ServoTraversalStatistics),
"::",
stringify!(mElementsMatched)
)
);
assert_eq!(
unsafe {
&(*(::std::ptr::null::<ServoTraversalStatistics>())).mStylesShared as *const _
as usize
},
12usize,
concat!(
"Offset of field: ",
stringify!(ServoTraversalStatistics),
"::",
stringify!(mStylesShared)
)
);
assert_eq!(
unsafe {
&(*(::std::ptr::null::<ServoTraversalStatistics>())).mStylesReused as *const _
as usize
},
16usize,
concat!(
"Offset of field: ",
stringify!(ServoTraversalStatistics),
"::",
stringify!(mStylesReused)
)
);
}
impl Clone for ServoTraversalStatistics {
fn clone(&self) -> Self {
*self
}
}
#[repr(C)]
#[derive(Debug)]
pub struct CSSFontFaceDescriptors {
pub mFamily: root::nsCSSValue,