美文网首页程序员
simpleperf源码阅读-0.Python

simpleperf源码阅读-0.Python

作者: 骆驼骑士 | 来源:发表于2020-05-23 15:20 被阅读0次

    简介


    SimplePref是Android NDK自带的Profiler工具,

    官方文档:
    https://developer.android.com/ndk/guides/simpleperf

    simplepref是一个命令行的工具(shell), 提供一个python的工具, 可在PC里通过adb shell里调用simplepref来运行.

    要使用 Simpleperf,您必须遵循以下要求:

    • 使用运行 Android 5.0(API 级别 21)或更高版本的设备来分析您的应用。
    • 通过 USB 调试连接,将设备连接至您的开发计算机。
    • 要运行 Python 脚本以进行记录和报告(推荐),需在您的开发计算机上安装以下项目:
      • Python 2.7 或更高版本。
      • 最新版 Android SDK 和 NDK。 您可通过 Android Studio 中的 SDK Manager 安装这些项目。`

    simplepref工具的参数:
    https://developer.android.com/ndk/guides/simpleperf-commands

    基于版本 NDK r17

    SimplePerf Python


    app_profiler.py

    开始record:

    python app_profiler.py -p com.your.packagename
    

    例如:

    python app_profiler.py  \--app com.uboxue4.demo.u416 --skip_collect_binaries --disable_adb_root -r "-e task-clock:u -f 1000 -g --call-graph fp" -o perf.data2
    

    则真实在手机上运行的命令为:

    /data/local/tmp/simpleperf record -o /data/local/tmp/perf.data -e task-clock:u -f 1000 -g --duration 60 --call-graph fp --app com.uboxue4.demo.u416
    

    不传入 --duration 60 则在Ctrl+C的时候 停止, 模拟Ctrl+C, 可以使用信号量 (Ctrl+C的信号量为15 SIGTERM ) , 例如

    kill -15 pid
    

    参数:

    • --record_options 传入到simpleperf里的record参数
    • --native_lib_dir 本地含有符号的so文件的目录(会遍历这个目录下的所有so文件传入到手机中的/data/local/tmp/native_libs/目录 , 并将该目录作为simpleperf的 -symfs 目录传入 )
    • --skip_collect_binaries 默认情况下会收集所有的so文件包括系统的so到PC的build_cache, 用作分析(report_html.py在用)
    • --disable_adb_root 默认会使用root模式运行, 该参数可关闭root, 使用普通用户权限

    Android < N:

    • 在某些机器上默认的 --call-graph dwarf,8192 不支持, 需要使用 --call-graph fp
    • 在Android >= N的时候会使用 package compile -f -m speed来完整的重新编译Java Code

    启动APP的命令

    am force-stop packagename
    
    
    // android N上面force-stop可能不能, 需要kill
    kill -9 pid
    

    查询指定包名的pid命令

    pidof packagename
    

    遍历native_lib_dirs下所有so文件, 使用 readelf 读取so的 build_id, 是否包括debug信息段, 然后将这些so文件push到手机的 /data/local/tmp/native_libs/ 目录.
    这个目录会作为参数传给simpleperf, simpleperf会使用这些so读取符号信息.
    在本地的native_library_dir和手机的native_libs目录会进行同步.

    拷贝simpleperf二进制文件

    adb push simpleperf /data/local/tmp
    adb shell chmod a+x /data/local/tmp/simpleperf
    

    运行simpleperf命令, 在一个子进程里运行

    adb shell /data/local/tmp/simpleperf record -o /data/local/tmp/perf.data \--symfs /data/local/tmp/native_libs/ ##args
    

    然后一直等待这个子进程主动退出, 如果returncode为0, 则表示正常退出, 准备收集已经采集好的数据.

    将数据从手机拉取到电脑:

    adb pull /data/local/tmp/perf.data
    

    如果没有skip_collect_binaries参数, 则会调用 binary_cache_builder.py 去拉取手机里所有涉及到的so文件(包括系统的so文件)

    binary_cache_builder.py

    参数:

    • perf_data_path, perf.data的路径
    • symfs_dirs 符号文件路径
    • ndk_path NDK路径

    收集使用的so文件

    遍历perf.data里的所有samples, 每个sample都包括: symbols, 和 callchain

    首先从函数调用栈 callchain 里获取所有涉及到的symbol, 将其合并到symbols里.
    然后遍历所有symbol, 获取dso_name (SO的文件名, 含路径)

    即得到了perf.data里所有涉及到的符号所在的so文件列表.

    保存到一个dict里, key为so_name, value为so_build_id

    从symfs_dirs拷贝so文件

    遍历 symfs_dirs, 对比其中的so名称, build_id, 如果是perf.data里使用的, 则将其拷贝到 build_cache 目录

    从手机拷贝so文件

    然后遍历perf.data所有用到的so文件, 将其so_name作为路径, 全部pull到电脑上的build_cache目录(但是会跳过之前在symfs_dirs目录的so文件, 因为该目录下的so文件会比手机上的so文件提供更多的符号信息)

    拷贝文件都会先将文件从原始目录 临时拷贝(cp) 到 /data/local/tmp 目录, 然后再 pull, 然后删除到 /data/local/tmp 目录下的临时so文件.

    从手机拷贝内核符号文件

    如果是root手机, 则会去修改手机里的 /proc/sys/kernel/kptr_restrict 文件为 0, 关闭掉这个限制, 然后拷贝内核符号文件
    /proc/kallsyms

    report.py

    report.py 只是 simpleperf report 命令的一个python壳子, 这个脚本有两种模式:

    1. 直接调用 simpleperf report 生成报告文件
    2. 调用simpleperf report生成报告文件后, 使用GUI来展示数据. (使用--gui参数即可)

    将pref.data数据转换为txt数据

    python report.py -o output_report.txt
    

    其内部执行的命令为:

    simpleperf report --full-callgraph -o pref.report ##args
    

    数据格式默认为:

    Cmdline: /data/local/tmp/simpleperf record -o /data/local/tmp/perf.data -e task-clock:u -f 1000 -g --duration 10 --app com.uboxue4.demo.u416
    Arch: arm64
    Event: task-clock:u (type 1, config 1)
    Samples: 8988
    Event count: 8988000000
    
    
    Overhead  Command          Pid    Tid    Shared Object                                                  Symbol
    1.46%     RenderThread 2   13321  13400  /system/lib/libc.so                                            memcpy
    1.07%     RenderThread 2   13321  13400  /data/app/com.uboxue4.demo.u416-1/lib/arm/libUE4.so            FOpenGLShaderParameterCache::CommitPackedUniformBuffers(FOpenGLLinkedProgram*, int, TRefCountPtr<FRHIUniformBuffer>*, TArray<CrossCompiler::FUniformBufferCopyInfo, FDefaultAllocator> const&)
    1.00%     Thread-2         13321  13359  /data/app/com.uboxue4.demo.u416-1/lib/arm/libgnustl_shared.so  .udivsi3_skip_div0_test
    0.96%     RenderThread 2   13321  13400  /system/vendor/lib/egl/libGLESv2_adreno.so                     EsxGfxMem::UpdateTimestamp(EsxContext const*, EsxAccessType, EsxBucketIdReference*)
    0.92%     RenderThread 0   13321  13390  /data/app/com.uboxue4.demo.u416-1/lib/arm/libUE4.so            void FLandscapeSharedBuffers::CreateIndexBuffers<unsigned short>(ERHIFeatureLevel::Type, bool)
    0.88%     RenderThread 2   13321  13400  /system/lib/libc.so                                            memset
    0.80%     Thread-2         13321  13359  /system/lib/libc.so                                            memcpy
    

    有函数调用关系的格式为: (参数 -g callee 被调用关系)

    Cmdline: /data/local/tmp/simpleperf record -o /data/local/tmp/perf.data -e task-clock:u -f 1000 -g --duration 10 --app com.uboxue4.demo.u416
    Arch: arm64
    Event: task-clock:u (type 1, config 1)
    Samples: 8988
    Event count: 8988000000
    
    
    Children  Self   Command          Pid    Tid    Shared Object                                                  Symbol
    49.14%    0.00%  RenderThread 2   13321  13400  /data/app/com.uboxue4.demo.u416-1/lib/arm/libUE4.so            FNamedTaskThread::ProcessTasksUntilQuit(int)
           |
           -- FNamedTaskThread::ProcessTasksUntilQuit(int)
              |
               -- RenderingThreadMain(FEvent*)
                  FRenderingThread::Run()
                  FRunnableThreadPThread::Run()
                  FRunnableThreadPThread::_ThreadProc(void*)
                  __pthread_start(void*)
                  __start_thread
    49.14%    0.00%  RenderThread 2   13321  13400  /system/lib/libc.so                                            __start_thread
    49.14%    0.00%  RenderThread 2   13321  13400  /data/app/com.uboxue4.demo.u416-1/lib/arm/libUE4.so            FRenderingThread::Run()
           [skipped in brief callgraph mode]
    49.14%    0.00%  RenderThread 2   13321  13400  /data/app/com.uboxue4.demo.u416-1/lib/arm/libUE4.so            FRunnableThreadPThread::Run()
           [skipped in brief callgraph mode]
    49.14%    0.00%  RenderThread 2   13321  13400  /data/app/com.uboxue4.demo.u416-1/lib/arm/libUE4.so            FRunnableThreadPThread::_ThreadProc(void*)
           [skipped in brief callgraph mode]
    49.14%    0.00%  RenderThread 2   13321  13400  /data/app/com.uboxue4.demo.u416-1/lib/arm/libUE4.so            RenderingThreadMain(FEvent*)
           [skipped in brief callgraph mode]
    49.14%    0.00%  RenderThread 2   13321  13400  /system/lib/libc.so                                            __pthread_start(void*)
           [skipped in brief callgraph mode]
    49.02%    0.06%  RenderThread 2   13321  13400  /data/app/com.uboxue4.demo.u416-1/lib/arm/libUE4.so            FNamedTaskThread::ProcessTasksNamedThread(int, bool)
           |
           -- FNamedTaskThread::ProcessTasksNamedThread(int, bool)
              |
               --99.89%-- FNamedTaskThread::ProcessTasksUntilQuit(int)
                          RenderingThreadMain(FEvent*)
                          FRenderingThread::Run()
                          FRunnableThreadPThread::Run()
                          FRunnableThreadPThread::_ThreadProc(void*)
                          __pthread_start(void*)
                          __start_thread
    

    函数调用关系格式( -g caller)

    Cmdline: /data/local/tmp/simpleperf record -o /data/local/tmp/perf.data -e task-clock:u -f 1000 -g --duration 10 --app com.uboxue4.demo.u416
    Arch: arm64
    Event: task-clock:u (type 1, config 1)
    Samples: 8988
    Event count: 8988000000
    
    
    Children  Self   Command          Pid    Tid    Shared Object                                                  Symbol
    49.14%    0.00%  RenderThread 2   13321  13400  /system/lib/libc.so                                            __start_thread
           |
           -- __start_thread
              |
               -- __pthread_start(void*)
                  FRunnableThreadPThread::_ThreadProc(void*)
                  FRunnableThreadPThread::Run()
                  FRenderingThread::Run()
                  RenderingThreadMain(FEvent*)
                  FNamedTaskThread::ProcessTasksUntilQuit(int)
                   |
                   |--99.75%-- FNamedTaskThread::ProcessTasksNamedThread(int, bool)
                   |    |--0.11%-- [hit in function]
                   |    |
                   |    |--80.07%-- libUE4.so[+4586d24]
                   |    |    |
                   |    |    |--99.23%-- libUE4.so[+4526690]
                   |    |    |    |
                   |    |    |    |--99.83%-- FMobileSceneRenderer::Render(FRHICommandListImmediate&)
                   |    |    |    |    |--0.11%-- [hit in function]
                   |    |    |    |    |
                   |    |    |    |    |--63.03%-- FMobileSceneRenderer::RenderMobileBasePass(FRHICommandListImmediate&, TArrayView<FViewInfo const*>)
                   |    |    |    |    |    |--0.27%-- [hit in function]
                   |    |    |    |    |    |
                   |    |    |    |    |    |--96.10%-- libUE4.so[+4876e90]
                   |    |    |    |    |    |    |
                   |    |    |    |    |    |    |--99.95%-- int TStaticMeshDrawList<TMobileBasePassDrawingPolicy<FUniformLightMapPolicy, 0> >::DrawVisibleFrontToBackInner<(InstancedStereoPolicy)2>(FRHICommandList&, FViewInfo const&, FDrawingPolicyRenderState&, FMeshDrawingPolicy::ContextDataType, TBitArray<SceneRenderingBitArrayAllocator> const*, TArray<unsigned long long, SceneRenderingAllocator> const*, StereoPair const*, int)
                   |    |    |    |    |    |    |    |--2.50%-- [hit in function]
                   |    |    |    |    |    |    |    |
                   |    |    |    |    |    |    |    |--96.98%-- int TStaticMeshDrawList<TMobileBasePassDrawingPolicy<FUniformLightMapPolicy, 0> >::DrawElement<(InstancedStereoPolicy)2>(FRHICommandList&, FViewInfo const&, FMeshDrawingPolicy::ContextDataType, FDrawingPolicyRenderState&, TStaticMeshDrawList<TMobileBasePassDrawingPolicy<FUniformLightMapPolicy, 0> >::FElement const&, unsigned long long, TStaticMeshDrawList<TMobileBasePassDrawingPolicy<FUniformLightMapPolicy, 0> >::FDrawingPolicyLink*, bool&)
    

    参数:

    • --gui 可视化
    • 其他参数直接传入到simpleperf report

    NOTE ATTRIBUTES

    Created Date: 2018-08-03 07:12:45
    Last Evernote Update Date: 2019-04-27 05:04:01

    相关文章

      网友评论

        本文标题:simpleperf源码阅读-0.Python

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