Repository navigation
Conversation
SkewMatrixHelper.isAffine2DTransformWithSkew runs before every transform update on Android 10 and later. It walked the transform array from Kotlin, importing each element and its keys over JNI, only to look for skewX/skewY. Fabric always passes a NativeArray, so read it in C++ instead, as nativeProcessTransform already does.
Visual regressionNo visual differences at ios: no capture |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary:
On Android 10 and later,
BaseViewManager.setTransformPropertycallsSkewMatrixHelper.isAffine2DTransformWithSkewon every transform update to decide whether the transform needs the skew path. That check walks the transform array from Kotlin.ReadableNativeArrayimports the array and its types over JNI, and each entry'sReadableNativeMapimports its keys, only so the check can read the first key of each entry. Without skew, the same array then goes tonativeProcessTransform, which reads it in C++ in one call.This adds
nativeIsAffine2DTransformWithSkewnext tonativeProcessTransforminTransformHelper.cpp. It reads theNativeArray'sfolly::dynamicin place and returns the same result as the Kotlin check.SkewMatrixHelper.isAffine2DTransformWithSkewuses it whenever the array is aNativeArray, which it is for props that Fabric mounts. Other arrays, such as theJavaOnlyArrays in the unit tests, still take the Kotlin path.Changelog:
[ANDROID] [CHANGED] - Check transforms for skew in C++ instead of crossing JNI for every transform entry
Test Plan:
./gradlew :packages:react-native:ReactAndroid:testDebugUnitTest --tests '*SkewMatrixHelperTest*'passes (17 tests). They useJavaOnlyArray, so they cover the Kotlin path, which stays.assembleRelease(-PreactNativeArchitectures=arm64-v8a) on a Samsung Galaxy A16 and a Google Pixel 9a. One APK with a temporary switch between the Kotlin and the C++ check, and a temporary trace section around the check insetTransformProperty; neither is part of this PR. 8 interleaved pairs per row, 12 s Perfetto captures.setNativeProps({style: {transform}})from arequestAnimationFrameloop or through JS-drivenAnimated(useNativeDriver: false).setNativePropssetNativePropsAnimatedAnimatedThe trace section adds the same few µs to both arms. "UI thread saved" is the saving per call times the number of calls per second in that run.
The cost of a whole mounted prop update doesn't move beyond noise (within ±1.6% either way): in these repros most mount instructions aren't transform updates, so the check is a small part of the average.
Where every mount carries an animated transform, the difference shows on the whole frame. I measured that on React Native 0.88 with Reanimated: 100 views animate
transformandbackgroundColorthroughuseAnimatedStyle. There, this change cut UI-thread CPU per frame by 5.5% on the Galaxy A16 (17.31 → 16.37 ms, medians) and by 4.0% on the Pixel 9a (11.17 → 10.73 ms).🤖 Generated with Claude Code