Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added dom obj counting to decide sequential/parallel layout (#10110) #11713

Closed
wants to merge 2 commits into from
Closed
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

@@ -32,7 +32,7 @@ range = {path = "../range"}
rustc-serialize = "0.3"
script = {path = "../script"}
script_traits = {path = "../script_traits"}
selectors = {version = "0.6", features = ["heap_size"]}
selectors = {git = "https://github.com/avadacatavra/rust-selectors.git", features = ["heap_size"]}
serde_json = "0.7"
serde_macros = "0.7"
smallvec = "0.1"
@@ -1131,6 +1131,8 @@ impl BlockFlow {
self.base.position = LogicalRect::from_point_size(self.base.writing_mode,
origin,
self.base.position.size);

debug!("{}", self.base.writing_mode);
}

pub fn explicit_block_containing_size(&self, layout_context: &LayoutContext) -> Option<Au> {
@@ -1345,6 +1347,7 @@ impl BlockFlow {

let mut inline_start_margin_edge = inline_start_content_edge;
let mut inline_end_margin_edge = inline_end_content_edge;


let mut iterator = self.base.child_iter_mut().enumerate().peekable();
while let Some((i, kid)) = iterator.next() {
@@ -1358,9 +1361,11 @@ impl BlockFlow {
if kid_base.flags.contains(INLINE_POSITION_IS_STATIC) {
kid_base.position.start.i =
if kid_mode.is_bidi_ltr() == containing_block_mode.is_bidi_ltr() {
debug!("Is LTR");
inline_start_content_edge
} else {
// The kid's inline 'start' is at the parent's 'end'
debug!("Is RTL");
inline_end_content_edge
};
}
@@ -2333,6 +2338,7 @@ pub trait ISizeAndMarginsComputer {

// FIXME (mbrubeck): Get correct containing block for positioned blocks?
let container_mode = block.base.block_container_writing_mode;
debug!("Flow {} is in container writing mode {}", block.base.debug_id(), container_mode);
let container_size = block.base.block_container_inline_size;

let fragment = block.fragment();
@@ -117,6 +117,12 @@ impl<'a> DoubleEndedIterator for FlowListIterator<'a> {
}
}

impl<'a> DoubleEndedIterator for MutFlowListIterator<'a> {
fn next_back(&mut self) -> Option<&'a mut Flow> {
self.it.next_back().map(flow_ref::deref_mut)
}
}

impl<'a> Iterator for MutFlowListIterator<'a> {
type Item = &'a mut Flow;
#[inline]
@@ -189,7 +189,10 @@ pub struct LayoutThread {
first_reflow: bool,

/// The workers that we use for parallel operation.
parallel_traversal: Option<WorkQueue<SharedLayoutContext, WorkQueueData>>,
parallel_traversal: WorkQueue<SharedLayoutContext, WorkQueueData>,

/// Flag to indicate whether to use parallel operations
parallel_flag: bool,

/// Starts at zero, and increased by one every time a layout completes.
/// This can be used to easily check for invalid stale data.
@@ -396,12 +399,13 @@ impl LayoutThread {
let device = Device::new(
MediaType::Screen,
opts::get().initial_window_size.as_f32() * ScaleFactor::new(1.0));
let parallel_traversal = if opts::get().layout_threads != 1 {
Some(WorkQueue::new("LayoutWorker", thread_state::LAYOUT,
opts::get().layout_threads))
} else {
None
};

let parallel_traversal = WorkQueue::new("LayoutWorker",
thread_state::LAYOUT,
opts::get().layout_threads);


debug!("Possible layout Threads: {}", opts::get().layout_threads);

// Create the channel on which new animations can be sent.
let (new_animations_sender, new_animations_receiver) = channel();
@@ -448,6 +452,7 @@ impl LayoutThread {
font_cache_receiver: font_cache_receiver,
font_cache_sender: ipc_font_cache_sender,
parallel_traversal: parallel_traversal,
parallel_flag: true,
generation: 0,
new_animations_sender: new_animations_sender,
new_animations_receiver: new_animations_receiver,
@@ -721,16 +726,15 @@ impl LayoutThread {
});

// ... as do each of the LayoutWorkers, if present.
if let Some(ref traversal) = self.parallel_traversal {
let sizes = traversal.heap_size_of_tls(heap_size_of_local_context);
for (i, size) in sizes.iter().enumerate() {
reports.push(Report {
path: path![formatted_url,
format!("layout-worker-{}-local-context", i)],
kind: ReportKind::ExplicitJemallocHeapSize,
size: *size,
});
}
let ref traversal = self.parallel_traversal;
let sizes = traversal.heap_size_of_tls(heap_size_of_local_context);
for (i, size) in sizes.iter().enumerate() {
reports.push(Report {
path: path![formatted_url,
format!("layout-worker-{}-local-context", i)],
kind: ReportKind::ExplicitJemallocHeapSize,
size: *size,
});
}

reports_chan.send(reports);
@@ -783,9 +787,8 @@ impl LayoutThread {
/// Shuts down the layout thread now. If there are any DOM nodes left, layout will now (safely)
/// crash.
fn exit_now(&mut self) {
if let Some(ref mut traversal) = self.parallel_traversal {
traversal.shutdown()
}
let ref mut traversal = self.parallel_traversal;
traversal.shutdown();

self.paint_chan.send(LayoutToPaintMsg::Exit).unwrap();
}
@@ -1003,7 +1006,14 @@ impl LayoutThread {
let document = unsafe { ServoLayoutNode::new(&data.document) };
let document = document.as_document().unwrap();

// Parallelize if there's more than 750 objects based on rzambre's suggestion
// https://github.com/servo/servo/issues/10110
//self.parallel_flag = opts::get().layout_threads > 1;// && data.dom_count > 750;
self.parallel_flag = false;
//self.parallel_flag = true;
debug!("layout: received layout request for: {}", self.url);
debug!("Number of objects in DOM: {}", data.dom_count);
debug!("layout: parallel? {}", self.parallel_flag);

let mut rw_data = possibly_locked_rw_data.lock();

@@ -1127,18 +1137,15 @@ impl LayoutThread {
self.time_profiler_chan.clone(),
|| {
// Perform CSS selector matching and flow construction.
match self.parallel_traversal {
None => {
sequential::traverse_dom::<ServoLayoutNode, RecalcStyleAndConstructFlows>(
node, &shared_layout_context);
}
Some(ref mut traversal) => {
parallel::traverse_dom::<ServoLayoutNode, RecalcStyleAndConstructFlows>(
node, &shared_layout_context, traversal);
}
}
});

if self.parallel_flag {
// Parallel mode
parallel::traverse_dom::<ServoLayoutNode, RecalcStyleAndConstructFlows>(
node, &shared_layout_context, &mut self.parallel_traversal);
} else {
// Sequential mode
sequential::traverse_dom::<ServoLayoutNode, RecalcStyleAndConstructFlows>(
node, &shared_layout_context);
}});
// TODO(pcwalton): Measure energy usage of text shaping, perhaps?
let text_shaping_time =
(font::get_and_reset_text_shaping_performance_counter() as u64) /
@@ -1388,19 +1395,18 @@ impl LayoutThread {
self.time_profiler_chan.clone(),
|| {
let profiler_metadata = self.profiler_metadata();
match self.parallel_traversal {
None => {
// Sequential mode.
LayoutThread::solve_constraints(&mut root_flow, &layout_context)
}
Some(ref mut parallel) => {
// Parallel mode.
LayoutThread::solve_constraints_parallel(parallel,
&mut root_flow,
profiler_metadata,
self.time_profiler_chan.clone(),
&*layout_context);
}

debug!("layout: post style parallel? {}", self.parallel_flag);
if self.parallel_flag {
// Parallel mode.
LayoutThread::solve_constraints_parallel(&mut self.parallel_traversal,
&mut root_flow,
profiler_metadata,
self.time_profiler_chan.clone(),
&*layout_context);
} else {
//Sequential mode
LayoutThread::solve_constraints(&mut root_flow, &layout_context);
}
});
}
@@ -50,6 +50,7 @@ pub fn traverse_flow_tree_preorder(root: &mut FlowRef,
}

for kid in flow::child_iter_mut(flow) {
debug!("Assign sizes for KID"); //not called
doit(kid, assign_inline_sizes, assign_block_sizes);
}

@@ -54,7 +54,7 @@ ref_slice = "1.0"
regex = "0.1.43"
rustc-serialize = "0.3"
script_traits = {path = "../script_traits"}
selectors = {version = "0.6", features = ["heap_size"]}
selectors = {git = "https://github.com/avadacatavra/rust-selectors.git", features = ["heap_size"]}
serde = "0.7"
smallvec = "0.1"
string_cache = {version = "0.2.18", features = ["heap_size", "unstable"]}
@@ -239,6 +239,8 @@ pub struct Document {
origin: Origin,
/// https://w3c.github.io/webappsec-referrer-policy/#referrer-policy-states
referrer_policy: Cell<Option<ReferrerPolicy>>,
/// track number of dom elements issue #10110
dom_count: Cell<u32>,
}

#[derive(JSTraceable, HeapSizeOf)]
@@ -396,6 +398,14 @@ impl Document {
self.base_element.set(base.r());
}

pub fn dom_count(&self) -> u32 {
self.dom_count.get()
}

pub fn increment_dom_count(&self) {
self.dom_count.set(self.dom_count.get() + 1);
}

pub fn quirks_mode(&self) -> QuirksMode {
self.quirks_mode.get()
}
@@ -1699,6 +1709,7 @@ impl Document {
origin: origin,
//TODO - setting this for now so no Referer header set
referrer_policy: Cell::new(Some(ReferrerPolicy::NoReferrer)),
dom_count: Cell::new(0),
}
}

@@ -255,6 +255,7 @@ impl ServoHTMLParser {
pipeline: pipeline,
};


reflect_dom_object(box parser, GlobalRef::Window(document.window()),
ServoHTMLParserBinding::Wrap)
}
@@ -313,6 +314,7 @@ impl ServoHTMLParser {
&self.pending_input
}


}

impl ServoHTMLParser {
@@ -1082,6 +1082,7 @@ impl Window {
window_size: window_size,
script_join_chan: join_chan,
query_type: query_type,
dom_count: self.Document().dom_count(),
};

self.layout_chan.send(Msg::Reflow(reflow)).unwrap();
@@ -226,6 +226,8 @@ pub struct ScriptReflow {
pub script_join_chan: Sender<()>,
/// The type of query if any to perform during this reflow.
pub query_type: ReflowQueryType,
/// The number of objects in the dom #10110
pub dom_count: u32,
}

impl Drop for ScriptReflow {
@@ -91,6 +91,8 @@ impl<'a> TreeSink for servohtmlparser::Sink {
elem.set_attribute_from_parser(attr.name, DOMString::from(String::from(attr.value)), None);
}

self.document.increment_dom_count();

JS::from_ref(elem.upcast())
}

Some generated files are not rendered by default. Learn more.

@@ -29,7 +29,7 @@ matches = "0.1"
num-traits = "0.1.32"
plugins = {path = "../plugins"}
rustc-serialize = "0.3"
selectors = {version = "0.6", features = ["heap_size", "unstable"]}
selectors = {git = "https://github.com/avadacatavra/rust-selectors.git", features = ["heap_size", "unstable"]}
serde = {version = "0.7", features = ["nightly"]}
serde_macros = "0.7"
smallvec = "0.1"
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.