初始化流程:
介绍CxxBridge
CxxBridge是个对象,他拥有:
-
RCTModuleData(Array)这是moduleClass的对象和instance
-
RCTMessageThread 这里面封装了runAsync、runSync、runOnQueue等同步、异步、跨线程调用等方法。
-
Instance 这个是一个关键 loadJS、 native->js、 js->native 都是它
所以所初始化CxxBridge的时候,大概做了什么?
- 把所有遵循了RCTBridgeModule协议的nativeModule都封装成RCTModuleData,另外js的所有变量及block也都被封装成nativeModule,怎么把js的东西初始化成这样的?
jscore->jscontext
- 初始化一个NSThread 并且用NSThread的runtime初始化一个RCTMessageThread,用RCTMessageThread对象实现调用,怎么调用:
void RCTMessageThread::runAsync(std::function<void()> func) {
CFRunLoopPerformBlock(m_cfRunLoop, kCFRunLoopCommonModes, ^{ func(); });
CFRunLoopWakeUp(m_cfRunLoop);
}
- 初始化Instance 用来初始化js代码、注册"RAM" bundle、js<->native,怎么调?
找到nativeModule就可以啦
屏幕快照 2019-04-10 下午5.53.30.png
下面是加载流程,代码开始也是在cxx的start方法中
如果不是RAMBundle,有可能是String、BCBundle比如我们的工程就是String,我们的资源包是
总结:初始化桥就是:创建js线程、下载js代码、通过js代码生成JSIExecutor、初始化nativeModule的总和
RCTPerformanceLogger(线上或者dev都存在)
markStartForTag和markStopForTag
mark:此日志 在DEV状态下也会存储于RCTProfileAddEvent中
如何存储
- 调用- (void)markStopForTag:(RCTPLTag)tag 最终存储于_data中
都存储了那些、什么时候存储
存储了那些?
typedef NS_ENUM(NSUInteger, RCTPLTag) {
RCTPLScriptDownload,
RCTPLScriptExecution,
RCTPLRAMBundleLoad,
RCTPLRAMStartupCodeSize,
RCTPLRAMStartupNativeRequires,
RCTPLRAMStartupNativeRequiresCount,
RCTPLRAMNativeRequires,
RCTPLRAMNativeRequiresCount,
RCTPLNativeModuleInit,
RCTPLNativeModuleMainThread,
RCTPLNativeModulePrepareConfig,
RCTPLNativeModuleInjectConfig,
RCTPLNativeModuleMainThreadUsesCount,
RCTPLJSCWrapperOpenLibrary,
RCTPLJSCExecutorSetup,
RCTPLBridgeStartup,
RCTPLTTI,
RCTPLBundleSize,
RCTPLSize
};
何时存储、存储数据类型、存储顺序 (CACurrentMediaTime() * 1000)
- RCTPLScriptDownload,
mark:download jS资源
RCTPLScriptDownload_start(timestamp) order:11
RCTPLScriptDownload_end(timestamp) order:12
- RCTPLScriptExecution,
mark:Download完成之后执行js时发出
RCTPLScriptExecution_start(timestamp) order:15
RCTPLScriptExecution_end(timestamp) order:16
- RCTPLRAMBundleLoad,
mark:Download完成之后执行js时发出,比RCTPLScriptExecution早,但是只有当jssource是RAMBundle格式的时候才发
RCTPLRAMBundleLoad_start(timestamp) order:null
RCTPLRAMBundleLoad_end(timestamp) order:null
- RCTPLRAMStartupCodeSize,
mark:RCTPLRAMBundleLoad之后发,也就是说同样jssource是RAMBundle格式的时候才发
RCTPLRAMBundleLoad_start(0) order:null
RCTPLRAMBundleLoad_end(int——size) order:null
- RCTPLRAMStartupNativeRequires,
mark:未知
RCTPLRAMStartupNativeRequires_start(0) order:null
RCTPLRAMStartupNativeRequires_end(0) order:null
- RCTPLRAMStartupNativeRequiresCount,
mark:未知
RCTPLRAMStartupNativeRequiresCount_start(0) order:null
RCTPLRAMStartupNativeRequiresCount_end(0) order:null
- RCTPLRAMNativeRequires,
mark:未知
RCTPLRAMNativeRequirest_start(0) order:null
RCTPLRAMNativeRequires_end(0) order:null
- RCTPLRAMNativeRequiresCount,
mark:未知
RCTPLRAMNativeRequiresCount_start(0) order:null
RCTPLRAMNativeRequiresCount_end(0) order:null
- RCTPLNativeModuleInit,
mark:初始化NativeModule
RCTPLNativeModuleInit_start(timestamp) order:3
RCTPLNativeModuleInit_end(timestamp) order:10
- RCTPLNativeModuleMainThread,
mark:主线程初始化NativeModule
RCTPLNativeModuleMainThread_start(0) order:4
RCTPLNativeModuleMainThread_end(timestamp差值n个在主线程初始化的Module时间和) order:5
- RCTPLNativeModulePrepareConfig,
mark:为初始化NativeModule做准备,在初始化Instance的时候
RCTPLNativeModulePrepareConfig_start(timestamp) order:8
RCTPLNativeModulePrepareConfig_end(timestamp) order:9
- RCTPLNativeModuleInjectConfig,
mark:未知
RCTPLNativeModuleInjectConfig_start(0) order:null
RCTPLNativeModuleInjectConfig_end(0) order:null
- RCTPLNativeModuleMainThreadUsesCount,
mark:主线程初始化Module完成后统计在主线程初始化的Module的个数
RCTPLNativeModuleMainThreadUsesCount_start(0) order:6
RCTPLNativeModuleMainThreadUsesCount_end(int) order:7
- RCTPLJSCWrapperOpenLibrary,
mark:未知
RCTPLJSCWrapperOpenLibrary_start(0) order:null
RCTPLJSCWrapperOpenLibrary_end(0) order:null
- RCTPLJSCExecutorSetup,
mark:未知
RCTPLJSCExecutorSetup_start(0) order:null
RCTPLJSCExecutorSetup_end(0) order:null
- RCTPLBridgeStartup,
mark:初始化桥,最最早的,一直到桥初始化结束
RCTPLBridgeStartup_start(timestamp) order:1
RCTPLBridgeStartup_end(timestamp) order:17
- RCTPLTTI,
mark:从初始化桥到rootView被渲染出来
RCTPLTTI_start(timestamp) order:2(和RCTPLBridgeStartup_start一样)
RCTPLTTI_end(timestamp) order: 18
- RCTPLBundleSize,
mark:记录下载下来的js的字符长度,下载结束之后就存起来了
RCTPLBundleSize_start(0) order:13
RCTPLBundleSize_end(int) order:14
- RCTPLSize
mark:保留字段,目的是获取上面一共多少个日志
打开方式:QRN关闭了
RCTProfileAddEvent
以name为维度
- "VSYNC"
RCTProfileDisplayLink = [CADisplayLink displayLinkWithTarget:[RCTProfile class]
selector:@selector(vsync:)];
[RCTProfileDisplayLink addToRunLoop:[NSRunLoop mainRunLoop]
forMode:NSRunLoopCommonModes];
与屏幕帧率同步发出VSYNC,使用RCTProfileImmediateEvent记录时间戳,可用来检测屏幕卡顿。
- "flow"
调用RCTProfileBeginFlowEvent、RCTProfileEndFlowEvent会添加,所以"flow"以两个一组的形式出现:他们有相同的id,ph的值(s标识Start f标识Finish)
{
"name": "flow",
"id": 129,
"ts": 2959452.9999885708,
"cat": "flow",
"ph": "s",
"tid": "com.facebook.react.JavaScript",
"pid": 14689
}, {
"name": "flow",
"id": 129,
"ts": 2959476.8750248477,
"cat": "flow",
"ph": "f",
"tid": "com.facebook.react.JavaScript",
"pid": 14689
}
> "flow"(调用流程)记录的时机如下:jscall 或者 callJSCallback 也或者 loadApplicationScript的时候RCTProfileBeginFlowEvent在放jsThread放入一个命令的时间戳、RCTProfileEndFlowEvent代表这个命令开始执行的时间戳,所以当这个间距时间长了,说明jsThread中有耗时操作,影响了其他任务的执行
- "thread_sort_index"
固定5个分别是
JS async
(下载js资源)、RCTPerformanceLogger
(com.facebook.react.Profiler 写日志的)、com.facebook.react.JavaScript
(js线程)、com.facebook.react.ShadowQueue
(RCTShadowView创建的地方)、main
{
"ph" : "M",
"tid" : "JS async",
"args" : {
"sort_index" : -1000
},
"name" : "thread_sort_index",
"pid" : 14290
},
args中的sort_index表示这5个线程id pid NSProcess的进程id
- "RCTProfileHookModules"
只有一个,记录所有 modelHook打开的时间差,开启之后会产生js<-->native的调用链记录
- JS Thread Tick
RCTDisplayLink 中CADisplayLink的轮训时间,使用RCTProfileImmediateEvent记录时间戳,可以通过来比对出js线程是否卡顿了
打开方式:rn->RCTDevSettings->setProfilingEnabled
网友评论