Addresses thread safety, GitHub issue #769. #855

Closed
jpap wants to merge 1 commits from issue-769-thread-safety into master
jpap commented 2019-01-16 18:36:11 -08:00 (Migrated from github.com)

See also: discussions in PR #852 and #786.

In addition to improving thread safety, it removes 8 bytes of heap per node.

See also: discussions in PR #852 and #786. In addition to improving thread safety, it removes 8 bytes of heap per node.
jpap commented 2019-01-16 18:51:50 -08:00 (Migrated from github.com)

Looks like the android Travis CI configuration is borked:

Buck wasn't able to parse /home/travis/build/facebook/yoga/lib/soloader/BUCK:
IOError: [Errno 2] No such file or directory: '/home/travis/build/facebook/yoga/tools/build_defs/fb_native_wrapper.bzl'
Call stack:
  File "/home/travis/buck/python-dsl/buck_parser/buck.py", line 1748, in process_with_diagnostics
    package_implicit_load=package_implicit_load,
  File "/home/travis/buck/python-dsl/buck_parser/buck.py", line 1638, in process
    package_implicit_load=package_implicit_load,
  File "/home/travis/buck/python-dsl/buck_parser/buck.py", line 1626, in _process_build_file
    package_implicit_load=package_implicit_load,
  File "/home/travis/buck/python-dsl/buck_parser/buck.py", line 1561, in _process
    exec(code, module.__dict__)
  File "/home/travis/build/facebook/yoga/lib/soloader/BUCK", line 6
    load("//tools/build_defs:fb_native_wrapper.bzl", "fb_native")
  File "/home/travis/buck/python-dsl/buck_parser/buck.py", line 1292, in _load
    inner_env, module = self._process_include(build_include, is_implicit_include)
  File "/home/travis/buck/python-dsl/buck_parser/buck.py", line 1586, in _process_include
    package_implicit_load=None,
  File "/home/travis/buck/python-dsl/buck_parser/buck.py", line 1550, in _process
    with open(path, "r") as f:

This PR builds OK and tests pass on my local macOS machine.

Looks like the android Travis CI configuration is borked: ``` Buck wasn't able to parse /home/travis/build/facebook/yoga/lib/soloader/BUCK: IOError: [Errno 2] No such file or directory: '/home/travis/build/facebook/yoga/tools/build_defs/fb_native_wrapper.bzl' Call stack: File "/home/travis/buck/python-dsl/buck_parser/buck.py", line 1748, in process_with_diagnostics package_implicit_load=package_implicit_load, File "/home/travis/buck/python-dsl/buck_parser/buck.py", line 1638, in process package_implicit_load=package_implicit_load, File "/home/travis/buck/python-dsl/buck_parser/buck.py", line 1626, in _process_build_file package_implicit_load=package_implicit_load, File "/home/travis/buck/python-dsl/buck_parser/buck.py", line 1561, in _process exec(code, module.__dict__) File "/home/travis/build/facebook/yoga/lib/soloader/BUCK", line 6 load("//tools/build_defs:fb_native_wrapper.bzl", "fb_native") File "/home/travis/buck/python-dsl/buck_parser/buck.py", line 1292, in _load inner_env, module = self._process_include(build_include, is_implicit_include) File "/home/travis/buck/python-dsl/buck_parser/buck.py", line 1586, in _process_include package_implicit_load=None, File "/home/travis/buck/python-dsl/buck_parser/buck.py", line 1550, in _process with open(path, "r") as f: ``` This PR builds OK and tests pass on my local macOS machine.
rmhartog commented 2019-01-16 23:42:06 -08:00 (Migrated from github.com)

There seems to be a file missing for CI indeed, I've proposed a fix in #843.

There seems to be a file missing for CI indeed, I've proposed a fix in #843.
facebook-github-bot (Migrated from github.com) reviewed 2019-01-28 13:39:15 -08:00
facebook-github-bot (Migrated from github.com) left a comment

@davidaurelio has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator.

