Skip to content

Commit 503a6f4

Browse files
mdvaccafacebook-github-bot
authored andcommittedDec 6, 2020
Optimize iteration of ReadableNativeMaps
Summary: Props are transferred from C++ to Java using ReadableNativeMaps. The current implementation of ReadableNativeMaps creates an internal HashMap the first time one of its methods is executed. During the update of props ReadableNativeMaps are consumed only once and they are accessed through an Iterator. That's why there is no reason to create the internal HashMap, which is inefficient from performance and memory point of view. This diff creates an experiment that avoids the creation of the internal HashMap during prop updates, additionally it removes a lock that was being used in the creation of the internal HashMap. I expect this change to have a positive impact in TTRC and memory (in particular for ME devices) This diff reduces the amount of ReadableNativeMaps's internal HashMaps created during initial render of MP Home by ~35%. Changelog: [Internal] Reviewed By: JoshuaGross Differential Revision: D25361169 fbshipit-source-id: 7b6efda11922d56127131494ca39b5cec75f1703
1 parent 158abfe commit 503a6f4

File tree

2 files changed

+68
-2
lines changed

2 files changed

+68
-2
lines changed
 

‎ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableNativeMap.java

+65-2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import com.facebook.infer.annotation.Assertions;
1313
import com.facebook.jni.HybridData;
1414
import com.facebook.proguard.annotations.DoNotStrip;
15+
import com.facebook.react.config.ReactFeatureFlags;
1516
import java.util.HashMap;
1617
import java.util.Iterator;
1718
import java.util.Map;
@@ -88,6 +89,64 @@ private HashMap<String, Object> getLocalMap() {
8889
return mLocalTypeMap;
8990
}
9091

92+
private Iterator<Map.Entry<String, Object>> createExperimentalIterator() {
93+
if (mKeys == null) {
94+
mKeys = Assertions.assertNotNull(importKeys());
95+
}
96+
final String[] iteratorKeys = mKeys;
97+
final Object[] iteratorValues = Assertions.assertNotNull(importValues());
98+
return new Iterator<Map.Entry<String, Object>>() {
99+
int currentIndex = 0;
100+
101+
@Override
102+
public boolean hasNext() {
103+
return currentIndex < iteratorKeys.length;
104+
}
105+
106+
@Override
107+
public Map.Entry<String, Object> next() {
108+
final int index = currentIndex++;
109+
return new Map.Entry<String, Object>() {
110+
@Override
111+
public String getKey() {
112+
return iteratorKeys[index];
113+
}
114+
115+
@Override
116+
public Object getValue() {
117+
return iteratorValues[index];
118+
}
119+
120+
@Override
121+
public Object setValue(Object value) {
122+
throw new UnsupportedOperationException(
123+
"Can't set a value while iterating over a ReadableNativeMap");
124+
}
125+
};
126+
}
127+
};
128+
}
129+
130+
private ReadableMapKeySetIterator createExperimentalKeySetIterator() {
131+
if (mKeys == null) {
132+
mKeys = Assertions.assertNotNull(importKeys());
133+
}
134+
final String[] iteratorKeys = mKeys;
135+
return new ReadableMapKeySetIterator() {
136+
int currentIndex = 0;
137+
138+
@Override
139+
public boolean hasNextKey() {
140+
return currentIndex < iteratorKeys.length;
141+
}
142+
143+
@Override
144+
public String nextKey() {
145+
return iteratorKeys[currentIndex++];
146+
}
147+
};
148+
}
149+
91150
private native Object[] importTypes();
92151

93152
@Override
@@ -187,12 +246,16 @@ public int getInt(@NonNull String name) {
187246

188247
@Override
189248
public @NonNull Iterator<Map.Entry<String, Object>> getEntryIterator() {
190-
return getLocalMap().entrySet().iterator();
249+
return ReactFeatureFlags.enableExperimentalReadableNativeMapIterator
250+
? createExperimentalIterator()
251+
: getLocalMap().entrySet().iterator();
191252
}
192253

193254
@Override
194255
public @NonNull ReadableMapKeySetIterator keySetIterator() {
195-
return new ReadableNativeMapKeySetIterator(this);
256+
return ReactFeatureFlags.enableExperimentalReadableNativeMapIterator
257+
? createExperimentalKeySetIterator()
258+
: new ReadableNativeMapKeySetIterator(this);
196259
}
197260

198261
@Override

‎ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java

+3
Original file line numberDiff line numberDiff line change
@@ -97,4 +97,7 @@ public class ReactFeatureFlags {
9797
* we verify the fix is correct in production
9898
*/
9999
public static boolean enableStartSurfaceRaceConditionFix = false;
100+
101+
/** Enables the usage of an experimental optimized iterator for ReadableNativeMaps. */
102+
public static boolean enableExperimentalReadableNativeMapIterator = false;
100103
}

0 commit comments

Comments
 (0)
Please sign in to comment.