4 ms·
You may want to actually read this code. You can start by searching "LayoutStyleRecalc" at https://github.com/servo/servo/blob/master/components/layout_thread/l
by sanxiyn 9y ago
You may want to actually read this code. You can start by searching "LayoutStyleRecalc" at https://github.com/servo/servo/blob/master/components/layout_thread/lib.rs https://github.com/servo/servo/blob/master/components/layout.... Following is verbatim copy.
// Perform CSS selector matching and flow construction.
if traversal_driver.is_parallel() {
let pool = self.parallel_traversal.as_ref().unwrap();
// Parallel mode
parallel::traverse_dom::<ServoLayoutElement, RecalcStyleAndConstructFlows>(
&traversal, element, token, pool);
} else {
// Sequential mode
sequential::traverse_dom::<ServoLayoutElement, RecalcStyleAndConstructFlows>(
&traversal, element, token);
}
- sanxiyn 9y agoHm, you may be lost if you don't have Rust IDE handy to jump around. Web cross reference for Rust code navigation is in development, but until that is ready, the next step is https://github.com/servo/servo/blob/master/components/layout/traversal.rs https://github.com/servo/servo/blob/master/components/layout... parallel and sequential traverse_dom is generic traversal code which calls DomTraversal::process_preorder etc to do actual work. Here is lightly edited code: impl<'a, E> DomTraversal<E> for RecalcStyleAndConstructFlows<'a> where E: TElement, E::ConcreteNode: LayoutNode, E::FontMetricsProvider: Send, { fn process_preorder<F>(&self, traversal_data: &PerLevelTraversalData, context: &mut StyleContext<E>, node: E::ConcreteNode, note_child: F) where F: FnMut(E::ConcreteNode) { if !node.is_text_node() { let el = node.as_element().unwrap(); let mut data = el.mutate_data().unwrap(); recalc_style_at(self, traversal_data, context, el, &mut data, note_child); } } }
- taeric 9y agoWhat am I aiming for on this read? I'm assuming the hard parts are swallowed elsewhere, which is good. I'm a little surprised there are two methods for the traversal, depending on the parallel versus sequential. (I'd expect that could have been switched based on the "pool" parameter passed to a single method. No, I don't actually care.)
- sanxiyn 9y agoWhat do you consider hard parts? The actual magic is that there is no hard parts.
- taeric 9y agoI haven't read it. That snippet just seemed odd to me. The hard parts, in this case, would be in Rust, most likely. I'm assuming that flipping CSS to parallel is not a trivial process. I'm further assuming that there is still some sort of locking mechanism so that you don't fire off two parallel traversals at the same time. Or allow updates during a scan. (Or abort running scans if an update happens?)
- sanxiyn 9y agoAh yes, parallelism (locking etc) part is entirely handled in generic Rust library (Rayon in this case), and not specific to Stylo at all. Here is where Stylo meets Rayon, https://github.com/servo/servo/blob/master/components/style/parallel.rs https://github.com/servo/servo/blob/master/components/style/... //! Implements parallel traversal over the DOM tree. //! //! This traversal is based on Rayon, and therefore its safety is largely //! verified by the type system. /// A parallel top-down DOM traversal. /// /// This algorithm traverses the DOM in a breadth-first, top-down manner. The /// goals are: /// * Never process a child before its parent (since child style depends on /// parent style). If this were to happen, the styling algorithm would panic. /// * Prioritize discovering nodes as quickly as possible to maximize /// opportunities for parallelism. But this needs to be weighed against /// styling cousins on a single thread to improve sharing. /// * Style all the children of a given node (i.e. all sibling nodes) on /// a single thread (with an upper bound to handle nodes with an /// abnormally large number of children). This is important because we use /// a thread-local cache to share styles between siblings.
- peoplewindow 9y agoIt looks like Rayon is the same thing as Java's ForkJoinPool and parallel streams but with the neat trick (really, Rust's neat trick) that it can statically check that the code is safe to parallelise through the borrow checker.
- bholley 9y agoNote that everything in components/layout is servo-specific and not used by Stylo / Firefox. The code in components/style is shared, and the code that hooks it up to Firefox is in ports/geckolib/glue.rs (specifically Servo_TraverseSubtree).