Skip to content

Commit d05142d

Browse files
shubh73claude
andcommitted
Write executeMount int buffer to Java in a single JNI call
executeMount called SetIntArrayRegion for every writeInt/writeIntArray, ~4.5k JNI calls for a commit mounting 1500 views. The exact size is already known from computeBufferSizes, so fill a std::vector<jint> and copy it once before createIntBufferBatchMountItem. The int[] Java receives is unchanged. Changelog: [ANDROID] [CHANGED] - Write Fabric mount instruction ints to Java in a single JNI call Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
1 parent d7ff82e commit d05142d

1 file changed

Lines changed: 14 additions & 11 deletions

File tree

‎packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.cpp‎

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "StateWrapperImpl.h"
1313

1414
#include <cxxreact/TraceSection.h>
15+
#include <react/debug/react_native_assert.h>
1516
#include <react/featureflags/ReactNativeFeatureFlags.h>
1617
#include <react/jni/ReadableNativeArray.h>
1718
#include <react/jni/ReadableNativeMap.h>
@@ -359,22 +360,18 @@ jni::local_ref<jobject> getProps(
359360
}
360361

361362
struct InstructionBuffer {
362-
JNIEnv* env;
363-
jintArray ints;
363+
std::vector<jint> ints;
364364
jni::local_ref<jni::JArrayClass<jobject>> objects;
365365

366-
int intsPosition = 0;
367366
int objectsPosition = 0;
368367

369368
inline void writeInt(int value) {
370-
env->SetIntArrayRegion(ints, intsPosition, 1, &value);
371-
intsPosition += 1;
369+
ints.push_back(value);
372370
}
373371

374372
template <size_t N>
375373
inline void writeIntArray(const std::array<int, N>& buffer) {
376-
env->SetIntArrayRegion(ints, intsPosition, N, buffer.data());
377-
intsPosition += N;
374+
ints.insert(ints.end(), buffer.begin(), buffer.end());
378375
}
379376

380377
inline void writeObject(jobject obj) {
@@ -863,10 +860,9 @@ void FabricMountingManager::executeMount(
863860
// Allocate the intBuffer and object array, now that we know exact sizes
864861
// necessary
865862
InstructionBuffer buffer = {
866-
.env = env,
867-
.ints = env->NewIntArray(batchMountItemIntsSize),
868863
.objects = jni::JArrayClass<jobject>::newArray(batchMountItemObjectsSize),
869864
};
865+
buffer.ints.reserve(batchMountItemIntsSize);
870866

871867
// Fill in arrays
872868
int prevMountItemType = -1;
@@ -996,6 +992,13 @@ void FabricMountingManager::executeMount(
996992
}
997993
}
998994

995+
// Copy the ints to Java in a single JNI call, rather than one per write
996+
react_native_assert(
997+
static_cast<int>(buffer.ints.size()) == batchMountItemIntsSize);
998+
jintArray ints = env->NewIntArray(static_cast<jsize>(buffer.ints.size()));
999+
env->SetIntArrayRegion(
1000+
ints, 0, static_cast<jsize>(buffer.ints.size()), buffer.ints.data());
1001+
9991002
static auto createMountItemsIntBufferBatchContainer =
10001003
JFabricUIManager::javaClassStatic()
10011004
->getMethod<jni::alias_ref<JMountItem>(
@@ -1006,7 +1009,7 @@ void FabricMountingManager::executeMount(
10061009
surfaceId,
10071010
// If there are no items, we pass a nullptr instead of passing the
10081011
// object through the JNI
1009-
batchMountItemIntsSize > 0 ? buffer.ints : nullptr,
1012+
batchMountItemIntsSize > 0 ? ints : nullptr,
10101013
batchMountItemObjectsSize > 0 ? buffer.objects.get() : nullptr,
10111014
revisionNumber);
10121015

@@ -1026,7 +1029,7 @@ void FabricMountingManager::executeMount(
10261029
telemetry.getAffectedLayoutNodesCount(),
10271030
static_cast<jboolean>(synchronous));
10281031

1029-
env->DeleteLocalRef(buffer.ints);
1032+
env->DeleteLocalRef(ints);
10301033
}
10311034

10321035
void FabricMountingManager::drainPreallocateViewsQueue() {

0 commit comments

Comments
 (0)