三种Linux性能分析工具的比较

无论是在CPU设计、服务器研发还是存储系统开发的过程中,性能总是一个绕不过去的硬指标。很多时候,我们发现系统功能完备,但就是性能不尽如意,这时候就需要找到性能瓶颈、进行优化。首先我们需要结合硬件特点、操作系统和应用程序的特点深入了解系统内部的运行机制、数据流图和关键路径,最好找出核心模块、建立起抽象模型;接着需要利用各种性能分析工具,探测相关模块的热点路径、耗时统计和占比。在这方面,Linux操作系统自带了多种灵活又具有专对性的工具,此外一些厂家也开源了不少优秀的性能分析工具。下面就结合笔者最近对某服务器上IO写性能分析的过程,和大家分享一下对这三种主流工具的使用方法和感受。

1.普通应用程序性能分析的利器 gprof

gprof能生成C、Pascal、Fortan77程序执行时候的调用关系profile,profile里面记录了程序每一次的内部调用关系和耗时。它要求程序在最后的链接阶段制定-pg选项,注意必须是在链接阶段而不是在编译生成.o文件的阶段,否则生成的可执行文件运行后不会生成profile,默认的profile文件名是gmou.out。

比如有下面的测试文件:

#include
<stdio.h>

#include
<string.h>

unsigned
long f3(unsigned long cnt)

{

//return
cnt*cnt*cnt*cnt*cnt*cnt*cnt;

return
cnt*cnt*cnt*cnt*cnt*cnt;

}

unsigned
long f2(unsigned long cnt)

{

//return
(f3(cnt) ^ f3(cnt + 1)) % cnt;

return
(f3(cnt) ^ f3(cnt + 1));

}

unsigned
long f1(unsigned long cnt)

{

if (cnt == 0)

return
0;

if (cnt == 1)

return
1;

return
(f2(cnt-1)^f2(cnt-2));

}

int
main(void)

