Refactor RCTPerformanceLogger to avoid having global state

Reviewed By: javache

Differential Revision: D3509004

fbshipit-source-id: c4ab12b3f1defa32c2b1c211e775f6782ede4b7f
This commit is contained in:
Alexey Lang 2016-07-07 07:20:03 -07:00 committed by Facebook Github Bot 4
parent 4f5c2b48fe
commit 97299260b6
12 changed files with 206 additions and 176 deletions

View File

@ -97,7 +97,7 @@ RCT_EXTERN NSArray<Class> *RCTGetModuleClasses(void);
dispatch_group_enter(initModulesAndLoadSource);
__weak RCTBatchedBridge *weakSelf = self;
__block NSData *sourceCode;
[self loadSource:^(NSError *error, NSData *source) {
[self loadSource:^(NSError *error, NSData *source, int64_t sourceLength) {
if (error) {
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf stopLoadingWithError:error];
@ -111,6 +111,7 @@ RCT_EXTERN NSArray<Class> *RCTGetModuleClasses(void);
// Synchronously initialize all native modules that cannot be loaded lazily
[self initModulesWithDispatchGroup:initModulesAndLoadSource];
RCTPerformanceLogger *performanceLogger = self->_performanceLogger;
__block NSString *config;
dispatch_group_enter(initModulesAndLoadSource);
dispatch_async(bridgeQueue, ^{
@ -118,17 +119,17 @@ RCT_EXTERN NSArray<Class> *RCTGetModuleClasses(void);
// Asynchronously initialize the JS executor
dispatch_group_async(setupJSExecutorAndModuleConfig, bridgeQueue, ^{
RCTPerformanceLoggerStart(RCTPLJSCExecutorSetup);
[performanceLogger markStartForTag:RCTPLJSCExecutorSetup];
[weakSelf setUpExecutor];
RCTPerformanceLoggerEnd(RCTPLJSCExecutorSetup);
[performanceLogger markStopForTag:RCTPLJSCExecutorSetup];
});
// Asynchronously gather the module config
dispatch_group_async(setupJSExecutorAndModuleConfig, bridgeQueue, ^{
if (weakSelf.valid) {
RCTPerformanceLoggerStart(RCTPLNativeModulePrepareConfig);
[performanceLogger markStartForTag:RCTPLNativeModulePrepareConfig];
config = [weakSelf moduleConfig];
RCTPerformanceLoggerEnd(RCTPLNativeModulePrepareConfig);
[performanceLogger markStopForTag:RCTPLNativeModulePrepareConfig];
}
});
@ -136,9 +137,9 @@ RCT_EXTERN NSArray<Class> *RCTGetModuleClasses(void);
// We're not waiting for this to complete to leave dispatch group, since
// injectJSONConfiguration and executeSourceCode will schedule operations
// on the same queue anyway.
RCTPerformanceLoggerStart(RCTPLNativeModuleInjectConfig);
[performanceLogger markStartForTag:RCTPLNativeModuleInjectConfig];
[weakSelf injectJSONConfiguration:config onComplete:^(NSError *error) {
RCTPerformanceLoggerEnd(RCTPLNativeModuleInjectConfig);
[performanceLogger markStopForTag:RCTPLNativeModuleInjectConfig];
if (error) {
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf stopLoadingWithError:error];
@ -159,18 +160,19 @@ RCT_EXTERN NSArray<Class> *RCTGetModuleClasses(void);
- (void)loadSource:(RCTSourceLoadBlock)_onSourceLoad
{
RCTPerformanceLoggerStart(RCTPLScriptDownload);
[_performanceLogger markStartForTag:RCTPLScriptDownload];
RCTSourceLoadBlock onSourceLoad = ^(NSError *error, NSData *source) {
RCTPerformanceLoggerEnd(RCTPLScriptDownload);
_onSourceLoad(error, source);
RCTPerformanceLogger *performanceLogger = _performanceLogger;
RCTSourceLoadBlock onSourceLoad = ^(NSError *error, NSData *source, int64_t sourceLength) {
[performanceLogger markStopForTag:RCTPLScriptDownload];
[performanceLogger setValue:sourceLength forTag:RCTPLBundleSize];
_onSourceLoad(error, source, sourceLength);
};
if ([self.delegate respondsToSelector:@selector(loadSourceForBridge:withBlock:)]) {
[self.delegate loadSourceForBridge:_parentBridge withBlock:onSourceLoad];
} else if (self.bundleURL) {
[RCTJavaScriptLoader loadBundleAtURL:self.bundleURL onComplete:^(NSError *error, NSData *source) {
[RCTJavaScriptLoader loadBundleAtURL:self.bundleURL onComplete:^(NSError *error, NSData *source, int64_t sourceLength) {
if (error && [self.delegate respondsToSelector:@selector(fallbackSourceURLForBridge:)]) {
NSURL *fallbackURL = [self.delegate fallbackSourceURLForBridge:_parentBridge];
if (fallbackURL && ![fallbackURL isEqual:self.bundleURL]) {
@ -180,7 +182,7 @@ RCT_EXTERN NSArray<Class> *RCTGetModuleClasses(void);
return;
}
}
onSourceLoad(error, source);
onSourceLoad(error, source, sourceLength);
}];
} else {
// Allow testing without a script
@ -190,7 +192,7 @@ RCT_EXTERN NSArray<Class> *RCTGetModuleClasses(void);
postNotificationName:RCTJavaScriptDidLoadNotification
object:_parentBridge userInfo:@{@"bridge": self}];
});
onSourceLoad(nil, nil);
onSourceLoad(nil, nil, 0);
}
}
@ -235,7 +237,7 @@ RCT_EXTERN NSArray<Class> *RCTGetModuleClasses(void);
- (void)initModulesWithDispatchGroup:(dispatch_group_t)dispatchGroup
{
RCTPerformanceLoggerStart(RCTPLNativeModuleInit);
[_performanceLogger markStartForTag:RCTPLNativeModuleInit];
NSArray<id<RCTBridgeModule>> *extraModules = nil;
if (self.delegate) {
@ -382,7 +384,7 @@ RCT_EXTERN NSArray<Class> *RCTGetModuleClasses(void);
_moduleSetupComplete = YES;
// Set up modules that require main thread init or constants export
RCTPerformanceLoggerSet(RCTPLNativeModuleMainThread, 0);
[_performanceLogger setValue:0 forTag:RCTPLNativeModuleMainThread];
NSUInteger modulesOnMainQueueCount = 0;
for (RCTModuleData *moduleData in _moduleDataByID) {
__weak RCTBatchedBridge *weakSelf = self;
@ -393,19 +395,22 @@ RCT_EXTERN NSArray<Class> *RCTGetModuleClasses(void);
// modules on the main thread in parallel with loading the JS code, so
// they will already be available before they are ever required.
dispatch_group_async(dispatchGroup, dispatch_get_main_queue(), ^{
if (weakSelf.valid) {
RCTPerformanceLoggerAppendStart(RCTPLNativeModuleMainThread);
(void)[moduleData instance];
[moduleData gatherConstants];
RCTPerformanceLoggerAppendEnd(RCTPLNativeModuleMainThread);
RCTBatchedBridge *strongSelf = weakSelf;
if (!strongSelf.valid) {
return;
}
[strongSelf->_performanceLogger appendStartForTag:RCTPLNativeModuleMainThread];
(void)[moduleData instance];
[moduleData gatherConstants];
[strongSelf->_performanceLogger appendStopForTag:RCTPLNativeModuleMainThread];
});
modulesOnMainQueueCount++;
}
}
RCTPerformanceLoggerEnd(RCTPLNativeModuleInit);
RCTPerformanceLoggerSet(RCTPLNativeModuleMainThreadUsesCount, modulesOnMainQueueCount);
[_performanceLogger markStopForTag:RCTPLNativeModuleInit];
[_performanceLogger setValue:modulesOnMainQueueCount forTag:RCTPLNativeModuleMainThreadUsesCount];
}
- (void)setUpExecutor
@ -497,7 +502,7 @@ RCT_EXTERN NSArray<Class> *RCTGetModuleClasses(void);
- (void)didFinishLoading
{
RCTPerformanceLoggerEnd(RCTPLBridgeStartup);
[_performanceLogger markStopForTag:RCTPLBridgeStartup];
_loading = NO;
[_javaScriptExecutor executeBlockOnJavaScriptQueue:^{
for (dispatch_block_t call in _pendingCalls) {

View File

@ -10,8 +10,13 @@
#import "RCTBridge.h"
@class RCTModuleData;
@class RCTPerformanceLogger;
@interface RCTBridge ()
{
@public
RCTPerformanceLogger *_performanceLogger;
}
// Used for the profiler flow events between JS and native
@property (nonatomic, assign) int64_t flowID;

View File

@ -18,6 +18,7 @@
@class RCTBridge;
@class RCTEventDispatcher;
@class RCTPerformanceLogger;
/**
* This notification triggers a reload of all bridges currently running.
@ -160,6 +161,11 @@ RCT_EXTERN NSString *RCTBridgeModuleNameForClass(Class bridgeModuleClass);
*/
@property (nonatomic, readonly, getter=isValid) BOOL valid;
/**
* Link to the Performance Logger that logs React Native perf events.
*/
@property (nonatomic, readonly, strong) RCTPerformanceLogger *performanceLogger;
/**
* Reload the bundle and reset executor & modules. Safe to call from any thread.
*/

View File

@ -110,26 +110,36 @@ static RCTBridge *RCTCurrentBridgeInstance = nil;
- (instancetype)initWithDelegate:(id<RCTBridgeDelegate>)delegate
launchOptions:(NSDictionary *)launchOptions
{
if ((self = [super init])) {
RCTPerformanceLoggerStart(RCTPLBridgeStartup);
RCTPerformanceLoggerStart(RCTPLTTI);
_delegate = delegate;
_launchOptions = [launchOptions copy];
[self setUp];
RCTExecuteOnMainQueue(^{ [self bindKeys]; });
}
return self;
return [self initWithDelegate:delegate
bundleURL:nil
moduleProvider:nil
launchOptions:launchOptions];
}
- (instancetype)initWithBundleURL:(NSURL *)bundleURL
moduleProvider:(RCTBridgeModuleProviderBlock)block
launchOptions:(NSDictionary *)launchOptions
{
if ((self = [super init])) {
RCTPerformanceLoggerStart(RCTPLBridgeStartup);
RCTPerformanceLoggerStart(RCTPLTTI);
return [self initWithDelegate:nil
bundleURL:bundleURL
moduleProvider:block
launchOptions:launchOptions];
}
/**
* Private designated initializer
*/
- (instancetype)initWithDelegate:(id<RCTBridgeDelegate>)delegate
bundleURL:(NSURL *)bundleURL
moduleProvider:(RCTBridgeModuleProviderBlock)block
launchOptions:(NSDictionary *)launchOptions
{
if ((self = [super init])) {
_performanceLogger = [RCTPerformanceLogger new];
[_performanceLogger markStartForTag:RCTPLBridgeStartup];
[_performanceLogger markStartForTag:RCTPLTTI];
_delegate = delegate;
_bundleURL = bundleURL;
_moduleProvider = block;
_launchOptions = [launchOptions copy];

View File

@ -7,7 +7,7 @@
* of patent rights can be found in the PATENTS file in the same directory.
*/
typedef void (^RCTSourceLoadBlock)(NSError *error, NSData *source);
typedef void (^RCTSourceLoadBlock)(NSError *error, NSData *source, int64_t sourceLength);
@class RCTBridge;

View File

@ -35,7 +35,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
NSError *error = [NSError errorWithDomain:@"JavaScriptLoader" code:1 userInfo:@{
NSLocalizedDescriptionKey: errorDescription
}];
onComplete(error, nil);
onComplete(error, nil, 0);
return;
}
@ -51,14 +51,14 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
// modules into JSC as they're required.
FILE *bundle = fopen(scriptURL.path.UTF8String, "r");
if (!bundle) {
onComplete(RCTErrorWithMessage([NSString stringWithFormat:@"Error opening bundle %@", scriptURL.path]), source);
onComplete(RCTErrorWithMessage([NSString stringWithFormat:@"Error opening bundle %@", scriptURL.path]), source, 0);
return;
}
uint32_t magicNumber;
if (fread(&magicNumber, sizeof(magicNumber), 1, bundle) != 1) {
fclose(bundle);
onComplete(RCTErrorWithMessage(@"Error reading bundle"), source);
onComplete(RCTErrorWithMessage(@"Error reading bundle"), source, 0);
return;
}
@ -81,9 +81,8 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
sourceLength = source.length;
}
RCTPerformanceLoggerSet(RCTPLBundleSize, sourceLength);
fclose(bundle);
onComplete(error, source);
onComplete(error, source, sourceLength);
});
return;
}
@ -105,7 +104,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
code:error.code
userInfo:userInfo];
}
onComplete(error, nil);
onComplete(error, nil, 0);
return;
}
@ -143,11 +142,10 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
code:((NSHTTPURLResponse *)response).statusCode
userInfo:userInfo];
onComplete(error, nil);
onComplete(error, nil, 0);
return;
}
RCTPerformanceLoggerSet(RCTPLBundleSize, data.length);
onComplete(nil, data);
onComplete(nil, data, data.length);
}];
[task resume];

View File

@ -9,8 +9,6 @@
#import <Foundation/Foundation.h>
#import "RCTDefines.h"
typedef NS_ENUM(NSUInteger, RCTPLTag) {
RCTPLScriptDownload = 0,
RCTPLScriptExecution,
@ -25,7 +23,6 @@ typedef NS_ENUM(NSUInteger, RCTPLTag) {
RCTPLNativeModuleInjectConfig,
RCTPLNativeModuleMainThreadUsesCount,
RCTPLJSCWrapperOpenLibrary,
RCTPLJSCWrapperLoadFunctions,
RCTPLJSCExecutorSetup,
RCTPLBridgeStartup,
RCTPLTTI,
@ -33,44 +30,74 @@ typedef NS_ENUM(NSUInteger, RCTPLTag) {
RCTPLSize
};
@interface RCTPerformanceLogger : NSObject
/**
* Starts measuring a metric with the given tag.
* Overrides previous value if the measurement has been already started.
* If RCTProfile is enabled it also begins appropriate async event.
* All work is scheduled on the background queue so this doesn't block current thread.
*/
RCT_EXTERN void RCTPerformanceLoggerStart(RCTPLTag tag);
- (void)markStartForTag:(RCTPLTag)tag;
/**
* Stops measuring a metric with given tag.
* Checks if RCTPerformanceLoggerStart() has been called before
* and doesn't do anything and log a message if it hasn't.
* If RCTProfile is enabled it also ends appropriate async event.
* All work is scheduled on the background queue so this doesn't block current thread.
*/
RCT_EXTERN void RCTPerformanceLoggerEnd(RCTPLTag tag);
- (void)markStopForTag:(RCTPLTag)tag;
/**
* Sets given value for a metric with given tag.
* All work is scheduled on the background queue so this doesn't block current thread.
*/
RCT_EXTERN void RCTPerformanceLoggerSet(RCTPLTag tag, int64_t value);
- (void)setValue:(int64_t)value forTag:(RCTPLTag)tag;
/**
* Adds given value to the current value for a metric with given tag.
* All work is scheduled on the background queue so this doesn't block current thread.
*/
RCT_EXTERN void RCTPerformanceLoggerAdd(RCTPLTag tag, int64_t value);
- (void)addValue:(int64_t)value forTag:(RCTPLTag)tag;
/**
* Starts an additional measurement for a metric with given tag.
* It doesn't override previous measurement, instead it'll append a new value
* to the old one.
* All work is scheduled on the background queue so this doesn't block current thread.
*/
RCT_EXTERN void RCTPerformanceLoggerAppendStart(RCTPLTag tag);
- (void)appendStartForTag:(RCTPLTag)tag;
/**
* Stops measurement and appends the result to the metric with given tag.
* Checks if RCTPerformanceLoggerAppendStart() has been called before
* and doesn't do anything and log a message if it hasn't.
* All work is scheduled on the background queue so this doesn't block current thread.
*/
RCT_EXTERN void RCTPerformanceLoggerAppendEnd(RCTPLTag tag);
- (void)appendStopForTag:(RCTPLTag)tag;
RCT_EXTERN NSArray<NSNumber *> *RCTPerformanceLoggerOutput(void);
RCT_EXTERN NSArray *RCTPerformanceLoggerLabels(void);
/**
* Returns an array with values for all tags.
* Use RCTPLTag to go over the array, there's a pair of values
* for each tag: start and stop (with indexes 2 * tag and 2 * tag + 1).
*/
- (NSArray<NSNumber *> *)valuesForTags;
/**
* Returns a duration (stop_time - start_time) for given RCTPLTag.
*/
- (int64_t)durationForTag:(RCTPLTag)tag;
/**
* Returns a value for given RCTPLTag.
*/
- (int64_t)valueForTag:(RCTPLTag)tag;
/**
* Returns an array with values for all tags.
* Use RCTPLTag to go over the array.
*/
- (NSArray<NSString *> *)labelsForTags;
@end

View File

@ -14,77 +14,22 @@
#import "RCTLog.h"
#import "RCTProfile.h"
static int64_t RCTPLData[RCTPLSize][2] = {};
static NSUInteger RCTPLCookies[RCTPLSize] = {};
void RCTPerformanceLoggerStart(RCTPLTag tag)
@interface RCTPerformanceLogger ()
{
if (RCTProfileIsProfiling()) {
NSString *label = RCTPerformanceLoggerLabels()[tag];
RCTPLCookies[tag] = RCTProfileBeginAsyncEvent(RCTProfileTagAlways, label, nil);
}
RCTPLData[tag][0] = CACurrentMediaTime() * 1000;
RCTPLData[tag][1] = 0;
int64_t _data[RCTPLSize][2];
NSUInteger _cookies[RCTPLSize];
}
void RCTPerformanceLoggerEnd(RCTPLTag tag)
{
if (RCTPLData[tag][0] != 0 && RCTPLData[tag][1] == 0) {
RCTPLData[tag][1] = CACurrentMediaTime() * 1000;
@property (nonatomic, copy) NSArray<NSString *> *labelsForTags;
if (RCTProfileIsProfiling()) {
NSString *label = RCTPerformanceLoggerLabels()[tag];
RCTProfileEndAsyncEvent(RCTProfileTagAlways, @"native", RCTPLCookies[tag], label, @"RCTPerformanceLogger", nil);
}
} else {
RCTLogInfo(@"Unbalanced calls start/end for tag %li", (unsigned long)tag);
}
}
@end
void RCTPerformanceLoggerSet(RCTPLTag tag, int64_t value)
{
RCTPLData[tag][0] = 0;
RCTPLData[tag][1] = value;
}
@implementation RCTPerformanceLogger
void RCTPerformanceLoggerAdd(RCTPLTag tag, int64_t value)
- (instancetype)init
{
RCTPLData[tag][0] = 0;
RCTPLData[tag][1] += value;
}
void RCTPerformanceLoggerAppendStart(RCTPLTag tag)
{
RCTPLData[tag][0] = CACurrentMediaTime() * 1000;
}
void RCTPerformanceLoggerAppendEnd(RCTPLTag tag)
{
if (RCTPLData[tag][0] != 0) {
RCTPLData[tag][1] += CACurrentMediaTime() * 1000 - RCTPLData[tag][0];
RCTPLData[tag][0] = 0;
} else {
RCTLogInfo(@"Unbalanced calls start/end for tag %li", (unsigned long)tag);
}
}
NSArray<NSNumber *> *RCTPerformanceLoggerOutput(void)
{
NSMutableArray *result = [NSMutableArray array];
for (NSUInteger index = 0; index < RCTPLSize; index++) {
[result addObject:@(RCTPLData[index][0])];
[result addObject:@(RCTPLData[index][1])];
}
return result;
}
NSArray *RCTPerformanceLoggerLabels(void)
{
static NSArray *labels;
static dispatch_once_t token;
dispatch_once(&token, ^{
labels = @[
if (self = [super init]) {
_labelsForTags = @[
@"ScriptDownload",
@"ScriptExecution",
@"RAMBundleLoad",
@ -98,56 +43,84 @@ NSArray *RCTPerformanceLoggerLabels(void)
@"NativeModuleInjectConfig",
@"NativeModuleMainThreadUsesCount",
@"JSCWrapperOpenLibrary",
@"JSCWrapperLoadFunctions",
@"JSCExecutorSetup",
@"BridgeStartup",
@"RootViewTTI",
@"BundleSize",
];
});
return labels;
}
return self;
}
@interface RCTPerformanceLogger : NSObject <RCTBridgeModule>
@end
@implementation RCTPerformanceLogger
RCT_EXPORT_MODULE()
@synthesize bridge = _bridge;
- (instancetype)init
- (void)markStartForTag:(RCTPLTag)tag
{
// We're only overriding this to ensure the module gets created at startup
// TODO (t11106126): Remove once we have more declarative control over module setup.
return [super init];
if (RCTProfileIsProfiling()) {
NSString *label = _labelsForTags[tag];
_cookies[tag] = RCTProfileBeginAsyncEvent(RCTProfileTagAlways, label, nil);
}
_data[tag][0] = CACurrentMediaTime() * 1000;
_data[tag][1] = 0;
}
- (void)setBridge:(RCTBridge *)bridge
{
_bridge = bridge;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(sendTimespans)
name:RCTContentDidAppearNotification
object:nil];
- (void)markStopForTag:(RCTPLTag)tag
{
if (RCTProfileIsProfiling()) {
NSString *label =_labelsForTags[tag];
RCTProfileEndAsyncEvent(RCTProfileTagAlways, @"native", _cookies[tag], label, @"RCTPerformanceLogger", nil);
}
if (_data[tag][0] != 0 && _data[tag][1] == 0) {
_data[tag][1] = CACurrentMediaTime() * 1000;
} else {
RCTLogInfo(@"Unbalanced calls start/end for tag %li", (unsigned long)tag);
}
}
- (void)dealloc
- (void)setValue:(int64_t)value forTag:(RCTPLTag)tag
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
_data[tag][0] = 0;
_data[tag][1] = value;
}
- (void)sendTimespans
- (void)addValue:(int64_t)value forTag:(RCTPLTag)tag
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
_data[tag][0] = 0;
_data[tag][1] += value;
}
[_bridge enqueueJSCall:@"PerformanceLogger.addTimespans" args:@[
RCTPerformanceLoggerOutput(),
RCTPerformanceLoggerLabels(),
]];
- (void)appendStartForTag:(RCTPLTag)tag
{
_data[tag][0] = CACurrentMediaTime() * 1000;
}
- (void)appendStopForTag:(RCTPLTag)tag
{
if (_data[tag][0] != 0) {
_data[tag][1] += CACurrentMediaTime() * 1000 - _data[tag][0];
_data[tag][0] = 0;
} else {
RCTLogInfo(@"Unbalanced calls start/end for tag %li", (unsigned long)tag);
}
}
- (NSArray<NSNumber *> *)valuesForTags
{
NSMutableArray *result = [NSMutableArray array];
for (NSUInteger index = 0; index < RCTPLSize; index++) {
[result addObject:@(_data[index][0])];
[result addObject:@(_data[index][1])];
}
return result;
}
- (int64_t)durationForTag:(RCTPLTag)tag
{
return _data[tag][1] - _data[tag][0];
}
- (int64_t)valueForTag:(RCTPLTag)tag;
{
return _data[tag][1];
}
@end

View File

@ -340,7 +340,7 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder:(nonnull NSCoder *)aDecoder)
- (void)insertReactSubview:(UIView *)subview atIndex:(NSInteger)atIndex
{
[super insertReactSubview:subview atIndex:atIndex];
RCTPerformanceLoggerEnd(RCTPLTTI);
[_bridge->_performanceLogger markStopForTag:RCTPLTTI];
dispatch_async(dispatch_get_main_queue(), ^{
if (!_contentHasAppeared) {
_contentHasAppeared = YES;

View File

@ -136,6 +136,8 @@ RCT_NOT_IMPLEMENTED(-(instancetype)init)
RCTJSCWrapper *_jscWrapper;
BOOL _useCustomJSCLibrary;
RCTPerformanceLogger *_performanceLogger;
}
@synthesize valid = _valid;
@ -263,6 +265,12 @@ static void RCTInstallJSCProfiler(RCTBridge *bridge, JSContextRef context)
}
}
- (void)setBridge:(RCTBridge *)bridge
{
_bridge = bridge;
_performanceLogger = [bridge performanceLogger];
}
- (instancetype)init
{
return [self initWithUseCustomJSCLibrary:NO];
@ -328,7 +336,9 @@ static void RCTInstallJSCProfiler(RCTBridge *bridge, JSContextRef context)
return;
}
[strongSelf->_performanceLogger markStartForTag:RCTPLJSCWrapperOpenLibrary];
strongSelf->_jscWrapper = RCTJSCWrapperCreate(strongSelf->_useCustomJSCLibrary);
[strongSelf->_performanceLogger markStopForTag:RCTPLJSCWrapperOpenLibrary];
}];
@ -660,14 +670,13 @@ static void RCTInstallJSCProfiler(RCTBridge *bridge, JSContextRef context)
}
__weak RCTJSCExecutor *weakSelf = self;
[self executeBlockOnJavaScriptQueue:RCTProfileBlock((^{
RCTJSCExecutor *strongSelf = weakSelf;
if (!strongSelf || !strongSelf.isValid) {
return;
}
RCTPerformanceLoggerStart(RCTPLScriptExecution);
[strongSelf->_performanceLogger markStartForTag:RCTPLScriptExecution];
JSValueRef jsError = NULL;
RCTJSCWrapper *jscWrapper = strongSelf->_jscWrapper;
@ -676,7 +685,8 @@ static void RCTInstallJSCProfiler(RCTBridge *bridge, JSContextRef context)
JSValueRef result = jscWrapper->JSEvaluateScript(strongSelf->_context.ctx, execJSString, NULL, bundleURL, 0, &jsError);
jscWrapper->JSStringRelease(bundleURL);
jscWrapper->JSStringRelease(execJSString);
RCTPerformanceLoggerEnd(RCTPLScriptExecution);
[strongSelf->_performanceLogger markStopForTag:RCTPLScriptExecution];
if (onComplete) {
NSError *error;
@ -783,9 +793,9 @@ static void executeRandomAccessModule(RCTJSCExecutor *executor, uint32_t moduleI
- (void)registerNativeRequire
{
RCTPerformanceLoggerSet(RCTPLRAMNativeRequires, 0);
RCTPerformanceLoggerSet(RCTPLRAMNativeRequiresCount, 0);
RCTPerformanceLoggerSet(RCTPLRAMNativeRequiresSize, 0);
[_performanceLogger setValue:0 forTag:RCTPLRAMNativeRequires];
[_performanceLogger setValue:0 forTag:RCTPLRAMNativeRequiresCount];
[_performanceLogger setValue:0 forTag:RCTPLRAMNativeRequiresSize];
__weak RCTJSCExecutor *weakSelf = self;
[self addSynchronousHookWithName:@"nativeRequire" usingBlock:^(NSNumber *moduleID) {
@ -794,8 +804,8 @@ static void executeRandomAccessModule(RCTJSCExecutor *executor, uint32_t moduleI
return;
}
RCTPerformanceLoggerAdd(RCTPLRAMNativeRequiresCount, 1);
RCTPerformanceLoggerAppendStart(RCTPLRAMNativeRequires);
[strongSelf->_performanceLogger addValue:1 forTag:RCTPLRAMNativeRequiresCount];
[strongSelf->_performanceLogger appendStartForTag:RCTPLRAMNativeRequires];
RCT_PROFILE_BEGIN_EVENT(RCTProfileTagAlways,
[@"nativeRequire_" stringByAppendingFormat:@"%@", moduleID], nil);
@ -810,12 +820,12 @@ static void executeRandomAccessModule(RCTJSCExecutor *executor, uint32_t moduleI
return;
}
RCTPerformanceLoggerAdd(RCTPLRAMNativeRequiresSize, size);
[strongSelf->_performanceLogger addValue:size forTag:RCTPLRAMNativeRequiresSize];
executeRandomAccessModule(strongSelf, ID, NSSwapLittleIntToHost(moduleData->offset), size);
}
RCT_PROFILE_END_EVENT(RCTProfileTagAlways, @"js_call", nil);
RCTPerformanceLoggerAppendEnd(RCTPLRAMNativeRequires);
[strongSelf->_performanceLogger appendStopForTag:RCTPLRAMNativeRequires];
}];
}
@ -858,7 +868,7 @@ static RandomAccessBundleStartupCode readRAMBundle(file_ptr bundle, RandomAccess
- (NSData *)loadRAMBundle:(NSURL *)sourceURL error:(NSError **)error
{
RCTPerformanceLoggerStart(RCTPLRAMBundleLoad);
[_performanceLogger markStartForTag:RCTPLRAMBundleLoad];
file_ptr bundle(fopen(sourceURL.path.UTF8String, "r"), fclose);
if (!bundle) {
if (error) {
@ -878,8 +888,8 @@ static RandomAccessBundleStartupCode readRAMBundle(file_ptr bundle, RandomAccess
return nil;
}
RCTPerformanceLoggerEnd(RCTPLRAMBundleLoad);
RCTPerformanceLoggerSet(RCTPLRAMStartupCodeSize, startupCode.size);
[_performanceLogger markStopForTag:RCTPLRAMBundleLoad];
[_performanceLogger setValue:startupCode.size forTag:RCTPLRAMStartupCodeSize];
return [NSData dataWithBytesNoCopy:startupCode.code.release() length:startupCode.size freeWhenDone:YES];
}

View File

@ -13,7 +13,6 @@
#import <JavaScriptCore/JavaScriptCore.h>
#import "RCTLog.h"
#import "RCTPerformanceLogger.h"
#include <dlfcn.h>
@ -26,9 +25,7 @@ static void *RCTCustomLibraryHandler(void)
ofType:nil
inDirectory:@"Frameworks/JavaScriptCore.framework"] UTF8String];
if (path) {
RCTPerformanceLoggerStart(RCTPLJSCWrapperOpenLibrary);
handler = dlopen(path, RTLD_LAZY);
RCTPerformanceLoggerEnd(RCTPLJSCWrapperOpenLibrary);
if (!handler) {
RCTLogWarn(@"Can't load custom JSC library: %s", dlerror());
}
@ -69,7 +66,6 @@ static void RCTSetUpCustomLibraryPointers(RCTJSCWrapper *wrapper)
return;
}
RCTPerformanceLoggerStart(RCTPLJSCWrapperLoadFunctions);
wrapper->JSValueToStringCopy = (JSValueToStringCopyFuncType)dlsym(libraryHandle, "JSValueToStringCopy");
wrapper->JSStringCreateWithCFString = (JSStringCreateWithCFStringFuncType)dlsym(libraryHandle, "JSStringCreateWithCFString");
wrapper->JSStringCopyCFString = (JSStringCopyCFStringFuncType)dlsym(libraryHandle, "JSStringCopyCFString");
@ -90,7 +86,6 @@ static void RCTSetUpCustomLibraryPointers(RCTJSCWrapper *wrapper)
wrapper->JSContext = (__bridge Class)dlsym(libraryHandle, "OBJC_CLASS_$_JSContext");
wrapper->JSValue = (__bridge Class)dlsym(libraryHandle, "OBJC_CLASS_$_JSValue");
wrapper->configureJSContextForIOS = (configureJSContextForIOSFuncType)dlsym(libraryHandle, "configureJSContextForIOS");
RCTPerformanceLoggerEnd(RCTPLJSCWrapperLoadFunctions);
}
RCTJSCWrapper *RCTJSCWrapperCreate(BOOL useCustomJSC)

View File

@ -510,8 +510,9 @@ RCT_EXPORT_MODULE()
{
NSUInteger i = 0;
NSMutableArray<NSString *> *data = [NSMutableArray new];
NSArray<NSNumber *> *values = RCTPerformanceLoggerOutput();
for (NSString *label in RCTPerformanceLoggerLabels()) {
RCTPerformanceLogger *performanceLogger = [_bridge performanceLogger];
NSArray<NSNumber *> *values = [performanceLogger valuesForTags];
for (NSString *label in [performanceLogger labelsForTags]) {
long long value = values[i+1].longLongValue - values[i].longLongValue;
NSString *unit = @"ms";
if ([label hasSuffix:@"Size"]) {