/* This Source Code Form is subject to the terms of the Mozilla Public *License,v.2.0.IfacopyoftheMPLwasnotdistributedwiththis
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
//! Implements parallel traversal over the DOM tree. //! //! This traversal is based on Rayon, and therefore its safety is largely //! verified by the type system. //! //! The primary trickiness and fine print for the above relates to the //! thread safety of the DOM nodes themselves. Accessing a DOM element //! concurrently on multiple threads is actually mostly "safe", since all //! the mutable state is protected by an AtomicRefCell, and so we'll //! generally panic if something goes wrong. Still, we try to to enforce our //! thread invariants at compile time whenever possible. As such, TNode and //! TElement are not Send, so ordinary style system code cannot accidentally //! share them with other threads. In the parallel traversal, we explicitly //! invoke |unsafe { SendNode::new(n) }| to put nodes in containers that may //! be sent to other threads. This occurs in only a handful of places and is //! easy to grep for. At the time of this writing, there is no other unsafe //! code in the parallel traversal.
#![deny(missing_docs)]
usecrate::context::{StyleContext, ThreadLocalStyleContext}; usecrate::dom::{OpaqueNode, SendNode, TElement}; usecrate::scoped_tls::ScopedTLS; usecrate::traversal::{DomTraversal, PerLevelTraversalData}; use std::collections::VecDeque;
/// The minimum stack size for a thread in the styling pool, in kilobytes. #[cfg(feature = "gecko")] pubconst STYLE_THREAD_STACK_SIZE_KB: usize = 256;
/// The minimum stack size for a thread in the styling pool, in kilobytes. /// Servo requires a bigger stack in debug builds. #[cfg(feature = "servo")] pubconst STYLE_THREAD_STACK_SIZE_KB: usize = 512;
/// The stack margin. If we get this deep in the stack, we will skip recursive /// optimizations to ensure that there is sufficient room for non-recursive work. /// /// We allocate large safety margins because certain OS calls can use very large /// amounts of stack space [1]. Reserving a larger-than-necessary stack costs us /// address space, but if we keep our safety margin big, we will generally avoid /// committing those extra pages, and only use them in edge cases that would /// otherwise cause crashes. /// /// When measured with 128KB stacks and 40KB margin, we could support 53 /// levels of recursion before the limiter kicks in, on x86_64-Linux [2]. When /// we doubled the stack size, we added it all to the safety margin, so we should /// be able to get the same amount of recursion. /// /// [1] https://bugzilla.mozilla.org/show_bug.cgi?id=1395708#c15 /// [2] See Gecko bug 1376883 for more discussion on the measurements. pubconst STACK_SAFETY_MARGIN_KB: usize = 168;
/// A callback to create our thread local context. This needs to be /// out of line so we don't allocate stack space for the entire struct /// in the caller. #[inline(never)] pub(crate) fn create_thread_local_context<'scope, E>(slot: &mut Option<ThreadLocalStyleContext<E>>) where
E: TElement + 'scope,
{
*slot = Some(ThreadLocalStyleContext::new());
}
// If we have enough children at the next depth in the DOM, spawn them to a different job // relatively soon, while keeping always at least `local_queue_size` worth of work for // ourselves. let discovered_children = discovered.len() - nodes_remaining_at_current_depth; if discovered_children >= work_unit_max &&
discovered.len() >= local_queue_size + work_unit_max &&
scope.is_some()
{ let kept_work = std::cmp::max(nodes_remaining_at_current_depth, local_queue_size); letmut traversal_data_copy = traversal_data.clone();
traversal_data_copy.current_dom_depth += 1;
distribute_work(
discovered.range(kept_work..).cloned(),
traversal_root,
work_unit_max,
traversal_data_copy,
scope.unwrap(),
traversal,
tls,
);
discovered.truncate(kept_work);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.