SlideShare a Scribd company logo
1 of 44
Download to read offline
C/C++ 调试、
        跟踪及性能分析工具综述




             C/C++ 调试、
                     跟踪及性能分析工具综述

                                    清无 (王晓哲)1



                                       2012-07-30




     1                                                        .   .   .   . . . .   . . . . . . . .           .    .        .    .    .
         qingwu@taobao.com, chaoslawful@gmail.com, @chaoslawful ..
                                                     .. .. .. .. .. .. ..           .. .. .. .. .. .. .. ..   ..       ..   ..   ..
C/C++ 调试、
        跟踪及性能分析工具综述




Outline

   1 基本概念

   2 C/C++ 调试工具

   3 C/C++ 性能分析工具

   4 C/C++ 跟踪工具

   5 其他实用技巧

   6 参考资料


                           .    .    .      . . . . . . . . . . . .               .    .        .    .    .
                      ..   ..   ..       .. .. .. .. .. .. .. .. .. .. .. .. ..   ..       ..   ..   ..
C/C++ 调试、
        跟踪及性能分析工具综述
 基本概念




                      基本概念



                                  .    .    .      . . . . . . . . . . . .               .    .        .    .    .
                             ..   ..   ..       .. .. .. .. .. .. .. .. .. .. .. .. ..   ..       ..   ..   ..
C/C++ 调试、
        跟踪及性能分析工具综述
 基本概念




定义


        调试 (debugging) - 寻找程序运行时行为异常的原因并解决
        的过程;
        性能分析 (profiling) - 分析程序运行时行为以提供对关键指
        标 (执行速度/资源占用/…) 的统计性结论;
        跟踪 (tracing) - 在时域上记录程序运行行为,
                                   为后续调试或
        性能分析提供第一手数据;
   所有的调试、      性能分析和跟踪工具都依赖于某种 逻辑注入
   (instrumentation) 机制,
                       注入可以是静态的 (编译期发生) 也可以
   是动态的 (运行期发生)。


                                   .    .    .      . . . . . . . . . . . .               .    .        .    .    .
                              ..   ..   ..       .. .. .. .. .. .. .. .. .. .. .. .. ..   ..       ..   ..   ..
C/C++ 调试、
        跟踪及性能分析工具综述
 C/C++ 调试工具




              C/C++ 调试工具



                           .    .    .      . . . . . . . . . . . .               .    .        .    .    .
                      ..   ..   ..       .. .. .. .. .. .. .. .. .. .. .. .. ..   ..       ..   ..   ..
C/C++ 调试、
        跟踪及性能分析工具综述
 C/C++ 调试工具




调试工具的实现原理

        核心功能:断点
              硬件断点
                 x86 体系下使用调试寄存器 DR0˜7
                 DR0˜3 - 4 个独立的硬件断点线性地址
                 DR6(DR4) - 断点触发状态
                 DR7(DR5) - 断点控制
              软件断点
                 x86 体系下使用 INT3 (0xcc) 机器指令
                 自行抛出 SIGTRAP 信号模拟可移植软件断点
              虚拟机解释器
                 逐条解释而不是直接批量执行目标程序代码

        Linux 平台上用户态调试的基础设施
              ptrace 系统调用

                                          .    .    .      . . . . . . . . . . . .               .    .        .    .    .
                                     ..   ..   ..       .. .. .. .. .. .. .. .. .. .. .. .. ..   ..       ..   ..   ..
C/C++ 调试、
        跟踪及性能分析工具综述
 C/C++ 调试工具




GDB - 通用调试器
   基于 ptrace 系统调用实现
   同时支持硬件和软件断点 - hbreak/break
   7.x 以上版本支持         向调试 功能
        通过在执行每条机器指令前保存其修改的寄存器/内存地址内容实
        现,
         开销很大但很有用

   例子:
        独立调试 - gdb --args <exec> [<arg1> [...]]
        分析 coredump - gdb <exec> <core>
        调试运行中进程 - gdb <exec> <pid>

   网上资源很多,
         可自行搜索学习:-)
                                               .    .    .      . . . . . . . . . . . .               .    .        .    .    .
                                          ..   ..   ..       .. .. .. .. .. .. .. .. .. .. .. .. ..   ..       ..   ..   ..
C/C++ 调试、
        跟踪及性能分析工具综述
 C/C++ 调试工具




