Skip to content

Commit

Permalink
style: Add Gecko profiler labels for when the style threads are doing…
Browse files Browse the repository at this point in the history
… work.

Differential Revision: https://phabricator.services.mozilla.com/D30869
  • Loading branch information
heycam authored and emilio committed May 29, 2019
1 parent 8dc7a25 commit 3a22bb6
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 0 deletions.
1 change: 1 addition & 0 deletions components/style/Cargo.toml
Expand Up @@ -22,6 +22,7 @@ servo = ["serde", "style_traits/servo", "servo_atoms", "servo_config", "html5eve
"cssparser/serde", "encoding_rs", "malloc_size_of/servo", "arrayvec/use_union",
"servo_url", "string_cache", "crossbeam-channel", "to_shmem/servo", "servo_arc/servo"]
gecko_debug = []
gecko_profiler = []

[dependencies]
app_units = "0.7"
Expand Down
1 change: 1 addition & 0 deletions components/style/driver.rs
Expand Up @@ -134,6 +134,7 @@ pub fn traverse_dom<E, D>(
let drain = discovered.drain(..);
pool.install(|| {
rayon::scope(|scope| {
profiler_label!(Style);
parallel::traverse_nodes(
drain,
DispatchMode::TailCall,
Expand Down
2 changes: 2 additions & 0 deletions components/style/gecko/mod.rs
Expand Up @@ -13,6 +13,8 @@ pub mod conversions;
pub mod data;
pub mod media_features;
pub mod media_queries;
#[cfg(feature = "gecko_profiler")]
pub mod profiler;
pub mod pseudo_element;
pub mod restyle_damage;
pub mod rules;
Expand Down
76 changes: 76 additions & 0 deletions components/style/gecko/profiler.rs
@@ -0,0 +1,76 @@
/* 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 https://mozilla.org/MPL/2.0/. */

//! Gecko profiler support.
//!
//! Use the `profiler_label!` macro from macros.rs.

use crate::gecko_bindings::structs;

/// A label describing a category of work that style threads can perform.
pub enum ProfilerLabel {
/// Style computation.
Style,
/// Style sheet parsing.
Parse,
}

/// RAII object that constructs and destroys a C++ AutoProfilerLabel object
/// pointed to be the specified reference.
#[cfg(feature = "gecko_profiler")]
pub struct AutoProfilerLabel<'a>(&'a mut structs::AutoProfilerLabel);

#[cfg(feature = "gecko_profiler")]
impl<'a> AutoProfilerLabel<'a> {
/// Creates a new AutoProfilerLabel with the specified label type.
///
/// unsafe since the caller must ensure that `label` is allocated on the
/// stack.
#[inline]
pub unsafe fn new(
label: &mut structs::AutoProfilerLabel,
label_type: ProfilerLabel,
) -> AutoProfilerLabel {
let category_pair = match label_type {
ProfilerLabel::Style => structs::JS::ProfilingCategoryPair_LAYOUT_StyleComputation,
ProfilerLabel::Parse => structs::JS::ProfilingCategoryPair_LAYOUT_CSSParsing,
};
structs::Gecko_Construct_AutoProfilerLabel(label, category_pair);
AutoProfilerLabel(label)
}
}

#[cfg(feature = "gecko_profiler")]
impl<'a> Drop for AutoProfilerLabel<'a> {
#[inline]
fn drop(&mut self) {
unsafe {
structs::Gecko_Destroy_AutoProfilerLabel(self.0);
}
}
}

/// Whether the Gecko profiler is currently active.
///
/// This implementation must be kept in sync with
/// `mozilla::profiler::detail::RacyFeatures::IsActive`.
#[cfg(feature = "gecko_profiler")]
#[inline]
pub fn profiler_is_active() -> bool {
use self::structs::profiler::detail;
use std::mem;
use std::sync::atomic::{AtomicU32, Ordering};

let active_and_features: &AtomicU32 = unsafe {
mem::transmute(&detail::RacyFeatures_sActiveAndFeatures)
};
(active_and_features.load(Ordering::Relaxed) & detail::RacyFeatures_Active) != 0
}

/// Always false when the Gecko profiler is disabled.
#[cfg(not(feature = "gecko_profiler"))]
#[inline]
pub fn profiler_is_active() -> bool {
false
}
30 changes: 30 additions & 0 deletions components/style/macros.rs
Expand Up @@ -104,3 +104,33 @@ macro_rules! define_keyword_type {
}
};
}

/// Place a Gecko profiler label on the stack.
///
/// The `label_type` argument must be the name of a variant of `ProfilerLabel`.
#[cfg(feature = "gecko_profiler")]
#[macro_export]
macro_rules! profiler_label {
($label_type:ident) => {
let mut _profiler_label: $crate::gecko_bindings::structs::AutoProfilerLabel = unsafe {
::std::mem::uninitialized()
};
let _profiler_label = if $crate::gecko::profiler::profiler_is_active() {
unsafe {
Some($crate::gecko::profiler::AutoProfilerLabel::new(
&mut _profiler_label,
$crate::gecko::profiler::ProfilerLabel::$label_type,
))
}
} else {
None
};
}
}

/// No-op when the Gecko profiler is not available.
#[cfg(not(feature = "gecko_profiler"))]
#[macro_export]
macro_rules! profiler_label {
($label_type:ident) => {}
}
2 changes: 2 additions & 0 deletions components/style/parallel.rs
Expand Up @@ -277,6 +277,7 @@ pub fn traverse_nodes<'a, 'scope, E, D, I>(
top_down_dom(&work, root, traversal_data, scope, pool, traversal, tls);
} else {
scope.spawn(move |scope| {
profiler_label!(Style);
let work = work;
top_down_dom(&work, root, traversal_data, scope, pool, traversal, tls);
});
Expand All @@ -286,6 +287,7 @@ pub fn traverse_nodes<'a, 'scope, E, D, I>(
let nodes: WorkUnit<E::ConcreteNode> = chunk.collect();
let traversal_data_copy = traversal_data.clone();
scope.spawn(move |scope| {
profiler_label!(Style);
let n = nodes;
top_down_dom(&*n, root, traversal_data_copy, scope, pool, traversal, tls)
});
Expand Down

0 comments on commit 3a22bb6

Please sign in to comment.