
在上一篇文章的golang代码中,函数add的上一行,增加了一条注释语句: //go:noinline 。在bpftrace追踪时,是否可以去掉?有什么作用?
为了说明该问题,设计一个例子。
golang代码中,有两个求和函数。其中,add1加上 //go:noinline ,另一个add2不加。代码如下:
bpftrace程序分别对函数add1和add2的输入参数、返回值进行追踪,代码如下:
执行程序后,可以看到bpftrace程序能够正常追踪到函数add1,但是无法追踪到函数add2。
通过上文中的示例代码,可以看到,没有加 //go:noinline 的函数无法被bpftrace程序追踪到。通过查阅golang相关文档,可以知道, //go:noinline 表示该函数在编译时,不会被内联。
使用 objump -S 生成golang程序的汇编代码如下:
通过汇编代码,我们可以看到,主函数中,地址 0x498e52 处 callq 498e00 调用了add1函数,地址 0x498ebb 处 movq $0x4,(%rsp) 直接计算求值。
因此,golang编译器在编译代码时,会对代码进行分析,并按照内联规则,将某些函数生成内联代码。一旦函数被内联,bpftrace将无法追踪到对应函数。也就是,上文中函数 add2 无法被追踪到。
针对golang程序中编译器内联的问题,可以通过禁止内联的方式来解决。禁止内联的方式有:
在实践中,可以通过 go build -gcflags="-m -m" 来查看,哪些函数会在编译时执行内联,如:
从输出中,可以看到:
关于golang编译器进行内联的场景,可以参考golang源码:>
在传统的单应用架构下,接口的日志监控还是非常简单的,但是随着分布式、微服务架构的兴起,我们会面对更为复杂的服务交互关系;
也就是说,以往的系统,更多的是A系统调用B系统,而现在可能面对这A->B->C->D,而在这种情况下,如果没有链路跟踪的方案,那么查找和定位问题就会非常困难。
理论基础
Google公司研发了Dapper分布式跟踪系统,并发表了论文《Dapper, a Large-Scale Distributed Systems Tracing Infrastructure》;
目前行业内大部分的分布式跟踪方案都是基于这篇论文来实现的;这篇论文中提到了几个比较重要的概念:
A:parentId=null、spanId=1;
B:parentId=1、spanId=2;
C:parentId=2、spanId=3;
D:parentId=2、spanId=4;
实现方案
我将持续分享Java开发、架构设计、程序员职业发展等方面的见解,希望能得到你的关注。
集成zipkin或者spring cloud sleuth都可以的
以上就是关于bpftrace动态追踪golang应用-函数内联问题全部的内容,包括:bpftrace动态追踪golang应用-函数内联问题、xcode怎么清除crashes、在微服务架构下,如何实现接口调用链路的跟踪等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)