性能分析之从 CPU 高到定位到代码行(C/C++)

Posted zuozewei

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了性能分析之从 CPU 高到定位到代码行(C/C++)相关的知识,希望对你有一定的参考价值。

前言

如果分析思路方向是正确的,对于 Java 应用和 C/C++ 应用来说,也是几个命令就可以跳到代码行了。前提是要能看得懂堆栈信息。所以一直以来我在讲课的过程中都有画过这样的一个分析思路的图。

在性能分析中,如果是 C/C++ 的应用的话,也同样是有些工具可以做得到的。

一个例子

今天我们来看一个简单的 C 代码示例,看下如何做到这几步。我在网上看到有一段示例代码,也省得自己写了。就直接拿来编译用了。下面来看一下操作。

[root@7dgroup Sample6]# gcc -o test6 -g test6.c

#编译的时候记得加-g的参数,可以生成调试信息。
[root@7dgroup Sample6]# ./test6

# 运行起来:
[root@7dgroup Sample6]# ./test6
返回值 :3
返回值 5
返回值 :5
返回值 7
返回值 :7
返回值 9

执行过程会产生这样的数据。同时查看top。

看到 31356 这个进程已经消耗了 CPU。因为这个进程非常的简单,所以这里我就不再细化到线程级了。直接打堆栈看了。
(如果是复杂的应用的话,在这一步,还要再细化一步的就是打印线程级的状态。方法有多种,可以用 top -H,也可以 pidstat,也可以用调试工具 attach 上去再查 threaddump。总之选择自己喜欢的方式就好。)

直接 gstack 打印堆栈。

[root@7dgroup ~]# gstack 31356
#0  0x00000000004005ed in function2 (input=963) at test6.c:4
#1  0x000000000040065b in function1 (a=9, b=10) at test6.c:21
#2  0x00000000004006e8 in main () at test6.c:39

# 当然你也可以pstack打印堆栈(因为我重新运行了一次,所以PID变了)。
[root@7dgroup ~]# pstack 31438
#0  0x0000000000400620 in function3 (input=3524) at test6.c:14
#1  0x000000000040067e in function1 (a=5, b=6) at test6.c:25
#2  0x00000000004006e8 in main () at test6.c:39

通过堆栈信息就可以看出来,这里面只有一个线程,并且调用关系是:

  • 第一次打印的堆栈是:39行 -> 21行 -> 4行
  • 第二次打印的堆栈是:39行 -> 25行 -> 14行

(因为是同一个文件,所以我只写行号了)。

这样就可以在 C/C++ 的应用中从 CPU 分析到具体的代码行了。

小结

再重复强调,分析思路的完整性非常重要。要先知道想看什么数据,才能知道用什么工具去做。会工具没什么了不起,但是把原理搞清楚又能融会贯通才是真的厉害。

可能有人会说,我连工具都不知道怎么用,怎么知道看什么数据呢。看似悖论的一个问题,实际上就是经验不足,需要多学习基础的知识。
比如说,了解了 Linux 上运行java语言的分析过程,那其他的分析过程也是类似的,只是工具不同。并不是说只会分析 Linux 上运行Java,换成 HPunix+C/C++ 就没有思路了。

就像小学做的数学题一样:一行有四棵树,总共四行,共有几棵树?16棵!
但是把树换成电线杆就有人不会算了。

以上是关于性能分析之从 CPU 高到定位到代码行(C/C++)的主要内容,如果未能解决你的问题,请参考以下文章

性能分析之CPU高到定位到代码行(JAVA)

性能分析之CPU高到定位到代码行(JAVA)

性能分析之从 IO 高定位到具体文件

JVM调优之jstack找出最耗cpu的线程并定位代码

解决日常bug的正确姿势

90%的人会遇到性能问题,如何用1行代码快速定位?