Valgrind - 动态调试分析工具框架
   本质上是一个指令级解释器/虚拟机框架, 不可能 用来调试运
                     故
   行中进程:-(
   有用的调试用插件:
        memcheck
              内存相关错误检查器
        massif
              运行时堆栈使用情况分析器
        helgrind
              线程错误检查器
        DRD
              另一类线程错误检查器
        sgcheck (原 ptrcheck)
              栈/全局数组越界错误检查器
                                    .    .    .      . . . . . . . . . . . .               .    .        .    .    .
                               ..   ..   ..       .. .. .. .. .. .. .. .. .. .. .. .. ..   ..       ..   ..   ..
C/C++ 调试、
        跟踪及性能分析工具综述
 C/C++ 调试工具




Valgrind - memcheck


   检查启动进程及其派生的所有进程中的内存错误:

        valgrind --tool=memcheck --leak-check=full
        --leak-resolution=high --track-origins=yes
        --trace-children=yes --log-file=result.log <exec>

   查看 memcheck 插件特有选项的帮助:

        valgrind --tool=memcheck --help




                                               .    .    .      . . . . . . . . . . . .               .    .        .    .    .
                                          ..   ..   ..       .. .. .. .. .. .. .. .. .. .. .. .. ..   ..       ..   ..   ..
C/C++ 调试、
        跟踪及性能分析工具综述
 C/C++ 调试工具




Valgrind - massif


   统计进程整个生命期内的堆栈使用情况:

        valgrind --tool=massif --stacks=yes <exec>
        ms_print massif.*

   ms_print 输出统计图中:

        : 表示普通采样快照,
                  其只采集对应时刻的堆栈使用量
        @ 表示详细采样快照,
                  除堆栈使用量外其还会采集调用栈
        # 表示整个生命期中的使用量峰值



                                               .    .    .      . . . . . . . . . . . .               .    .        .    .    .
                                          ..   ..   ..       .. .. .. .. .. .. .. .. .. .. .. .. ..   ..       ..   ..   ..
C/C++ 调试、
        跟踪及性能分析工具综述
 C/C++ 调试工具




Valgrind - helgrind/DRD/sgcheck
   helgrind 例子:
        检查 POSIX 线程 API 误用 / 锁顺序不一致 / 竟态条件等错误:
              valgrind --tool=helgrind <exec>

   DRD 例子:
        检查 POSIX 线程 API 误用 / 竟态条件 / 锁竞争错误,
                                         并跟踪所有
        mutex 操作:
              valgrind --tool=drd --trace-mutex=yes <exec>

   sgcheck 例子:
        检查栈/全局数组访问越界错误:
              valgrind --tool=exp-sgcheck <exec>
              Valgrind 版本较低时应将 exp-sgcheck 换为 exp-ptrcheck
                                                     .    .    .      . . . . . . . . . . . .               .    .        .    .    .
                                                ..   ..   ..       .. .. .. .. .. .. .. .. .. .. .. .. ..   ..       ..   ..   ..
C/C++ 调试、
        跟踪及性能分析工具综述
 C/C++ 调试工具




Valgrind - 静态注入机制

   工具并非万能,     部分场景下需要开发人员给予提示信息帮助检查,
   Valgrind 提供若干 Client Request 宏,
                                 能够在目标程序中静态注入
   代码,   以便在运行时向 Valgrind 及其插件报告有用信息

   Client Request 静态注入的代码开销很小 (每个注入点 20 余条整
   数操作指令),      通常不影响目标程序性能
   更多对 Client Request 静态注入宏的说明请参考:

        Valgrind User Manual 中标题含有 Client Request 字样的章节
        头文件 valgrind/{valgrind.h, memcheck.h, callgrind.h,
        helgrind.h, drd.h} 中的相关注释
        演示代码: https://github.com/chaoslawful/TIP/tree/master/tip1-
        examples/vg-callreq
                                                  .    .    .      . . . . . . . . . . . .               .    .        .    .    .
                                             ..   ..   ..       .. .. .. .. .. .. .. .. .. .. .. .. ..   ..       ..   ..   ..
C/C++ 调试、
        跟踪及性能分析工具综述
 C/C++ 调试工具




C/C++ 程序调试原则
   发布编译时要产生调试符号 (-g/-g3), 线上部署时要保证原始包
   和 debuginfo 包都存在且版本相符,
                        不要自找麻烦!
   通常来说所有程序都应通过 Valgrind 的 memcheck/sgcheck 检
   查,
    以消除绝大部分内存访问问题;
   多线程程序应通过 Valgrind 的 helgrind/DRD 检查,
                                      以消除一般
   的竟态错误;
   Valgrind massif 插件可用来排查非预期的堆分配操作源头;
   自定义内存分配器/线程同步机制时应主动添加 Valgrind Client
   Request 宏,
            以帮助检查问题;
   GDB 可用来手工排查代码中的逻辑错误;但多进程/多线程程序
   用 GDB 调试非常麻烦,
               多数情况下用跟踪工具跟踪此类程序的
   行为寻找问题来源要更方便、 快捷;                 .    .    .      . . . . . . . . . . . .               .    .        .    .    .
                                ..   ..   ..       .. .. .. .. .. .. .. .. .. .. .. .. ..   ..       ..   ..   ..
C/C++ 调试、
        跟踪及性能分析工具综述
 C/C++ 性能分析工具




          C/C++ 性能分析工具



                           .    .    .      . . . . . . . . . . . .               .    .        .    .    .
                      ..   ..   ..       .. .. .. .. .. .. .. .. .. .. .. .. ..   ..       ..   ..   ..
C/C++ 调试、
        跟踪及性能分析工具综述
 C/C++ 性能分析工具




性能分析工具的实现原理

   基于事件 (Event) 的性能分析

       为特定事件增加回调,
                记录事件发生次数

   基于采样 (Sampling) 的性能分析

       构造以一定周期重复的触发器用来采样
       在触发器中记录当前代码位置及调用栈
       根据记录数据生成统计性报表结果


   注意: 性能分析工具通常 无法 揭示 睡眠 (主动睡眠、     …)
                                 锁等待、
   或 I/O  (socket 访问、   …)  但这 2 个耗时往往
                    磁盘访问、 耗时,
   是实际应用程序 主要的视在性能瓶颈 !故需要根据具体应用场
   景决定是否使用性能分析工具。               .    .    .      . . . . . . . . . . . .               .    .        .    .    .
                           ..   ..   ..       .. .. .. .. .. .. .. .. .. .. .. .. ..   ..       ..   ..   ..
C/C++ 调试、
        跟踪及性能分析工具综述
 C/C++ 性能分析工具




基于事件的性能分析工具 - gcov
   本来是 gcc 工具链中的覆盖率测试工具,
                       但可以用来当作用户代
   码的行计数性能分析工具
   需要静态注入目标程序,    用以下 gcc 选项之一编译即可,
                                  编译成功
   后会生成 *.gcno 数据文件:
       --coverage
       -fprofile-arcs -ftest-coverage

   经过静态注入的目标程序运行 正常结束 后,     会在启动目录中生
                通过 gcov 工具即可用这些数据产生行计数
   成 *.gcda 数据文件,
   分析结果
   例子:
       gcc --coverage x.c -ox
       gcov x.c # 生成 x.c.gcov
                                             .    .    .      . . . . . . . . . . . .               .    .        .    .    .
                                        ..   ..   ..       .. .. .. .. .. .. .. .. .. .. .. .. ..   ..       ..   ..   ..
C/C++ 调试、
        跟踪及性能分析工具综述
 C/C++ 性能分析工具




基于事件的性能分析工具 - gcov
   gcov 背后发生的事:

   -ftest-coverage 让编译器生成 *.gcno 文件,
                                   该文件含有重建
   基本块依赖图和将源代码关联至基本块的必要信息,           以便 gcov 工
   具使用;

   -fprofile-arcs 让编译器静态注入对每个源代码行关联的计数
   器进行操作的代码,       并在链接阶段链入静态库 libgcov.a ,
                                         其中
   包含在程序正常结束时生成 *.gcda 文件的逻辑;
   参考:

       gcc -S x.c -o x1.s
       gcc -S --coverage x.c -o x2.s
       vimdiff *.s
                                            .    .    .      . . . . . . . . . . . .               .    .        .    .    .
                                       ..   ..   ..       .. .. .. .. .. .. .. .. .. .. .. .. ..   ..       ..   ..   ..
C/C++ 调试、
        跟踪及性能分析工具综述
 C/C++ 性能分析工具




基于事件的性能分析工具 - gcov
   lcov
          一个 gcov 可视化报表前端
          可生成 HTML 格式的漂亮报表

   例子:
          假设源代码位于 app/x.c 处
          cd app
          gcc --coverage x.c -ox
          ./x
          lcov -d . -c -o x.info
          genhtml -o report x.info
          最终报表入口位于 app/report/index.html 处
                                           .    .    .      . . . . . . . . . . . .               .    .        .    .    .
                                      ..   ..   ..       .. .. .. .. .. .. .. .. .. .. .. .. ..   ..       ..   ..   ..
C/C++ 调试、
        跟踪及性能分析工具综述
 C/C++ 性能分析工具




基于事件的性能分析工具 - Valgrind/callgrind
   Valgrind 的 callgrind 插件

                  有很好用的 GUI 前端 kcachegrind
       一个指令级性能分析工具,
       支持 CPU 缓存和分支跳转概率分析,
                         并能将结果标注在源代码上
       方便查看
               请在编译时用 -g 选项启用调试符号
       若需要源代码标注,

   例子:

       gcc -g x.c -ox
       valgrind --tool=callgrind --dump-instr=yes
       --cache-sim=yes --branch-sim=yes ./x
       kcachegrind callgrind.*
                                              .    .    .      . . . . . . . . . . . .               .    .        .    .    .
                                         ..   ..   ..       .. .. .. .. .. .. .. .. .. .. .. .. ..   ..       ..   ..   ..
C/C++ 调试、
        跟踪及性能分析工具综述
 C/C++ 性能分析工具




基于采样的性能分析工具 - gprof
   基于定时器的指令寄存器 (IP) 采样 + 函数调用事件计数
   Linux 下使用 setitimer(ITIMER_PROF, ...) 设置定时器
           取决于内核设定的 HZ 参数
   采样周期尽可能快,
   支持扁平化报表、
          调用图报表和标注源代码
   编译和链接时都要增加选项 -pg
           请在编译时用 -g 选项启用调试符号
   若需要源代码标注,
   例子:
       gcc -g -pg x.c -ox
       ./x # 生成 gmon.out
       gprof ./x # 查看扁平化/调用图报表
       gprof -A ./x # 查看标注源代码          .    .    .      . . . . . . . . . . . .               .    .        .    .    .
                                  ..   ..   ..       .. .. .. .. .. .. .. .. .. .. .. .. ..   ..       ..   ..   ..
C/C++ 调试、
        跟踪及性能分析工具综述
 C/C++ 性能分析工具




基于采样的性能分析工具 - gprof
   gprof 背后发生的事:
   gprof 本应使用 profil 系统调用进行指令寄存器采样, Linux
                                  但
   并未真正实现该系统调用, gprof 退而使用系统调用
                      故
   setitimer
   -pg 让编译器在每个函数入口处静态注入对 mcount() 函数的调
   用, 该函数会收集调用栈信息并更新函数调用计数
       gcc -S x.c -ox1.s
       gcc -S -pg x.c -ox2.s
       vimdiff *.s

   -pg 让链接器链入 gcrt1.o 而不是通常情况下的 crt1.o ,
                                       前者
   在程序启动时会初始化采样定时器及相关资源:
       gcc -v x.c 2>&1 | grep crt
       gcc -v -pg x.c 2>&1 | grep crt        .    .    .      . . . . . . . . . . . .               .    .        .    .    .
                                        ..   ..   ..       .. .. .. .. .. .. .. .. .. .. .. .. ..   ..       ..   ..   ..
C/C++ 调试、
        跟踪及性能分析工具综述
 C/C++ 性能分析工具




基于采样的性能分析工具 - google-perftools/CPU Profiler
   基于定时器的调用栈采样机制
          Linux 下同 gprof 一样使用 setitimer(ITIMER_PROF, ...)
          通过环境变量 PROFILEFREQUENCY 可设置采样频率

   例子:
          直接链接使用方式:
                                                2
               gcc -g x.c -ox -lprofiler
               CPUPROFILE=/tmp/xxx ./x
          预加载使用方式:
               LD_PRELOAD=/usr/local/lib/libprofiler.so
               CPUPROFILE=/tmp/xxx ./x
          显示分析报告:
               pprof --text ./x /tmp/xxx
      2
       注意:  用户代码中应存在对 profiler 共享库符号的引用,        否则链接时会忽略
                                       .  . . . . . . . . . . . . . .               .    .        .    .    .
   profiler 动态库!                     .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..       ..   ..   ..
C/C++ 调试、
        跟踪及性能分析工具综述
 C/C++ 性能分析工具




基于采样的性能分析工具 - oprofile
   支持基于定时器 / 中断 / PMC / tracepoint 的采样
       PMC = Performance Counter

   可进行整个系统级的性能分析
       在高于 2.6.26 版本的内核中,
                        推荐直接用 perf 工具替代 oprofile

   例子:
       sudo opcontrol --init # 加载 oprofile 内核模块
       sudo opcontrol -s
       ./x
       sudo opcontrol -h
       sudo opreport # 显示报表
       sudo opannotate -s # 显示标注源代码
                                           .    .    .      . . . . . . . . . . . .               .    .        .    .    .
                                      ..   ..   ..       .. .. .. .. .. .. .. .. .. .. .. .. ..   ..       ..   ..   ..
C/C++ 调试、
        跟踪及性能分析工具综述
 C/C++ 性能分析工具




基于采样的性能分析工具 - perf

   是随 Linux 内核发布的访问 PMC 的前端工具,
                             在高于 2.6.26 版
   本的内核中可用

   支持基于 PMC / tracepoint 的采样

   可进行整个系统级的性能分析,
                原始采样事件数据可以输出作其
   他分析之用
   例子:

       sudo perf record -a -g -- ./x
       sudo perf report # 显示报表
       sudo perf annotate # 显示标注源代码

                                            .    .    .      . . . . . . . . . . . .               .    .        .    .    .
                                       ..   ..   ..       .. .. .. .. .. .. .. .. .. .. .. .. ..   ..       ..   ..   ..
C/C++ 调试、
        跟踪及性能分析工具综述
 C/C++ 性能分析工具




C/C++ 程序性能分析原则

   在进行性能分析前,         首先确定目标程序运行时特性, time 命令输
   出的 sys/usr/wall time 可以帮助我们简单地进行判断:
                       目标程序是 CPU 密集型应用
       sys+usr ~ wall 时,
            sys >> usr - 尝试减少系统调用次数,
                                   或使用系统级性能分析工具
            sys << usr - 使用用户态性能分析工具

       sys+usr << wall 时,
                        目标程序并未执行太多代码,不要考虑使用
       通用性能分析工具,       此时用户态跟踪工具往往能更好地帮助你

   进行性能分析并解析报告结果时应层次化进行,先从最外层入手,
   逐层深入寻找瓶颈,
           避免无目的地深入底层细节

   性能瓶颈要逐个解决,
            首先处理已知的最大瓶颈,
                       解决完毕后再重
   新进行性能分析并处理下一个最大的瓶颈
                                      .    .    .      . . . . . . . . . . . .               .    .        .    .    .
                                 ..   ..   ..       .. .. .. .. .. .. .. .. .. .. .. .. ..   ..       ..   ..   ..
C/C++ 调试、
        跟踪及性能分析工具综述
 C/C++ 跟踪工具




              C/C++ 跟踪工具



                           .    .    .      . . . . . . . . . . . .               .    .        .    .    .
                      ..   ..   ..       .. .. .. .. .. .. .. .. .. .. .. .. ..   ..       ..   ..   ..
C/C++ 调试、
        跟踪及性能分析工具综述
 C/C++ 跟踪工具




跟踪工具的实现原理
   解耦事件的记录和导出操作:环形缓冲区 (ring buffer)
   用户态跟踪
        侵入式: 修改用户代码添加对跟踪 API 的调用,
                                需要重新编译
        非侵入式:
              ptrace 系统调用 (man ptrace)
              GNU 动态链接器的 LD_AUDIT 支持 (man rtld-audit)
              utrace 内核补丁 (>=3.5 版本的内核内置了 uprobes 机制替代
              utrace 补丁)

   内核态跟踪
        动态机制: kprobes / jprobes / kretprobes,
                                            通过 trap 或 short-jmp
        指令实现
        静态机制
              tracepoints: 实质为手工插入的条件跳转
              ftrace (>=2.6.26 版本的内核): 利用 gcc 注入 . mcount .函数调用
                                               . .  . . . . . . . . . . .                                        .    .        .    .    .
                                                   ..   ..   ..   .. .. .. ..   .. .. .. ..   .. .. .. ..   ..   ..       ..   ..   ..
C/C++ 调试、
        跟踪及性能分析工具综述
 C/C++ 跟踪工具




基于 ptrace 的跟踪工具 - strace

   跟踪用户程序发起的系统调用
   支持已运行进程的跟踪

        非 root 用户要注意内核新增的 ptrace 安全补丁,
                                     其会禁止无直接
        继承关系的进程间进行 ptrace 跟踪!
        补丁控制开关:/proc/sys/kernel/yama/ptrace_scope

   可很好地用于多线程/多进程程序跟踪
   例子:

        strace -f -i -tt -T -v -s1024 -C -o trace.out ./x
        参数详解请参考 man strace
                                               .    .    .      . . . . . . . . . . . .               .    .        .    .    .
                                          ..   ..   ..       .. .. .. .. .. .. .. .. .. .. .. .. ..   ..       ..   ..   ..
C/C++ 调试、
        跟踪及性能分析工具综述
 C/C++ 跟踪工具




基于 ptrace 的跟踪工具 - ltrace

   跟踪用户程序发起的动态库函数调用

   可跟踪通过 glibc 包装层发起的系统调用,    但解析系统调用参数需
                                不如 strace 方便
   要自行修改 /etc/ltrace.conf 增加类型描述,

                    也不支持通过 dlopen
   不支持动态库到动态库调用的函数跟踪,
   自行打开的动态库函数调用跟踪

   无法用于多线程程序的跟踪!
   例子:

        ltrace -C -f -i -n4 -s1024 -S -tt -T ./x
        参数详解请参考 man ltrace

                                               .    .    .      . . . . . . . . . . . .               .    .        .    .    .
                                          ..   ..   ..       .. .. .. .. .. .. .. .. .. .. .. .. ..   ..       ..   ..   ..
C/C++ 调试、
        跟踪及性能分析工具综述
 C/C++ 跟踪工具




基于 ptrace 的跟踪工具缺陷

   跟踪开销极大 ,  每个跟踪点至少需要 2 次上下文切换 + 2 个系
   统调用 + 1 次信号传递开销,跟踪点较多时效率极低

   无法跟踪 init(1) 进程

   多个跟踪工具无法跟踪同一个目标进程
   ptrace 系统调用可能 影响被跟踪进程的运行行为 :

        子进程被 ptrace 跟踪并退出时,    原有的父进程不会得到 SIGCHLD
        信号通知 (见 man ptrace 说明)
        ptrace 极大的跟踪开销会影响真正并行运行的线程数量。对并发
        数或时序敏感的竟态条件可能在跟踪后消失,    使其变成海森堡问题
        (Heisenbug)

                                       .    .    .      . . . . . . . . . . . .               .    .        .    .    .
                                  ..   ..   ..       .. .. .. .. .. .. .. .. .. .. .. .. ..   ..       ..   ..   ..
C/C++ 调试、
        跟踪及性能分析工具综述
 C/C++ 跟踪工具




基于 LD_AUDIT 机制的跟踪工具 - latrace

   跟踪用户程序发起的动态库函数调用

   无法跟踪 已经运行的进程

   LD_AUDIT 机制用运行在目标进程上下文内的回调函数替代了
   ptrace 机制所用的信号通信,
                   从而使跟踪开销大幅度降低

   可以很好地跟踪多线程程序
   例子:

        latrace -SAD -o trace.out ./x
        参数含义请参考 man latrace


                                             .    .    .      . . . . . . . . . . . .               .    .        .    .    .
                                        ..   ..   ..       .. .. .. .. .. .. .. .. .. .. .. .. ..   ..       ..   ..   ..
C/C++ 调试、
        跟踪及性能分析工具综述
 C/C++ 跟踪工具




基于 ftrace 框架的跟踪工具 - trace-cmd


   >= 2.6.26 版本的内核可用, ftrace 框架的命令行前端
                    是

             无法跟踪用户态事件 (上下文切换、
   系统级内核态跟踪工具,               调度
   等事件除外,
        因它们本质上是内核态事件,
                    不过同样无法获取这些
   事件发生时用户态程序的现场数据)
   例子:

        sudo trace-cmd record -e all -p function_graph -F ./x
        trace-cmd report




                                               .    .    .      . . . . . . . . . . . .               .    .        .    .    .
                                          ..   ..   ..       .. .. .. .. .. .. .. .. .. .. .. .. ..   ..       ..   ..   ..
C/C++ 调试、
        跟踪及性能分析工具综述
 C/C++ 跟踪工具




基于 ftrace 框架的跟踪工具 - trace-cmd



   kernelshark

        是 trace-cmd 跟踪数据的 GUI 查看器,
                                 方便对事件的可视化筛选查
        看
        例子:
              sudo trace-cmd record -e all -p function_graph -F ./x
              kernelshark




                                                     .    .    .      . . . . . . . . . . . .               .    .        .    .    .
                                                ..   ..   ..       .. .. .. .. .. .. .. .. .. .. .. .. ..   ..       ..   ..   ..
C/C++ 调试、
        跟踪及性能分析工具综述
 C/C++ 跟踪工具




复合跟踪工具 - SystemTap

   Solaris 长期以来都有很牛的跟踪工具 DTrace,但由于许可证问题
   无法引入 Linux, 于是 Linux 社区自行开发了功能媲美 DTrace 的
   SystemTap

   是一个脚本化的跟踪框架,               能整合利用 Linux kernel 现有的
   kprobes / tracepoints / uprobes(utrace) 等跟踪机制,并在源码级
   兼容 DTrace 静态探针

   可进行内核 / 用户态联合跟踪,        用户态程序的跟踪需要带有
   utrace 补丁的内核 (或 >=3.5 版本的内核,       因其内置了 uprobes
   功能);   RedHat 系发行版 (RHEL / CentOS / Fedora) 内核都默认
   打上了 utrace 补丁。

                                          .    .    .      . . . . . . . . . . . .               .    .        .    .    .
                                     ..   ..   ..       .. .. .. .. .. .. .. .. .. .. .. .. ..   ..       ..   ..   ..
C/C++ 调试、
        跟踪及性能分析工具综述
 C/C++ 跟踪工具




复合跟踪工具 - SystemTap



   系统调用跟踪示例:
  §                                                                                                                         ¤
      // syscalls.stp
      probe syscall.* {
         println( thread_indent(4), "−>", probefunc() )
      }
      probe syscall.*.return {
         println( thread_indent(−4), "<−", probefunc() )
      }
  ¦                                                                                                                         ¥
   调用:stap -c ./x syscalls.stp




                                                                .    .    .      . . . . . . . . . . . .               .    .        .    .    .
                                                           ..   ..   ..       .. .. .. .. .. .. .. .. .. .. .. .. ..   ..       ..   ..   ..
C/C++ 调试、
        跟踪及性能分析工具综述
 C/C++ 跟踪工具




复合跟踪工具 - SystemTap
   静态探针示例:
  §                                                                                                                         ¤
      // x.c
      #include <stdio.h>
      #include <sys/sdt.h>
      void f(int a)
      {
         int b = 20;
         DTRACE_PROBE2(f, probe1, a, b);
         printf("a=%d, b=%dn", a, b);
         DTRACE_PROBE2(f, probe2, a, b);
         printf("a=%d, b=%dn", a, b);
      }
      int main()
      {
         f(10);
      }
  ¦                                                                                                                         ¥
   编译:gcc -g x.c -ox
  §                                                                                                                         ¤
      // u.stp
      probe process("x").mark("*") {
         println("*** ", probefunc(), ": ", $arg1, ", ", $arg2);
      }
  ¦                                                                                                                         ¥
   调用:stap -c ./x u.stp                                         .    .    .      . . . . . . . . . . . .               .    .        .    .    .
                                                           ..   ..   ..       .. .. .. .. .. .. .. .. .. .. .. .. ..   ..       ..   ..   ..
C/C++ 调试、
        跟踪及性能分析工具综述
 C/C++ 跟踪工具




复合跟踪工具 - LTTng 2.0
   是 LTTng 0.9.x 的重写,
                    不再需要给内核打补丁, SystemTap 比
                              同
   起来跟踪开销更低一些
   可进行内核 / 用户态联合跟踪,
                  用户态跟踪是侵入式的,       需要手
   工给用户程序增加静态跟踪点, 尚不兼容 SystemTap / DTrace 的
   静态探针
   例子:
        sudo lttng create sess1
        sudo lttng enable-event -a -k -u
        sudo lttng start
        ./x
        sudo lttng stop
        babeltrace ~/lttng/sess1*
                                                .    .    .      . . . . . . . . . . . .               .    .        .    .    .
                                           ..   ..   ..       .. .. .. .. .. .. .. .. .. .. .. .. ..   ..       ..   ..   ..
C/C++ 调试、
        跟踪及性能分析工具综述
 C/C++ 跟踪工具




复合跟踪工具 - DTrace

   源于 Sun Solaris, 已经移植到了 MacOS / FreeBSD / Oracle
   Unbreakable Linux 上

   是一个脚本化的跟踪框架,
              跟踪开销很低

   可进行内核 / 用户态联合跟踪,        用户态跟踪可以是非侵入式 (通
   过 pid provider) 或侵入式的 (通过手工插入静态跟踪点)

   支持大量通用语言和应用的应用态跟踪:                      Java(Sun) / PHP(Zend)
   / Javascript(Firefox) / CPython / CRuby / MySQL / PostgreSQL
   / Erlang (DTrace fork)

   例子:可参考 http://dtracehol.com

                                                 .    .    .      . . . . . . . . . . . .               .    .        .    .    .
                                            ..   ..   ..       .. .. .. .. .. .. .. .. .. .. .. .. ..   ..       ..   ..   ..
C/C++ 调试、
        跟踪及性能分析工具综述
 C/C++ 跟踪工具




C/C++ 程序跟踪原则

     告! 跟踪并分析程序行为需要牵扯大量精力, 同时可能需要对
   Linux 内核有一定了解。实际跟踪之前,
                       先好好了解目标程序如何
   工作,   确定跟踪的重点再动手!

            大部分场合下 strace / ltrace 就能满足需要
   仅进行用户态跟踪时,
   了

   需要进行内核态 / 用户态混合跟踪时, RedHat 系或其他内核
                            在
   有 utrace 补丁的发行版中可用 SystemTap; MacOS / FreeBSD
                                在
   下可用 DTrace

   若能修改代码插入跟踪调用,
               且对跟踪开销非常敏感时,
                          可以选择
   LTTng 2.0

                                      .    .    .      . . . . . . . . . . . .               .    .        .    .    .
                                 ..   ..   ..       .. .. .. .. .. .. .. .. .. .. .. .. ..   ..       ..   ..   ..
C/C++ 调试、
        跟踪及性能分析工具综述
 其他实用技巧




其他实用技巧

   gcc -finstrument-functions - 在所有函数的入口和出口静态
   注入回调函数调用,       可用来嵌入特定的跟踪逻辑

       进入函数后调用 __cyg_profile_func_enter 函数
       退出函数前调用 __cyg_profile_func_exit 函数

   使用 LD_PRELOAD 预加载崩溃信号处理器,
                           可对生产环境中的
   程序崩溃进行持续监控

                      以便在 gprof / gcov
   为持续运行的服务程序增加退出信号处理器,
   时正常获取分析结果

   以上技巧的例子在这里:https://github.com/chaoslawful/TIP
                                        .    .    .      . . . . . . . . . . . .               .    .        .    .    .
                                   ..   ..   ..       .. .. .. .. .. .. .. .. .. .. .. .. ..   ..       ..   ..   ..
C/C++ 调试、
        跟踪及性能分析工具综述
 参考资料




参考资料
   综述
        Linux Instrumentation
        http://lwn.net/Kernel/Index/

   跟踪工具
        玩转 utrace
        utrace Documentation
        Introducing utrace
        Playing with ptrace, Part I
        Playing with ptrace, Part II
        SystemTap / DTrace / LTTng / perf Comparison
        ftrace 简介
        Solaris Dynamic Tracing Guide              .    .    .      . . . . . . . . . . . .               .    .        .    .    .
                                              ..   ..   ..       .. .. .. .. .. .. .. .. .. .. .. .. ..   ..       ..   ..   ..
C/C++ 调试、
        跟踪及性能分析工具综述
 参考资料




参考资料
   跟踪工具
        DTrace for Linux
        Observing and Optimizing your Application with DTrace
        SystemTap Beginner’s Guide
        SystemTap Language Reference
        SystemTap Tapset Reference
        LTTng recommended bundles
        LTTng Ubuntu daily PPA
        An introduction to KProbes
        使用 KProbes 调试内核
        Tracing: no shortage of options
        Uprobes: 11th time is the charm?
                                                      .    .    .      . . . . . . . . . . . .               .    .        .    .    .
                                                 ..   ..   ..       .. .. .. .. .. .. .. .. .. .. .. .. ..   ..       ..   ..   ..
C/C++ 调试、
        跟踪及性能分析工具综述
 参考资料




参考资料
   跟踪工具
        Ptrace, Utrace, Uprobes: Lightweight, Dynamic Tracing for User
        Apps
        LTTng Tracing Book

   性能分析与调试
        google-perftools Profiling heap usage
        google-perftools CPU Profiler
        Valgrind User Manual
        OProfile Manual
        Debugging with GDB
        GDB Internals Manual
        Implementation of GProf
                                                       .    .    .      . . . . . . . . . . . .               .    .        .    .    .
        Gcov Data Files                           ..   ..   ..       .. .. .. .. .. .. .. .. .. .. .. .. ..   ..       ..   ..   ..
C/C++ 调试、
        跟踪及性能分析工具综述




    “The important thing is not to stop questioning; never lose
                a holy curiosity.” — Albert Einstein


                That’s all, thanks!


                                                .    .    .      . . . . . . . . . . . .               .    .        .    .    .
                                           ..   ..   ..       .. .. .. .. .. .. .. .. .. .. .. .. ..   ..       ..   ..   ..

More Related Content

What's hot

RISC-Vのセキュリティ技術(TEE, Root of Trust, Remote Attestation)
RISC-Vのセキュリティ技術(TEE, Root of Trust, Remote Attestation)RISC-Vのセキュリティ技術(TEE, Root of Trust, Remote Attestation)
RISC-Vのセキュリティ技術(TEE, Root of Trust, Remote Attestation)Kuniyasu Suzaki
 
Java でつくる 低レイテンシ実装の技巧
Java でつくる低レイテンシ実装の技巧Java でつくる低レイテンシ実装の技巧
Java でつくる 低レイテンシ実装の技巧 Ryosuke Yamazaki
 
FPGAを用いたEdge AIの現状
FPGAを用いたEdge AIの現状FPGAを用いたEdge AIの現状
FPGAを用いたEdge AIの現状Yukitaka Takemura
 
20211118 dbts2021 マイクロサービスにおけるApache Geodeの効果的な使い方
20211118 dbts2021 マイクロサービスにおけるApache Geodeの効果的な使い方20211118 dbts2021 マイクロサービスにおけるApache Geodeの効果的な使い方
20211118 dbts2021 マイクロサービスにおけるApache Geodeの効果的な使い方Masaki Yamakawa
 
祝!PostgreSQLレプリケーション10周年!徹底紹介!!
祝!PostgreSQLレプリケーション10周年!徹底紹介!!祝!PostgreSQLレプリケーション10周年!徹底紹介!!
祝!PostgreSQLレプリケーション10周年!徹底紹介!!NTT DATA Technology & Innovation
 
Red Hat Enterprise Linux OpenStack Platform 7 - VM Instance HA Architecture
Red Hat Enterprise Linux OpenStack Platform 7 - VM Instance HA ArchitectureRed Hat Enterprise Linux OpenStack Platform 7 - VM Instance HA Architecture
Red Hat Enterprise Linux OpenStack Platform 7 - VM Instance HA ArchitectureEtsuji Nakai
 
V$SQLとその周辺でER図を描いてみよう!
V$SQLとその周辺でER図を描いてみよう!V$SQLとその周辺でER図を描いてみよう!
V$SQLとその周辺でER図を描いてみよう!歩 柴田
 
Oracle Gen 2 Exadata Cloud@Customer:サービス概要のご紹介 [2021年7月版]
Oracle Gen 2 Exadata Cloud@Customer:サービス概要のご紹介 [2021年7月版]Oracle Gen 2 Exadata Cloud@Customer:サービス概要のご紹介 [2021年7月版]
Oracle Gen 2 Exadata Cloud@Customer:サービス概要のご紹介 [2021年7月版]オラクルエンジニア通信
 
PostgreSQL16新機能紹介 - libpq接続ロード・バランシング(第41回PostgreSQLアンカンファレンス@オンライン 発表資料)
PostgreSQL16新機能紹介 - libpq接続ロード・バランシング(第41回PostgreSQLアンカンファレンス@オンライン 発表資料)PostgreSQL16新機能紹介 - libpq接続ロード・バランシング(第41回PostgreSQLアンカンファレンス@オンライン 発表資料)
PostgreSQL16新機能紹介 - libpq接続ロード・バランシング(第41回PostgreSQLアンカンファレンス@オンライン 発表資料)NTT DATA Technology & Innovation
 
PGOを用いたPostgreSQL on Kubernetes入門(PostgreSQL Conference Japan 2022 発表資料)
PGOを用いたPostgreSQL on Kubernetes入門(PostgreSQL Conference Japan 2022 発表資料)PGOを用いたPostgreSQL on Kubernetes入門(PostgreSQL Conference Japan 2022 発表資料)
PGOを用いたPostgreSQL on Kubernetes入門(PostgreSQL Conference Japan 2022 発表資料)NTT DATA Technology & Innovation
 
忙しい人のための Rocky Linux 入門〜Rocky LinuxはCentOSの後継者たり得るか?〜
忙しい人のための Rocky Linux 入門〜Rocky LinuxはCentOSの後継者たり得るか?〜忙しい人のための Rocky Linux 入門〜Rocky LinuxはCentOSの後継者たり得るか?〜
忙しい人のための Rocky Linux 入門〜Rocky LinuxはCentOSの後継者たり得るか?〜Masahito Zembutsu
 
デプロイメントパイプラインって何?
デプロイメントパイプラインって何?デプロイメントパイプラインって何?
デプロイメントパイプラインって何?ke-m kamekoopa
 
負荷テスト入門
負荷テスト入門負荷テスト入門
負荷テスト入門Takeo Noda
 
Oracleの実行計画を読んでみよう! #dbts2017
Oracleの実行計画を読んでみよう!  #dbts2017Oracleの実行計画を読んでみよう!  #dbts2017
Oracleの実行計画を読んでみよう! #dbts2017Ryota Watabe
 
Interrupt Affinityについて
Interrupt AffinityについてInterrupt Affinityについて
Interrupt AffinityについてTakuya ASADA
 
簡単!AWRをEXCELピボットグラフで分析しよう♪
簡単!AWRをEXCELピボットグラフで分析しよう♪簡単!AWRをEXCELピボットグラフで分析しよう♪
簡単!AWRをEXCELピボットグラフで分析しよう♪Yohei Azekatsu
 
initとプロセス再起動
initとプロセス再起動initとプロセス再起動
initとプロセス再起動Takashi Takizawa
 
アーキテクチャから理解するPostgreSQLのレプリケーション
アーキテクチャから理解するPostgreSQLのレプリケーションアーキテクチャから理解するPostgreSQLのレプリケーション
アーキテクチャから理解するPostgreSQLのレプリケーションMasahiko Sawada
 
使いこなそうGUC
使いこなそうGUC使いこなそうGUC
使いこなそうGUCAkio Ishida
 
MariaDB migration from commercial database
MariaDB migration from commercial databaseMariaDB migration from commercial database
MariaDB migration from commercial databaseGOTO Satoru
 

What's hot (20)

RISC-Vのセキュリティ技術(TEE, Root of Trust, Remote Attestation)
RISC-Vのセキュリティ技術(TEE, Root of Trust, Remote Attestation)RISC-Vのセキュリティ技術(TEE, Root of Trust, Remote Attestation)
RISC-Vのセキュリティ技術(TEE, Root of Trust, Remote Attestation)
 
Java でつくる 低レイテンシ実装の技巧
Java でつくる低レイテンシ実装の技巧Java でつくる低レイテンシ実装の技巧
Java でつくる 低レイテンシ実装の技巧
 
FPGAを用いたEdge AIの現状
FPGAを用いたEdge AIの現状FPGAを用いたEdge AIの現状
FPGAを用いたEdge AIの現状
 
20211118 dbts2021 マイクロサービスにおけるApache Geodeの効果的な使い方
20211118 dbts2021 マイクロサービスにおけるApache Geodeの効果的な使い方20211118 dbts2021 マイクロサービスにおけるApache Geodeの効果的な使い方
20211118 dbts2021 マイクロサービスにおけるApache Geodeの効果的な使い方
 
祝!PostgreSQLレプリケーション10周年!徹底紹介!!
祝!PostgreSQLレプリケーション10周年!徹底紹介!!祝!PostgreSQLレプリケーション10周年!徹底紹介!!
祝!PostgreSQLレプリケーション10周年!徹底紹介!!
 
Red Hat Enterprise Linux OpenStack Platform 7 - VM Instance HA Architecture
Red Hat Enterprise Linux OpenStack Platform 7 - VM Instance HA ArchitectureRed Hat Enterprise Linux OpenStack Platform 7 - VM Instance HA Architecture
Red Hat Enterprise Linux OpenStack Platform 7 - VM Instance HA Architecture
 
V$SQLとその周辺でER図を描いてみよう!
V$SQLとその周辺でER図を描いてみよう!V$SQLとその周辺でER図を描いてみよう!
V$SQLとその周辺でER図を描いてみよう!
 
Oracle Gen 2 Exadata Cloud@Customer:サービス概要のご紹介 [2021年7月版]
Oracle Gen 2 Exadata Cloud@Customer:サービス概要のご紹介 [2021年7月版]Oracle Gen 2 Exadata Cloud@Customer:サービス概要のご紹介 [2021年7月版]
Oracle Gen 2 Exadata Cloud@Customer:サービス概要のご紹介 [2021年7月版]
 
PostgreSQL16新機能紹介 - libpq接続ロード・バランシング(第41回PostgreSQLアンカンファレンス@オンライン 発表資料)
PostgreSQL16新機能紹介 - libpq接続ロード・バランシング(第41回PostgreSQLアンカンファレンス@オンライン 発表資料)PostgreSQL16新機能紹介 - libpq接続ロード・バランシング(第41回PostgreSQLアンカンファレンス@オンライン 発表資料)
PostgreSQL16新機能紹介 - libpq接続ロード・バランシング(第41回PostgreSQLアンカンファレンス@オンライン 発表資料)
 
PGOを用いたPostgreSQL on Kubernetes入門(PostgreSQL Conference Japan 2022 発表資料)
PGOを用いたPostgreSQL on Kubernetes入門(PostgreSQL Conference Japan 2022 発表資料)PGOを用いたPostgreSQL on Kubernetes入門(PostgreSQL Conference Japan 2022 発表資料)
PGOを用いたPostgreSQL on Kubernetes入門(PostgreSQL Conference Japan 2022 発表資料)
 
忙しい人のための Rocky Linux 入門〜Rocky LinuxはCentOSの後継者たり得るか?〜
忙しい人のための Rocky Linux 入門〜Rocky LinuxはCentOSの後継者たり得るか?〜忙しい人のための Rocky Linux 入門〜Rocky LinuxはCentOSの後継者たり得るか?〜
忙しい人のための Rocky Linux 入門〜Rocky LinuxはCentOSの後継者たり得るか?〜
 
デプロイメントパイプラインって何?
デプロイメントパイプラインって何?デプロイメントパイプラインって何?
デプロイメントパイプラインって何?
 
負荷テスト入門
負荷テスト入門負荷テスト入門
負荷テスト入門
 
Oracleの実行計画を読んでみよう! #dbts2017
Oracleの実行計画を読んでみよう!  #dbts2017Oracleの実行計画を読んでみよう!  #dbts2017
Oracleの実行計画を読んでみよう! #dbts2017
 
Interrupt Affinityについて
Interrupt AffinityについてInterrupt Affinityについて
Interrupt Affinityについて
 
簡単!AWRをEXCELピボットグラフで分析しよう♪
簡単!AWRをEXCELピボットグラフで分析しよう♪簡単!AWRをEXCELピボットグラフで分析しよう♪
簡単!AWRをEXCELピボットグラフで分析しよう♪
 
initとプロセス再起動
initとプロセス再起動initとプロセス再起動
initとプロセス再起動
 
アーキテクチャから理解するPostgreSQLのレプリケーション
アーキテクチャから理解するPostgreSQLのレプリケーションアーキテクチャから理解するPostgreSQLのレプリケーション
アーキテクチャから理解するPostgreSQLのレプリケーション
 
使いこなそうGUC
使いこなそうGUC使いこなそうGUC
使いこなそうGUC
 
MariaDB migration from commercial database
MariaDB migration from commercial databaseMariaDB migration from commercial database
MariaDB migration from commercial database
 

Similar to C/C++调试、跟踪及性能分析工具综述

Avm2虚拟机浅析与as3性能优化
Avm2虚拟机浅析与as3性能优化Avm2虚拟机浅析与as3性能优化
Avm2虚拟机浅析与as3性能优化Harvey Zhang
 
Linux 期末報告
Linux 期末報告Linux 期末報告
Linux 期末報告米米 林
 
Avm2虚拟机浅析与as3性能优化(陈士凯)
Avm2虚拟机浅析与as3性能优化(陈士凯)Avm2虚拟机浅析与as3性能优化(陈士凯)
Avm2虚拟机浅析与as3性能优化(陈士凯)FLASH开发者交流会
 
[Flash开发者交流][2010.05.30]avm2虚拟机浅析与as3性能优化(陈士凯)
[Flash开发者交流][2010.05.30]avm2虚拟机浅析与as3性能优化(陈士凯)[Flash开发者交流][2010.05.30]avm2虚拟机浅析与as3性能优化(陈士凯)
[Flash开发者交流][2010.05.30]avm2虚拟机浅析与as3性能优化(陈士凯)Shanda innovation institute
 
GCC_Porting_on_MiniSystem
GCC_Porting_on_MiniSystemGCC_Porting_on_MiniSystem
GCC_Porting_on_MiniSystemXiaojing Ma
 
Python 数据库技术第三讲
Python 数据库技术第三讲Python 数据库技术第三讲
Python 数据库技术第三讲March Liu
 
C++工程实践
C++工程实践C++工程实践
C++工程实践Shuo Chen
 
漫談 Source Control Management
漫談 Source Control Management漫談 Source Control Management
漫談 Source Control ManagementWen-Shih Chao
 
未来网络技术发展探梦 - 开篇
未来网络技术发展探梦 - 开篇未来网络技术发展探梦 - 开篇
未来网络技术发展探梦 - 开篇Yao-Wei Ou
 
Foundation of software development 2
Foundation of software development 2Foundation of software development 2
Foundation of software development 2netdbncku
 
Baidu LSP and DISQL for Log Analysis
Baidu LSP and DISQL for Log AnalysisBaidu LSP and DISQL for Log Analysis
Baidu LSP and DISQL for Log AnalysisXiaoming Chen
 
COSCUP 2014 : open source compiler 戰國時代的軍備競賽
COSCUP 2014 : open source compiler 戰國時代的軍備競賽COSCUP 2014 : open source compiler 戰國時代的軍備競賽
COSCUP 2014 : open source compiler 戰國時代的軍備競賽Kito Cheng
 
Java Crash分析(2012-05-10)
Java Crash分析(2012-05-10)Java Crash分析(2012-05-10)
Java Crash分析(2012-05-10)Kris Mok
 
常用开发工具介绍
常用开发工具介绍常用开发工具介绍
常用开发工具介绍haozes
 
Continuous Delivery Workshop with Ansible x GitLab CI (3rd)
Continuous Delivery Workshop with Ansible x GitLab CI (3rd)Continuous Delivery Workshop with Ansible x GitLab CI (3rd)
Continuous Delivery Workshop with Ansible x GitLab CI (3rd)Chu-Siang Lai
 
程式人雜誌 -- 2013年5月號
程式人雜誌 -- 2013年5月號程式人雜誌 -- 2013年5月號
程式人雜誌 -- 2013年5月號鍾誠 陳鍾誠
 
Full Stack Monitoring with Prometheus and Grafana (Updated)
Full Stack Monitoring with Prometheus and Grafana (Updated)Full Stack Monitoring with Prometheus and Grafana (Updated)
Full Stack Monitoring with Prometheus and Grafana (Updated)Jazz Yao-Tsung Wang
 
Skan it 6.0 user manual chinese
Skan it 6.0 user manual chineseSkan it 6.0 user manual chinese
Skan it 6.0 user manual chineseLenin TaMe
 

Similar to C/C++调试、跟踪及性能分析工具综述 (20)

Avm2虚拟机浅析与as3性能优化
Avm2虚拟机浅析与as3性能优化Avm2虚拟机浅析与as3性能优化
Avm2虚拟机浅析与as3性能优化
 
Linux 期末報告
Linux 期末報告Linux 期末報告
Linux 期末報告
 
Avm2虚拟机浅析与as3性能优化(陈士凯)
Avm2虚拟机浅析与as3性能优化(陈士凯)Avm2虚拟机浅析与as3性能优化(陈士凯)
Avm2虚拟机浅析与as3性能优化(陈士凯)
 
[Flash开发者交流][2010.05.30]avm2虚拟机浅析与as3性能优化(陈士凯)
[Flash开发者交流][2010.05.30]avm2虚拟机浅析与as3性能优化(陈士凯)[Flash开发者交流][2010.05.30]avm2虚拟机浅析与as3性能优化(陈士凯)
[Flash开发者交流][2010.05.30]avm2虚拟机浅析与as3性能优化(陈士凯)
 
GCC_Porting_on_MiniSystem
GCC_Porting_on_MiniSystemGCC_Porting_on_MiniSystem
GCC_Porting_on_MiniSystem
 
Python 数据库技术第三讲
Python 数据库技术第三讲Python 数据库技术第三讲
Python 数据库技术第三讲
 
C++工程实践
C++工程实践C++工程实践
C++工程实践
 
漫談 Source Control Management
漫談 Source Control Management漫談 Source Control Management
漫談 Source Control Management
 
未来网络技术发展探梦 - 开篇
未来网络技术发展探梦 - 开篇未来网络技术发展探梦 - 开篇
未来网络技术发展探梦 - 开篇
 
Foundation of software development 2
Foundation of software development 2Foundation of software development 2
Foundation of software development 2
 
Twido programming guide
Twido programming guideTwido programming guide
Twido programming guide
 
Baidu LSP and DISQL for Log Analysis
Baidu LSP and DISQL for Log AnalysisBaidu LSP and DISQL for Log Analysis
Baidu LSP and DISQL for Log Analysis
 
COSCUP 2014 : open source compiler 戰國時代的軍備競賽
COSCUP 2014 : open source compiler 戰國時代的軍備競賽COSCUP 2014 : open source compiler 戰國時代的軍備競賽
COSCUP 2014 : open source compiler 戰國時代的軍備競賽
 
Java Crash分析(2012-05-10)
Java Crash分析(2012-05-10)Java Crash分析(2012-05-10)
Java Crash分析(2012-05-10)
 
常用开发工具介绍
常用开发工具介绍常用开发工具介绍
常用开发工具介绍
 
Continuous Delivery Workshop with Ansible x GitLab CI (3rd)
Continuous Delivery Workshop with Ansible x GitLab CI (3rd)Continuous Delivery Workshop with Ansible x GitLab CI (3rd)
Continuous Delivery Workshop with Ansible x GitLab CI (3rd)
 
程式人雜誌 -- 2013年5月號
程式人雜誌 -- 2013年5月號程式人雜誌 -- 2013年5月號
程式人雜誌 -- 2013年5月號
 
LLVM introduction
LLVM introductionLLVM introduction
LLVM introduction
 
Full Stack Monitoring with Prometheus and Grafana (Updated)
Full Stack Monitoring with Prometheus and Grafana (Updated)Full Stack Monitoring with Prometheus and Grafana (Updated)
Full Stack Monitoring with Prometheus and Grafana (Updated)
 
Skan it 6.0 user manual chinese
Skan it 6.0 user manual chineseSkan it 6.0 user manual chinese
Skan it 6.0 user manual chinese
 

More from Xiaozhe Wang

Lua/LuaJIT 字节码浅析
Lua/LuaJIT 字节码浅析Lua/LuaJIT 字节码浅析
Lua/LuaJIT 字节码浅析Xiaozhe Wang
 
Erlang抽象数据结构简介
Erlang抽象数据结构简介Erlang抽象数据结构简介
Erlang抽象数据结构简介Xiaozhe Wang
 
TIP1 - Overview of C/C++ Debugging/Tracing/Profiling Tools
TIP1 - Overview of C/C++ Debugging/Tracing/Profiling ToolsTIP1 - Overview of C/C++ Debugging/Tracing/Profiling Tools
TIP1 - Overview of C/C++ Debugging/Tracing/Profiling ToolsXiaozhe Wang
 
中文编码杂谈
中文编码杂谈中文编码杂谈
中文编码杂谈Xiaozhe Wang
 
Lua/PHP哈希碰撞攻击浅析
Lua/PHP哈希碰撞攻击浅析Lua/PHP哈希碰撞攻击浅析
Lua/PHP哈希碰撞攻击浅析Xiaozhe Wang
 

More from Xiaozhe Wang (6)

Paxos 简介
Paxos 简介Paxos 简介
Paxos 简介
 
Lua/LuaJIT 字节码浅析
Lua/LuaJIT 字节码浅析Lua/LuaJIT 字节码浅析
Lua/LuaJIT 字节码浅析
 
Erlang抽象数据结构简介
Erlang抽象数据结构简介Erlang抽象数据结构简介
Erlang抽象数据结构简介
 
TIP1 - Overview of C/C++ Debugging/Tracing/Profiling Tools
TIP1 - Overview of C/C++ Debugging/Tracing/Profiling ToolsTIP1 - Overview of C/C++ Debugging/Tracing/Profiling Tools
TIP1 - Overview of C/C++ Debugging/Tracing/Profiling Tools
 
中文编码杂谈
中文编码杂谈中文编码杂谈
中文编码杂谈
 
Lua/PHP哈希碰撞攻击浅析
Lua/PHP哈希碰撞攻击浅析Lua/PHP哈希碰撞攻击浅析
Lua/PHP哈希碰撞攻击浅析
 

C/C++调试、跟踪及性能分析工具综述

  • 1. C/C++ 调试、 跟踪及性能分析工具综述 C/C++ 调试、 跟踪及性能分析工具综述 清无 (王晓哲)1 2012-07-30 1 . . . . . . . . . . . . . . . . . . . . qingwu@taobao.com, chaoslawful@gmail.com, @chaoslawful .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
  • 2. C/C++ 调试、 跟踪及性能分析工具综述 Outline 1 基本概念 2 C/C++ 调试工具 3 C/C++ 性能分析工具 4 C/C++ 跟踪工具 5 其他实用技巧 6 参考资料 . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
  • 3. C/C++ 调试、 跟踪及性能分析工具综述 基本概念 基本概念 . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
  • 4. C/C++ 调试、 跟踪及性能分析工具综述 基本概念 定义 调试 (debugging) - 寻找程序运行时行为异常的原因并解决 的过程; 性能分析 (profiling) - 分析程序运行时行为以提供对关键指 标 (执行速度/资源占用/…) 的统计性结论; 跟踪 (tracing) - 在时域上记录程序运行行为, 为后续调试或 性能分析提供第一手数据; 所有的调试、 性能分析和跟踪工具都依赖于某种 逻辑注入 (instrumentation) 机制, 注入可以是静态的 (编译期发生) 也可以 是动态的 (运行期发生)。 . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
  • 5. C/C++ 调试、 跟踪及性能分析工具综述 C/C++ 调试工具 C/C++ 调试工具 . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
  • 6. C/C++ 调试、 跟踪及性能分析工具综述 C/C++ 调试工具 调试工具的实现原理 核心功能:断点 硬件断点 x86 体系下使用调试寄存器 DR0˜7 DR0˜3 - 4 个独立的硬件断点线性地址 DR6(DR4) - 断点触发状态 DR7(DR5) - 断点控制 软件断点 x86 体系下使用 INT3 (0xcc) 机器指令 自行抛出 SIGTRAP 信号模拟可移植软件断点 虚拟机解释器 逐条解释而不是直接批量执行目标程序代码 Linux 平台上用户态调试的基础设施 ptrace 系统调用 . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
  • 7. C/C++ 调试、 跟踪及性能分析工具综述 C/C++ 调试工具 GDB - 通用调试器 基于 ptrace 系统调用实现 同时支持硬件和软件断点 - hbreak/break 7.x 以上版本支持 向调试 功能 通过在执行每条机器指令前保存其修改的寄存器/内存地址内容实 现, 开销很大但很有用 例子: 独立调试 - gdb --args <exec> [<arg1> [...]] 分析 coredump - gdb <exec> <core> 调试运行中进程 - gdb <exec> <pid> 网上资源很多, 可自行搜索学习:-) . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
  • 8. C/C++ 调试、 跟踪及性能分析工具综述 C/C++ 调试工具 Valgrind - 动态调试分析工具框架 本质上是一个指令级解释器/虚拟机框架, 不可能 用来调试运 故 行中进程:-( 有用的调试用插件: memcheck 内存相关错误检查器 massif 运行时堆栈使用情况分析器 helgrind 线程错误检查器 DRD 另一类线程错误检查器 sgcheck (原 ptrcheck) 栈/全局数组越界错误检查器 . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
  • 9. C/C++ 调试、 跟踪及性能分析工具综述 C/C++ 调试工具 Valgrind - memcheck 检查启动进程及其派生的所有进程中的内存错误: valgrind --tool=memcheck --leak-check=full --leak-resolution=high --track-origins=yes --trace-children=yes --log-file=result.log <exec> 查看 memcheck 插件特有选项的帮助: valgrind --tool=memcheck --help . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
  • 10. C/C++ 调试、 跟踪及性能分析工具综述 C/C++ 调试工具 Valgrind - massif 统计进程整个生命期内的堆栈使用情况: valgrind --tool=massif --stacks=yes <exec> ms_print massif.* ms_print 输出统计图中: : 表示普通采样快照, 其只采集对应时刻的堆栈使用量 @ 表示详细采样快照, 除堆栈使用量外其还会采集调用栈 # 表示整个生命期中的使用量峰值 . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
  • 11. C/C++ 调试、 跟踪及性能分析工具综述 C/C++ 调试工具 Valgrind - helgrind/DRD/sgcheck helgrind 例子: 检查 POSIX 线程 API 误用 / 锁顺序不一致 / 竟态条件等错误: valgrind --tool=helgrind <exec> DRD 例子: 检查 POSIX 线程 API 误用 / 竟态条件 / 锁竞争错误, 并跟踪所有 mutex 操作: valgrind --tool=drd --trace-mutex=yes <exec> sgcheck 例子: 检查栈/全局数组访问越界错误: valgrind --tool=exp-sgcheck <exec> Valgrind 版本较低时应将 exp-sgcheck 换为 exp-ptrcheck . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
  • 12. C/C++ 调试、 跟踪及性能分析工具综述 C/C++ 调试工具 Valgrind - 静态注入机制 工具并非万能, 部分场景下需要开发人员给予提示信息帮助检查, Valgrind 提供若干 Client Request 宏, 能够在目标程序中静态注入 代码, 以便在运行时向 Valgrind 及其插件报告有用信息 Client Request 静态注入的代码开销很小 (每个注入点 20 余条整 数操作指令), 通常不影响目标程序性能 更多对 Client Request 静态注入宏的说明请参考: Valgrind User Manual 中标题含有 Client Request 字样的章节 头文件 valgrind/{valgrind.h, memcheck.h, callgrind.h, helgrind.h, drd.h} 中的相关注释 演示代码: https://github.com/chaoslawful/TIP/tree/master/tip1- examples/vg-callreq . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
  • 13. C/C++ 调试、 跟踪及性能分析工具综述 C/C++ 调试工具 C/C++ 程序调试原则 发布编译时要产生调试符号 (-g/-g3), 线上部署时要保证原始包 和 debuginfo 包都存在且版本相符, 不要自找麻烦! 通常来说所有程序都应通过 Valgrind 的 memcheck/sgcheck 检 查, 以消除绝大部分内存访问问题; 多线程程序应通过 Valgrind 的 helgrind/DRD 检查, 以消除一般 的竟态错误; Valgrind massif 插件可用来排查非预期的堆分配操作源头; 自定义内存分配器/线程同步机制时应主动添加 Valgrind Client Request 宏, 以帮助检查问题; GDB 可用来手工排查代码中的逻辑错误;但多进程/多线程程序 用 GDB 调试非常麻烦, 多数情况下用跟踪工具跟踪此类程序的 行为寻找问题来源要更方便、 快捷; . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
  • 14. C/C++ 调试、 跟踪及性能分析工具综述 C/C++ 性能分析工具 C/C++ 性能分析工具 . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
  • 15. C/C++ 调试、 跟踪及性能分析工具综述 C/C++ 性能分析工具 性能分析工具的实现原理 基于事件 (Event) 的性能分析 为特定事件增加回调, 记录事件发生次数 基于采样 (Sampling) 的性能分析 构造以一定周期重复的触发器用来采样 在触发器中记录当前代码位置及调用栈 根据记录数据生成统计性报表结果 注意: 性能分析工具通常 无法 揭示 睡眠 (主动睡眠、 …) 锁等待、 或 I/O (socket 访问、 …) 但这 2 个耗时往往 磁盘访问、 耗时, 是实际应用程序 主要的视在性能瓶颈 !故需要根据具体应用场 景决定是否使用性能分析工具。 . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
  • 16. C/C++ 调试、 跟踪及性能分析工具综述 C/C++ 性能分析工具 基于事件的性能分析工具 - gcov 本来是 gcc 工具链中的覆盖率测试工具, 但可以用来当作用户代 码的行计数性能分析工具 需要静态注入目标程序, 用以下 gcc 选项之一编译即可, 编译成功 后会生成 *.gcno 数据文件: --coverage -fprofile-arcs -ftest-coverage 经过静态注入的目标程序运行 正常结束 后, 会在启动目录中生 通过 gcov 工具即可用这些数据产生行计数 成 *.gcda 数据文件, 分析结果 例子: gcc --coverage x.c -ox gcov x.c # 生成 x.c.gcov . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
  • 17. C/C++ 调试、 跟踪及性能分析工具综述 C/C++ 性能分析工具 基于事件的性能分析工具 - gcov gcov 背后发生的事: -ftest-coverage 让编译器生成 *.gcno 文件, 该文件含有重建 基本块依赖图和将源代码关联至基本块的必要信息, 以便 gcov 工 具使用; -fprofile-arcs 让编译器静态注入对每个源代码行关联的计数 器进行操作的代码, 并在链接阶段链入静态库 libgcov.a , 其中 包含在程序正常结束时生成 *.gcda 文件的逻辑; 参考: gcc -S x.c -o x1.s gcc -S --coverage x.c -o x2.s vimdiff *.s . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
  • 18. C/C++ 调试、 跟踪及性能分析工具综述 C/C++ 性能分析工具 基于事件的性能分析工具 - gcov lcov 一个 gcov 可视化报表前端 可生成 HTML 格式的漂亮报表 例子: 假设源代码位于 app/x.c 处 cd app gcc --coverage x.c -ox ./x lcov -d . -c -o x.info genhtml -o report x.info 最终报表入口位于 app/report/index.html 处 . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
  • 19. C/C++ 调试、 跟踪及性能分析工具综述 C/C++ 性能分析工具 基于事件的性能分析工具 - Valgrind/callgrind Valgrind 的 callgrind 插件 有很好用的 GUI 前端 kcachegrind 一个指令级性能分析工具, 支持 CPU 缓存和分支跳转概率分析, 并能将结果标注在源代码上 方便查看 请在编译时用 -g 选项启用调试符号 若需要源代码标注, 例子: gcc -g x.c -ox valgrind --tool=callgrind --dump-instr=yes --cache-sim=yes --branch-sim=yes ./x kcachegrind callgrind.* . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
  • 20. C/C++ 调试、 跟踪及性能分析工具综述 C/C++ 性能分析工具 基于采样的性能分析工具 - gprof 基于定时器的指令寄存器 (IP) 采样 + 函数调用事件计数 Linux 下使用 setitimer(ITIMER_PROF, ...) 设置定时器 取决于内核设定的 HZ 参数 采样周期尽可能快, 支持扁平化报表、 调用图报表和标注源代码 编译和链接时都要增加选项 -pg 请在编译时用 -g 选项启用调试符号 若需要源代码标注, 例子: gcc -g -pg x.c -ox ./x # 生成 gmon.out gprof ./x # 查看扁平化/调用图报表 gprof -A ./x # 查看标注源代码 . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
  • 21. C/C++ 调试、 跟踪及性能分析工具综述 C/C++ 性能分析工具 基于采样的性能分析工具 - gprof gprof 背后发生的事: gprof 本应使用 profil 系统调用进行指令寄存器采样, Linux 但 并未真正实现该系统调用, gprof 退而使用系统调用 故 setitimer -pg 让编译器在每个函数入口处静态注入对 mcount() 函数的调 用, 该函数会收集调用栈信息并更新函数调用计数 gcc -S x.c -ox1.s gcc -S -pg x.c -ox2.s vimdiff *.s -pg 让链接器链入 gcrt1.o 而不是通常情况下的 crt1.o , 前者 在程序启动时会初始化采样定时器及相关资源: gcc -v x.c 2>&1 | grep crt gcc -v -pg x.c 2>&1 | grep crt . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
  • 22. C/C++ 调试、 跟踪及性能分析工具综述 C/C++ 性能分析工具 基于采样的性能分析工具 - google-perftools/CPU Profiler 基于定时器的调用栈采样机制 Linux 下同 gprof 一样使用 setitimer(ITIMER_PROF, ...) 通过环境变量 PROFILEFREQUENCY 可设置采样频率 例子: 直接链接使用方式: 2 gcc -g x.c -ox -lprofiler CPUPROFILE=/tmp/xxx ./x 预加载使用方式: LD_PRELOAD=/usr/local/lib/libprofiler.so CPUPROFILE=/tmp/xxx ./x 显示分析报告: pprof --text ./x /tmp/xxx 2 注意: 用户代码中应存在对 profiler 共享库符号的引用, 否则链接时会忽略 . . . . . . . . . . . . . . . . . . . . profiler 动态库! .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
  • 23. C/C++ 调试、 跟踪及性能分析工具综述 C/C++ 性能分析工具 基于采样的性能分析工具 - oprofile 支持基于定时器 / 中断 / PMC / tracepoint 的采样 PMC = Performance Counter 可进行整个系统级的性能分析 在高于 2.6.26 版本的内核中, 推荐直接用 perf 工具替代 oprofile 例子: sudo opcontrol --init # 加载 oprofile 内核模块 sudo opcontrol -s ./x sudo opcontrol -h sudo opreport # 显示报表 sudo opannotate -s # 显示标注源代码 . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
  • 24. C/C++ 调试、 跟踪及性能分析工具综述 C/C++ 性能分析工具 基于采样的性能分析工具 - perf 是随 Linux 内核发布的访问 PMC 的前端工具, 在高于 2.6.26 版 本的内核中可用 支持基于 PMC / tracepoint 的采样 可进行整个系统级的性能分析, 原始采样事件数据可以输出作其 他分析之用 例子: sudo perf record -a -g -- ./x sudo perf report # 显示报表 sudo perf annotate # 显示标注源代码 . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
  • 25. C/C++ 调试、 跟踪及性能分析工具综述 C/C++ 性能分析工具 C/C++ 程序性能分析原则 在进行性能分析前, 首先确定目标程序运行时特性, time 命令输 出的 sys/usr/wall time 可以帮助我们简单地进行判断: 目标程序是 CPU 密集型应用 sys+usr ~ wall 时, sys >> usr - 尝试减少系统调用次数, 或使用系统级性能分析工具 sys << usr - 使用用户态性能分析工具 sys+usr << wall 时, 目标程序并未执行太多代码,不要考虑使用 通用性能分析工具, 此时用户态跟踪工具往往能更好地帮助你 进行性能分析并解析报告结果时应层次化进行,先从最外层入手, 逐层深入寻找瓶颈, 避免无目的地深入底层细节 性能瓶颈要逐个解决, 首先处理已知的最大瓶颈, 解决完毕后再重 新进行性能分析并处理下一个最大的瓶颈 . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
  • 26. C/C++ 调试、 跟踪及性能分析工具综述 C/C++ 跟踪工具 C/C++ 跟踪工具 . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
  • 27. C/C++ 调试、 跟踪及性能分析工具综述 C/C++ 跟踪工具 跟踪工具的实现原理 解耦事件的记录和导出操作:环形缓冲区 (ring buffer) 用户态跟踪 侵入式: 修改用户代码添加对跟踪 API 的调用, 需要重新编译 非侵入式: ptrace 系统调用 (man ptrace) GNU 动态链接器的 LD_AUDIT 支持 (man rtld-audit) utrace 内核补丁 (>=3.5 版本的内核内置了 uprobes 机制替代 utrace 补丁) 内核态跟踪 动态机制: kprobes / jprobes / kretprobes, 通过 trap 或 short-jmp 指令实现 静态机制 tracepoints: 实质为手工插入的条件跳转 ftrace (>=2.6.26 版本的内核): 利用 gcc 注入 . mcount .函数调用 . . . . . . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
  • 28. C/C++ 调试、 跟踪及性能分析工具综述 C/C++ 跟踪工具 基于 ptrace 的跟踪工具 - strace 跟踪用户程序发起的系统调用 支持已运行进程的跟踪 非 root 用户要注意内核新增的 ptrace 安全补丁, 其会禁止无直接 继承关系的进程间进行 ptrace 跟踪! 补丁控制开关:/proc/sys/kernel/yama/ptrace_scope 可很好地用于多线程/多进程程序跟踪 例子: strace -f -i -tt -T -v -s1024 -C -o trace.out ./x 参数详解请参考 man strace . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
  • 29. C/C++ 调试、 跟踪及性能分析工具综述 C/C++ 跟踪工具 基于 ptrace 的跟踪工具 - ltrace 跟踪用户程序发起的动态库函数调用 可跟踪通过 glibc 包装层发起的系统调用, 但解析系统调用参数需 不如 strace 方便 要自行修改 /etc/ltrace.conf 增加类型描述, 也不支持通过 dlopen 不支持动态库到动态库调用的函数跟踪, 自行打开的动态库函数调用跟踪 无法用于多线程程序的跟踪! 例子: ltrace -C -f -i -n4 -s1024 -S -tt -T ./x 参数详解请参考 man ltrace . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
  • 30. C/C++ 调试、 跟踪及性能分析工具综述 C/C++ 跟踪工具 基于 ptrace 的跟踪工具缺陷 跟踪开销极大 , 每个跟踪点至少需要 2 次上下文切换 + 2 个系 统调用 + 1 次信号传递开销,跟踪点较多时效率极低 无法跟踪 init(1) 进程 多个跟踪工具无法跟踪同一个目标进程 ptrace 系统调用可能 影响被跟踪进程的运行行为 : 子进程被 ptrace 跟踪并退出时, 原有的父进程不会得到 SIGCHLD 信号通知 (见 man ptrace 说明) ptrace 极大的跟踪开销会影响真正并行运行的线程数量。对并发 数或时序敏感的竟态条件可能在跟踪后消失, 使其变成海森堡问题 (Heisenbug) . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
  • 31. C/C++ 调试、 跟踪及性能分析工具综述 C/C++ 跟踪工具 基于 LD_AUDIT 机制的跟踪工具 - latrace 跟踪用户程序发起的动态库函数调用 无法跟踪 已经运行的进程 LD_AUDIT 机制用运行在目标进程上下文内的回调函数替代了 ptrace 机制所用的信号通信, 从而使跟踪开销大幅度降低 可以很好地跟踪多线程程序 例子: latrace -SAD -o trace.out ./x 参数含义请参考 man latrace . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
  • 32. C/C++ 调试、 跟踪及性能分析工具综述 C/C++ 跟踪工具 基于 ftrace 框架的跟踪工具 - trace-cmd >= 2.6.26 版本的内核可用, ftrace 框架的命令行前端 是 无法跟踪用户态事件 (上下文切换、 系统级内核态跟踪工具, 调度 等事件除外, 因它们本质上是内核态事件, 不过同样无法获取这些 事件发生时用户态程序的现场数据) 例子: sudo trace-cmd record -e all -p function_graph -F ./x trace-cmd report . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
  • 33. C/C++ 调试、 跟踪及性能分析工具综述 C/C++ 跟踪工具 基于 ftrace 框架的跟踪工具 - trace-cmd kernelshark 是 trace-cmd 跟踪数据的 GUI 查看器, 方便对事件的可视化筛选查 看 例子: sudo trace-cmd record -e all -p function_graph -F ./x kernelshark . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
  • 34. C/C++ 调试、 跟踪及性能分析工具综述 C/C++ 跟踪工具 复合跟踪工具 - SystemTap Solaris 长期以来都有很牛的跟踪工具 DTrace,但由于许可证问题 无法引入 Linux, 于是 Linux 社区自行开发了功能媲美 DTrace 的 SystemTap 是一个脚本化的跟踪框架, 能整合利用 Linux kernel 现有的 kprobes / tracepoints / uprobes(utrace) 等跟踪机制,并在源码级 兼容 DTrace 静态探针 可进行内核 / 用户态联合跟踪, 用户态程序的跟踪需要带有 utrace 补丁的内核 (或 >=3.5 版本的内核, 因其内置了 uprobes 功能); RedHat 系发行版 (RHEL / CentOS / Fedora) 内核都默认 打上了 utrace 补丁。 . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
  • 35. C/C++ 调试、 跟踪及性能分析工具综述 C/C++ 跟踪工具 复合跟踪工具 - SystemTap 系统调用跟踪示例: § ¤ // syscalls.stp probe syscall.* { println( thread_indent(4), "−>", probefunc() ) } probe syscall.*.return { println( thread_indent(−4), "<−", probefunc() ) } ¦ ¥ 调用:stap -c ./x syscalls.stp . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
  • 36. C/C++ 调试、 跟踪及性能分析工具综述 C/C++ 跟踪工具 复合跟踪工具 - SystemTap 静态探针示例: § ¤ // x.c #include <stdio.h> #include <sys/sdt.h> void f(int a) { int b = 20; DTRACE_PROBE2(f, probe1, a, b); printf("a=%d, b=%dn", a, b); DTRACE_PROBE2(f, probe2, a, b); printf("a=%d, b=%dn", a, b); } int main() { f(10); } ¦ ¥ 编译:gcc -g x.c -ox § ¤ // u.stp probe process("x").mark("*") { println("*** ", probefunc(), ": ", $arg1, ", ", $arg2); } ¦ ¥ 调用:stap -c ./x u.stp . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
  • 37. C/C++ 调试、 跟踪及性能分析工具综述 C/C++ 跟踪工具 复合跟踪工具 - LTTng 2.0 是 LTTng 0.9.x 的重写, 不再需要给内核打补丁, SystemTap 比 同 起来跟踪开销更低一些 可进行内核 / 用户态联合跟踪, 用户态跟踪是侵入式的, 需要手 工给用户程序增加静态跟踪点, 尚不兼容 SystemTap / DTrace 的 静态探针 例子: sudo lttng create sess1 sudo lttng enable-event -a -k -u sudo lttng start ./x sudo lttng stop babeltrace ~/lttng/sess1* . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
  • 38. C/C++ 调试、 跟踪及性能分析工具综述 C/C++ 跟踪工具 复合跟踪工具 - DTrace 源于 Sun Solaris, 已经移植到了 MacOS / FreeBSD / Oracle Unbreakable Linux 上 是一个脚本化的跟踪框架, 跟踪开销很低 可进行内核 / 用户态联合跟踪, 用户态跟踪可以是非侵入式 (通 过 pid provider) 或侵入式的 (通过手工插入静态跟踪点) 支持大量通用语言和应用的应用态跟踪: Java(Sun) / PHP(Zend) / Javascript(Firefox) / CPython / CRuby / MySQL / PostgreSQL / Erlang (DTrace fork) 例子:可参考 http://dtracehol.com . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
  • 39. C/C++ 调试、 跟踪及性能分析工具综述 C/C++ 跟踪工具 C/C++ 程序跟踪原则 告! 跟踪并分析程序行为需要牵扯大量精力, 同时可能需要对 Linux 内核有一定了解。实际跟踪之前, 先好好了解目标程序如何 工作, 确定跟踪的重点再动手! 大部分场合下 strace / ltrace 就能满足需要 仅进行用户态跟踪时, 了 需要进行内核态 / 用户态混合跟踪时, RedHat 系或其他内核 在 有 utrace 补丁的发行版中可用 SystemTap; MacOS / FreeBSD 在 下可用 DTrace 若能修改代码插入跟踪调用, 且对跟踪开销非常敏感时, 可以选择 LTTng 2.0 . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
  • 40. C/C++ 调试、 跟踪及性能分析工具综述 其他实用技巧 其他实用技巧 gcc -finstrument-functions - 在所有函数的入口和出口静态 注入回调函数调用, 可用来嵌入特定的跟踪逻辑 进入函数后调用 __cyg_profile_func_enter 函数 退出函数前调用 __cyg_profile_func_exit 函数 使用 LD_PRELOAD 预加载崩溃信号处理器, 可对生产环境中的 程序崩溃进行持续监控 以便在 gprof / gcov 为持续运行的服务程序增加退出信号处理器, 时正常获取分析结果 以上技巧的例子在这里:https://github.com/chaoslawful/TIP . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
  • 41. C/C++ 调试、 跟踪及性能分析工具综述 参考资料 参考资料 综述 Linux Instrumentation http://lwn.net/Kernel/Index/ 跟踪工具 玩转 utrace utrace Documentation Introducing utrace Playing with ptrace, Part I Playing with ptrace, Part II SystemTap / DTrace / LTTng / perf Comparison ftrace 简介 Solaris Dynamic Tracing Guide . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
  • 42. C/C++ 调试、 跟踪及性能分析工具综述 参考资料 参考资料 跟踪工具 DTrace for Linux Observing and Optimizing your Application with DTrace SystemTap Beginner’s Guide SystemTap Language Reference SystemTap Tapset Reference LTTng recommended bundles LTTng Ubuntu daily PPA An introduction to KProbes 使用 KProbes 调试内核 Tracing: no shortage of options Uprobes: 11th time is the charm? . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
  • 43. C/C++ 调试、 跟踪及性能分析工具综述 参考资料 参考资料 跟踪工具 Ptrace, Utrace, Uprobes: Lightweight, Dynamic Tracing for User Apps LTTng Tracing Book 性能分析与调试 google-perftools Profiling heap usage google-perftools CPU Profiler Valgrind User Manual OProfile Manual Debugging with GDB GDB Internals Manual Implementation of GProf . . . . . . . . . . . . . . . . . . . . Gcov Data Files .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
  • 44. C/C++ 调试、 跟踪及性能分析工具综述 “The important thing is not to stop questioning; never lose a holy curiosity.” — Albert Einstein That’s all, thanks! . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..