十、如何使用perf工具分析java程序

问题 1: 使用 perf 工具时,看到的是 16 进制地址而不是函数名

在 CentOS 系统中,使用 perf 工具看不到函数名,只能看到一些 16 进制格式的函数地址

# 只要你观察一下 perf 界面最下面的那一行,就会发现一个警告信息:
Failed to open /opt/bitnami/php/lib/php/extensions/opcache.so, continuing without symbols
  • 针对这种情况,我总结了下面四个解决方法
  1. 在容器外面构建相同路径的依赖库.原理上可行,但是并不推荐,一方面是因为找出这些依赖库比较麻烦,更重要的是,构建这些路径,会污染容器主机的环境。
  2. 在容器内部运行 perf.这需要容器运行在特权模式下,但实际的应用程序往往只以普通容器的方式运行。所以,容器内部一般没有权限执行 perf 分析。比方说,如果你在普通容器内部运行 perf record ,你将会看到下面这个错误提示:
    $ perf_4.9 record -a -g
    perf_event_open(..., PERF_FLAG_FD_CLOEXEC) failed with unexpected error 1 (Operation not permitted)
    perf_event_open(..., 0) failed unexpectedly with error 1 (Operation not permitted)
    

当然,其实你还可以通过配置 /proc/sys/kernel/perf_event_paranoid (比如改成 -1),来允许非特权用户执行 perf 事件分析。不过为了安全起见,这种方法也不推荐。

  1. 指定符号路径为容器文件系统的路径
    $ mkdir /tmp/foo
    $ PID=$(docker inspect --format {{.State.Pid}} phpfpm)
    $ bindfs /proc/$PID/root /tmp/foo
    $ perf report --symfs /tmp/foo
    
    # 使用完成后不要忘记解除绑定
    $ umount /tmp/foo/
    
  2. 在容器外面把分析纪录保存下来,再去容器里查看结
    $ perf record -g -p < pid>   # 宿主机采样
    $ docker cp perf.data phpfpm:/tmp 
    $ docker exec -i -t phpfpm bash #进入虚拟机
    $ cd /tmp/ 
    $ apt-get update && apt-get install -y linux-tools linux-perf procps
    $ perf_4.9 report   #虚拟机中分析
    
  • ubuntu安装perf
    $ apt-get install -y linux-tools-common linux-tools-generic linux-tools-$(uname -r))
    
  • Debian
    $ apt-get install -y linux-perf
    

问题 2:如何用 perf 工具分析 Java 程序

从系统层面你只能看到 JVM 的函数堆栈,而不能直接得到 Java 应用程序的堆栈

perf_events 实际上已经支持了 JIT,但还需要一个 /tmp/perf-PID.map 文件,来进行符号翻译。当然,开源项目 perf-map-agent 可以帮你生成这个符号表
此外,为了生成全部调用栈,你还需要开启 JDK 的选项 -XX:+PreserveFramePointer.还可以参考Netflix 的技术博客,来查看详细的使用步骤。

问题 3:为什么 perf 的报告中,很多符号都不显示调用栈

通过man可以看到,-g 选项等同于 –call-graph,它的参数是后面那些被逗号隔开的选项,意思分别是输出类型、最小阈值、输出限制、排序方法、排序关键词、分支以及值的类型。其中 threshold 的默认值为 0.5%,也就是说,事件比例超过 0.5% 时,调用栈才能被显示.

这种情况下,你只需要给 perf report 设置一个小于 0.34% 的阈值,就可以显示我们想看到的调用图了。比如执行下面的命令:

$ perf report -g graph,0.3

问题 4:怎么理解 perf report 报告中 Children 和 Self 的含义

关于 Children 和 Self 的含义,手册里其实有详细说明,还很友好地举了一个例子,来说明它们的百分比的计算方法。简单来说:

  1. Self 是最后一列的符号(可以理解为函数)本身所占比例;
  2. Children 是这个符号调用的其他符号(可以理解为子函数,包括直接和间接调用)占用的比例之和。
  3. perf 这种动态追踪工具,会给系统带来一定的性能损失。
  4. vmstat、pidstat 这些直接读取 proc 文件系统来获取指标的工具,不会带来性能损失。
 
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值