美文网首页
RN中的系统日志

RN中的系统日志

作者: 面朝对象_春暖花开 | 来源:发表于2019-04-10 17:58 被阅读0次

    初始化流程:

    介绍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

    相关文章

      网友评论

          本文标题:RN中的系统日志

          本文链接:https://www.haomeiwen.com/subject/rwfqoftx.html