Your SlideShare is downloading. ×
  • Like
C/C++调试、跟踪及性能分析工具综述
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Now you can save presentations on your phone or tablet

Available for both IPhone and Android

Text the download link to your phone

Standard text messaging rates apply

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

  • 3,300 views
Published

 

Published in Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
3,300
On SlideShare
0
From Embeds
0
Number of Embeds
1

Actions

Shares
Downloads
107
Comments
0
Likes
15

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 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! . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..