Skip to content

Commit

Permalink
Introduce TurboModule Setup Metric (facebook#24732)
Browse files Browse the repository at this point in the history
Summary:
With the introduction of TurboModules, it would be beneficial to measure the setup time of these modules, as we currently have it in place for NativeModules.

The instantiation of the TMs occurs in the `RCTTurboModuleManager`. In order to successfully measure the time it took to setup the module, we need to ensure that we don't take into account cached modules. As such, we need to:

1. Check if module is in `_turboModuleCache`
  a. Start mark for `RCTPLTurboModuleSetup` tag if not found
2. Get the TM via `[self provideTurboModule:]`
3. Check if module is in `_turboModuleCache`
   a. Stop mark for `RCTPLTurboModuleSetup` if we did not find module in cache prior to **step 2** and if it's now present in the cache.
   b. Notify about setup time if the above is true.
4. Return TM

## Changelog

[iOS] [Added] - Gain insights on the the turbo module setup times by observing `RCTDidSetupModuleNotification`. The userInfo dictionary will contain the module name and setup time in milliseconds. These values can be extracted via `RCTDidSetupModuleNotificationModuleNameKey` and `RCTDidSetupModuleNotificationSetupTimeKey`.
Pull Request resolved: facebook#24732

Differential Revision: D15362088

Pulled By: RSNara

fbshipit-source-id: e6a8044e4aba5a12ae63e9c7dbf707a17ec00180
  • Loading branch information
a-dilettante authored and M-i-k-e-l committed Mar 10, 2020
1 parent 4dc1393 commit 64b5d52
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 2 deletions.
2 changes: 1 addition & 1 deletion React/Base/RCTBridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ RCT_EXTERN NSString *const RCTJavaScriptDidFailToLoadNotification;
RCT_EXTERN NSString *const RCTDidInitializeModuleNotification;

/**
* This notification fires each time a native module is setup after it is initialized. The
* This notification fires each time a module is setup after it is initialized. The
* `RCTDidSetupModuleNotificationModuleNameKey` key will contain a reference to the module name and
* `RCTDidSetupModuleNotificationSetupTimeKey` will contain the setup time in ms.
*/
Expand Down
1 change: 1 addition & 0 deletions React/Base/RCTPerformanceLogger.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ typedef NS_ENUM(NSUInteger, RCTPLTag) {
RCTPLNativeModulePrepareConfig,
RCTPLNativeModuleMainThreadUsesCount,
RCTPLNativeModuleSetup,
RCTPLTurboModuleSetup,
RCTPLJSCWrapperOpenLibrary,
RCTPLBridgeStartup,
RCTPLTTI,
Expand Down
1 change: 1 addition & 0 deletions React/Base/RCTPerformanceLogger.m
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ - (instancetype)init
@"NativeModuleInjectConfig",
@"NativeModuleMainThreadUsesCount",
@"NativeModuleSetup",
@"TurboModuleSetup",
@"JSCWrapperOpenLibrary",
@"JSCExecutorSetup",
@"BridgeStartup",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#import <cassert>

#import <React/RCTBridge+Private.h>
#import <React/RCTPerformanceLogger.h>
#import <React/RCTBridgeModule.h>
#import <React/RCTCxxModule.h>
#import <React/RCTLog.h>
Expand Down Expand Up @@ -65,19 +66,45 @@ - (instancetype)initWithBridge:(RCTBridge *)bridge delegate:(id<RCTTurboModuleMa

__strong __typeof(self) strongSelf = weakSelf;

auto moduleName = name.c_str();
auto moduleWasNotInitialized = ![strongSelf moduleIsInitialized:moduleName];
if (moduleWasNotInitialized) {
[strongSelf->_bridge.performanceLogger markStartForTag:RCTPLTurboModuleSetup];
}

/**
* By default, all TurboModules are long-lived.
* Additionally, if a TurboModule with the name `name` isn't found, then we
* trigger an assertion failure.
*/
return [strongSelf provideTurboModule: name.c_str()];
auto turboModule = [strongSelf provideTurboModule:moduleName];

if (moduleWasNotInitialized && [strongSelf moduleIsInitialized:moduleName]) {
[strongSelf->_bridge.performanceLogger markStopForTag:RCTPLTurboModuleSetup];
[strongSelf notifyAboutTurboModuleSetup:moduleName];
}

return turboModule;
};

_binding = std::make_shared<react::TurboModuleBinding>(moduleProvider);
}
return self;
}

- (void)notifyAboutTurboModuleSetup:(const char*)name {
NSString *moduleName = [[NSString alloc] initWithUTF8String:name];
if (moduleName) {
int64_t setupTime = [self->_bridge.performanceLogger durationForTag:RCTPLTurboModuleSetup];
[[NSNotificationCenter defaultCenter] postNotificationName:RCTDidSetupModuleNotification
object:nil
userInfo:@{
RCTDidSetupModuleNotificationModuleNameKey: moduleName,
RCTDidSetupModuleNotificationSetupTimeKey: @(setupTime)
}];
}
}

/**
* Given a name for a TurboModule, return a C++ object which is the instance
* of that TurboModule C++ class. This class wraps the TurboModule's ObjC instance.
Expand Down

0 comments on commit 64b5d52

Please sign in to comment.