diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2018-12-23 09:39:07 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-12-23 09:39:07 -0500 |
commit | b5a10e9c968940106ecfdaf85a99e4538d9011ed (patch) | |
tree | ff1ce499369c682fb1b718ece73b9005e7d24e79 | |
parent | 596b06367f43bfb613f4d7faf557a0317d4d2ec6 (diff) | |
parent | 006e71c7dec624935d3d4faf9ea5f783e2a24a67 (diff) | |
download | servo-b5a10e9c968940106ecfdaf85a99e4538d9011ed.tar.gz servo-b5a10e9c968940106ecfdaf85a99e4538d9011ed.zip |
Auto merge of #22487 - emilio:single-layout-thread-pool, r=jdm
style: Make Servo use a single thread-pool for layout-related tasks per process.
Instead of per-document. This also allows to reuse this thread-pool if needed
for other stuff, like parallel CSS parsing (#22478), and to share more code with
Gecko, which is always nice.
<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/22487)
<!-- Reviewable:end -->
-rw-r--r-- | components/constellation/pipeline.rs | 7 | ||||
-rw-r--r-- | components/layout_thread/lib.rs | 67 | ||||
-rw-r--r-- | components/layout_traits/lib.rs | 1 | ||||
-rw-r--r-- | components/script/dom/htmliframeelement.rs | 2 | ||||
-rw-r--r-- | components/script/dom/windowproxy.rs | 2 | ||||
-rw-r--r-- | components/script/script_thread.rs | 2 | ||||
-rw-r--r-- | components/script_layout_interface/message.rs | 1 | ||||
-rw-r--r-- | components/script_traits/lib.rs | 2 | ||||
-rw-r--r-- | components/style/Cargo.toml | 5 | ||||
-rw-r--r-- | components/style/gecko/mod.rs | 1 | ||||
-rw-r--r-- | components/style/global_style_data.rs (renamed from components/style/gecko/global_style_data.rs) | 42 | ||||
-rw-r--r-- | components/style/lib.rs | 1 |
12 files changed, 56 insertions, 77 deletions
diff --git a/components/constellation/pipeline.rs b/components/constellation/pipeline.rs index 589b4e6f521..bbbe095d918 100644 --- a/components/constellation/pipeline.rs +++ b/components/constellation/pipeline.rs @@ -219,7 +219,6 @@ impl Pipeline { window_size: window_size, pipeline_port: pipeline_port, content_process_shutdown_chan: Some(layout_content_process_shutdown_chan), - layout_threads: PREFS.get("layout.threads").as_u64().expect("count") as usize, }; if let Err(e) = @@ -556,12 +555,6 @@ impl UnprivilegedPipelineContent { Some(self.layout_content_process_shutdown_chan), self.webrender_api_sender, self.webrender_document, - self.prefs - .get("layout.threads") - .expect("exists") - .value() - .as_u64() - .expect("count") as usize, paint_time_metrics, ); diff --git a/components/layout_thread/lib.rs b/components/layout_thread/lib.rs index 0d0293d86aa..5b82577932f 100644 --- a/components/layout_thread/lib.rs +++ b/components/layout_thread/lib.rs @@ -102,10 +102,11 @@ use std::thread; use std::time::Duration; use style::animation::Animation; use style::context::{QuirksMode, RegisteredSpeculativePainter, RegisteredSpeculativePainters}; -use style::context::{SharedStyleContext, StyleSystemOptions, ThreadLocalStyleContextCreationInfo}; +use style::context::{SharedStyleContext, ThreadLocalStyleContextCreationInfo}; use style::dom::{ShowSubtree, ShowSubtreeDataAndPrimaryValues, TElement, TNode}; use style::driver; use style::error_reporting::RustLogReporter; +use style::global_style_data::{GLOBAL_STYLE_DATA, STYLE_THREAD_POOL}; use style::invalidation::element::restyle_hints::RestyleHint; use style::logical_geometry::LogicalPoint; use style::media_queries::{Device, MediaList, MediaType}; @@ -178,9 +179,6 @@ pub struct LayoutThread { /// Is this the first reflow in this LayoutThread? first_reflow: Cell<bool>, - /// The workers that we use for parallel operation. - parallel_traversal: Option<rayon::ThreadPool>, - /// Flag to indicate whether to use parallel operations parallel_flag: bool, @@ -238,10 +236,6 @@ pub struct LayoutThread { /// only be a test-mode timer during testing for animations. timer: Timer, - // Number of layout threads. This is copied from `servo_config::opts`, but we'd - // rather limit the dependency on that module here. - layout_threads: usize, - /// Paint time metrics. paint_time_metrics: PaintTimeMetrics, @@ -270,7 +264,6 @@ impl LayoutThreadFactory for LayoutThread { content_process_shutdown_chan: Option<IpcSender<()>>, webrender_api_sender: webrender_api::RenderApiSender, webrender_document: webrender_api::DocumentId, - layout_threads: usize, paint_time_metrics: PaintTimeMetrics, ) { thread::Builder::new() @@ -308,7 +301,6 @@ impl LayoutThreadFactory for LayoutThread { mem_profiler_chan.clone(), webrender_api_sender, webrender_document, - layout_threads, paint_time_metrics, ); @@ -470,7 +462,6 @@ impl LayoutThread { mem_profiler_chan: profile_mem::ProfilerChan, webrender_api_sender: webrender_api::RenderApiSender, webrender_document: webrender_api::DocumentId, - layout_threads: usize, paint_time_metrics: PaintTimeMetrics, ) -> LayoutThread { // The device pixel ratio is incorrect (it does not have the hidpi value), @@ -481,17 +472,6 @@ impl LayoutThread { TypedScale::new(opts::get().device_pixels_per_px.unwrap_or(1.0)), ); - let workers = rayon::ThreadPoolBuilder::new() - .num_threads(layout_threads) - .start_handler(|_| thread_state::initialize_layout_worker_thread()) - .build(); - let parallel_traversal = if layout_threads > 1 { - Some(workers.expect("ThreadPool creation failed")) - } else { - None - }; - debug!("Possible layout Threads: {}", layout_threads); - // Create the channel on which new animations can be sent. let (new_animations_sender, new_animations_receiver) = unbounded(); @@ -521,7 +501,6 @@ impl LayoutThread { first_reflow: Cell::new(true), font_cache_receiver: font_cache_receiver, font_cache_sender: ipc_font_cache_sender, - parallel_traversal: parallel_traversal, parallel_flag: true, generation: Cell::new(0), new_animations_sender: new_animations_sender, @@ -563,7 +542,6 @@ impl LayoutThread { } else { Timer::new() }, - layout_threads: layout_threads, paint_time_metrics: paint_time_metrics, layout_query_waiting_time: Histogram::new(), } @@ -596,8 +574,8 @@ impl LayoutThread { id: self.id, style_context: SharedStyleContext { stylist: &self.stylist, - options: StyleSystemOptions::default(), - guards: guards, + options: GLOBAL_STYLE_DATA.options.clone(), + guards, visited_styles_enabled: false, running_animations: self.running_animations.clone(), expired_animations: self.expired_animations.clone(), @@ -881,7 +859,6 @@ impl LayoutThread { info.content_process_shutdown_chan, self.webrender_api.clone_sender(), self.webrender_document, - info.layout_threads, info.paint_time_metrics, ); } @@ -924,8 +901,6 @@ impl LayoutThread { ); self.root_flow.borrow_mut().take(); - // Drop the rayon threadpool if present. - let _ = self.parallel_traversal.take(); self.background_hang_monitor.unregister(); } @@ -1166,7 +1141,7 @@ impl LayoutThread { // Parallelize if there's more than 750 objects based on rzambre's suggestion // https://github.com/servo/servo/issues/10110 - self.parallel_flag = self.layout_threads > 1 && data.dom_count > 750; + self.parallel_flag = data.dom_count > 750; debug!("layout: received layout request for: {}", self.url); debug!("Number of objects in DOM: {}", data.dom_count); debug!("layout: parallel? {}", self.parallel_flag); @@ -1373,10 +1348,13 @@ impl LayoutThread { // Create a layout context for use throughout the following passes. let mut layout_context = self.build_layout_context(guards.clone(), true, &map); - let thread_pool = if self.parallel_flag { - self.parallel_traversal.as_ref() + let (thread_pool, num_threads) = if self.parallel_flag { + ( + STYLE_THREAD_POOL.style_thread_pool.as_ref(), + STYLE_THREAD_POOL.num_threads, + ) } else { - None + (None, 1) }; let traversal = RecalcStyleAndConstructFlows::new(layout_context); @@ -1404,14 +1382,14 @@ impl LayoutThread { }, ); // TODO(pcwalton): Measure energy usage of text shaping, perhaps? - let text_shaping_time = (font::get_and_reset_text_shaping_performance_counter() as u64) / - (self.layout_threads as u64); + let text_shaping_time = + font::get_and_reset_text_shaping_performance_counter() / num_threads; profile_time::send_profile_data( profile_time::ProfilerCategory::LayoutTextShaping, self.profiler_metadata(), &self.time_profiler_chan, 0, - text_shaping_time, + text_shaping_time as u64, 0, 0, ); @@ -1742,12 +1720,16 @@ impl LayoutThread { || { let profiler_metadata = self.profiler_metadata(); - if let (true, Some(traversal)) = - (self.parallel_flag, self.parallel_traversal.as_ref()) - { + let thread_pool = if self.parallel_flag { + STYLE_THREAD_POOL.style_thread_pool.as_ref() + } else { + None + }; + + if let Some(pool) = thread_pool { // Parallel mode. LayoutThread::solve_constraints_parallel( - traversal, + pool, FlowRef::deref_mut(root_flow), profiler_metadata, self.time_profiler_chan.clone(), @@ -1913,7 +1895,8 @@ fn get_ua_stylesheets() -> Result<UserAgentStylesheets, &'static str> { )))) } - let shared_lock = SharedRwLock::new(); + let shared_lock = &GLOBAL_STYLE_DATA.shared_lock; + // FIXME: presentational-hints.css should be at author origin with zero specificity. // (Does it make a difference?) let mut user_or_user_agent_stylesheets = vec![ @@ -1958,7 +1941,7 @@ fn get_ua_stylesheets() -> Result<UserAgentStylesheets, &'static str> { )?; Ok(UserAgentStylesheets { - shared_lock: shared_lock, + shared_lock: shared_lock.clone(), user_or_user_agent_stylesheets: user_or_user_agent_stylesheets, quirks_mode_stylesheet: quirks_mode_stylesheet, }) diff --git a/components/layout_traits/lib.rs b/components/layout_traits/lib.rs index 5e58938a277..a1f33bdf827 100644 --- a/components/layout_traits/lib.rs +++ b/components/layout_traits/lib.rs @@ -43,7 +43,6 @@ pub trait LayoutThreadFactory { content_process_shutdown_chan: Option<IpcSender<()>>, webrender_api_sender: webrender_api::RenderApiSender, webrender_document: webrender_api::DocumentId, - layout_threads: usize, paint_time_metrics: PaintTimeMetrics, ); } diff --git a/components/script/dom/htmliframeelement.rs b/components/script/dom/htmliframeelement.rs index 288584932f0..0e23a04fc39 100644 --- a/components/script/dom/htmliframeelement.rs +++ b/components/script/dom/htmliframeelement.rs @@ -38,7 +38,6 @@ use script_traits::{ WindowSizeData, }; use script_traits::{NewLayoutInfo, ScriptMsg}; -use servo_config::prefs::PREFS; use servo_url::ServoUrl; use std::cell::Cell; use style::attr::{AttrValue, LengthOrPercentageOrAuto}; @@ -204,7 +203,6 @@ impl HTMLIFrameElement { }, device_pixel_ratio: window.device_pixel_ratio(), }, - layout_threads: PREFS.get("layout.threads").as_u64().expect("count") as usize, }; self.pipeline_id.set(Some(new_pipeline_id)); diff --git a/components/script/dom/windowproxy.rs b/components/script/dom/windowproxy.rs index 65362ee0d17..8b0af9a147e 100644 --- a/components/script/dom/windowproxy.rs +++ b/components/script/dom/windowproxy.rs @@ -45,7 +45,6 @@ use msg::constellation_msg::BrowsingContextId; use msg::constellation_msg::PipelineId; use msg::constellation_msg::TopLevelBrowsingContextId; use script_traits::{AuxiliaryBrowsingContextLoadInfo, LoadData, NewLayoutInfo, ScriptMsg}; -use servo_config::prefs::PREFS; use servo_url::ServoUrl; use std::cell::Cell; use std::ptr; @@ -290,7 +289,6 @@ impl WindowProxy { pipeline_port: pipeline_receiver, content_process_shutdown_chan: None, window_size: window.window_size(), - layout_threads: PREFS.get("layout.threads").as_u64().expect("count") as usize, }; let constellation_msg = ScriptMsg::ScriptNewAuxiliary(load_info, pipeline_sender); window.send_to_constellation(constellation_msg); diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index 50f6135ff52..8383caa9800 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -1910,7 +1910,6 @@ impl ScriptThread { window_size, pipeline_port, content_process_shutdown_chan, - layout_threads, } = new_layout_info; let layout_pair = unbounded(); @@ -1927,7 +1926,6 @@ impl ScriptThread { script_chan: self.control_chan.clone(), image_cache: self.image_cache.clone(), content_process_shutdown_chan: content_process_shutdown_chan, - layout_threads: layout_threads, paint_time_metrics: PaintTimeMetrics::new( new_pipeline_id, self.time_profiler_chan.clone(), diff --git a/components/script_layout_interface/message.rs b/components/script_layout_interface/message.rs index ae346041439..d17a8fc5e2f 100644 --- a/components/script_layout_interface/message.rs +++ b/components/script_layout_interface/message.rs @@ -220,6 +220,5 @@ pub struct NewLayoutThreadInfo { pub script_chan: IpcSender<ConstellationControlMsg>, pub image_cache: Arc<dyn ImageCache>, pub content_process_shutdown_chan: Option<IpcSender<()>>, - pub layout_threads: usize, pub paint_time_metrics: PaintTimeMetrics, } diff --git a/components/script_traits/lib.rs b/components/script_traits/lib.rs index 2dfc2378d2f..45e31ca3a0a 100644 --- a/components/script_traits/lib.rs +++ b/components/script_traits/lib.rs @@ -195,8 +195,6 @@ pub struct NewLayoutInfo { pub pipeline_port: IpcReceiver<LayoutControlMsg>, /// A shutdown channel so that layout can tell the content process to shut down when it's done. pub content_process_shutdown_chan: Option<IpcSender<()>>, - /// Number of threads to use for layout. - pub layout_threads: usize, } /// When a pipeline is closed, should its browsing context be discarded too? diff --git a/components/style/Cargo.toml b/components/style/Cargo.toml index 0acd6044c78..7feaf90f992 100644 --- a/components/style/Cargo.toml +++ b/components/style/Cargo.toml @@ -16,8 +16,7 @@ path = "lib.rs" doctest = false [features] -gecko = ["num_cpus", - "style_traits/gecko", "fallible/known_system_malloc"] +gecko = ["style_traits/gecko", "fallible/known_system_malloc"] use_bindgen = ["bindgen", "regex", "toml"] servo = ["serde", "style_traits/servo", "servo_atoms", "servo_config", "html5ever", "cssparser/serde", "encoding_rs", "malloc_size_of/servo", "arrayvec/use_union", @@ -47,7 +46,7 @@ log = "0.4" malloc_size_of = { path = "../malloc_size_of" } malloc_size_of_derive = { path = "../malloc_size_of_derive" } matches = "0.1" -num_cpus = {version = "1.1.0", optional = true} +num_cpus = {version = "1.1.0"} num-integer = "0.1" num-traits = "0.2" num-derive = "0.2" diff --git a/components/style/gecko/mod.rs b/components/style/gecko/mod.rs index 28472642a3d..1051f84fc52 100644 --- a/components/style/gecko/mod.rs +++ b/components/style/gecko/mod.rs @@ -10,7 +10,6 @@ mod non_ts_pseudo_class_list; pub mod arc_types; pub mod conversions; pub mod data; -pub mod global_style_data; pub mod media_features; pub mod media_queries; pub mod pseudo_element; diff --git a/components/style/gecko/global_style_data.rs b/components/style/global_style_data.rs index e6682e9370e..7928db13d81 100644 --- a/components/style/gecko/global_style_data.rs +++ b/components/style/global_style_data.rs @@ -5,15 +5,13 @@ //! Global style data use crate::context::StyleSystemOptions; +#[cfg(feature = "gecko")] use crate::gecko_bindings::bindings; use crate::parallel::STYLE_THREAD_STACK_SIZE_KB; use crate::shared_lock::SharedRwLock; use crate::thread_state; -use num_cpus; use rayon; -use std::cmp; use std::env; -use std::ffi::CString; /// Global style data pub struct GlobalStyleData { @@ -37,20 +35,22 @@ fn thread_name(index: usize) -> String { format!("StyleThread#{}", index) } -fn thread_startup(index: usize) { +fn thread_startup(_index: usize) { thread_state::initialize_layout_worker_thread(); + #[cfg(feature = "gecko")] unsafe { + use std::ffi::CString; + bindings::Gecko_SetJemallocThreadLocalArena(true); - } - let name = thread_name(index); - let name = CString::new(name).unwrap(); - unsafe { + let name = thread_name(_index); + let name = CString::new(name).unwrap(); // Gecko_RegisterProfilerThread copies the passed name here. bindings::Gecko_RegisterProfilerThread(name.as_ptr()); } } fn thread_shutdown(_: usize) { + #[cfg(feature = "gecko")] unsafe { bindings::Gecko_UnregisterProfilerThread(); bindings::Gecko_SetJemallocThreadLocalArena(false); @@ -64,12 +64,26 @@ lazy_static! { .map(|s| s.parse::<usize>().expect("invalid STYLO_THREADS value")); let mut num_threads = match stylo_threads { Ok(num) => num, - // The default heuristic is num_virtual_cores * .75. This gives us - // three threads on a hyper-threaded dual core, and six threads on - // a hyper-threaded quad core. The performance benefit of additional - // threads seems to level off at around six, so we cap it there on - // many-core machines (see bug 1431285 comment 14). - _ => cmp::min(cmp::max(num_cpus::get() * 3 / 4, 1), 6), + #[cfg(feature = "servo")] + _ => { + // We always set this pref on startup, before layout or script + // have had a chance of accessing (and thus creating) the + // thread-pool. + use servo_config::prefs::PREFS; + PREFS.get("layout.threads").as_u64().unwrap() as usize + } + #[cfg(feature = "gecko")] + _ => { + // The default heuristic is num_virtual_cores * .75. This gives + // us three threads on a hyper-threaded dual core, and six + // threads on a hyper-threaded quad core. The performance + // benefit of additional threads seems to level off at around + // six, so we cap it there on many-core machines + // (see bug 1431285 comment 14). + use num_cpus; + use std::cmp; + cmp::min(cmp::max(num_cpus::get() * 3 / 4, 1), 6) + } }; // If num_threads is one, there's no point in creating a thread pool, so diff --git a/components/style/lib.rs b/components/style/lib.rs index df4f090ca4b..d4a296bada5 100644 --- a/components/style/lib.rs +++ b/components/style/lib.rs @@ -133,6 +133,7 @@ pub mod font_metrics; #[cfg(feature = "gecko")] #[allow(unsafe_code)] pub mod gecko_bindings; +pub mod global_style_data; pub mod hash; pub mod invalidation; #[allow(missing_docs)] // TODO. |