Skip to content

Check transforms for skew in C++ on Android - #59461

Draft
tomekzaw wants to merge 1 commit into
react:mainfrom
tomekzaw:android-native-skew-check
Draft

tomekzaw wants to merge 1 commit into
react:mainfrom
tomekzaw:android-native-skew-check

Conversation

@tomekzaw

@tomekzaw tomekzaw commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

Summary:

On Android 10 and later, BaseViewManager.setTransformProperty calls SkewMatrixHelper.isAffine2DTransformWithSkew on every transform update to decide whether the transform needs the skew path. That check walks the transform array from Kotlin. ReadableNativeArray imports the array and its types over JNI, and each entry's ReadableNativeMap imports its keys, only so the check can read the first key of each entry. Without skew, the same array then goes to nativeProcessTransform, which reads it in C++ in one call.

This adds nativeIsAffine2DTransformWithSkew next to nativeProcessTransform in TransformHelper.cpp. It reads the NativeArray's folly::dynamic in place and returns the same result as the Kotlin check. SkewMatrixHelper.isAffine2DTransformWithSkew uses it whenever the array is a NativeArray, which it is for props that Fabric mounts. Other arrays, such as the JavaOnlyArrays 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 use JavaOnlyArray, so they cover the Kotlin path, which stays.
  • Setup. RNTester 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 in setTransformProperty; neither is part of this PR. 8 interleaved pairs per row, 12 s Perfetto captures.
  • Repros. The Playground renders 100 rounded views whose transform changes on every frame, either through setNativeProps({style: {transform}}) from a requestAnimationFrame loop or through JS-driven Animated (useNativeDriver: false).
Repro Device Skew check per call, Kotlin → C++ Faster in UI thread saved
setNativeProps Galaxy A16 32.3 → 12.4 µs (−61%) 8/8 pairs 7.5 ms/s
setNativeProps Pixel 9a 12.3 → 3.6 µs (−70%) 8/8 pairs 6.0 ms/s
JS-driven Animated Galaxy A16 33.6 → 12.0 µs (−64%) 8/8 pairs 7.1 ms/s
JS-driven Animated Pixel 9a 13.3 → 3.9 µs (−70%) 8/8 pairs 4.8 ms/s

The 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 transform and backgroundColor through useAnimatedStyle. 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

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.
@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Oct 24, 2026
@facebook-github-tools facebook-github-tools Bot added p: Software Mansion Partner: Software Mansion Partner labels Oct 24, 2026
@github-actions

Copy link
Copy Markdown

Visual regression

No visual differences at 1fad084345bf.

ios: no capture

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. p: Software Mansion Partner: Software Mansion Partner

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant