mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-17 06:09:19 +00:00
Bug 1595708 - Cargo build timings SVG output Freezes the entire browser with WebRender r=nical,jrmuizel
Differential Revision: https://phabricator.services.mozilla.com/D56244 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
30f2b5474f
commit
8edb97a47a
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -4457,6 +4457,7 @@ dependencies = [
|
||||
"thread_profiler 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"uuid 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"webrender 0.60.0",
|
||||
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -29,6 +29,7 @@ features = ["capture", "serialize_program"]
|
||||
[target.'cfg(target_os = "windows")'.dependencies]
|
||||
dwrote = "0.9"
|
||||
dirs = "1.0"
|
||||
winapi = "0.3"
|
||||
|
||||
[target.'cfg(target_os = "macos")'.dependencies]
|
||||
core-foundation = "0.6"
|
||||
|
@ -45,6 +45,8 @@ static StaticRefPtr<RenderThread> sRenderThread;
|
||||
|
||||
RenderThread::RenderThread(base::Thread* aThread)
|
||||
: mThread(aThread),
|
||||
mThreadPool(false),
|
||||
mThreadPoolLP(true),
|
||||
mWindowInfos("RenderThread.mWindowInfos"),
|
||||
mRenderTextureMapLock("RenderThread.mRenderTextureMapLock"),
|
||||
mHasShutdown(false),
|
||||
@ -118,6 +120,7 @@ void RenderThread::ShutDownTask(layers::SynchronousTask* aTask) {
|
||||
|
||||
// Let go of our handle to the (internally ref-counted) thread pool.
|
||||
mThreadPool.Release();
|
||||
mThreadPoolLP.Release();
|
||||
|
||||
// Releasing on the render thread will allow us to avoid dispatching to remove
|
||||
// remaining textures from the texture map.
|
||||
@ -867,8 +870,8 @@ WebRenderPipelineInfo::~WebRenderPipelineInfo() {
|
||||
wr_pipeline_info_delete(mPipelineInfo);
|
||||
}
|
||||
|
||||
WebRenderThreadPool::WebRenderThreadPool() {
|
||||
mThreadPool = wr_thread_pool_new();
|
||||
WebRenderThreadPool::WebRenderThreadPool(bool low_priority) {
|
||||
mThreadPool = wr_thread_pool_new(low_priority);
|
||||
}
|
||||
|
||||
WebRenderThreadPool::~WebRenderThreadPool() { Release(); }
|
||||
|
@ -44,7 +44,7 @@ class RenderThread;
|
||||
/// process.
|
||||
class WebRenderThreadPool {
|
||||
public:
|
||||
WebRenderThreadPool();
|
||||
explicit WebRenderThreadPool(bool low_priority);
|
||||
|
||||
~WebRenderThreadPool();
|
||||
|
||||
@ -230,6 +230,10 @@ class RenderThread final {
|
||||
/// Can be called from any thread.
|
||||
WebRenderThreadPool& ThreadPool() { return mThreadPool; }
|
||||
|
||||
/// Thread pool for low priority scene building
|
||||
/// Can be called from any thread.
|
||||
WebRenderThreadPool& ThreadPoolLP() { return mThreadPoolLP; }
|
||||
|
||||
/// Returns the cache used to serialize shader programs to disk, if enabled.
|
||||
///
|
||||
/// Can only be called from the render thread.
|
||||
@ -288,6 +292,7 @@ class RenderThread final {
|
||||
base::Thread* const mThread;
|
||||
|
||||
WebRenderThreadPool mThreadPool;
|
||||
WebRenderThreadPool mThreadPoolLP;
|
||||
|
||||
UniquePtr<WebRenderProgramCache> mProgramCache;
|
||||
UniquePtr<WebRenderShaders> mShaders;
|
||||
|
@ -73,11 +73,15 @@ class NewRenderer : public RendererEvent {
|
||||
bool allow_texture_swizzling = gfx::gfxVars::UseGLSwizzle();
|
||||
bool isMainWindow = true; // TODO!
|
||||
bool supportLowPriorityTransactions = isMainWindow;
|
||||
bool supportLowPriorityThreadpool =
|
||||
supportLowPriorityTransactions &&
|
||||
StaticPrefs::gfx_webrender_enable_low_priority_pool();
|
||||
bool supportPictureCaching = isMainWindow;
|
||||
wr::Renderer* wrRenderer = nullptr;
|
||||
if (!wr_window_new(
|
||||
aWindowId, mSize.width, mSize.height,
|
||||
supportLowPriorityTransactions, allow_texture_swizzling,
|
||||
supportLowPriorityTransactions, supportLowPriorityThreadpool,
|
||||
allow_texture_swizzling,
|
||||
StaticPrefs::gfx_webrender_picture_caching() &&
|
||||
supportPictureCaching,
|
||||
#ifdef NIGHTLY_BUILD
|
||||
@ -92,7 +96,8 @@ class NewRenderer : public RendererEvent {
|
||||
aRenderThread.GetShaders()
|
||||
? aRenderThread.GetShaders()->RawShaders()
|
||||
: nullptr,
|
||||
aRenderThread.ThreadPool().Raw(), &WebRenderMallocSizeOf,
|
||||
aRenderThread.ThreadPool().Raw(),
|
||||
aRenderThread.ThreadPoolLP().Raw(), &WebRenderMallocSizeOf,
|
||||
&WebRenderMallocEnclosingSizeOf, (uint32_t)wr::RenderRoot::Default,
|
||||
compositor->ShouldUseNativeCompositor() ? compositor.get()
|
||||
: nullptr,
|
||||
|
@ -7,6 +7,10 @@ use std::ffi::{CStr, CString};
|
||||
use std::ffi::OsString;
|
||||
#[cfg(target_os = "windows")]
|
||||
use std::os::windows::ffi::OsStringExt;
|
||||
#[cfg(target_os = "windows")]
|
||||
use winapi::um::processthreadsapi::{SetThreadPriority,GetCurrentThread};
|
||||
#[cfg(target_os = "windows")]
|
||||
use winapi::um::winbase::{SetThreadAffinityMask};
|
||||
#[cfg(not(any(target_os = "macos", target_os = "windows")))]
|
||||
use std::os::unix::ffi::OsStringExt;
|
||||
use std::io::Cursor;
|
||||
@ -38,6 +42,7 @@ use rayon;
|
||||
use num_cpus;
|
||||
use euclid::SideOffsets2D;
|
||||
use nsstring::nsAString;
|
||||
//linux only//use thread_priority::*;
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
use core_foundation::string::CFString;
|
||||
@ -1053,18 +1058,35 @@ impl ThreadListener for GeckoProfilerThreadListener {
|
||||
pub struct WrThreadPool(Arc<rayon::ThreadPool>);
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wr_thread_pool_new() -> *mut WrThreadPool {
|
||||
pub unsafe extern "C" fn wr_thread_pool_new(low_priority: bool) -> *mut WrThreadPool {
|
||||
// Clamp the number of workers between 1 and 8. We get diminishing returns
|
||||
// with high worker counts and extra overhead because of rayon and font
|
||||
// management.
|
||||
let num_threads = num_cpus::get().max(2).min(8);
|
||||
|
||||
let priority_tag = if low_priority { "LP" } else { "" };
|
||||
|
||||
let worker = rayon::ThreadPoolBuilder::new()
|
||||
.thread_name(|idx|{ format!("WRWorker#{}", idx) })
|
||||
.thread_name(move |idx|{ format!("WRWorker{}#{}", priority_tag, idx) })
|
||||
.num_threads(num_threads)
|
||||
.start_handler(|idx| {
|
||||
.start_handler(move |idx| {
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
SetThreadPriority(
|
||||
GetCurrentThread(),
|
||||
if low_priority {
|
||||
-1 /* THREAD_PRIORITY_BELOW_NORMAL */
|
||||
} else {
|
||||
0 /* THREAD_PRIORITY_NORMAL */
|
||||
});
|
||||
SetThreadAffinityMask(GetCurrentThread(), 1usize << idx);
|
||||
}
|
||||
/*let thread_id = thread_native_id();
|
||||
set_thread_priority(thread_id,
|
||||
if low_priority { ThreadPriority::Min } else { ThreadPriority::Max },
|
||||
ThreadSchedulePolicy::Normal(NormalThreadSchedulePolicy::Normal));*/
|
||||
wr_register_thread_local_arena();
|
||||
let name = format!("WRWorker#{}", idx);
|
||||
let name = format!("WRWorker{}#{}",priority_tag, idx);
|
||||
register_thread_with_profiler(name.clone());
|
||||
gecko_profiler_register_thread(CString::new(name).unwrap().as_ptr());
|
||||
})
|
||||
@ -1305,6 +1327,7 @@ pub extern "C" fn wr_window_new(window_id: WrWindowId,
|
||||
window_width: i32,
|
||||
window_height: i32,
|
||||
support_low_priority_transactions: bool,
|
||||
support_low_priority_threadpool: bool,
|
||||
allow_texture_swizzling: bool,
|
||||
enable_picture_caching: bool,
|
||||
start_debug_server: bool,
|
||||
@ -1313,6 +1336,7 @@ pub extern "C" fn wr_window_new(window_id: WrWindowId,
|
||||
program_cache: Option<&mut WrProgramCache>,
|
||||
shaders: Option<&mut WrShaders>,
|
||||
thread_pool: *mut WrThreadPool,
|
||||
thread_pool_low_priority: *mut WrThreadPool,
|
||||
size_of_op: VoidPtrToSizeFn,
|
||||
enclosing_size_of_op: VoidPtrToSizeFn,
|
||||
document_id: u32,
|
||||
@ -1347,6 +1371,13 @@ pub extern "C" fn wr_window_new(window_id: WrWindowId,
|
||||
let workers = unsafe {
|
||||
Arc::clone(&(*thread_pool).0)
|
||||
};
|
||||
let workers_low_priority = unsafe {
|
||||
if support_low_priority_threadpool {
|
||||
Arc::clone(&(*thread_pool_low_priority).0)
|
||||
} else {
|
||||
Arc::clone(&(*thread_pool).0)
|
||||
}
|
||||
};
|
||||
|
||||
let upload_method = if unsafe { is_glcontext_angle(gl_context) } {
|
||||
UploadMethod::Immediate
|
||||
@ -1390,7 +1421,7 @@ pub extern "C" fn wr_window_new(window_id: WrWindowId,
|
||||
support_low_priority_transactions,
|
||||
allow_texture_swizzling,
|
||||
recorder: recorder,
|
||||
blob_image_handler: Some(Box::new(Moz2dBlobImageHandler::new(workers.clone()))),
|
||||
blob_image_handler: Some(Box::new(Moz2dBlobImageHandler::new(workers.clone(), workers_low_priority.clone()))),
|
||||
workers: Some(workers.clone()),
|
||||
thread_listener: Some(Box::new(GeckoProfilerThreadListener::new())),
|
||||
size_of_op: Some(size_of_op),
|
||||
|
@ -21,6 +21,8 @@ extern crate log;
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
extern crate dwrote;
|
||||
#[cfg(target_os = "windows")]
|
||||
extern crate winapi;
|
||||
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
|
@ -77,6 +77,7 @@ fn dump_index(blob: &[u8]) -> () {
|
||||
/// Handles the interpretation and rasterization of gecko-based (moz2d) WR blob images.
|
||||
pub struct Moz2dBlobImageHandler {
|
||||
workers: Arc<ThreadPool>,
|
||||
workers_low_priority: Arc<ThreadPool>,
|
||||
blob_commands: HashMap<BlobImageKey, BlobCommand>,
|
||||
}
|
||||
|
||||
@ -502,6 +503,8 @@ struct BlobCommand {
|
||||
struct Moz2dBlobRasterizer {
|
||||
/// Pool of rasterizers.
|
||||
workers: Arc<ThreadPool>,
|
||||
/// Pool of low priority rasterizers.
|
||||
workers_low_priority: Arc<ThreadPool>,
|
||||
/// Blobs to rasterize.
|
||||
blob_commands: HashMap<BlobImageKey, BlobCommand>,
|
||||
}
|
||||
@ -559,9 +562,14 @@ impl AsyncBlobImageRasterizer for Moz2dBlobRasterizer {
|
||||
// Parallel version synchronously installs a job on the thread pool which will
|
||||
// try to do the work in parallel.
|
||||
// This thread is blocked until the thread pool is done doing the work.
|
||||
self.workers.install(||{
|
||||
requests.into_par_iter().map(rasterize_blob).collect()
|
||||
})
|
||||
let lambda = ||{ requests.into_par_iter().map(rasterize_blob).collect() };
|
||||
if low_priority {
|
||||
//TODO --bpe runtime flag to A/B test these two
|
||||
self.workers_low_priority.install(lambda)
|
||||
//self.workers.install(lambda)
|
||||
} else {
|
||||
self.workers.install(lambda)
|
||||
}
|
||||
} else {
|
||||
requests.into_iter().map(rasterize_blob).collect()
|
||||
}
|
||||
@ -653,6 +661,7 @@ impl BlobImageHandler for Moz2dBlobImageHandler {
|
||||
fn create_blob_rasterizer(&mut self) -> Box<dyn AsyncBlobImageRasterizer> {
|
||||
Box::new(Moz2dBlobRasterizer {
|
||||
workers: Arc::clone(&self.workers),
|
||||
workers_low_priority: Arc::clone(&self.workers_low_priority),
|
||||
blob_commands: self.blob_commands.clone(),
|
||||
})
|
||||
}
|
||||
@ -705,10 +714,11 @@ extern "C" {
|
||||
|
||||
impl Moz2dBlobImageHandler {
|
||||
/// Create a new BlobImageHandler with the given thread pool.
|
||||
pub fn new(workers: Arc<ThreadPool>) -> Self {
|
||||
pub fn new(workers: Arc<ThreadPool>, workers_low_priority: Arc<ThreadPool>) -> Self {
|
||||
Moz2dBlobImageHandler {
|
||||
blob_commands: HashMap::new(),
|
||||
workers: workers,
|
||||
workers_low_priority: workers_low_priority,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3749,6 +3749,11 @@
|
||||
mirror: always
|
||||
#endif
|
||||
|
||||
- name: gfx.webrender.enable-low-priority-pool
|
||||
type: RelaxedAtomicBool
|
||||
value: false
|
||||
mirror: always
|
||||
|
||||
# Use vsync events generated by hardware
|
||||
- name: gfx.work-around-driver-bugs
|
||||
type: bool
|
||||
|
Loading…
x
Reference in New Issue
Block a user