Build objects in parallel!

This commit is contained in:
Patrick Walton 2018-12-29 17:08:49 -08:00
parent abb062bf71
commit ad9da96336
3 changed files with 22 additions and 3 deletions

1
Cargo.lock generated
View File

@ -1492,6 +1492,7 @@ dependencies = [
"quick-xml 0.12.4 (registry+https://github.com/rust-lang/crates.io-index)", "quick-xml 0.12.4 (registry+https://github.com/rust-lang/crates.io-index)",
"quickcheck 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "quickcheck 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
"rayon 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"svgtypes 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "svgtypes 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]

View File

@ -14,6 +14,7 @@ jemallocator = "0.1"
lyon_geom = "0.12" lyon_geom = "0.12"
lyon_path = "0.12" lyon_path = "0.12"
quick-xml = "0.12" quick-xml = "0.12"
rayon = "1.0"
svgtypes = "0.2" svgtypes = "0.2"
[dependencies.pathfinder_path_utils] [dependencies.pathfinder_path_utils]

View File

@ -28,6 +28,7 @@ use lyon_path::iterator::PathIter;
use pathfinder_path_utils::stroke::{StrokeStyle, StrokeToFillIter}; use pathfinder_path_utils::stroke::{StrokeStyle, StrokeToFillIter};
use quick_xml::Reader; use quick_xml::Reader;
use quick_xml::events::{BytesStart, Event}; use quick_xml::events::{BytesStart, Event};
use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator};
use std::cmp::Ordering; use std::cmp::Ordering;
use std::fmt::{self, Debug, Formatter}; use std::fmt::{self, Debug, Formatter};
use std::fs::File; use std::fs::File;
@ -57,6 +58,9 @@ fn main() {
.value_name("COUNT") .value_name("COUNT")
.takes_value(true) .takes_value(true)
.help("Run a benchmark with COUNT runs")) .help("Run a benchmark with COUNT runs"))
.arg(Arg::with_name("sequential").short("s")
.long("sequential")
.help("Use only one thread"))
.arg(Arg::with_name("INPUT").help("Path to the SVG file to render") .arg(Arg::with_name("INPUT").help("Path to the SVG file to render")
.required(true) .required(true)
.index(1)) .index(1))
@ -68,6 +72,7 @@ fn main() {
Some(runs) => runs.parse().unwrap(), Some(runs) => runs.parse().unwrap(),
None => 1, None => 1,
}; };
let sequential = matches.is_present("sequential");
let input_path = PathBuf::from(matches.value_of("INPUT").unwrap()); let input_path = PathBuf::from(matches.value_of("INPUT").unwrap());
let output_path = matches.value_of("OUTPUT").map(PathBuf::from); let output_path = matches.value_of("OUTPUT").map(PathBuf::from);
@ -77,7 +82,12 @@ fn main() {
let start_time = Instant::now(); let start_time = Instant::now();
let mut built_scene = BuiltScene::new(&scene.view_box, scene.objects.len() as u32); let mut built_scene = BuiltScene::new(&scene.view_box, scene.objects.len() as u32);
for _ in 0..runs { for _ in 0..runs {
built_scene = BuiltScene::from_objects(&scene.view_box, &scene.build_objects()); let built_objects = if sequential {
scene.build_objects_sequentially()
} else {
scene.build_objects_in_parallel()
};
built_scene = BuiltScene::from_objects(&scene.view_box, &built_objects);
} }
let elapsed_time = Instant::now() - start_time; let elapsed_time = Instant::now() - start_time;
@ -311,8 +321,7 @@ impl Scene {
&self.styles[style.0 as usize] &self.styles[style.0 as usize]
} }
fn build_objects(&self) -> Vec<BuiltObject> { fn build_objects_sequentially(&self) -> Vec<BuiltObject> {
// TODO(pcwalton): Parallelize!
self.objects.iter().enumerate().map(|(object_index, object)| { self.objects.iter().enumerate().map(|(object_index, object)| {
let mut tiler = Tiler::new(&object.outline, object_index as u32, &self.view_box); let mut tiler = Tiler::new(&object.outline, object_index as u32, &self.view_box);
tiler.generate_tiles(); tiler.generate_tiles();
@ -320,6 +329,14 @@ impl Scene {
}).collect() }).collect()
} }
fn build_objects_in_parallel(&self) -> Vec<BuiltObject> {
self.objects.par_iter().enumerate().map(|(object_index, object)| {
let mut tiler = Tiler::new(&object.outline, object_index as u32, &self.view_box);
tiler.generate_tiles();
tiler.built_object
}).collect()
}
fn push_svg_path(&mut self, value: &str, style: StyleId, name: String) { fn push_svg_path(&mut self, value: &str, style: StyleId, name: String) {
if self.get_style(style).stroke_color.is_some() { if self.get_style(style).stroke_color.is_some() {
let computed_style = self.get_style(style); let computed_style = self.get_style(style);