{

int i, cnt =
40000;

for
(i=0;i<cnt;i++)

printf("F1(%d)
= %ld\n", i, f1(i));

return 0;

}

我们可以通过下面的命令生成gmon.out文件:

gcc
-c -o test.o test.c

gcc
-o -pg test test.c

执行一次之后,可以看到gmon.out已经生成,可以通过下面的命令,看到每个函数及其调用的函数时间占比和调用次数:

[[email protected]
backup]# gprof test gmon.out -p

Flat
profile:

Each
sample counts as 0.01 seconds.

%
 cumulative   self              self     total

time
 seconds   seconds    calls  ns/call  ns/call  name

67.37
    0.02     0.02   159992   126.32   126.32  f3

33.68
    0.03     0.01    79996   126.32   378.97  f2

0.00
    0.03     0.00    40000     0.00   757.89  f1

%
       the percentage of the total running time of the

time
     program used by this function.

cumulative
a running sum of the number of seconds accounted

seconds
 for by this function and those listed above it.

self
    the number of seconds accounted for by this

seconds
  function alone.  This is the major sort for this

listing.

calls
    the number of times this function was invoked, if

this
function is profiled, else blank.

self
    the average number of milliseconds spent in this

ms/call
  function per call, if this function is profiled,

else blank.

total
   the average number of milliseconds spent in this

ms/call
  function and its descendents per call, if this

function is
profiled, else blank.

name
     the name of the function.  This is the minor sort

for this
listing. The index shows the location of

the
function in the gprof listing. If the index is

in
parenthesis it shows where it would appear in

the gprof
listing if it were to be printed.

当然,用户还可以用gprof
test gmon.out -q或者gprof
test gmon.out -l得到更详细的信息:

Call
graph (explanation follows)

granularity:
each sample hit covers 2 byte(s) for 32.99% of 0.03 seconds

index
% time    self  children    called     name

0.01  
0.02   79996/79996       f1 [2]

[1]
  100.0    0.01    0.02   79996         f2 [1]

0.02  
0.00  159992/159992      f3 [4]

-----------------------------------------------

0.00  
0.03   40000/40000       main [3]

[2]
  100.0    0.00    0.03   40000         f1 [2]

0.01  
0.02   79996/79996       f2 [1]

-----------------------------------------------

<spontaneous>

[3]
  100.0    0.00    0.03                 main [3]

0.00  
0.03   40000/40000       f1 [2]

-----------------------------------------------

0.02  
0.00  159992/159992      f2 [1]

[4]     66.7
 0.02    0.00  159992         f3 [4]

可以看到,gprof可以根据函数的调用关系,很容易得到相关函数的调用次数和时间占比。美中不足的是它对多线程支持不好,如果需要加入多线程,需要利用gprof-helper.c文件生成libgprof-helper.so:

gcc
-shared -fPIC gprof-helper.c -o gprof-helper.so -lpthread-ldl

然后cp
gprof-helper.so /usr/lib/ /usr/lib64,最后链接到应用程序:

gcc
-o test.o -pg -lgprof-helper -lpthread

2.内核和应用程序性能分析的集成工具perf

除了上面提供的gprof外,google也提供了一款强大的性能分析工具perf,它被广泛应用在内核和应用程序的性能分析当中。目前大部分Linux
OS 自带perf工具,使用也很简单,在应用程序执行前,需要指定统计的时间和模式,比如用CPU时间来统计函数运行时间占比:

perf
record  -e cpu-clock --call-graph fp ./test

可以看到后面会生成perf.data,使用perf report
-v -i perf.data,可以看到libc到内核函数的调用过程和执行时间统计:

从上面的图可以看到printf()占了整体执行时间的3.8%,剩下的大部分时间都是在内核里面。

3.专业人士的瑞士军刀 stap
- systemtap

systemtap能把stap脚本语言翻译成C代码,并把这些生成的代码加入到内核模块,或者利用动态代码插桩的方式加入加入到应用程序执行的过程中,和perf一样,它也不用修改任何代码,就能得到期望的统计信息。除此之外,它还能在程序执行的过程中打印内核或者应用程序中的参数或变值。

比如在内核中,我们可以用systemtap的前端工具stap写脚本来打印iSCSI驱动中的一个参数信息:

[[email protected]
perf]# cat d2.stp

probe
module("iscsi_target_mod").function("iscsi_target_locate_portal")

{

printf("iSCIS
initiator login: %s\n", kernel_string($login->req_buf));

}

参考下面的命令运行stap脚本:

[[email protected]
perf]# stap d2.stp -v

Pass
1: parsed user script and 117 library script(s) using
223476virt/40972res/3064shr/38364data kb, in 170usr/20sys/212real ms.

Pass
2: analyzed script: 1 probe(s), 2 function(s), 0 embed(s), 0
global(s) using 225668virt/44044res/3936shr/40556data kb, in
50usr/220sys/282real ms.

Pass
3: translated to C into
"/tmp/stapXY9W47/stap_482377c0eab312aca9dcd34efac51d67_2620_src.c"
using 225668virt/44400res/4276shr/40556data kb, in
50usr/220sys/268real ms.

Pass
4: compiled C into "stap_482377c0eab312aca9dcd34efac51d67_2620.ko"
in 5000usr/1120sys/6094real ms.

Pass
5: starting run.

iSCIS
initiator login: InitiatorName=iqn.1991-05.com.microsoft:dell-pc

可以看到上面在target端打印出了initiator的IQN名称。

同样我们也可以在应用程序中用到stap,还是以上面的./test程序为例,可以用下面的stap脚本来统计test执行过程中f1函数占用的时间:

[[email protected]
~]# cat test.stp

#
path of zfs-fuse should be take care

#

#
usage: stap test.stp -v -x `pidof test`

global
f1, f1_intervals;

probe
process("/root/test").function("f1")

{

f1[tid()] =
gettimeofday_us()

}

probe
process("/root/test").function("f1").return

{

t
= gettimeofday_us()

old_t =
f1[tid()]

if
(old_t) f1_intervals  <<< t - old_t

delete
f1[tid()]

}

probe
end

{

if
(@count(f1_intervals)) {

printf("zvol_log_write
latency min:%dus avg:%dus max:%dus count:%d\n",

@min(f1_intervals),
@avg(f1_intervals), @max(f1_intervals),

@count(f1_intervals))

print(@hist_log(f1_intervals));

}

}

[[email protected]
~]# stap test.stp -v -x `pidof test`

可以看到stap统计的精度非常之高,f1()函数执行时间在1us到17us之间。

4.三种工具的比较分析

通过上面基于test.c用三种性能分析工具运行的过程和结果可以看到,gporf、perf适合对整个应用程序所有的函数进行批量处理,而stap很小微,能够轻易测量到某个函数或者某组函数的执行时间、乃至运行时修改程序里的变量。三种工具的分析比较如下:


实现原理


前端工具


后端工具


时间精度


多线程支持


界面友好度


批量处理


应用场景


gprof


链接时插桩



gprof


粗粒度,默认0.01s


要额外链接

gprof-helper.so




应用程序热点分析、时间占比统计


perf


运行时插桩


perf
record


Perf
report


细粒度,CPU
clock



较好



全系统热点定位、CPU 性能分析


stap


运行时插桩


stap


systemtap


细粒度,1us





特定模块、函数耗时测量、精确调优

因此,在今后的性能优化工作过程中,如果碰到一个不太熟悉和了解的系统,我们可以先用perf(没有源代码的情况)、gprof(有源代码的情况)快速定位热点函数和模块,然后针对热点模块用stap进行测量相关函数的具体时间分布,按照这种自顶向下的思路能够快速找到要害、对症下药。而对于我们已经熟悉的模块或者已知的瓶颈,就可以直接用stap进行分析了,这样能提高效率。

5.参考文献和资料

http://sam.zoy.org/writings/programming/gprof.html

https://en.wikipedia.org/wiki/DynInst

http://blog.csdn.net/u010838822/article/details/14094287

时间: 09-29

三种Linux性能分析工具的比较的相关文章

超全整理!Linux性能分析工具汇总合集

出于对Linux操作系统的兴趣,以及对底层知识的强烈欲望,因此整理了这篇文章.本文也可以作为检验基础知识的指标,另外文章涵盖了一个系统的方方面面.如果没有完善的计算机系统知识,网络知识和操作系统知识,文档中的工具,是不可能完全掌握的,另外对系统性能分析和优化是一个长期的系列. 本文档主要是结合Linux 大牛,Netflix 高级性能架构师 Brendan Gregg 更新 Linux 性能调优工具的博文,搜集Linux系统性能优化相关文章整理后的一篇综合性文章,主要是结合博文对涉及到的原理和性

Linux 性能分析工具汇总合集

出于对Linux操作系统的兴趣,以及对底层知识的强烈欲望,因此整理了这篇文章.本文也可以作为检验基础知识的指标,另外文章涵盖了一个系统的方方面面.如果没有完善的计算机系统知识,网络知识和操作系统知识,文档中的工具,是不可能完全掌握的,另外对系统性能分析和优化是一个长期的系列. 本文档主要是结合Linux 大牛,Netflix 高级性能架构师 Brendan Gregg 更新 Linux 性能调优工具的博文,搜集Linux系统性能优化相关文章整理后的一篇综合性文章,主要是结合博文对涉及到的原理和性

Linux性能分析工具汇总合集

出于对Linux操作系统的兴趣,以及对底层知识的强烈欲望,因此整理了这篇文章.本文也可以作为检验基础知识的指标,另外文章涵盖了一个系统的方方面面.如果没有完善的计算机系统知识,网络知识和操作系统知识,文档中的工具,是不可能完全掌握的,另外对系统性能分析和优化是一个长期的系列. 本文档主要是结合Linux 大牛,Netflix 高级性能架构师 Brendan Gregg 更新 Linux 性能调优工具的博文,搜集Linux系统性能优化相关文章整理后的一篇综合性文章,主要是结合博文对涉及到的原理和性

Linux 性能分析工具 nmon

nmon 是 Nigel's performance Monitor for Linux on POWER, x86, x86_64, Mainframe & now ARM (Raspberry Pi) 的缩写,意思是 Nigel(nmon 的作者是 Nigel Griffiths) 的 Linux 性能检测器. 这一系统管理员.调谐器.基准测试工具将提供给你大量重要的性能信息.它可以有两种方式输出这些数据: 1. 使用低 CPU 影响的 courses屏幕上(终端控制台.telnet.VNC

linux性能分析工具之火焰图

一.环境 1.1 [email protected]:~$ uname -a Linux jello 4.4.0-98-generic #121-Ubuntu SMP Tue Oct 10 14:24:03 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux 1.2 [email protected]:~$ lsb_release -a Distributor ID: UbuntuDescription: Ubuntu 16.04.3 LTSRelease: 16.0

linux性能分析工具

概览 uptime dmesg | tail vmstat 1 mpstat -P ALL 1 pidstat 1 iostat -xz 1 free -m sar -n DEV 1 sar -n TCP,ETCP 1 top uptime $ uptime 23:51:26 up 21:31, 1 user, load average: 30.02, 26.43, 19.02 dmesg | tail $ dmesg | tail [1880957.563150] perl invoked o

系统级性能分析工具perf的介绍与使用

测试环境:Ubuntu14.04  on VMWare Kernel:3.13.0-32 系统级性能优化通常包括两个阶段:性能剖析(performance profiling)和代码优化.性能剖析的目标是寻找性能瓶颈,查找引发性能问题的原因及热点代码.代码优化的目标是针对具体性能问题而优化代码或编译选项,以改善软件性能. 在性能剖析阶段,需要借助于现有的profiling工具,如perf等.在代码优化阶段往往需要借助开发者的经验,编写简洁高效的代码,甚至在汇编级别合理使用各种指令,合理安排各种指

perf 性能分析工具

1. perf简介 perf是一款Linux性能分析工具.Linux性能计数器是一个新的基于内核的子系统,它提供一个性能分析框架,比如硬件(CPU.PMU(Performance Monitoring Unit))功能和软件(软件计数器.tracepoint)功能.通过perf,应用程序可以利用PMU.tracepoint和内核中的计数器来进行性能统计.它不但可以分析制定应用程序的性能问题(per thread),也可以用来分析内核的性能问题,当然也可以同事分析应用程序和内核,从而全面理解应用程

perf工具-linux下性能分析工具

从2.6.31内核开始,linux内核自带了一个性能分析工具perf,能够进行函数级与指令级的热点查找. perf Performance analysis tools for Linux. Performance counters for Linux are a new kernel-based subsystem that provide a framework for all things performance analysis. It covers hardware level (CP