mirror of
https://github.com/servo/servo.git
synced 2025-06-19 14:48:59 +01:00
auto merge of #1152 : ILyoan/servo/parallel_selector_matching, r=SimonSapin
This an attempt to parallelize selector matching. Approach * Let the `match_subtree` spawn limited number of tasks. * Each of them takes a list of nodes that is uniformly distributed * And then each task does the selector matching for every single node in its list. (Not sure if this is worthwhile for long term especially considering CSS optimizing techniques such as ancestor filter or style sharing) Benchmark from my machine (LayoutSelectorMatchCategory) (intel i7 3.4GHz * 8, linux x86_64) * src/test/demo.html * original: 0.07ms * parallel: 0.20ms * perf-rainbow.html * original: 485ms * parallel: 245ms * A test page with 15000 nodes and 3000 CSS selector(including inline style). * original: 140ms * parallel: 60ms
This commit is contained in:
commit
ddce8b8fa0
2 changed files with 47 additions and 11 deletions
|
@ -5,6 +5,12 @@
|
|||
// High-level interface to CSS selector matching.
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::comm;
|
||||
use std::rt::default_sched_threads;
|
||||
use std::task;
|
||||
use std::vec;
|
||||
use extra::arc::RWArc;
|
||||
|
||||
use css::node_style::StyledNode;
|
||||
use css::node_util::NodeUtil;
|
||||
use layout::incremental;
|
||||
|
@ -16,7 +22,7 @@ use servo_util::tree::TreeNodeRef;
|
|||
|
||||
pub trait MatchMethods {
|
||||
fn match_node(&self, stylist: &Stylist);
|
||||
fn match_subtree(&self, stylist: &Stylist);
|
||||
fn match_subtree(&self, stylist: RWArc<Stylist>);
|
||||
|
||||
fn cascade_node(&self, parent: Option<AbstractNode<LayoutView>>);
|
||||
fn cascade_subtree(&self, parent: Option<AbstractNode<LayoutView>>);
|
||||
|
@ -36,14 +42,41 @@ impl MatchMethods for AbstractNode<LayoutView> {
|
|||
data.applicable_declarations = cell.take();
|
||||
}
|
||||
}
|
||||
fn match_subtree(&self, stylist: &Stylist) {
|
||||
self.match_node(stylist);
|
||||
fn match_subtree(&self, stylist: RWArc<Stylist>) {
|
||||
let num_tasks = default_sched_threads() * 2;
|
||||
let mut node_count = 0;
|
||||
let mut nodes_per_task = vec::from_elem(num_tasks, ~[]);
|
||||
|
||||
for kid in self.children() {
|
||||
if kid.is_element() {
|
||||
kid.match_subtree(stylist);
|
||||
for node in self.traverse_preorder() {
|
||||
if node.is_element() {
|
||||
nodes_per_task[node_count % num_tasks].push(node);
|
||||
node_count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
let (port, chan) = comm::stream();
|
||||
let chan = comm::SharedChan::new(chan);
|
||||
let mut num_spawned = 0;
|
||||
|
||||
for nodes in nodes_per_task.move_iter() {
|
||||
if nodes.len() > 0 {
|
||||
let chan = chan.clone();
|
||||
let stylist = stylist.clone();
|
||||
do task::spawn_with((nodes, stylist)) |(nodes, stylist)| {
|
||||
let nodes = Cell::new(nodes);
|
||||
do stylist.read |stylist| {
|
||||
for node in nodes.take().move_iter() {
|
||||
node.match_node(stylist);
|
||||
}
|
||||
}
|
||||
chan.send(());
|
||||
}
|
||||
num_spawned += 1;
|
||||
}
|
||||
}
|
||||
for _ in range(0, num_spawned) {
|
||||
port.recv();
|
||||
}
|
||||
}
|
||||
|
||||
fn cascade_node(&self, parent: Option<AbstractNode<LayoutView>>) {
|
||||
|
|
|
@ -20,7 +20,7 @@ use std::cast::transmute;
|
|||
use std::cell::Cell;
|
||||
use std::comm::{Port};
|
||||
use std::task;
|
||||
use extra::arc::Arc;
|
||||
use extra::arc::{Arc, RWArc};
|
||||
use geom::point::Point2D;
|
||||
use geom::rect::Rect;
|
||||
use geom::size::Size2D;
|
||||
|
@ -65,7 +65,7 @@ struct LayoutTask {
|
|||
|
||||
display_list: Option<Arc<DisplayList<AbstractNode<()>>>>,
|
||||
|
||||
stylist: Stylist,
|
||||
stylist: RWArc<Stylist>,
|
||||
profiler_chan: ProfilerChan,
|
||||
}
|
||||
|
||||
|
@ -241,7 +241,7 @@ impl LayoutTask {
|
|||
|
||||
display_list: None,
|
||||
|
||||
stylist: new_stylist(),
|
||||
stylist: RWArc::new(new_stylist()),
|
||||
profiler_chan: profiler_chan,
|
||||
}
|
||||
}
|
||||
|
@ -294,7 +294,10 @@ impl LayoutTask {
|
|||
}
|
||||
|
||||
fn handle_add_stylesheet(&mut self, sheet: Stylesheet) {
|
||||
self.stylist.add_stylesheet(sheet, AuthorOrigin);
|
||||
let sheet = Cell::new(sheet);
|
||||
do self.stylist.write |stylist| {
|
||||
stylist.add_stylesheet(sheet.take(), AuthorOrigin)
|
||||
}
|
||||
}
|
||||
|
||||
/// Performs layout constraint solving.
|
||||
|
@ -359,7 +362,7 @@ impl LayoutTask {
|
|||
ReflowDocumentDamage => {}
|
||||
MatchSelectorsDocumentDamage => {
|
||||
do profile(time::LayoutSelectorMatchCategory, self.profiler_chan.clone()) {
|
||||
node.match_subtree(&self.stylist);
|
||||
node.match_subtree(self.stylist.clone());
|
||||
node.cascade_subtree(None);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue