Skip to content

Commit

Permalink
Switch to std::unordered_map for shadow and Yoga nodes (#10543)
Browse files Browse the repository at this point in the history
* Switch to std::unordered_map for shadow and Yoga nodes

We previously used std::map in ShadowNodeRegistry and NativeUIManager
for the storage of shadow nodes (former) and Yoga nodes and context
(latter), which has O(log(n)) complexity for insertion, removal, and
access. The main reason for using std::map over std::unordered_map is
when you require ordered enumeration of keys, which none of these maps
require.
- Shadow nodes are only enumerated when destroying the UIManagerModule
to cleanup by calling `DropView` on the shadow node. Tag indices
themselves do not specify much besides creation order, and while
children generally have smaller indices than parents in very simple
cases, this is not always the case (consider a component that adds a
child after some state change, the child index will be larger than its
parent). Thus, there is no semantics coupled to the tag value, and no
point in enforcing in-order enumeration.
- Yoga nodes are only enumerated for applying Yoga results to views, and
the same logic above applies, there is no semantics to tag order, thus
no point in enforcing in-order enumeration. #10422 actually changes this
behavior to recursively apply Yoga results to children in depth-first
order, so there will be no remaining enumerations of Yoga nodes.
- Yoga context values are never enumerated, so an ordered map is not
required.

There are two motivations for switching the map type:
1. Effects of logarithmic insertion, removal, and access become
noticeable in apps with many nodes, like Messenger.
2. We are experimenting with ViewFlattening in the Paper UIManager for
RN Windows, which require many more accesses of the ShadowNodeRegistry
than are required today.

* Change files
  • Loading branch information
rozele committed Sep 19, 2022
1 parent d0cf558 commit d83e4b1
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "prerelease",
"comment": "Switch to std::unordered_map for shadow and Yoga nodes",
"packageName": "react-native-windows",
"email": "erozell@outlook.com",
"dependentChangeType": "patch"
}
5 changes: 3 additions & 2 deletions vnext/Microsoft.ReactNative/Modules/NativeUIManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <nativemodules.h>
#include <map>
#include <memory>
#include <unordered_map>
#include <vector>

namespace Microsoft::ReactNative {
Expand Down Expand Up @@ -112,8 +113,8 @@ class NativeUIManager final : public INativeUIManager {
YGConfigRef m_yogaConfig;
bool m_inBatch = false;

std::map<int64_t, YogaNodePtr> m_tagsToYogaNodes;
std::map<int64_t, std::unique_ptr<YogaContext>> m_tagsToYogaContext;
std::unordered_map<int64_t, YogaNodePtr> m_tagsToYogaNodes;
std::unordered_map<int64_t, std::unique_ptr<YogaContext>> m_tagsToYogaContext;
std::vector<xaml::FrameworkElement::SizeChanged_revoker> m_sizeChangedVector;
std::vector<std::function<void()>> m_batchCompletedCallbacks;
std::vector<int64_t> m_extraLayoutNodes;
Expand Down
4 changes: 2 additions & 2 deletions vnext/Microsoft.ReactNative/Views/ShadowNodeRegistry.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#pragma once
#include <Views/PaperShadowNode.h>
#include <functional/functorref.h>
#include <map>
#include <unordered_map>

namespace Microsoft::ReactNative {

Expand Down Expand Up @@ -36,7 +36,7 @@ struct ShadowNodeRegistry {

private:
std::unordered_set<int64_t> m_roots;
std::map<int64_t, std::unique_ptr<ShadowNode, ShadowNodeDeleter>> m_allNodes;
std::unordered_map<int64_t, std::unique_ptr<ShadowNode, ShadowNodeDeleter>> m_allNodes;
};

} // namespace Microsoft::ReactNative

0 comments on commit d83e4b1

Please sign in to comment.