-
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
[Need Design Review] Set up an experiment to share one lock across each entire embedding #1528
base: master
Are you sure you want to change the base?
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.
I like the direction we are going here! One question that came up while looking over it is that if a developer would like to implement it's own container class does he need to know and handle the fact there is a context? We are currently providing support within our container classes (ASTableView
, ASCollectionView
and ASViewController
), but if so it would add some burden on top of developers to understand and handle the existance of an ASNodeContext
.
/** | ||
* Get the context for this node, if one was set during creation. | ||
*/ | ||
@property (nullable, readonly) ASNodeContext *nodeContext; |
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.
Do we need to expose the nodeContext
publicly?
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.
To your question above, if users want to implement custom containers, and they want to add new nodes to a given context outside of our automatic places (like layout) they will need to push the context for an existing node. At least that's my thinking although I haven't written out an example case yet.
Minor updates, just harder experiment gating and a build fix. |
I like this direction. In the multi-threaded WebCore iPhone fork (all of 2 threads) back in 2007, there was a single lock for the entire DOM. It would be taken as needed by the web thread or the main thread. Maybe when you say there is one lock per "embedded" this is conceptually like the "node tree"? Another possibility (something we did later around 2008 or 2009) was to allow each thread to take the web lock. Once either thread had it, it then held the lock until the "bottom" of the run loop. This is because we found we had tons of contention for the single lock. It was faster in the end to let each thread complete its work instead of bouncing around. |
Is it possible to write tests for this behavior? Are there many developers that have custom containers? I'm so unaware, my bet is the Pinterest is one of them. ;) |
@bolsinga Thanks for weighing in! Yep it's effectively a node tree, the only difference being somewhat pedantic – before & after a given layout is applied, the nodes in that layout may not be formally in the tree but they are still subject to the same lock. This is important because invalidating the layout of a random node that is part of a layout spec tree/yoga tree but isn't yet in the node tree should still be subject to the same serialization. An open question that got raised elsewhere:
To the question about custom embeddings, I'd like to see how this looks in practice (Pinterest indeed) but the thinking now is, you will need to call Interesting to hear about the WebCore prior art here! I won't land this before adding unit tests, indeed. |
I think a first pass of using #2 sounds best, as keeping first steps simple is best. If it winds up being an onerous ordeal for clients, then building the library code to do it could be considered. I also like for how large of a conceptual/runtime change this is, it is a surprisingly small diff. Thanks. |
515eac2
to
150d842
Compare
9e458d1
to
691ddde
Compare
6e9fb4a
to
41342f6
Compare
🚫 CI failed with log |
🚫 CI failed with log |
Generated by 🚫 Danger |
🚫 CI failed with log |
FYI, CI seems to hit legitimate errors. |
I have an improved version of this downstream. Let me upstream it and we'll see what people think |
@Adlai-Holler Did a diff like this get into production? It looks like something we'd like to try out. Thanks. |
|
This diff works.
Basically when a node is initialized it needs a target "context." Node context might be a cell in a table, or a view controller, or some silo'd off area that we will prohibit users from changing for a given node.
If we're willing to accept this restriction, then the context can own a mutex which is an invariant, and which is pointed to by all the nodes in the context, and we can freely traverse the tree, go crazy, and do whatever we need to do during our transactions on the tree. Right now we are tippy-toeing around things that should be easy, like upward propagation of layout invalidation.
So first of all, please people take a look and give useful feedback.
One thing you'll notice is in the
ASDisplayNode+*.mm
files I have redefined__instanceLock__
as a macro that points to our_mutexOrPtr.get()
which acts as the switch during experimentation. As soon as this lands, I will land a find-and-replace that removes those macros. It's just to keep this diff from being cluttered.The end state is for all the major consumers to experiment with this, prove it works, then launch it and remove the forking. Nodes no longer own their own mutexes, all nodes have a context, boom.