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 SharedLayoutContext threadsafe. #7524
Conversation
highfive
commented
Sep 3, 2015
1c8114f
to
1d17d86
|
r? @pcwalton |
| @@ -201,7 +201,7 @@ impl<'a> PreorderDomTraversal for RecalcStyleForNode<'a> { | |||
| parent_opt, | |||
| &applicable_declarations, | |||
| &mut self.layout_context.applicable_declarations_cache(), | |||
| &self.layout_context.shared.new_animations_sender); | |||
| &self.layout_context.shared.new_animations_sender.lock().unwrap()); | |||
This comment has been minimized.
This comment has been minimized.
| @@ -185,8 +185,8 @@ impl<'a> PreorderDomTraversal for RecalcStyleForNode<'a> { | |||
|
|
|||
| if node.as_element().is_some() { | |||
| // Perform the CSS selector matching. | |||
| let stylist = unsafe { &*self.layout_context.shared.stylist }; | |||
| node.match_node(stylist, | |||
| let stylist = self.layout_context.shared.stylist.read().unwrap(); | |||
This comment has been minimized.
This comment has been minimized.
pcwalton
Sep 3, 2015
Contributor
Can you make the stylist itself thread-safe? I worry this is going to be too slow.
This comment has been minimized.
This comment has been minimized.
eefriedman
Sep 3, 2015
Author
Contributor
I don't see how that's possible...
Actually, I'm pretty sure the current usage of Stylist on master is actually threadsafe without any additional locking. It's just impossible to prove that to the compiler at the moment because we can't attach a lifetime to SharedLayoutContext with the current WorkQueue API.
This comment has been minimized.
This comment has been minimized.
pcwalton
Sep 3, 2015
Contributor
It would be nice if we could do that. I'm fine with changing the WorkQueue API.
I think taking a lock for every node here will probably erase most parallelism in Servo, so we can't land this.
| @@ -303,6 +303,7 @@ impl<'a> FlowConstructor<'a> { | |||
| layout_data.remove_compositor_layers(self.layout_context | |||
| .shared | |||
| .constellation_chan | |||
| .lock().unwrap() | |||
This comment has been minimized.
This comment has been minimized.
pcwalton
Sep 3, 2015
Contributor
This will probably be too slow. Can you pass the mutex to remove_compositor_layers and take the lock only if necessary?
1d17d86
to
8982fe4
|
Figured out how to avoid the Stylist locking. Current version is WIP; but I'd like to double-check that the approach is sane. |
6d5244a
to
a293c79
|
Updated. Not sure why I thought the other stuff needed mutexes; I was probably just confused by the comment claiming they do. |
|
|
a293c79
to
c900824
|
|
c900824
to
b385969
|
Updated version. Rebased, and fixed so it adds zero new mutexes. |
|
|
|
(I'm not planning to rebase this again until it gets reviewed.) |
| /// The position and size of the visible rect for each layer. We do not build display lists | ||
| /// for any areas more than `DISPLAY_PORT_SIZE_FACTOR` screens away from this area. | ||
| pub visible_rects: Arc<HashMap<LayerId, Rect<Au>, DefaultState<FnvHasher>>>, | ||
| } |
This comment has been minimized.
This comment has been minimized.
pcwalton
Sep 25, 2015
Contributor
What does "Frozen"/"Unfrozen" mean? I'm a bit confused. Is "Frozen" immutable? If so, that would be called "Sync" in Rust.
This comment has been minimized.
This comment has been minimized.
eefriedman
Sep 25, 2015
Author
Contributor
Frozen probably isn't the best terminology, but I was having trouble thinking of something better.
When we do layout, we have to build a SharedLayoutContext. To avoid extraneous locking/copying, it needs to have a pointer into the current LayoutTaskData. (There's probably more unnecessary copying that could be avoided as a followup, but I wanted to keep this from getting too complicated.) However, some bits need to be mutated while the SharedLayoutContext exists. So this patch splits LayoutTaskData into the bits which are immutably borrowed by SharedLayoutContext and the bits which need to be mutated. The "frozen" section is the one which is borrowed, and therefore can't be mutated.
b385969
to
1086c59
|
Updated. Forgot a Sync bound in WorkQueue, so I managed to confuse myself about Sender (which in practice is Sync, but doesn't expose a Sync bound; see rust-lang/rfcs#1299 .) Renamed the usage of Frozen to Sync, which is essentially appropriate here given that SharedLayoutContext is Sync. |
Making the Stylist usage threadsafe without unsafe code or extra locking required some changes to WorkQueue; the changes are mostly straightforward. Some refactoring of LayoutTaskData was also required: this is basically just splitting the structure in two so the borrow checker can understand that building a SharedLayoutContext only borrows part of LayoutTaskData. The "frozen" part is the part that can't be safely modified while a parallel work-queue is running. It might be worth considering switching to some sort of threadsafe channel to avoid the mutexes... see Rust RFC PR #1299. Fixes #2604. Pretty sure the issue with the other version mentioned there was just that it held on to the lock too long.
1086c59
to
e11c00a
|
|
|
This seems fine to me in general. I'm a little worried about performance of the font cache task mutex, but if it's measured to be not a problem then I'm fine with it. |
I'm not sure how this could be an issue... each layout thread takes the lock exactly once in its entire lifetime. |
|
Oh, OK then. In that case looks good after a rebase. |
|
Fwiw, I'd like to have this wait a bit; I'm looking into an alternative approach. |
|
Okay. I might try to split out the WorkQueue-related changes into a separate PR, since they're probably useful anyway. |
|
Any updates? |
|
I'll revisit this once #9050 is resolved, I guess. |
eefriedman commentedSep 3, 2015
Not sure if this is the best way to structure the code; there are a lot
of mutexes involved.
Fixes #2604. Pretty sure the issue with the other version mentioned
there was just that it held on to the lock too long.