-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Performance] Convert ASLayoutElementSize to atomic #trivial #331
[Performance] Convert ASLayoutElementSize to atomic #trivial #331
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately this isn't correct.
I don't know that there is any way to achieve this with an atomic.
Now, we could definitely have the storage here be atomic<CGFloat> width, atomic<CGFloat> height
etc, and only use a lock when reading/writing .size
, and build the size out of those different fields, but I think that would be pretty ugly and probably wouldn't provide a justifying performance improvement.
@appleguy Thoughts?
Source/Layout/ASLayoutElement.mm
Outdated
_size.height = height; | ||
ASLayoutElementSize newSize = _size.load(); | ||
newSize.height = height; | ||
_size.store(newSize); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately this breaks atomicity =/ Imagine:
Thread 1: read size A
Thread 2: read size A
Thread 1: write size { A, height = x }
Thread 2: write size { A, width = y }
So we end up with size { A, width = y }
, thread 2 overwrote thread 1's change. We should have ended up with size { A, height = x, width = y }
.
We have to do the read-update-write all in one operation.
Source/Layout/ASLayoutElement.mm
Outdated
ASLayoutElementSize newSize = _size.load(); | ||
newSize.maxWidth = maxLayoutSize.width; | ||
newSize.maxHeight = maxLayoutSize.height; | ||
_size.store(newSize); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if _size
is changed after it's loaded here but before the new size is stored?
@Adlai-Holler @nguyenhuy good catch. I hadn't considered the size writing problem with this. Is it correct that the issue only occurs in the writing methods, and that it would occur for all the writing methods including the ones for scalar values in the struct? I think this would still be worth the win if we take the lock for the writing cases and let reading use the atomic directly. Reads are drastically more common than writes, especially because of relayouts that often get performed on the main thread. |
@appleguy Sadly I don't think acquiring the lock only in writing methods will work. @Adlai-Holler Please correct me if I'm wrong. |
@nguyenhuy @Adlai-Holler If the atomic were kept and then also the lock used in the writing methods, why would this not work? This is ready for another review. Let me know if you can think of another accessing way that would break this. |
@Adlai-Holler @nguyenhuy I've taken a look, and could be missing something, but this seems safe to me...very curious to know what I might have failed to consider. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm 2% of CPU is no joke, but this pattern also isn't very scalable. Since this is such an insanely hot variable, let's roll with this ⚡️
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Talked to Adlai about it, let's get this in.
@appleguy - I don't have merge permissions, could you land this? |
Don't worry, I got it :) |
…Group#331) * [Performance] Convert ASLayoutElementSize to atomic * [ASLayoutElementStyle] Put locks around setter methods. * Also add lock to setSize: internal method.
Resolves #318