Reduce allocations during parallel layout

This commit is contained in:
Matt Brubeck 2017-06-06 11:54:37 -07:00
parent ea154d8278
commit 7fd1626901

View file

@ -14,6 +14,7 @@ use flow_ref::FlowRef;
use profile_traits::time::{self, TimerMetadata, profile}; use profile_traits::time::{self, TimerMetadata, profile};
use rayon; use rayon;
use servo_config::opts; use servo_config::opts;
use smallvec::SmallVec;
use std::mem; use std::mem;
use std::sync::atomic::{AtomicIsize, Ordering}; use std::sync::atomic::{AtomicIsize, Ordering};
use style::dom::UnsafeNode; use style::dom::UnsafeNode;
@ -25,6 +26,8 @@ pub use style::parallel::traverse_dom;
/// Traversal chunk size. /// Traversal chunk size.
const CHUNK_SIZE: usize = 16; const CHUNK_SIZE: usize = 16;
pub type FlowList = SmallVec<[UnsafeNode; CHUNK_SIZE]>;
#[allow(dead_code)] #[allow(dead_code)]
fn static_assertion(node: UnsafeNode) { fn static_assertion(node: UnsafeNode) {
unsafe { unsafe {
@ -128,7 +131,7 @@ fn top_down_flow<'scope>(unsafe_flows: &[UnsafeFlow],
assign_isize_traversal: &'scope AssignISizes, assign_isize_traversal: &'scope AssignISizes,
assign_bsize_traversal: &'scope AssignBSizes) assign_bsize_traversal: &'scope AssignBSizes)
{ {
let mut discovered_child_flows = vec![]; let mut discovered_child_flows = FlowList::new();
for unsafe_flow in unsafe_flows { for unsafe_flow in unsafe_flows {
let mut had_children = false; let mut had_children = false;
@ -161,13 +164,30 @@ fn top_down_flow<'scope>(unsafe_flows: &[UnsafeFlow],
} }
} }
for chunk in discovered_child_flows.chunks(CHUNK_SIZE) { if discovered_child_flows.is_empty() {
let nodes = chunk.iter().cloned().collect::<Vec<_>>().into_boxed_slice(); return
}
if discovered_child_flows.len() <= CHUNK_SIZE {
// We can handle all the children in this work unit.
top_down_flow(&discovered_child_flows,
scope,
&assign_isize_traversal,
&assign_bsize_traversal);
} else {
// Spawn a new work unit for each chunk after the first.
let mut chunks = discovered_child_flows.chunks(CHUNK_SIZE);
let first_chunk = chunks.next();
for chunk in chunks {
let nodes = chunk.iter().cloned().collect::<FlowList>();
scope.spawn(move |scope| { scope.spawn(move |scope| {
top_down_flow(&nodes, scope, &assign_isize_traversal, &assign_bsize_traversal); top_down_flow(&nodes, scope, &assign_isize_traversal, &assign_bsize_traversal);
}); });
} }
if let Some(chunk) = first_chunk {
top_down_flow(chunk, scope, &assign_isize_traversal, &assign_bsize_traversal);
}
}
} }
pub fn traverse_flow_tree_preorder( pub fn traverse_flow_tree_preorder(
@ -183,7 +203,7 @@ pub fn traverse_flow_tree_preorder(
let assign_isize_traversal = &AssignISizes { layout_context: &context }; let assign_isize_traversal = &AssignISizes { layout_context: &context };
let assign_bsize_traversal = &AssignBSizes { layout_context: &context }; let assign_bsize_traversal = &AssignBSizes { layout_context: &context };
let nodes = vec![borrowed_flow_to_unsafe_flow(root)].into_boxed_slice(); let nodes = [borrowed_flow_to_unsafe_flow(root)];
queue.install(move || { queue.install(move || {
rayon::scope(move |scope| { rayon::scope(move |scope| {