Profile 分析 Erlang 虚拟机源码时要注意的一个问题
最近用 Intel Vtune 剖析 Erlang 虚拟机的运行,想看看那些函数和语句耗时最多,遇到一个小问题,那就是 Vtune 给出的源码和汇编码对应有问题。这个问题在 profile 或 debug 其他程序的时候也有可能会碰到的。
看下面的例子,运行 dialyzer 的时候用 Vtune 进行采样,然后看结果:
很自然,process_main 函数耗时最多,是 CPU 主要利用者,因为整个 Erlang 虚拟机的指令执行引擎都在这个函数中。那么双击这个函数,进去看详细的源代码的耗时信息,会看到奇怪的现象:
可以看到第 12 行的注释和下面的 #include 指令竟然耗时间了,更神奇的是,这些源码行还输出了汇编,比如第 12 行对应右边的 mov 指令。还有下图中,第 38 行的 #include 生成这么多汇编码也是不可能的:
这会不会是和宏展开相关呢?会不会是和编译器的优化相关呢?会不会是编译器弄错了呢?
以上问题的答案都是否定的。因为这个文件(beam_emu.c)宏展开也不会在第 12 行有代码。而且编译器不会这么笨的。优化也不可能,因为我没开优化,为了详细观察语句(对应指令)执行耗时情况,关闭了优化(-O0),而且请求编译器包含最丰富的调试信息(-g3)。也不太可能是编译器弄错了,因为 gcc 和 Intel 的 icc 都出现了这个现象,而且都是在同样的位置。假设真的是编译器弄错了,那么完全不同的编译器也不太可能会错成一样,所以感觉这里肯定是有确定性原因的。
那到底是怎么回事呢?用 objdump -S 导出目标文件 beam_emu.o 的源码和汇编码信息,可以看出编译器是很忠诚的,没有奇怪的问题,而且很显然那些注释和 #include 指令那些地方是没有输出汇编代码的,编译器既然能在目标文件中内嵌正确的源码信息,那就不太可能会弄错行号。那就看看第 12 行对应的汇编码到底对应的源码是什么。下图中框出来的 3 条汇编指令是 NextPF 宏生成的,中间那一条就是之前图中在 0x5d7e6c 处对应第 12 行的那条汇编。
那就找这几行源代码在 beam_emu.c 中对应的位置应该就可以看出究竟了。有趣的是,在 beam_emu.c 中其实找不到这几行代码。beam_emu.c 把一些热门指令的代码单独放在 beam_hot.h 文件中了,这个文件是在 build 过程中自动生成的。果然,在这个文件中看到了这段代码:
哈,找到原因了。调用 NextPF 宏的刚好是第 12 行,原来编译器记录的是被包含文件中的行数。当然这并不是编译器的处理方式不对,而是这种将源代码 #include 到另一个源代码文件中的做法本身不是一个好的编程习惯,但是鉴于 process_main 的特殊性,这有助于保持代码的简洁(尽管这样 process_main 还是有好几千行)。
注意,这里的代码映射错误的问题并不是 Vtune 的问题,Vtune 只是忠实地反映出目标文件中调试信息里面的内容,而调试信息是编译器生成的。
那么为了能在 profile 过程中准确对应到源码行,我们手工把 beam_hot.h 文件的内容(还有 beam_cold.h,对应冷门指令)拷贝到 beam_emu.c 中对应的位置并重新 build 即可。再次运行 profile,可以看出代码映射完全正确了:
对右侧的汇编指令的耗时排序:
可以看出跳转指令的开销还是不小的,因为虚拟机每执行下一条指令都是一个跳转。所以 Erlang 虚拟机中的指令数目也非常多,每一条都尽量完成尽可能多的工作,以减少指令分发的次数。
Profile 分析 Erlang 虚拟机源码时要注意的一个问题的更多相关文章
- 分析jQuery源码时记录的一点感悟
分析jQuery源码时记录的一点感悟 1. 链式写法 这是jQuery语法上的最大特色,也许该改改POJO里的set方法,和其他的非get方法什么的,可以把多行代码合并,减去每次 ...
- IDEA查看源码时提示:Library source does not match the bytecode for class的问题分析
通过Maven查看依赖的源码时,通常是Maven自动下载JAR包附属的source包,但是会出现一个问题,由于使用lombok插件会造成编写的Java文件和编译后的class上有差别,所以IDEA打开 ...
- Spring Ioc源码分析系列--Ioc源码入口分析
Spring Ioc源码分析系列--Ioc源码入口分析 本系列文章代码基于Spring Framework 5.2.x 前言 上一篇文章Spring Ioc源码分析系列--Ioc的基础知识准备介绍了I ...
- [Erlang 0119] Erlang OTP 源码阅读指引
上周Erlang讨论群里面提到lists的++实现,争论大多基于猜测,其实打开代码看一下就都明了.贴出代码截图后有同学问这代码是哪里找的? "代码去哪里找?",关于Erla ...
- Android5.1.1 - APK签名校验分析和修改源码绕过签名校验
Android5.1.1 - APK签名校验分析和修改源码绕过签名校验 作者:寻禹@阿里聚安全 APK签名校验分析 找到PackageParser类,该类在文件“frameworks/base/cor ...
- JPEG概述和头分析(C源码)
原创文章,转载请注明:JPEG概述和头分析(C源码) By Lucio.Yang 部分内容来自:w285868925,JPEG压缩标准 1.JPEG概述 JPEG是一个压缩标准,又可分为标准 JPE ...
- [strongswan][autoconf][automake][cento] 在CentOS上编译strongswan git源码时遇到的autoconf问题
编译strongswan的git源码问题 1. 概述 首先,我们想要通过源码编译strongswan.当满足以下条件时,通常你会遇见此问题: 源码时通过git clone的得来的,而不是官网下载的源码 ...
- Cesium专栏-填挖方分析(附源码下载)
Cesium 是一款面向三维地球和地图的,世界级的JavaScript开源产品.它提供了基于JavaScript语言的开发包,方便用户快速搭建一款零插件的虚拟地球Web应用,并在性能,精度,渲染质量以 ...
- Proxy Server源码及分析(TCP Proxy源码 Socket实现端口映射)
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/u014530704/article/de ...
随机推荐
- [python]爬代理ip v2.0(未完待续)
爬代理ip 所有的代码都放到了我的github上面, HTTP代理常识 HTTP代理按匿名度可分为透明代理.匿名代理和高度匿名代理. 特别感谢:勤奋的小孩 在评论中指出我文章中的错误. REMOTE_ ...
- Cocos2d-x网络通信
Cocos2d-x示例提供了三种内置的网咯通信类 HttpClient,WebSocket,SocketIO. 其中第一个是简单的HTTP协议的使用,提供很多Http请求方式. 剩下的Socket*是 ...
- HT图形组件设计之道(三)
上篇我们通过定制了CPU和内存展示界面,体验了HT for Web通过定义矢量实现图形绘制与业务数据的代码解耦及绑定联动,这类案例后续文章还会继续以便大家掌握更多的矢量应用场景,本篇我们先切换个话题, ...
- 【Android进阶系列教程】前言
起因 因为初学Android的时候还没有写博客的意识,现在Android的门是入了,正在进阶的道路上行走,但是就这一路也走了不少的弯路.我想,总得来说Android入门还是比较容易的,网络资源比较丰富 ...
- mysql主从复制replication的一些相关命令
主服务器上的相关命令:show master status; mysql> show master status\G . row *************************** Posi ...
- sprint3(第六天)
由于昨天下午晚上停电又没网,所以我们没做成什么功能,而且也没发博客. 今天燃尽图:
- redhat Nginx 安装
1.Nginx 简介 Nginx ("engine x") 是一个高性能的 HTTP 和 反向代理 服务器,也是一个 IMAP/POP3/SMTP 代理服务器. Nginx 是由 ...
- 自己动手搞定支付宝手机网站支付接口 FOR ECShop
支付宝WAP网站版本的支付接口网上整合的比较少,看到很多网站在卖,顿觉无语. 主要是得自己查看支付宝官方提供的SDK中的开发文档. 支付宝sdk下载地址:https://doc.open.alipay ...
- js小数计算小数点后显示多位小数(转)
首先写一个demo 重现问题,我使用的是一个js在线测试环境[打开] 改写displaynum()函数 function displaynum(){var num = 22.77;alert(num ...
- jdk1.8 ThreadPoolExecutor实现机制分析
ThreadPoolExecutor几个重要的状态码字段 private static final int COUNT_BITS = Integer.SIZE - 3; private static ...