Join GitHub today
GitHub is home to over 50 million developers working together to host and review code, manage projects, and build software together.
Sign upMake image cache per-document rather than global #16048
Conversation
highfive
commented
Mar 20, 2017
|
Heads up! This PR modifies the following files:
|
highfive
commented
Mar 20, 2017
|
r? @jdm |
|
One thing I see when skimming this PR - by moving image_cache_thread from net to net_traits, we make changing its implementation take longer to compile. We should consider moving the implementation back to net and providing a trait in net_traits for consumers instead. |
2c6ff8f
to
f9968f7
|
@bors-servo try |
|
@ferjm: |
|
@jdm it seems that I still don't have privileges to trigger try runs. I guess servo/saltfs@09aa211 has not been pushed to production yet. Could you trigger a try run for me, please? I'd like to see if this patch breaks any tests. Thank you! |
|
@bors-servo: try |
Make image cache per-document rather than global - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [X] These changes fix #15701. - [X] These changes do not require new tests because there should already be WPTs for image loads. <!-- 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/16048) <!-- Reviewable:end -->
|
|
|
Good start! There are some tricky details that we still need to get right, however. |
|
|
||
| // Webrender API instance. | ||
| webrender_api: Mutex<webrender_traits::RenderApi>, |
This comment has been minimized.
This comment has been minimized.
jdm
Mar 21, 2017
Member
I'm tempted to recommend that we should avoid storing separate mutexes inside ImageCache, and make consumers wrap it in a single Mutex instead.
This comment has been minimized.
This comment has been minimized.
ferjm
Mar 22, 2017
Author
Member
May I ask why? :) I would prefer to hide the Mutex complexity to consumers.
This comment has been minimized.
This comment has been minimized.
jdm
Mar 22, 2017
Member
Multiple mutexes introduce opportunities for deadlocks. I would prefer to rely on Rust's borrow checker and write methods that accept &mut self arguments, rather than wrapping each member in a separate Mutex.
This comment has been minimized.
This comment has been minimized.
ferjm
Mar 22, 2017
Author
Member
Ok, thanks for the explanation.
I am a bit blocked trying to address this comment. I think I understand the issue, but I am not sure how to solve it.
So the ImageCacheImpl struct has a webrender_traits::RenderApi member and webrender_traits::RenderApi contains a Cell<webrender_traits::ResourceId>. The thing is that Cell implements Send but not Sync and I was solving this by wrapping the RenderApi member in its own Mutex. But now, removing this Mutex and wrapping the entire ImageCacheImpl in a Mutex makes the compiler unhappy:
rror[E0277]: the trait bound `std::cell::Cell<webrender_traits::ResourceId>: std::marker::Sync` is not satisfied in `image_cache::ImageCacheImpl`
--> /Volumes/mozilladev/servo/components/net/image_cache.rs:406:6
|
406 | impl ImageCache for ImageCacheImpl {
| ^^^^^^^^^^ within `image_cache::ImageCacheImpl`, the trait `std::marker::Sync` is not implemented for `std::cell::Cell<webrender_traits::ResourceId>`
|
= note: `std::cell::Cell<webrender_traits::ResourceId>` cannot be shared between threads safely
= note: required because it appears within the type `webrender_traits::RenderApi`
= note: required because it appears within the type `image_cache::ImageCacheImpl`
= note: required by `net_traits::image_cache::ImageCache`
error[E0277]: the trait bound `std::cell::Cell<()>: std::marker::Sync` is not satisfied in `image_cache::ImageCacheImpl`
--> /Volumes/mozilladev/servo/components/net/image_cache.rs:406:6
|
406 | impl ImageCache for ImageCacheImpl {
| ^^^^^^^^^^ within `image_cache::ImageCacheImpl`, the trait `std::marker::Sync` is not implemented for `std::cell::Cell<()>`
|
= note: `std::cell::Cell<()>` cannot be shared between threads safely
= note: required because it appears within the type `std::marker::PhantomData<std::cell::Cell<()>>`
= note: required because it appears within the type `ipc_channel::platform::OsIpcSender`
= note: required because it appears within the type `ipc_channel::ipc::IpcSender<webrender_traits::ApiMsg>`
= note: required because it appears within the type `webrender_traits::RenderApi`
= note: required because it appears within the type `image_cache::ImageCacheImpl`
= note: required by `net_traits::image_cache::ImageCache`
@jdm should I keep the Mutex for the webrender_traits::RenderApi member? Or is there a better way to solve this?
This comment has been minimized.
This comment has been minimized.
|
|
||
| // Public API | ||
|
|
||
| pub fn new(webrender_api: webrender_traits::RenderApi) -> Arc<ImageCache> { |
This comment has been minimized.
This comment has been minimized.
jdm
Mar 21, 2017
Member
Let's extract the public API into a trait that lives in net_traits/image_cache.rs, and move the implementation back into net_traits/image_cache.rs.
This comment has been minimized.
This comment has been minimized.
| DecoderMsg { | ||
| key: key, | ||
| image: image | ||
| if let Some(msg) = rx.recv().ok() { |
This comment has been minimized.
This comment has been minimized.
jdm
Mar 21, 2017
Member
Synchronously waiting on the result here makes spawning a thread redundant. We should call handle_decoder from inside the thread instead, but that suddenly makes this code more complicated to write. Maybe notify_pending_response needs to accept an additional argument which is an Arc for self? The other option is to given the image cache an interface it can use to enqueue an async operation to call handle_decoder on the original thread; this would mean that there is no risk of an image being decoded halfway through a layout operation, which sounds like a good idea.
This comment has been minimized.
This comment has been minimized.
| @@ -48,4 +48,4 @@ pub trait LayoutThreadFactory { | |||
| content_process_shutdown_chan: Option<IpcSender<()>>, | |||
| webrender_api_sender: webrender_traits::RenderApiSender, | |||
| layout_threads: usize); | |||
| } | |||
| } | |||
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
@jdm my last commit is not exactly what you were asking for, but I think it's a good middle ground solution where we have a single Mutex for the ImageCache data as you suggested but we don't require consumers to explicitly wrap with a Mutex and request the locks. I also removed the synchronous wait after spawning the image decoding thread. Thanks for your feedback! |
| @@ -405,14 +401,39 @@ impl ImageCacheImpl { | |||
| } | |||
| } | |||
|
|
|||
| struct ImageDecoderRunnable { | |||
This comment has been minimized.
This comment has been minimized.
jdm
Mar 27, 2017
Member
I don't see a reason for this separate structure rather than having the code inline in the caller of run.
| } | ||
| } | ||
|
|
||
| pub struct ImageCacheImpl { |
This comment has been minimized.
This comment has been minimized.
jdm
Mar 27, 2017
Member
All the code using this now puts it in an extra Arc, right? Can we fix that by making this structure Clone and storing ImageCacheImpl (perhaps renaming it to ImageCacheHandle).
This comment has been minimized.
This comment has been minimized.
ferjm
Mar 27, 2017
Author
Member
@jdm if I am not wrong, this means that I need to use net::image_cache::ImageCacheHandle instead of net_traits::image_cache::ImageCache in all consumers, is this ok?
This comment has been minimized.
This comment has been minimized.
|
@bors-servo: r+ |
|
|
Make image cache per-document rather than global - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [X] These changes fix #15701. - [X] These changes do not require new tests because there should already be WPTs for image loads. <!-- 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/16048) <!-- Reviewable:end -->
|
|
|
@bors-servo: retry |
|
|
|
|
|
@bors-servo: retry |
|
|
|
|
ferjm commentedMar 20, 2017
•
edited
./mach build -ddoes not report any errors./mach test-tidydoes not report any errorsThis change is