@davidaurelio has imported this pull request. If you are a Facebook employee, you can view this diff [on Phabricator](https://phabricator.internmc.facebook.com/D13848839).
davidaurelio commented 2019-01-29 02:56:25 -08:00 (Migrated from github.com)

This introduces double-digit regressions for layout calculation on ARM. I’m in favour of #852 at the moment, and will investigate whether we can remove the node counts.

This introduces double-digit regressions for layout calculation on ARM. I’m in favour of #852 at the moment, and will investigate whether we can remove the node counts.
jpap commented 2019-01-29 18:23:52 -08:00 (Migrated from github.com)

This introduces double-digit regressions for layout calculation on ARM.

@davidaurelio do you have any figures to share, and is there any documentation on how to run the performance tests? There may be ways in which to recover the std::map overhead.

The other approach in #852 suffers from not being able to concurrently perform a layout of a given tree, and any number of cloned subtrees. This is because per-layout state is stored in each (shared) node, and the generation count is different for each layout run. (If this is not of practical concern, it could be documented as a limitation.)

> This introduces double-digit regressions for layout calculation on ARM. @davidaurelio do you have any figures to share, and is there any documentation on how to run the performance tests? There may be ways in which to recover the `std::map` overhead. The other approach in #852 suffers from not being able to concurrently perform a layout of a given tree, and any number of cloned subtrees. This is because per-layout state is stored in each (shared) node, and the generation count is different for each layout run. (If this is not of practical concern, it could be documented as a limitation.)
davidaurelio commented 2019-02-01 00:34:05 -08:00 (Migrated from github.com)

@jpap for context: we have an internal device lab that will run benchmarks on physical Android and iOS devices. As much as I would like everyone to be able to run benchmarks, this will not become a publicly available resource.

Some numbers:

  • The synthetic benchmark that measures allocation, style assignment, layout calculation, layout reads, and deallocation recessed by ~11% (Android)
  • calculation in isolation recessed by ~11% on Android, ~8.5% on iOS
  • allocation/deallocation in isolation recessed by ~35% (Android)
  • The losses are smaller when using the Java API, as there’s fixed JNI overhead

These numbers don’t reflect real-life scenarios accurately (we will get there in the coming months), but they give an indication about the performance characteristics of changes.

The other approach in #852 suffers from not being able to concurrently perform a layout of a given tree, and any number of cloned subtrees. This is because per-layout state is stored in each (shared) node, and the generation count is different for each layout run. (If this is not of practical concern, it could be documented as a limitation.)

For now this is an acceptable limitation, and I agree that it should be documented. Shared subtrees are cloned lazily during layout calculation, and the only client making use of that is React Native. In their case, that’s thread safe, as the two highest ancestors sharing a node are never identical, and React Native treats subtrees as immutable.

That being said, it would be nicer to evolve Yoga into a direction where we can separate the layout outputs from the nodes, but this involves migrating client frameworks as well, including Litho, ComponentKit, React Native, React Native Windows, and internal projects at Facebook and other companies.

I think the short term goal should be to make parallel calculations on different trees possible.

Apologies if I am not always super responsive on Github. I really appreciate the input, though!

@jpap for context: we have an internal device lab that will run benchmarks on physical Android and iOS devices. As much as I would like everyone to be able to run benchmarks, this will not become a publicly available resource. Some numbers: - The synthetic benchmark that measures *allocation, style assignment, layout calculation, layout reads, and deallocation* recessed by ~11% (Android) - *calculation in isolation* recessed by ~11% on Android, ~8.5% on iOS - *allocation/deallocation* in isolation recessed by ~35% (Android) - The losses are smaller when using the Java API, as there’s fixed JNI overhead These numbers don’t reflect real-life scenarios accurately (we will get there in the coming months), but they give an indication about the performance characteristics of changes. > The other approach in #852 suffers from not being able to concurrently perform a layout of a given tree, and any number of cloned subtrees. This is because per-layout state is stored in each (shared) node, and the generation count is different for each layout run. (If this is not of practical concern, it could be documented as a limitation.) For now this is an acceptable limitation, and I agree that it should be documented. Shared subtrees are cloned lazily during layout calculation, and the only client making use of that is React Native. In their case, that’s thread safe, as the two highest ancestors sharing a node are never identical, and React Native treats subtrees as immutable. That being said, it would be nicer to evolve Yoga into a direction where we can separate the layout outputs from the nodes, but this involves migrating client frameworks as well, including Litho, ComponentKit, React Native, React Native Windows, and internal projects at Facebook and other companies. I think the short term goal should be to make parallel calculations on different trees possible. Apologies if I am not always super responsive on Github. I really appreciate the input, though!

Pull request closed

Sign in to join this conversation.
No description provided.