-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Makes Yoga threadsafed: #791
Conversation
- Uses <atomic> for gNodeInstanceCount & gConfigInstanceCount because of counting instance only. - Store gCurrentGenerationCount & gDepth in root node for multithreading.
Thank @rockerhieu for support. |
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 was very recently concerned by Yoga thread safety and saw your PR. Thanks for your contribution.
I see your PR sitting dormant for some time. I'd love to see this topic addressed, so I thought to provide a review with some suggestions for improvement, in the hope we can have an update merged.
If you lack time, or would like some help in refactoring the PR, let me know as I'm happy to help.
|
||
public: | ||
uint32_t gCurrentGenerationCount = 0; | ||
uint32_t gDepth = 0; |
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.
We can avoid storing gDepth
in every node (4 bytes overhead) by:
- Passing
gDepth
(perhaps renamed to justdepth
, again avoiding the global naming prefix) between function calls that stem fromYGNodeCalculateLayout
. - In
YGNodeCalculateLayout
, passdepth
as value 0, to indicate the root depth. - Since this depth state is only used during debugging (when
gPrintChanges
is true), you could further place the increment/decrement in an if-statement that gets optimized out by the compiler whengPrintChanges == false
, after further refactoring the latter to be const (or#define
'd).
Similarly, we can additionally pass the generation via function calls as above, to avoid the need for a pointer from each node to the tree root, saving another 8 bytes. I suspect the approach used in this PR also breaks cloning, which uses a "copy on write" scheme. In this PR, the pointer to the root is overwritten by YGNodeClone
immediately on all children when cloning; but now the cloned nodes are no-longer "shared": we would ideally need the cloned children to point to each of their tree roots; but that becomes awkward as we'd have to manage 1:M pointers, where M is the number of distinct clones. (This doesn't say how we'd then know which of the M pointers to use when performing layout on a cloned subtree; that would be difficult.)
By removing the pointer to the tree root we can also drop the new method setChildRoot
which performs a full subtree traversal that can be expensive.
YGNodeRef pRoot = nullptr; | ||
|
||
public: | ||
uint32_t gCurrentGenerationCount = 0; |
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.
We can probably reduce the storage here to just 16-bits (uint16_t
), saving 2 bytes overhead per node here, and in YGLayout
(saving another 4 bytes). Do we really need to track more than 65,535 generations?
Since this is now a member, we probably shouldn't use the "g" (global) prefix. It might also be a good idea to make it private, with inlined access via:
- void incrementGeneration() { this.generation++ }
- bool isEqualToGeneration(uint16_t g) { return g == this.generation }
Summary: Continuing facebook/yoga#791 nokia6686 is a former member of our team, so we are trying to pick up what he left and carry out the pull request. # Solution Improved from previous solution with jpap's suggestions. 2. Passing ```gDepth``` and ```gCurrentGenerationCount``` (renamed to **_depth_** and **_generationCount_** respectively) between function calls that stem from ```YGNodeCalculateLayout```. In ```YGNodeCalculateLayout```, pass ```depth``` as value 0, to indicate the root depth. Pull Request resolved: facebook/yoga#852 Reviewed By: SidharthGuglani Differential Revision: D15537450 Pulled By: davidaurelio fbshipit-source-id: 338f51383591ba27702ebe759f6c47c2dede3530
Summary: Continuing #791 nokia6686 is a former member of our team, so we are trying to pick up what he left and carry out the pull request. # Solution Improved from previous solution with jpap's suggestions. 2. Passing ```gDepth``` and ```gCurrentGenerationCount``` (renamed to **_depth_** and **_generationCount_** respectively) between function calls that stem from ```YGNodeCalculateLayout```. In ```YGNodeCalculateLayout```, pass ```depth``` as value 0, to indicate the root depth. Pull Request resolved: #852 Reviewed By: SidharthGuglani Differential Revision: D15537450 Pulled By: davidaurelio fbshipit-source-id: 338f51383591ba27702ebe759f6c47c2dede3530
Summary: Continuing facebook/yoga#791 nokia6686 is a former member of our team, so we are trying to pick up what he left and carry out the pull request. # Solution Improved from previous solution with jpap's suggestions. 2. Passing ```gDepth``` and ```gCurrentGenerationCount``` (renamed to **_depth_** and **_generationCount_** respectively) between function calls that stem from ```YGNodeCalculateLayout```. In ```YGNodeCalculateLayout```, pass ```depth``` as value 0, to indicate the root depth. Pull Request resolved: facebook/yoga#852 Reviewed By: SidharthGuglani Differential Revision: D15537450 Pulled By: davidaurelio fbshipit-source-id: 338f51383591ba27702ebe759f6c47c2dede3530
Summary: Continuing facebook/yoga#791 nokia6686 is a former member of our team, so we are trying to pick up what he left and carry out the pull request. # Solution Improved from previous solution with jpap's suggestions. 2. Passing ```gDepth``` and ```gCurrentGenerationCount``` (renamed to **_depth_** and **_generationCount_** respectively) between function calls that stem from ```YGNodeCalculateLayout```. In ```YGNodeCalculateLayout```, pass ```depth``` as value 0, to indicate the root depth. Pull Request resolved: facebook/yoga#852 Reviewed By: SidharthGuglani Differential Revision: D15537450 Pulled By: davidaurelio fbshipit-source-id: 338f51383591ba27702ebe759f6c47c2dede3530
Summary: Continuing facebook/yoga#791 nokia6686 is a former member of our team, so we are trying to pick up what he left and carry out the pull request. # Solution Improved from previous solution with jpap's suggestions. 2. Passing ```gDepth``` and ```gCurrentGenerationCount``` (renamed to **_depth_** and **_generationCount_** respectively) between function calls that stem from ```YGNodeCalculateLayout```. In ```YGNodeCalculateLayout```, pass ```depth``` as value 0, to indicate the root depth. Pull Request resolved: facebook/yoga#852 Reviewed By: SidharthGuglani Differential Revision: D15537450 Pulled By: davidaurelio fbshipit-source-id: 338f51383591ba27702ebe759f6c47c2dede3530
Summary: Continuing facebook#791 nokia6686 is a former member of our team, so we are trying to pick up what he left and carry out the pull request. # Solution Improved from previous solution with jpap's suggestions. 2. Passing ```gDepth``` and ```gCurrentGenerationCount``` (renamed to **_depth_** and **_generationCount_** respectively) between function calls that stem from ```YGNodeCalculateLayout```. In ```YGNodeCalculateLayout```, pass ```depth``` as value 0, to indicate the root depth. Pull Request resolved: facebook#852 Reviewed By: SidharthGuglani Differential Revision: D15537450 Pulled By: davidaurelio fbshipit-source-id: 338f51383591ba27702ebe759f6c47c2dede3530
It looks like this was succeeded by #852 which was merged. Going to close this PR. |
Issue ref: #769
Problem
gNodeInstanceCount
,gConfigInstanceCount
,gCurrentGenerationCount
,gDepth
are global variables inYoga.cpp
. They are not safe when using multithreading.My idea
atomic
forgNodeInstanceCount
andgConfigInstanceCount
because of counting instances only.gCurrentGenerationCount
andgDepth
in root node for multithreading.My solution
gNodeInstanceCount
andgConfigInstanceCount
gCurrentGenerationCount
andgDepth
are stored inYGNode
.