mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-02-10 17:22:45 +08:00
Introduce Perf Monitor
Summary: public Kill `RCTPerfStats` and introduce the new `RCTPerfMonitor`, including memory usage, JSC heap size, number of RN views in screen, FPS (both on UI and JS threads) and more to come. It removes all the previous traces that were previous spread across the bridge and the dev menu and moves everything to be more contained, so the whole thing can be safely striped in production. Reviewed By: nicklockwood Differential Revision: D2575158 fb-gh-sync-id: 6a6d0c4422adbddeeefddd32ec3409a7095ff2a9
This commit is contained in:
committed by
facebook-github-bot-7
parent
cae4761006
commit
9069bdf1c2
@@ -20,7 +20,6 @@
|
||||
#import "RCTModuleMap.h"
|
||||
#import "RCTBridgeMethod.h"
|
||||
#import "RCTPerformanceLogger.h"
|
||||
#import "RCTPerfStats.h"
|
||||
#import "RCTProfile.h"
|
||||
#import "RCTRedBox.h"
|
||||
#import "RCTSourceCode.h"
|
||||
@@ -68,7 +67,6 @@ RCT_EXTERN NSArray *RCTGetModuleClasses(void);
|
||||
NSMutableArray *_pendingCalls;
|
||||
NSMutableArray *_moduleDataByID;
|
||||
RCTModuleMap *_modulesByName;
|
||||
CADisplayLink *_mainDisplayLink;
|
||||
CADisplayLink *_jsDisplayLink;
|
||||
NSMutableSet *_frameUpdateObservers;
|
||||
}
|
||||
@@ -94,11 +92,6 @@ RCT_EXTERN NSArray *RCTGetModuleClasses(void);
|
||||
_frameUpdateObservers = [NSMutableSet new];
|
||||
_jsDisplayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(_jsThreadUpdate:)];
|
||||
|
||||
if (RCT_DEV) {
|
||||
_mainDisplayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(_mainThreadUpdate:)];
|
||||
[_mainDisplayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
|
||||
}
|
||||
|
||||
[RCTBridge setCurrentBridge:self];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:RCTJavaScriptWillStartLoadingNotification
|
||||
@@ -508,9 +501,6 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithBundleURL:(__unused NSURL *)bundleUR
|
||||
[RCTBridge setCurrentBridge:nil];
|
||||
}
|
||||
|
||||
[_mainDisplayLink invalidate];
|
||||
_mainDisplayLink = nil;
|
||||
|
||||
// Invalidate modules
|
||||
dispatch_group_t group = dispatch_group_create();
|
||||
for (RCTModuleData *moduleData in _moduleDataByID) {
|
||||
@@ -868,21 +858,6 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithBundleURL:(__unused NSURL *)bundleUR
|
||||
RCTProfileImmediateEvent(0, @"JS Thread Tick", 'g');
|
||||
|
||||
RCTProfileEndEvent(0, @"objc_call", nil);
|
||||
|
||||
RCT_IF_DEV(
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self.perfStats.jsGraph onTick:displayLink.timestamp];
|
||||
});
|
||||
)
|
||||
}
|
||||
|
||||
- (void)_mainThreadUpdate:(CADisplayLink *)displayLink
|
||||
{
|
||||
RCTAssertMainThread();
|
||||
|
||||
RCTProfileImmediateEvent(0, @"VSYNC", 'g');
|
||||
|
||||
_modulesByName == nil ?: [self.perfStats.uiGraph onTick:displayLink.timestamp];
|
||||
}
|
||||
|
||||
- (void)startProfiling
|
||||
|
||||
@@ -1,138 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#import "RCTFPSGraph.h"
|
||||
|
||||
#import "RCTAssert.h"
|
||||
#import "RCTDefines.h"
|
||||
|
||||
#if RCT_DEV
|
||||
|
||||
@implementation RCTFPSGraph
|
||||
{
|
||||
CAShapeLayer *_graph;
|
||||
NSString *_name;
|
||||
NSTimeInterval _prevTime;
|
||||
RCTFPSGraphPosition _position;
|
||||
UILabel *_label;
|
||||
|
||||
float *_frames;
|
||||
int _frameCount;
|
||||
int _maxFPS;
|
||||
int _minFPS;
|
||||
int _length;
|
||||
int _margin;
|
||||
int _height;
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame graphPosition:(RCTFPSGraphPosition)position name:(NSString *)name color:(UIColor *)color
|
||||
{
|
||||
if ((self = [super initWithFrame:frame])) {
|
||||
_margin = 2;
|
||||
_prevTime = -1;
|
||||
_maxFPS = 0;
|
||||
_minFPS = 60;
|
||||
_length = (frame.size.width - 2 * _margin) / 2;
|
||||
_height = frame.size.height - 2 * _margin;
|
||||
_frames = malloc(sizeof(float) * _length);
|
||||
memset(_frames, 0, sizeof(float) * _length);
|
||||
|
||||
_name = name ?: @"FPS";
|
||||
_position = position ?: RCTFPSGraphPositionLeft;
|
||||
|
||||
color = color ?: [UIColor greenColor];
|
||||
_graph = [self createGraph:color];
|
||||
_label = [self createLabel:color];
|
||||
|
||||
[self addSubview:_label];
|
||||
[self.layer addSublayer:_graph];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
RCT_NOT_IMPLEMENTED(- (instancetype)initWithFrame:(CGRect)frame)
|
||||
RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
free(_frames);
|
||||
}
|
||||
|
||||
- (void)layoutSubviews
|
||||
{
|
||||
[super layoutSubviews];
|
||||
}
|
||||
|
||||
- (CAShapeLayer *)createGraph:(UIColor *)color
|
||||
{
|
||||
CGFloat left = _position & RCTFPSGraphPositionLeft ? 0 : _length;
|
||||
CAShapeLayer *graph = [CAShapeLayer new];
|
||||
graph.frame = CGRectMake(left, 0, 2 * _margin + _length, self.frame.size.height);
|
||||
graph.backgroundColor = [color colorWithAlphaComponent:0.2].CGColor;
|
||||
graph.fillColor = color.CGColor;
|
||||
return graph;
|
||||
}
|
||||
|
||||
- (UILabel *)createLabel:(UIColor *)color
|
||||
{
|
||||
CGFloat left = _position & RCTFPSGraphPositionLeft ? 2 * _margin + _length : 0;
|
||||
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(left, 0, _length, self.frame.size.height)];
|
||||
label.textColor = color;
|
||||
label.font = [UIFont systemFontOfSize:9];
|
||||
label.minimumScaleFactor = .5;
|
||||
label.adjustsFontSizeToFitWidth = YES;
|
||||
label.numberOfLines = 3;
|
||||
label.lineBreakMode = NSLineBreakByWordWrapping;
|
||||
label.textAlignment = NSTextAlignmentCenter;
|
||||
return label;
|
||||
}
|
||||
|
||||
- (void)onTick:(NSTimeInterval)timestamp
|
||||
{
|
||||
_frameCount++;
|
||||
if (_prevTime == -1) {
|
||||
_prevTime = timestamp;
|
||||
} else if (timestamp - _prevTime > 1) {
|
||||
float fps = round(_frameCount / (timestamp - _prevTime));
|
||||
_minFPS = MIN(_minFPS, fps);
|
||||
_maxFPS = MAX(_maxFPS, fps);
|
||||
|
||||
_label.text = [NSString stringWithFormat:@"%@\n%d FPS\n(%d - %d)", _name, (int)fps, _minFPS, _maxFPS];
|
||||
|
||||
float scale = 60.0 / _height;
|
||||
for (int i = 0; i < _length - 1; i++) {
|
||||
_frames[i] = _frames[i + 1];
|
||||
}
|
||||
_frames[_length - 1] = fps / scale;
|
||||
|
||||
CGMutablePathRef path = CGPathCreateMutable();
|
||||
if (_position & RCTFPSGraphPositionLeft) {
|
||||
CGPathMoveToPoint(path, NULL, _margin, _margin + _height);
|
||||
for (int i = 0; i < _length; i++) {
|
||||
CGPathAddLineToPoint(path, NULL, _margin + i, _margin + _height - _frames[i]);
|
||||
}
|
||||
CGPathAddLineToPoint(path, NULL, _margin + _length - 1, _margin + _height);
|
||||
} else {
|
||||
CGPathMoveToPoint(path, NULL, _margin + _length - 1, _margin + _height);
|
||||
for (int i = 0; i < _length; i++) {
|
||||
CGPathAddLineToPoint(path, NULL, _margin + _length - i - 1, _margin + _height - _frames[i]);
|
||||
}
|
||||
CGPathAddLineToPoint(path, NULL, _margin, _margin + _height);
|
||||
}
|
||||
_graph.path = path;
|
||||
CGPathRelease(path);
|
||||
|
||||
_prevTime = timestamp;
|
||||
_frameCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -1,27 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#import "RCTBridge.h"
|
||||
#import "RCTFPSGraph.h"
|
||||
|
||||
@interface RCTPerfStats : NSObject
|
||||
|
||||
@property (nonatomic, strong) RCTFPSGraph *jsGraph;
|
||||
@property (nonatomic, strong) RCTFPSGraph *uiGraph;
|
||||
|
||||
- (void)show;
|
||||
- (void)hide;
|
||||
|
||||
@end
|
||||
|
||||
@interface RCTBridge (RCTPerfStats)
|
||||
|
||||
@property (nonatomic, strong, readonly) RCTPerfStats *perfStats;
|
||||
|
||||
@end
|
||||
@@ -1,147 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#import "RCTPerfStats.h"
|
||||
|
||||
#import "RCTDefines.h"
|
||||
#import "RCTUtils.h"
|
||||
|
||||
#if RCT_DEV
|
||||
|
||||
@interface RCTPerfStats() <RCTBridgeModule>
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTPerfStats
|
||||
{
|
||||
UIView *_container;
|
||||
}
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[self hide];
|
||||
}
|
||||
|
||||
- (UIView *)container
|
||||
{
|
||||
if (!_container) {
|
||||
_container = [UIView new];
|
||||
_container.backgroundColor = [UIColor colorWithRed:0 green:0 blue:34/255.0 alpha:1];
|
||||
_container.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleWidth;
|
||||
}
|
||||
return _container;
|
||||
}
|
||||
|
||||
- (RCTFPSGraph *)jsGraph
|
||||
{
|
||||
if (!_jsGraph && _container) {
|
||||
UIColor *jsColor = [UIColor colorWithRed:0 green:1 blue:0 alpha:1];
|
||||
_jsGraph = [[RCTFPSGraph alloc] initWithFrame:CGRectMake(2, 2, 124, 34)
|
||||
graphPosition:RCTFPSGraphPositionRight
|
||||
name:@"[ JS ]"
|
||||
color:jsColor];
|
||||
_jsGraph.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin;
|
||||
}
|
||||
return _jsGraph;
|
||||
}
|
||||
|
||||
- (RCTFPSGraph *)uiGraph
|
||||
{
|
||||
if (!_uiGraph && _container) {
|
||||
UIColor *uiColor = [UIColor colorWithRed:0 green:1 blue:1 alpha:1];
|
||||
_uiGraph = [[RCTFPSGraph alloc] initWithFrame:CGRectMake(2, 2, 124, 34)
|
||||
graphPosition:RCTFPSGraphPositionLeft
|
||||
name:@"[ UI ]"
|
||||
color:uiColor];
|
||||
}
|
||||
return _uiGraph;
|
||||
}
|
||||
|
||||
- (void)show
|
||||
{
|
||||
if (RCTRunningInAppExtension()) {
|
||||
return;
|
||||
}
|
||||
|
||||
UIView *targetView = RCTSharedApplication().delegate.window.rootViewController.view;
|
||||
|
||||
targetView.frame = (CGRect){
|
||||
targetView.frame.origin,
|
||||
{
|
||||
targetView.frame.size.width,
|
||||
targetView.frame.size.height - 38,
|
||||
}
|
||||
};
|
||||
|
||||
self.container.frame = (CGRect){{0, targetView.frame.size.height}, {targetView.frame.size.width, 38}};
|
||||
self.jsGraph.frame = (CGRect){
|
||||
{
|
||||
targetView.frame.size.width - self.uiGraph.frame.size.width - self.uiGraph.frame.origin.x,
|
||||
self.uiGraph.frame.origin.x,
|
||||
},
|
||||
self.uiGraph.frame.size,
|
||||
};
|
||||
|
||||
[self.container addSubview:self.jsGraph];
|
||||
[self.container addSubview:self.uiGraph];
|
||||
[targetView addSubview:self.container];
|
||||
}
|
||||
|
||||
- (void)hide
|
||||
{
|
||||
UIView *targetView = _container.superview;
|
||||
|
||||
targetView.frame = (CGRect){
|
||||
targetView.frame.origin,
|
||||
{
|
||||
targetView.frame.size.width,
|
||||
targetView.frame.size.height + _container.frame.size.height
|
||||
}
|
||||
};
|
||||
|
||||
[_container removeFromSuperview];
|
||||
}
|
||||
|
||||
- (dispatch_queue_t)methodQueue
|
||||
{
|
||||
return dispatch_get_main_queue();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTBridge (RCTPerfStats)
|
||||
|
||||
- (RCTPerfStats *)perfStats
|
||||
{
|
||||
return self.modules[RCTBridgeModuleNameForClass([RCTPerfStats class])];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#else
|
||||
|
||||
@implementation RCTPerfStats
|
||||
|
||||
- (void)show {}
|
||||
- (void)hide {}
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTBridge (RCTPerfStats)
|
||||
|
||||
- (RCTPerfStats *)perfStats
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -15,7 +15,6 @@
|
||||
#import "RCTEventDispatcher.h"
|
||||
#import "RCTKeyCommands.h"
|
||||
#import "RCTLog.h"
|
||||
#import "RCTPerfStats.h"
|
||||
#import "RCTProfile.h"
|
||||
#import "RCTRootView.h"
|
||||
#import "RCTSourceCode.h"
|
||||
@@ -182,22 +181,6 @@ RCT_EXPORT_MODULE()
|
||||
|
||||
__weak RCTDevMenu *weakSelf = self;
|
||||
|
||||
[_extraMenuItems addObject:[RCTDevMenuItem toggleItemWithKey:@"showFPS"
|
||||
title:@"Show FPS Monitor"
|
||||
selectedTitle:@"Hide FPS Monitor"
|
||||
handler:^(BOOL showFPS)
|
||||
{
|
||||
RCTDevMenu *strongSelf = weakSelf;
|
||||
if (strongSelf) {
|
||||
strongSelf->_showFPS = showFPS;
|
||||
if (showFPS) {
|
||||
[strongSelf.bridge.perfStats show];
|
||||
} else {
|
||||
[strongSelf.bridge.perfStats hide];
|
||||
}
|
||||
}
|
||||
}]];
|
||||
|
||||
[_extraMenuItems addObject:[RCTDevMenuItem toggleItemWithKey:@"showInspector"
|
||||
title:@"Show Inspector"
|
||||
selectedTitle:@"Hide Inspector"
|
||||
|
||||
@@ -9,15 +9,21 @@
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
typedef NS_ENUM(NSUInteger, RCTFPSGraphPosition) {
|
||||
RCTFPSGraphPositionLeft = 1,
|
||||
RCTFPSGraphPositionRight = 2
|
||||
};
|
||||
#import "RCTDefines.h"
|
||||
|
||||
#if RCT_DEV
|
||||
|
||||
@interface RCTFPSGraph : UIView
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame graphPosition:(RCTFPSGraphPosition)position name:(NSString *)name color:(UIColor *)color NS_DESIGNATED_INITIALIZER;
|
||||
@property (nonatomic, assign, readonly) NSUInteger FPS;
|
||||
@property (nonatomic, assign, readonly) NSUInteger maxFPS;
|
||||
@property (nonatomic, assign, readonly) NSUInteger minFPS;
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
color:(UIColor *)color NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
- (void)onTick:(NSTimeInterval)timestamp;
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
124
React/Profiler/RCTFPSGraph.m
Normal file
124
React/Profiler/RCTFPSGraph.m
Normal file
@@ -0,0 +1,124 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#import "RCTFPSGraph.h"
|
||||
|
||||
#import "RCTAssert.h"
|
||||
|
||||
#if RCT_DEV
|
||||
|
||||
@interface RCTFPSGraph()
|
||||
|
||||
@property (nonatomic, strong, readonly) CAShapeLayer *graph;
|
||||
@property (nonatomic, strong, readonly) UILabel *label;
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTFPSGraph
|
||||
{
|
||||
CAShapeLayer *_graph;
|
||||
UILabel *_label;
|
||||
|
||||
CGFloat *_frames;
|
||||
UIColor *_color;
|
||||
|
||||
NSTimeInterval _prevTime;
|
||||
NSUInteger _frameCount;
|
||||
NSUInteger _FPS;
|
||||
NSUInteger _maxFPS;
|
||||
NSUInteger _minFPS;
|
||||
NSUInteger _length;
|
||||
NSUInteger _height;
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame color:(UIColor *)color
|
||||
{
|
||||
if ((self = [super initWithFrame:frame])) {
|
||||
_frameCount = -1;
|
||||
_prevTime = -1;
|
||||
_maxFPS = 0;
|
||||
_minFPS = 60;
|
||||
_length = (NSUInteger)floor(frame.size.width);
|
||||
_height = (NSUInteger)floor(frame.size.height);
|
||||
_frames = calloc(sizeof(CGFloat), _length);
|
||||
_color = color;
|
||||
|
||||
[self.layer addSublayer:self.graph];
|
||||
[self addSubview:self.label];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
free(_frames);
|
||||
}
|
||||
|
||||
RCT_NOT_IMPLEMENTED(- (instancetype)initWithFrame:(CGRect)frame)
|
||||
RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)
|
||||
|
||||
- (CAShapeLayer *)graph
|
||||
{
|
||||
if (!_graph) {
|
||||
_graph = [CAShapeLayer new];
|
||||
_graph.frame = self.bounds;
|
||||
_graph.backgroundColor = [_color colorWithAlphaComponent:0.2].CGColor;
|
||||
_graph.fillColor = _color.CGColor;
|
||||
}
|
||||
|
||||
return _graph;
|
||||
}
|
||||
|
||||
- (UILabel *)label
|
||||
{
|
||||
if (!_label) {
|
||||
_label = [[UILabel alloc] initWithFrame:self.bounds];
|
||||
_label.font = [UIFont boldSystemFontOfSize:13];
|
||||
_label.textAlignment = NSTextAlignmentCenter;
|
||||
}
|
||||
|
||||
return _label;
|
||||
}
|
||||
|
||||
- (void)onTick:(NSTimeInterval)timestamp
|
||||
{
|
||||
_frameCount++;
|
||||
if (_prevTime == -1) {
|
||||
_prevTime = timestamp;
|
||||
} else if (timestamp - _prevTime >= 1) {
|
||||
_FPS = round(_frameCount / (timestamp - _prevTime));
|
||||
_minFPS = MIN(_minFPS, _FPS);
|
||||
_maxFPS = MAX(_maxFPS, _FPS);
|
||||
|
||||
_label.text = [NSString stringWithFormat:@"%lu", (unsigned long)_FPS];
|
||||
|
||||
CGFloat scale = 60.0 / _height;
|
||||
for (NSUInteger i = 0; i < _length - 1; i++) {
|
||||
_frames[i] = _frames[i + 1];
|
||||
}
|
||||
_frames[_length - 1] = _FPS / scale;
|
||||
|
||||
CGMutablePathRef path = CGPathCreateMutable();
|
||||
CGPathMoveToPoint(path, NULL, 0, _height);
|
||||
for (NSUInteger i = 0; i < _length; i++) {
|
||||
CGPathAddLineToPoint(path, NULL, i, _height - _frames[i]);
|
||||
}
|
||||
CGPathAddLineToPoint(path, NULL, _length - 1, _height);
|
||||
|
||||
_graph.path = path;
|
||||
CGPathRelease(path);
|
||||
|
||||
_prevTime = timestamp;
|
||||
_frameCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
450
React/Profiler/RCTPerfMonitor.m
Normal file
450
React/Profiler/RCTPerfMonitor.m
Normal file
@@ -0,0 +1,450 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#import "RCTDefines.h"
|
||||
|
||||
#if RCT_DEV
|
||||
|
||||
#import <dlfcn.h>
|
||||
|
||||
#import <mach/mach.h>
|
||||
|
||||
#import "RCTBridge.h"
|
||||
#import "RCTDevMenu.h"
|
||||
#import "RCTFPSGraph.h"
|
||||
#import "RCTInvalidating.h"
|
||||
#import "RCTJavaScriptExecutor.h"
|
||||
#import "RCTRootView.h"
|
||||
#import "RCTSparseArray.h"
|
||||
#import "RCTUIManager.h"
|
||||
|
||||
static NSString *const RCTPerfMonitorKey = @"RCTPerfMonitorKey";
|
||||
|
||||
typedef BOOL (*RCTJSCSetOptionType)(const char *);
|
||||
|
||||
static BOOL RCTJSCSetOption(const char *option)
|
||||
{
|
||||
static RCTJSCSetOptionType setOption;
|
||||
static dispatch_once_t onceToken;
|
||||
|
||||
dispatch_once(&onceToken, ^{
|
||||
setOption = dlsym(RTLD_DEFAULT, "_ZN3JSC7Options9setOptionEPKc");
|
||||
setOption("logGC=1");
|
||||
});
|
||||
|
||||
if (setOption) {
|
||||
return setOption(option);
|
||||
} else {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
static vm_size_t RCTGetResidentMemorySize(void)
|
||||
{
|
||||
struct task_basic_info info;
|
||||
mach_msg_type_number_t size = sizeof(info);
|
||||
kern_return_t kerr = task_info(mach_task_self(),
|
||||
TASK_BASIC_INFO,
|
||||
(task_info_t)&info,
|
||||
&size);
|
||||
if (kerr != KERN_SUCCESS) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return info.resident_size;
|
||||
}
|
||||
|
||||
@class RCTDevMenuItem;
|
||||
|
||||
@interface RCTPerfMonitor : NSObject <RCTBridgeModule, RCTInvalidating>
|
||||
|
||||
@property (nonatomic, strong, readonly) RCTDevMenuItem *devMenuItem;
|
||||
@property (nonatomic, strong, readonly) UIPanGestureRecognizer *gestureRecognizer;
|
||||
@property (nonatomic, strong, readonly) UIView *container;
|
||||
@property (nonatomic, strong, readonly) UILabel *memory;
|
||||
@property (nonatomic, strong, readonly) UILabel *heap;
|
||||
@property (nonatomic, strong, readonly) UILabel *views;
|
||||
@property (nonatomic, strong, readonly) RCTFPSGraph *jsGraph;
|
||||
@property (nonatomic, strong, readonly) RCTFPSGraph *uiGraph;
|
||||
@property (nonatomic, strong, readonly) UILabel *jsGraphLabel;
|
||||
@property (nonatomic, strong, readonly) UILabel *uiGraphLabel;
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTPerfMonitor {
|
||||
RCTDevMenuItem *_devMenuItem;
|
||||
UIPanGestureRecognizer *_gestureRecognizer;
|
||||
UIView *_container;
|
||||
UILabel *_memory;
|
||||
UILabel *_heap;
|
||||
UILabel *_views;
|
||||
UILabel *_uiGraphLabel;
|
||||
UILabel *_jsGraphLabel;
|
||||
|
||||
RCTFPSGraph *_uiGraph;
|
||||
RCTFPSGraph *_jsGraph;
|
||||
|
||||
CADisplayLink *_uiDisplayLink;
|
||||
CADisplayLink *_jsDisplayLink;
|
||||
|
||||
NSUInteger _heapSize;
|
||||
|
||||
dispatch_queue_t _queue;
|
||||
dispatch_io_t _io;
|
||||
int _stderr;
|
||||
int _pipe[2];
|
||||
NSString *_remaining;
|
||||
}
|
||||
|
||||
@synthesize bridge = _bridge;
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
|
||||
- (void)invalidate
|
||||
{
|
||||
[self hide];
|
||||
}
|
||||
|
||||
- (RCTDevMenuItem *)devMenuItem
|
||||
{
|
||||
if (!_devMenuItem) {
|
||||
__weak __typeof__(self) weakSelf = self;
|
||||
_devMenuItem =
|
||||
[RCTDevMenuItem toggleItemWithKey:RCTPerfMonitorKey
|
||||
title:@"Show Monitor"
|
||||
selectedTitle:@"Hide Monitor"
|
||||
handler:
|
||||
^(BOOL selected) {
|
||||
if (selected) {
|
||||
[weakSelf show];
|
||||
} else {
|
||||
[weakSelf hide];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
return _devMenuItem;
|
||||
}
|
||||
|
||||
- (UIPanGestureRecognizer *)gestureRecognizer
|
||||
{
|
||||
if (!_gestureRecognizer) {
|
||||
_gestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self
|
||||
action:@selector(gesture:)];
|
||||
}
|
||||
|
||||
return _gestureRecognizer;
|
||||
}
|
||||
|
||||
- (UIView *)container
|
||||
{
|
||||
if (!_container) {
|
||||
_container = [[UIView alloc] initWithFrame:CGRectMake(10, 25, 180, 50)];
|
||||
_container.backgroundColor = UIColor.whiteColor;
|
||||
_container.layer.borderWidth = 2;
|
||||
_container.layer.borderColor = [UIColor grayColor].CGColor;
|
||||
[_container addGestureRecognizer:self.gestureRecognizer];
|
||||
}
|
||||
|
||||
return _container;
|
||||
}
|
||||
|
||||
- (UILabel *)memory
|
||||
{
|
||||
if (!_memory) {
|
||||
_memory = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 44, 50)];
|
||||
_memory.font = [UIFont systemFontOfSize:12];
|
||||
_memory.numberOfLines = 3;
|
||||
_memory.textAlignment = NSTextAlignmentCenter;
|
||||
}
|
||||
|
||||
return _memory;
|
||||
}
|
||||
|
||||
- (UILabel *)heap
|
||||
{
|
||||
if (!_heap) {
|
||||
_heap = [[UILabel alloc] initWithFrame:CGRectMake(44, 0, 44, 50)];
|
||||
_heap.font = [UIFont systemFontOfSize:12];
|
||||
_heap.numberOfLines = 3;
|
||||
_heap.textAlignment = NSTextAlignmentCenter;
|
||||
}
|
||||
|
||||
return _heap;
|
||||
}
|
||||
|
||||
- (UILabel *)views
|
||||
{
|
||||
if (!_views) {
|
||||
_views = [[UILabel alloc] initWithFrame:CGRectMake(88, 0, 44, 50)];
|
||||
_views.font = [UIFont systemFontOfSize:12];
|
||||
_views.numberOfLines = 3;
|
||||
_views.textAlignment = NSTextAlignmentCenter;
|
||||
}
|
||||
|
||||
return _views;
|
||||
}
|
||||
|
||||
- (RCTFPSGraph *)uiGraph
|
||||
{
|
||||
if (!_uiGraph) {
|
||||
_uiGraph = [[RCTFPSGraph alloc] initWithFrame:CGRectMake(134, 14, 40, 30)
|
||||
color:[UIColor lightGrayColor]];
|
||||
}
|
||||
return _uiGraph;
|
||||
}
|
||||
|
||||
- (RCTFPSGraph *)jsGraph
|
||||
{
|
||||
if (!_jsGraph) {
|
||||
_jsGraph = [[RCTFPSGraph alloc] initWithFrame:CGRectMake(178, 14, 40, 30)
|
||||
color:[UIColor lightGrayColor]];
|
||||
}
|
||||
return _jsGraph;
|
||||
}
|
||||
|
||||
- (UILabel *)uiGraphLabel
|
||||
{
|
||||
if (!_uiGraphLabel) {
|
||||
_uiGraphLabel = [[UILabel alloc] initWithFrame:CGRectMake(134, 3, 40, 10)];
|
||||
_uiGraphLabel.font = [UIFont systemFontOfSize:11];
|
||||
_uiGraphLabel.textAlignment = NSTextAlignmentCenter;
|
||||
_uiGraphLabel.text = @"UI";
|
||||
}
|
||||
|
||||
return _uiGraphLabel;
|
||||
}
|
||||
|
||||
- (UILabel *)jsGraphLabel
|
||||
{
|
||||
if (!_jsGraphLabel) {
|
||||
_jsGraphLabel = [[UILabel alloc] initWithFrame:CGRectMake(178, 3, 38, 10)];
|
||||
_jsGraphLabel.font = [UIFont systemFontOfSize:11];
|
||||
_jsGraphLabel.textAlignment = NSTextAlignmentCenter;
|
||||
_jsGraphLabel.text = @"JS";
|
||||
}
|
||||
|
||||
return _jsGraphLabel;
|
||||
}
|
||||
|
||||
- (dispatch_queue_t)methodQueue
|
||||
{
|
||||
return dispatch_get_main_queue();
|
||||
}
|
||||
|
||||
- (void)setBridge:(RCTBridge *)bridge
|
||||
{
|
||||
_bridge = bridge;
|
||||
|
||||
[_bridge.devMenu addItem:self.devMenuItem];
|
||||
}
|
||||
|
||||
- (void)show
|
||||
{
|
||||
if (_container) {
|
||||
return;
|
||||
}
|
||||
|
||||
[self.container addSubview:self.memory];
|
||||
[self.container addSubview:self.heap];
|
||||
[self.container addSubview:self.views];
|
||||
[self.container addSubview:self.uiGraph];
|
||||
[self.container addSubview:self.uiGraphLabel];
|
||||
|
||||
[self redirectLogs];
|
||||
|
||||
RCTJSCSetOption("logGC=1");
|
||||
|
||||
[self updateStats];
|
||||
|
||||
UIWindow *window = [UIApplication sharedApplication].delegate.window;
|
||||
[window addSubview:self.container];
|
||||
|
||||
|
||||
_uiDisplayLink = [CADisplayLink displayLinkWithTarget:self
|
||||
selector:@selector(threadUpdate:)];
|
||||
[_uiDisplayLink addToRunLoop:[NSRunLoop mainRunLoop]
|
||||
forMode:NSRunLoopCommonModes];
|
||||
|
||||
id<RCTJavaScriptExecutor> executor = [_bridge valueForKey:@"javaScriptExecutor"];
|
||||
if ([executor isKindOfClass:NSClassFromString(@"RCTContextExecutor")]) {
|
||||
self.container.frame = (CGRect) {
|
||||
self.container.frame.origin, {
|
||||
self.container.frame.size.width + 44,
|
||||
self.container.frame.size.height
|
||||
}
|
||||
};
|
||||
[self.container addSubview:self.jsGraph];
|
||||
[self.container addSubview:self.jsGraphLabel];
|
||||
[executor executeBlockOnJavaScriptQueue:^{
|
||||
_jsDisplayLink = [CADisplayLink displayLinkWithTarget:self
|
||||
selector:@selector(threadUpdate:)];
|
||||
[_jsDisplayLink addToRunLoop:[NSRunLoop currentRunLoop]
|
||||
forMode:NSRunLoopCommonModes];
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)hide
|
||||
{
|
||||
if (!_container) {
|
||||
return;
|
||||
}
|
||||
|
||||
[self.container removeFromSuperview];
|
||||
_container = nil;
|
||||
_jsGraph = nil;
|
||||
_uiGraph = nil;
|
||||
|
||||
RCTJSCSetOption("logGC=0");
|
||||
|
||||
[self stopLogs];
|
||||
|
||||
[_uiDisplayLink invalidate];
|
||||
[_jsDisplayLink invalidate];
|
||||
|
||||
_uiDisplayLink = nil;
|
||||
_jsDisplayLink = nil;
|
||||
}
|
||||
|
||||
- (void)redirectLogs
|
||||
{
|
||||
_stderr = dup(STDERR_FILENO);
|
||||
|
||||
if (pipe(_pipe) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
dup2(_pipe[1], STDERR_FILENO);
|
||||
close(_pipe[1]);
|
||||
|
||||
__weak __typeof__(self) weakSelf = self;
|
||||
_queue = dispatch_queue_create("com.facebook.react.RCTPerfMonitor", DISPATCH_QUEUE_SERIAL);
|
||||
_io = dispatch_io_create(
|
||||
DISPATCH_IO_STREAM,
|
||||
_pipe[0],
|
||||
_queue,
|
||||
^(__unused int error) {});
|
||||
|
||||
dispatch_io_set_low_water(_io, 20);
|
||||
|
||||
dispatch_io_read(
|
||||
_io,
|
||||
0,
|
||||
SIZE_MAX,
|
||||
_queue,
|
||||
^(__unused bool done, dispatch_data_t data, __unused int error) {
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch_data_apply(
|
||||
data,
|
||||
^bool(
|
||||
__unused dispatch_data_t region,
|
||||
__unused size_t offset,
|
||||
const void *buffer,
|
||||
size_t size
|
||||
) {
|
||||
write(_stderr, buffer, size);
|
||||
|
||||
NSString *log = [[NSString alloc] initWithBytes:buffer
|
||||
length:size
|
||||
encoding:NSUTF8StringEncoding];
|
||||
[weakSelf parse:log];
|
||||
return true;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
- (void)stopLogs
|
||||
{
|
||||
dup2(_stderr, STDERR_FILENO);
|
||||
dispatch_io_close(_io, 0);
|
||||
}
|
||||
|
||||
- (void)parse:(NSString *)log
|
||||
{
|
||||
static NSRegularExpression *GCRegex;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
NSString *pattern = @"\\[GC: (Eden|Full)Collection, (?:Skipped copying|Did copy), ([\\d\\.]+) (\\wb), ([\\d.]+) (\\ws)\\]";
|
||||
GCRegex = [NSRegularExpression regularExpressionWithPattern:pattern
|
||||
options:0
|
||||
error:nil];
|
||||
});
|
||||
|
||||
if (_remaining) {
|
||||
log = [_remaining stringByAppendingString:log];
|
||||
_remaining = nil;
|
||||
}
|
||||
|
||||
NSArray *lines = [log componentsSeparatedByString:@"\n"];
|
||||
if (lines.count == 1) { // no newlines
|
||||
_remaining = log;
|
||||
return;
|
||||
}
|
||||
|
||||
for (NSString *line in lines) {
|
||||
NSTextCheckingResult *match = [GCRegex firstMatchInString:line options:0 range:NSMakeRange(0, line.length)];
|
||||
if (match) {
|
||||
NSString *heapSizeStr = [line substringWithRange:[match rangeAtIndex:2]];
|
||||
_heapSize = [heapSizeStr integerValue];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)updateStats
|
||||
{
|
||||
RCTSparseArray *views = [_bridge.uiManager valueForKey:@"viewRegistry"];
|
||||
NSUInteger viewCount = views.count;
|
||||
NSUInteger visibleViewCount = 0;
|
||||
for (UIView *view in views.allObjects) {
|
||||
if (view.window || view.superview.window) {
|
||||
visibleViewCount++;
|
||||
}
|
||||
}
|
||||
|
||||
double mem = (double)RCTGetResidentMemorySize() / 1024 / 1024;
|
||||
self.memory.text =[NSString stringWithFormat:@"RAM\n%.2lf\nMB", mem];
|
||||
self.heap.text = [NSString stringWithFormat:@"JSC\n%.2lf\nMB", (double)_heapSize / 1024];
|
||||
self.views.text = [NSString stringWithFormat:@"Views\n%lu\n%lu", (unsigned long)visibleViewCount, (unsigned long)viewCount];
|
||||
|
||||
__weak __typeof__(self) weakSelf = self;
|
||||
dispatch_after(
|
||||
dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)),
|
||||
dispatch_get_main_queue(),
|
||||
^{
|
||||
__strong __typeof__(weakSelf) strongSelf = weakSelf;
|
||||
if (strongSelf && strongSelf->_container.superview) {
|
||||
[strongSelf updateStats];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (void)gesture:(UIPanGestureRecognizer *)gestureRecognizer
|
||||
{
|
||||
CGPoint translation = [gestureRecognizer translationInView:self.container.superview];
|
||||
self.container.center = CGPointMake(
|
||||
self.container.center.x + translation.x,
|
||||
self.container.center.y + translation.y
|
||||
);
|
||||
[gestureRecognizer setTranslation:CGPointMake(0, 0)
|
||||
inView:self.container.superview];
|
||||
}
|
||||
|
||||
- (void)threadUpdate:(CADisplayLink *)displayLink
|
||||
{
|
||||
RCTFPSGraph *graph = displayLink == _jsDisplayLink ? _jsGraph : _uiGraph;
|
||||
[graph onTick:displayLink.timestamp];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -49,7 +49,6 @@
|
||||
13E067571A70F44B002CDEE1 /* RCTView.m in Sources */ = {isa = PBXBuildFile; fileRef = 13E067501A70F44B002CDEE1 /* RCTView.m */; };
|
||||
13E067591A70F44B002CDEE1 /* UIView+React.m in Sources */ = {isa = PBXBuildFile; fileRef = 13E067541A70F44B002CDEE1 /* UIView+React.m */; };
|
||||
13F17A851B8493E5007D4C75 /* RCTRedBox.m in Sources */ = {isa = PBXBuildFile; fileRef = 13F17A841B8493E5007D4C75 /* RCTRedBox.m */; };
|
||||
1403F2B31B0AE60700C2A9A4 /* RCTPerfStats.m in Sources */ = {isa = PBXBuildFile; fileRef = 1403F2B21B0AE60700C2A9A4 /* RCTPerfStats.m */; };
|
||||
14200DAA1AC179B3008EE6BA /* RCTJavaScriptLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = 14200DA91AC179B3008EE6BA /* RCTJavaScriptLoader.m */; };
|
||||
142014191B32094000CC17BA /* RCTPerformanceLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 142014171B32094000CC17BA /* RCTPerformanceLogger.m */; };
|
||||
14435CE51AAC4AE100FC20F4 /* RCTMap.m in Sources */ = {isa = PBXBuildFile; fileRef = 14435CE21AAC4AE100FC20F4 /* RCTMap.m */; };
|
||||
@@ -59,7 +58,6 @@
|
||||
1450FF881BCFF28A00208362 /* RCTProfileTrampoline-arm64.S in Sources */ = {isa = PBXBuildFile; fileRef = 1450FF831BCFF28A00208362 /* RCTProfileTrampoline-arm64.S */; settings = {ASSET_TAGS = (); }; };
|
||||
1450FF891BCFF28A00208362 /* RCTProfileTrampoline-x86.S in Sources */ = {isa = PBXBuildFile; fileRef = 1450FF841BCFF28A00208362 /* RCTProfileTrampoline-x86.S */; settings = {ASSET_TAGS = (); }; };
|
||||
1450FF8A1BCFF28A00208362 /* RCTProfileTrampoline-x86_64.S in Sources */ = {isa = PBXBuildFile; fileRef = 1450FF851BCFF28A00208362 /* RCTProfileTrampoline-x86_64.S */; settings = {ASSET_TAGS = (); }; };
|
||||
146459261B06C49500B389AA /* RCTFPSGraph.m in Sources */ = {isa = PBXBuildFile; fileRef = 146459251B06C49500B389AA /* RCTFPSGraph.m */; };
|
||||
14C2CA711B3AC63800E6CBB2 /* RCTModuleMethod.m in Sources */ = {isa = PBXBuildFile; fileRef = 14C2CA701B3AC63800E6CBB2 /* RCTModuleMethod.m */; };
|
||||
14C2CA741B3AC64300E6CBB2 /* RCTModuleData.m in Sources */ = {isa = PBXBuildFile; fileRef = 14C2CA731B3AC64300E6CBB2 /* RCTModuleData.m */; };
|
||||
14C2CA761B3AC64F00E6CBB2 /* RCTFrameUpdate.m in Sources */ = {isa = PBXBuildFile; fileRef = 14C2CA751B3AC64F00E6CBB2 /* RCTFrameUpdate.m */; };
|
||||
@@ -67,6 +65,8 @@
|
||||
14F3620D1AABD06A001CE568 /* RCTSwitch.m in Sources */ = {isa = PBXBuildFile; fileRef = 14F362081AABD06A001CE568 /* RCTSwitch.m */; };
|
||||
14F3620E1AABD06A001CE568 /* RCTSwitchManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 14F3620A1AABD06A001CE568 /* RCTSwitchManager.m */; };
|
||||
14F484561AABFCE100FDF6B9 /* RCTSliderManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 14F484551AABFCE100FDF6B9 /* RCTSliderManager.m */; };
|
||||
14F7A0EC1BDA3B3C003C6C10 /* RCTPerfMonitor.m in Sources */ = {isa = PBXBuildFile; fileRef = 14F7A0EB1BDA3B3C003C6C10 /* RCTPerfMonitor.m */; settings = {ASSET_TAGS = (); }; };
|
||||
14F7A0F01BDA714B003C6C10 /* RCTFPSGraph.m in Sources */ = {isa = PBXBuildFile; fileRef = 14F7A0EF1BDA714B003C6C10 /* RCTFPSGraph.m */; settings = {ASSET_TAGS = (); }; };
|
||||
58114A161AAE854800E7D092 /* RCTPicker.m in Sources */ = {isa = PBXBuildFile; fileRef = 58114A131AAE854800E7D092 /* RCTPicker.m */; };
|
||||
58114A171AAE854800E7D092 /* RCTPickerManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 58114A151AAE854800E7D092 /* RCTPickerManager.m */; };
|
||||
58114A501AAE93D500E7D092 /* RCTAsyncLocalStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 58114A4E1AAE93D500E7D092 /* RCTAsyncLocalStorage.m */; };
|
||||
@@ -196,8 +196,6 @@
|
||||
13EF7F441BC69646003F47DD /* RCTImageComponent.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RCTImageComponent.h; sourceTree = "<group>"; };
|
||||
13F17A831B8493E5007D4C75 /* RCTRedBox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTRedBox.h; sourceTree = "<group>"; };
|
||||
13F17A841B8493E5007D4C75 /* RCTRedBox.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTRedBox.m; sourceTree = "<group>"; };
|
||||
1403F2B11B0AE60700C2A9A4 /* RCTPerfStats.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTPerfStats.h; sourceTree = "<group>"; };
|
||||
1403F2B21B0AE60700C2A9A4 /* RCTPerfStats.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTPerfStats.m; sourceTree = "<group>"; };
|
||||
14200DA81AC179B3008EE6BA /* RCTJavaScriptLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTJavaScriptLoader.h; sourceTree = "<group>"; };
|
||||
14200DA91AC179B3008EE6BA /* RCTJavaScriptLoader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTJavaScriptLoader.m; sourceTree = "<group>"; };
|
||||
142014171B32094000CC17BA /* RCTPerformanceLogger.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTPerformanceLogger.m; sourceTree = "<group>"; };
|
||||
@@ -213,8 +211,6 @@
|
||||
1450FF831BCFF28A00208362 /* RCTProfileTrampoline-arm64.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = "RCTProfileTrampoline-arm64.S"; sourceTree = "<group>"; };
|
||||
1450FF841BCFF28A00208362 /* RCTProfileTrampoline-x86.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = "RCTProfileTrampoline-x86.S"; sourceTree = "<group>"; };
|
||||
1450FF851BCFF28A00208362 /* RCTProfileTrampoline-x86_64.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = "RCTProfileTrampoline-x86_64.S"; sourceTree = "<group>"; };
|
||||
146459241B06C49500B389AA /* RCTFPSGraph.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTFPSGraph.h; sourceTree = "<group>"; };
|
||||
146459251B06C49500B389AA /* RCTFPSGraph.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTFPSGraph.m; sourceTree = "<group>"; };
|
||||
1482F9E61B55B927000ADFF3 /* RCTBridgeDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RCTBridgeDelegate.h; sourceTree = "<group>"; };
|
||||
14C2CA6F1B3AC63800E6CBB2 /* RCTModuleMethod.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTModuleMethod.h; sourceTree = "<group>"; };
|
||||
14C2CA701B3AC63800E6CBB2 /* RCTModuleMethod.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTModuleMethod.m; sourceTree = "<group>"; };
|
||||
@@ -228,6 +224,9 @@
|
||||
14F3620A1AABD06A001CE568 /* RCTSwitchManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTSwitchManager.m; sourceTree = "<group>"; };
|
||||
14F484541AABFCE100FDF6B9 /* RCTSliderManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTSliderManager.h; sourceTree = "<group>"; };
|
||||
14F484551AABFCE100FDF6B9 /* RCTSliderManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTSliderManager.m; sourceTree = "<group>"; };
|
||||
14F7A0EB1BDA3B3C003C6C10 /* RCTPerfMonitor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTPerfMonitor.m; sourceTree = "<group>"; };
|
||||
14F7A0EE1BDA714B003C6C10 /* RCTFPSGraph.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTFPSGraph.h; sourceTree = "<group>"; };
|
||||
14F7A0EF1BDA714B003C6C10 /* RCTFPSGraph.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTFPSGraph.m; sourceTree = "<group>"; };
|
||||
58114A121AAE854800E7D092 /* RCTPicker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTPicker.h; sourceTree = "<group>"; };
|
||||
58114A131AAE854800E7D092 /* RCTPicker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTPicker.m; sourceTree = "<group>"; };
|
||||
58114A141AAE854800E7D092 /* RCTPickerManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTPickerManager.h; sourceTree = "<group>"; };
|
||||
@@ -433,6 +432,9 @@
|
||||
1450FF7F1BCFF28A00208362 /* Profiler */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
14F7A0EB1BDA3B3C003C6C10 /* RCTPerfMonitor.m */,
|
||||
14F7A0EE1BDA714B003C6C10 /* RCTFPSGraph.h */,
|
||||
14F7A0EF1BDA714B003C6C10 /* RCTFPSGraph.m */,
|
||||
1450FF801BCFF28A00208362 /* RCTProfile.h */,
|
||||
1450FF811BCFF28A00208362 /* RCTProfile.m */,
|
||||
1450FF821BCFF28A00208362 /* RCTProfileTrampoline-arm.S */,
|
||||
@@ -489,8 +491,6 @@
|
||||
13AF1F851AE6E777005F5298 /* RCTDefines.h */,
|
||||
83CBBA651A601EF300E9B192 /* RCTEventDispatcher.h */,
|
||||
83CBBA661A601EF300E9B192 /* RCTEventDispatcher.m */,
|
||||
146459241B06C49500B389AA /* RCTFPSGraph.h */,
|
||||
146459251B06C49500B389AA /* RCTFPSGraph.m */,
|
||||
1436DD071ADE7AA000A5ED7D /* RCTFrameUpdate.h */,
|
||||
14C2CA751B3AC64F00E6CBB2 /* RCTFrameUpdate.m */,
|
||||
83CBBA4C1A601E3B00E9B192 /* RCTInvalidating.h */,
|
||||
@@ -511,8 +511,6 @@
|
||||
14C2CA701B3AC63800E6CBB2 /* RCTModuleMethod.m */,
|
||||
142014181B32094000CC17BA /* RCTPerformanceLogger.h */,
|
||||
142014171B32094000CC17BA /* RCTPerformanceLogger.m */,
|
||||
1403F2B11B0AE60700C2A9A4 /* RCTPerfStats.h */,
|
||||
1403F2B21B0AE60700C2A9A4 /* RCTPerfStats.m */,
|
||||
830A229C1A66C68A008503DA /* RCTRootView.h */,
|
||||
830A229D1A66C68A008503DA /* RCTRootView.m */,
|
||||
83BEE46C1A6D19BC00B5863B /* RCTSparseArray.h */,
|
||||
@@ -635,15 +633,16 @@
|
||||
58114A501AAE93D500E7D092 /* RCTAsyncLocalStorage.m in Sources */,
|
||||
832348161A77A5AA00B55238 /* Layout.c in Sources */,
|
||||
13513F3C1B1F43F400FCE529 /* RCTProgressViewManager.m in Sources */,
|
||||
14F7A0F01BDA714B003C6C10 /* RCTFPSGraph.m in Sources */,
|
||||
14F3620D1AABD06A001CE568 /* RCTSwitch.m in Sources */,
|
||||
14F3620E1AABD06A001CE568 /* RCTSwitchManager.m in Sources */,
|
||||
13B080201A69489C00A75B9A /* RCTActivityIndicatorViewManager.m in Sources */,
|
||||
13E067561A70F44B002CDEE1 /* RCTViewManager.m in Sources */,
|
||||
58C571C11AA56C1900CDF9C8 /* RCTDatePickerManager.m in Sources */,
|
||||
1450FF8A1BCFF28A00208362 /* RCTProfileTrampoline-x86_64.S in Sources */,
|
||||
14F7A0EC1BDA3B3C003C6C10 /* RCTPerfMonitor.m in Sources */,
|
||||
1450FF881BCFF28A00208362 /* RCTProfileTrampoline-arm64.S in Sources */,
|
||||
13B080061A6947C200A75B9A /* RCTScrollViewManager.m in Sources */,
|
||||
146459261B06C49500B389AA /* RCTFPSGraph.m in Sources */,
|
||||
14200DAA1AC179B3008EE6BA /* RCTJavaScriptLoader.m in Sources */,
|
||||
137327EA1AA5CF210034F82E /* RCTTabBarManager.m in Sources */,
|
||||
13B080261A694A8400A75B9A /* RCTWrapperViewController.m in Sources */,
|
||||
@@ -688,7 +687,6 @@
|
||||
134FCB3E1A6E7F0800051CC8 /* RCTWebViewExecutor.m in Sources */,
|
||||
13B0801C1A69489C00A75B9A /* RCTNavItem.m in Sources */,
|
||||
1385D0341B665AAE000A309B /* RCTModuleMap.m in Sources */,
|
||||
1403F2B31B0AE60700C2A9A4 /* RCTPerfStats.m in Sources */,
|
||||
83CBBA691A601EF300E9B192 /* RCTEventDispatcher.m in Sources */,
|
||||
83A1FE8F1B62643A00BE0E65 /* RCTModalHostViewManager.m in Sources */,
|
||||
13E0674A1A70F434002CDEE1 /* RCTUIManager.m in Sources */,
|
||||
|
||||
Reference in New Issue
Block a user