зеркало из https://github.com/mozilla/gecko-dev.git
servo: Merge #15535 - geckolib: use a global thread pool for styling (from froydnj:global-style-thread-pool); r=bholley
By having a single thread pool, rather than one per document, we use less memory. This addresses https://bugzilla.mozilla.org/show_bug.cgi?id=1324250. This may be obvious to an experienced Rust programmer, but I went with raw pointers because trying to use `Option` global variables resulted in complaints about turning on feature flags in nightly Rust. Since this is for stylo, nightly features are not appropriate here. --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [ ] These changes fix #__ (github issue number if applicable). <!-- Either: --> - [ ] There are tests for these changes OR - [ ] These changes do not require tests because _____ <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> Source-Repo: https://github.com/servo/servo Source-Revision: 56a99577b31a942e340624f97377980b0e612088 --HG-- extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear extra : subtree_revision : 72e6b32e7662f3801e79c3894d89a0f9d25a861f
This commit is contained in:
Родитель
5e185e524c
Коммит
164d6cbbee
|
@ -906,6 +906,7 @@ dependencies = [
|
|||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num_cpus 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parking_lot 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rayon 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"selectors 0.18.0",
|
||||
"servo_url 0.0.1",
|
||||
"style 0.0.1",
|
||||
|
@ -2721,7 +2722,6 @@ dependencies = [
|
|||
"nsstring_vendor 0.1.0",
|
||||
"num-integer 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num_cpus 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ordered-float 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"owning_ref 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parking_lot 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -2794,6 +2794,7 @@ dependencies = [
|
|||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num_cpus 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parking_lot 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rayon 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"selectors 0.18.0",
|
||||
"servo_url 0.0.1",
|
||||
"style 0.0.1",
|
||||
|
|
|
@ -13,7 +13,7 @@ path = "lib.rs"
|
|||
doctest = false
|
||||
|
||||
[features]
|
||||
gecko = ["nsstring_vendor", "num_cpus", "rayon/unstable"]
|
||||
gecko = ["nsstring_vendor", "rayon/unstable"]
|
||||
use_bindgen = ["bindgen", "regex"]
|
||||
servo = ["serde/unstable", "serde", "serde_derive", "heapsize_derive",
|
||||
"style_traits/servo", "servo_atoms", "html5ever-atoms",
|
||||
|
@ -57,10 +57,6 @@ servo_url = {path = "../url"}
|
|||
time = "0.1"
|
||||
unicode-segmentation = "1.0"
|
||||
|
||||
[dependencies.num_cpus]
|
||||
optional = true
|
||||
version = "1.0"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
kernel32-sys = "0.2"
|
||||
|
||||
|
|
|
@ -11,13 +11,9 @@ use gecko_bindings::bindings::RawServoStyleSet;
|
|||
use gecko_bindings::structs::RawGeckoPresContextOwned;
|
||||
use gecko_bindings::sugar::ownership::{HasBoxFFI, HasFFI, HasSimpleFFI};
|
||||
use media_queries::Device;
|
||||
use num_cpus;
|
||||
use parking_lot::RwLock;
|
||||
use properties::ComputedValues;
|
||||
use rayon;
|
||||
use std::cmp;
|
||||
use std::collections::HashMap;
|
||||
use std::env;
|
||||
use std::sync::Arc;
|
||||
use std::sync::mpsc::{Receiver, Sender, channel};
|
||||
use stylesheets::Stylesheet;
|
||||
|
@ -48,29 +44,12 @@ pub struct PerDocumentStyleDataImpl {
|
|||
/// Unused. Will go away when we actually implement transitions and
|
||||
/// animations properly.
|
||||
pub expired_animations: Arc<RwLock<HashMap<OpaqueNode, Vec<Animation>>>>,
|
||||
|
||||
/// The worker thread pool.
|
||||
/// FIXME(bholley): This shouldn't be per-document.
|
||||
pub work_queue: Option<rayon::ThreadPool>,
|
||||
|
||||
/// The number of threads of the work queue.
|
||||
pub num_threads: usize,
|
||||
}
|
||||
|
||||
/// The data itself is an `AtomicRefCell`, which guarantees the proper semantics
|
||||
/// and unexpected races while trying to mutate it.
|
||||
pub struct PerDocumentStyleData(AtomicRefCell<PerDocumentStyleDataImpl>);
|
||||
|
||||
lazy_static! {
|
||||
/// The number of layout threads, computed statically.
|
||||
pub static ref NUM_THREADS: usize = {
|
||||
match env::var("STYLO_THREADS").map(|s| s.parse::<usize>().expect("invalid STYLO_THREADS")) {
|
||||
Ok(num) => num,
|
||||
_ => cmp::max(num_cpus::get() * 3 / 4, 1),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl PerDocumentStyleData {
|
||||
/// Create a dummy `PerDocumentStyleData`.
|
||||
pub fn new(pres_context: RawGeckoPresContextOwned) -> Self {
|
||||
|
@ -86,14 +65,6 @@ impl PerDocumentStyleData {
|
|||
new_animations_receiver: new_anims_receiver,
|
||||
running_animations: Arc::new(RwLock::new(HashMap::new())),
|
||||
expired_animations: Arc::new(RwLock::new(HashMap::new())),
|
||||
work_queue: if *NUM_THREADS <= 1 {
|
||||
None
|
||||
} else {
|
||||
let configuration =
|
||||
rayon::Configuration::new().set_num_threads(*NUM_THREADS);
|
||||
rayon::ThreadPool::new(configuration).ok()
|
||||
},
|
||||
num_threads: *NUM_THREADS,
|
||||
}))
|
||||
}
|
||||
|
||||
|
@ -141,9 +112,3 @@ unsafe impl HasFFI for PerDocumentStyleData {
|
|||
}
|
||||
unsafe impl HasSimpleFFI for PerDocumentStyleData {}
|
||||
unsafe impl HasBoxFFI for PerDocumentStyleData {}
|
||||
|
||||
impl Drop for PerDocumentStyleDataImpl {
|
||||
fn drop(&mut self) {
|
||||
let _ = self.work_queue.take();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,7 +61,6 @@ extern crate matches;
|
|||
#[cfg(feature = "gecko")] extern crate nsstring_vendor as nsstring;
|
||||
extern crate num_integer;
|
||||
extern crate num_traits;
|
||||
#[cfg(feature = "gecko")] extern crate num_cpus;
|
||||
extern crate ordered_float;
|
||||
extern crate owning_ref;
|
||||
extern crate parking_lot;
|
||||
|
|
|
@ -23,6 +23,7 @@ libc = "0.2"
|
|||
log = {version = "0.3.5", features = ["release_max_level_info"]}
|
||||
num_cpus = "1.1.0"
|
||||
parking_lot = "0.3"
|
||||
rayon = "0.6"
|
||||
selectors = {path = "../../components/selectors"}
|
||||
servo_url = {path = "../../components/url"}
|
||||
style = {path = "../../components/style", features = ["gecko"]}
|
||||
|
|
|
@ -8,10 +8,13 @@ use cssparser::Parser;
|
|||
use cssparser::ToCss as ParserToCss;
|
||||
use env_logger::LogBuilder;
|
||||
use euclid::Size2D;
|
||||
use num_cpus;
|
||||
use parking_lot::RwLock;
|
||||
use rayon;
|
||||
use selectors::Element;
|
||||
use servo_url::ServoUrl;
|
||||
use std::borrow::Cow;
|
||||
use std::cmp;
|
||||
use std::env;
|
||||
use std::fmt::Write;
|
||||
use std::mem;
|
||||
|
@ -23,7 +26,7 @@ use style::context::{ThreadLocalStyleContext, ThreadLocalStyleContextCreationInf
|
|||
use style::data::{ElementData, ElementStyles, RestyleData};
|
||||
use style::dom::{ShowSubtreeData, TElement, TNode};
|
||||
use style::error_reporting::StdoutErrorReporter;
|
||||
use style::gecko::data::{NUM_THREADS, PerDocumentStyleData, PerDocumentStyleDataImpl};
|
||||
use style::gecko::data::{PerDocumentStyleData, PerDocumentStyleDataImpl};
|
||||
use style::gecko::restyle_damage::GeckoRestyleDamage;
|
||||
use style::gecko::selector_parser::{SelectorImpl, PseudoElement};
|
||||
use style::gecko::traversal::RecalcStyleOnly;
|
||||
|
@ -90,6 +93,45 @@ use stylesheet_loader::StylesheetLoader;
|
|||
* depend on but good enough for our purposes.
|
||||
*/
|
||||
|
||||
struct GlobalStyleData {
|
||||
// How many threads parallel styling can use.
|
||||
pub num_threads: usize,
|
||||
|
||||
// The parallel styling thread pool.
|
||||
pub style_thread_pool: Option<rayon::ThreadPool>,
|
||||
}
|
||||
|
||||
impl GlobalStyleData {
|
||||
pub fn new() -> Self {
|
||||
let stylo_threads = env::var("STYLO_THREADS")
|
||||
.map(|s| s.parse::<usize>().expect("invalid STYLO_THREADS value"));
|
||||
let num_threads = match stylo_threads {
|
||||
Ok(num) => num,
|
||||
_ => cmp::max(num_cpus::get() * 3 / 4, 1),
|
||||
};
|
||||
|
||||
let pool = if num_threads <= 1 {
|
||||
None
|
||||
} else {
|
||||
let configuration =
|
||||
rayon::Configuration::new().set_num_threads(num_threads);
|
||||
let pool = rayon::ThreadPool::new(configuration).ok();
|
||||
pool
|
||||
};
|
||||
|
||||
GlobalStyleData {
|
||||
num_threads: num_threads,
|
||||
style_thread_pool: pool,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref GLOBAL_STYLE_DATA: GlobalStyleData = {
|
||||
GlobalStyleData::new()
|
||||
};
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Servo_Initialize() -> () {
|
||||
// Initialize logging.
|
||||
|
@ -148,7 +190,7 @@ fn traverse_subtree(element: GeckoElement, raw_data: RawServoStyleSetBorrowed,
|
|||
}
|
||||
}
|
||||
|
||||
let mut per_doc_data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
|
||||
let per_doc_data = PerDocumentStyleData::from_ffi(raw_data).borrow();
|
||||
|
||||
let token = RecalcStyleOnly::pre_traverse(element, &per_doc_data.stylist, unstyled_children_only);
|
||||
if !token.should_traverse() {
|
||||
|
@ -159,7 +201,9 @@ fn traverse_subtree(element: GeckoElement, raw_data: RawServoStyleSetBorrowed,
|
|||
debug!("{:?}", ShowSubtreeData(element.as_node()));
|
||||
|
||||
let shared_style_context = create_shared_context(&per_doc_data);
|
||||
let traversal_driver = if per_doc_data.num_threads == 1 || per_doc_data.work_queue.is_none() {
|
||||
let ref global_style_data = *GLOBAL_STYLE_DATA;
|
||||
|
||||
let traversal_driver = if global_style_data.style_thread_pool.is_none() {
|
||||
TraversalDriver::Sequential
|
||||
} else {
|
||||
TraversalDriver::Parallel
|
||||
|
@ -169,7 +213,7 @@ fn traverse_subtree(element: GeckoElement, raw_data: RawServoStyleSetBorrowed,
|
|||
let known_depth = None;
|
||||
if traversal_driver.is_parallel() {
|
||||
parallel::traverse_dom(&traversal, element, known_depth, token,
|
||||
per_doc_data.work_queue.as_mut().unwrap());
|
||||
global_style_data.style_thread_pool.as_ref().unwrap());
|
||||
} else {
|
||||
sequential::traverse_dom(&traversal, element, token);
|
||||
}
|
||||
|
@ -334,7 +378,7 @@ pub extern "C" fn Servo_AnimationValues_Populate(anim: RawGeckoAnimationValueLis
|
|||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Servo_StyleWorkerThreadCount() -> u32 {
|
||||
*NUM_THREADS as u32
|
||||
GLOBAL_STYLE_DATA.num_threads as u32
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
|
|
@ -9,9 +9,12 @@ extern crate atomic_refcell;
|
|||
extern crate cssparser;
|
||||
extern crate env_logger;
|
||||
extern crate euclid;
|
||||
#[macro_use] extern crate lazy_static;
|
||||
extern crate libc;
|
||||
#[macro_use] extern crate log;
|
||||
extern crate num_cpus;
|
||||
extern crate parking_lot;
|
||||
extern crate rayon;
|
||||
extern crate selectors;
|
||||
extern crate servo_url;
|
||||
extern crate style;
|
||||
|
|
|
@ -22,6 +22,7 @@ libc = "0.2"
|
|||
log = {version = "0.3.5", features = ["release_max_level_info"]}
|
||||
num_cpus = "1.1.0"
|
||||
parking_lot = "0.3"
|
||||
rayon = "0.6"
|
||||
selectors = {path = "../../../components/selectors"}
|
||||
servo_url = {path = "../../../components/url"}
|
||||
style_traits = {path = "../../../components/style_traits"}
|
||||
|
|
|
@ -8,8 +8,11 @@ extern crate cssparser;
|
|||
extern crate env_logger;
|
||||
extern crate euclid;
|
||||
extern crate geckoservo;
|
||||
#[macro_use] extern crate lazy_static;
|
||||
#[macro_use] extern crate log;
|
||||
extern crate num_cpus;
|
||||
extern crate parking_lot;
|
||||
extern crate rayon;
|
||||
extern crate selectors;
|
||||
extern crate servo_url;
|
||||
extern crate style;
|
||||
|
|
Загрузка…
Ссылка в новой задаче