Repository navigation
Commit 1d1fade
Look up each TurboModule method's signature once on iOS (#59394)
Summary:
On iOS, every call from JavaScript to an Objective-C TurboModule method goes through `ObjCTurboModule::createMethodInvocation` (`ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.mm`), which asks the module for the method's signature with `methodSignatureForSelector:`. For methods declared in a protocol, the runtime looks the selector up in the module's protocol list (`class_copyProtocolList`, `protocol_getMethodDescription`) and builds a new `NSMethodSignature` each time. In a Time Profiler trace of a loop of sync calls on an iPhone 15 Pro, this lookup was about 25% of `invokeObjCMethod`.
A method's signature doesn't change, so this change looks it up on the method's first call and keeps it. Each `ObjCTurboModule` now has one `MethodInfo` struct per method, keyed by the method's JS name, which holds the signature together with the metadata that was already kept per method: the argument types from `RCT_EXPORT_METHOD` and the `RCTCxxConvert` selectors set by the generated code. This replaces `methodArgConversionSelectors_` and `methodArgumentTypeNames_`, two dictionaries keyed by an `NSString` method name. The map is looked up with a `std::string_view`, so no string is allocated on a call. The cache is per instance and still calls `methodSignatureForSelector:` on the module instance, so it keeps the behavior from #51366: a mock module is a different instance and gets its own cache. A mutex guards the map. The members are private, so there is no API change.
Memory: one entry per method that is actually called. Running RNTester's TurboModule, Linking, AppState, Clipboard, Vibration, Share and Alert examples filled 40 entries across 12 modules. An `NSMethodSignature` for a method with 4–6 arguments takes about 620 bytes, so this is about 25 KB. The signatures were already created on every call and released right after.
## Changelog:
[IOS] [CHANGED] - Look up each TurboModule method's signature once instead of on every call
Pull Request resolved: #59394
Test Plan:
- `clang-format --dry-run --Werror` (the repository's pinned version) on the changed files passes.
- I could not run `RNTesterUnitTests` locally: with Xcode 26.3 the test build fails to link `RNTesterIntegrationTests` (`__swift_FORCE_LOAD_$_swiftCompatibility56` not found), which is unrelated to this change. `RCTTurboModuleArrayBufferTests` calls `invokeObjCMethod` directly, so I'm relying on CI for it; the same paths are covered by the TurboModule example below.
- RNTester built with `xcodebuild` in Release and run on a physical iPhone 15 Pro (iOS 26.6.1). In the TurboModule example, "Run function call tests" returns the expected value for all 18 methods, including callbacks, a resolved and a rejected promise, and ArrayBuffers. The Alert example, whose `alertWithArgs` argument goes through an `RCTCxxConvert` selector, shows its alerts as before.
- **Measurement.** RNTester Playground calling `NativeSampleTurboModule` methods in a loop (20,000 calls each for the sync methods, 5,000 for `voidFunc` and `getValueWithCallback`), measured with `performance.now()`. Two Release builds, before and after this change, installed in the order before, after, after, before, 4 launches each. The presses were driven by [Argent](https://github.com/software-mansion/argent) on the physical iPhone. Mean time per call:
| Call | before | this PR | change |
|---|--:|--:|--:|
| `getNumber` | 2.85 µs | 2.25 µs | −21% |
| `getBool` | 1.46 µs | 1.19 µs | −18% |
| `getString` | 1.56 µs | 1.31 µs | −16% |
| `getArray` (3 items) | 1.93 µs | 1.65 µs | −14% |
| `getObject` (small) | 2.75 µs | 2.53 µs | −8% |
| `getObject` (20 keys) | 11.08 µs | 10.81 µs | −2% |
| `getValue` | 2.97 µs | 2.81 µs | −6% |
| `voidFunc` (async) | 1.04 µs | 0.60 µs | −42% |
| `getValueWithCallback` | 1.51 µs | 0.98 µs | −35% |
For every row except `getNumber`, the ranges of the two arms don't overlap.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Reviewed By: andrewdacenko
Differential Revision: D127179102
Pulled By: javache
fbshipit-source-id: beb48cb385af0719f2d37040c1fbcd7dbfc0fd4c1 parent ca95277 commit 1d1fade
2 files changed
Lines changed: 80 additions & 51 deletions
File tree
- packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
16 | 16 | | |
17 | 17 | | |
18 | 18 | | |
| 19 | + | |
19 | 20 | | |
| 21 | + | |
20 | 22 | | |
| 23 | + | |
21 | 24 | | |
22 | 25 | | |
23 | 26 | | |
| |||
132 | 135 | | |
133 | 136 | | |
134 | 137 | | |
135 | | - | |
136 | | - | |
137 | | - | |
138 | | - | |
139 | | - | |
140 | | - | |
141 | | - | |
142 | | - | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
143 | 159 | | |
144 | 160 | | |
145 | 161 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
680 | 680 | | |
681 | 681 | | |
682 | 682 | | |
683 | | - | |
684 | | - | |
685 | | - | |
| 683 | + | |
| 684 | + | |
686 | 685 | | |
687 | 686 | | |
688 | 687 | | |
| |||
707 | 706 | | |
708 | 707 | | |
709 | 708 | | |
710 | | - | |
711 | | - | |
| 709 | + | |
| 710 | + | |
| 711 | + | |
712 | 712 | | |
713 | 713 | | |
714 | 714 | | |
715 | 715 | | |
716 | 716 | | |
717 | | - | |
| 717 | + | |
718 | 718 | | |
719 | 719 | | |
720 | | - | |
721 | | - | |
722 | | - | |
| 720 | + | |
| 721 | + | |
| 722 | + | |
| 723 | + | |
723 | 724 | | |
724 | 725 | | |
725 | 726 | | |
| |||
818 | 819 | | |
819 | 820 | | |
820 | 821 | | |
821 | | - | |
| 822 | + | |
822 | 823 | | |
823 | | - | |
824 | | - | |
825 | | - | |
826 | | - | |
827 | | - | |
828 | | - | |
829 | | - | |
830 | | - | |
831 | | - | |
832 | | - | |
| 824 | + | |
| 825 | + | |
| 826 | + | |
| 827 | + | |
| 828 | + | |
| 829 | + | |
| 830 | + | |
| 831 | + | |
| 832 | + | |
| 833 | + | |
| 834 | + | |
833 | 835 | | |
834 | 836 | | |
835 | 837 | | |
| |||
842 | 844 | | |
843 | 845 | | |
844 | 846 | | |
| 847 | + | |
| 848 | + | |
| 849 | + | |
| 850 | + | |
| 851 | + | |
| 852 | + | |
| 853 | + | |
| 854 | + | |
| 855 | + | |
| 856 | + | |
| 857 | + | |
| 858 | + | |
| 859 | + | |
| 860 | + | |
| 861 | + | |
| 862 | + | |
| 863 | + | |
| 864 | + | |
| 865 | + | |
| 866 | + | |
845 | 867 | | |
846 | 868 | | |
847 | 869 | | |
| |||
859 | 881 | | |
860 | 882 | | |
861 | 883 | | |
862 | | - | |
863 | | - | |
| 884 | + | |
864 | 885 | | |
865 | 886 | | |
866 | 887 | | |
| |||
986 | 1007 | | |
987 | 1008 | | |
988 | 1009 | | |
989 | | - | |
990 | | - | |
| 1010 | + | |
991 | 1011 | | |
992 | 1012 | | |
993 | 1013 | | |
994 | 1014 | | |
995 | | - | |
996 | | - | |
| 1015 | + | |
| 1016 | + | |
| 1017 | + | |
| 1018 | + | |
| 1019 | + | |
| 1020 | + | |
997 | 1021 | | |
998 | 1022 | | |
999 | 1023 | | |
1000 | 1024 | | |
1001 | | - | |
1002 | | - | |
1003 | | - | |
1004 | | - | |
1005 | | - | |
1006 | | - | |
1007 | | - | |
1008 | | - | |
1009 | | - | |
1010 | | - | |
1011 | | - | |
1012 | | - | |
| 1025 | + | |
| 1026 | + | |
| 1027 | + | |
| 1028 | + | |
| 1029 | + | |
1013 | 1030 | | |
1014 | | - | |
1015 | | - | |
1016 | | - | |
1017 | | - | |
1018 | | - | |
| 1031 | + | |
1019 | 1032 | | |
1020 | 1033 | | |
1021 | 1034 | | |
| |||
0 commit comments