Linux性能优化gprof使用
- gprof用于分析函数调用耗时,可用之抓出最耗时的函数,以便优化程序。
- gcc链接时也一定要加-pg参数,以使程序运行结束后生成gmon.out文件,供gprof分析。
- gprof默认不支持多线程程序,默认不支持共享库程序。
- gcc -pg 编译程序
- 运行程序,程序退出时生成 gmon.out
- gprof ./prog gmon.out -b 查看输出
要想产生gmon.out文件,必须在编译和链接时,都加上-pg -g选项。
1 简介
改进应用程序的性能是一项非常耗时耗力的工作,但是究竟程序中是哪些函数消耗掉了大部分执行时间,这通常都不是非常明显的。GNU 编译器工具包所提供了一种剖析工具 GNU profiler(gprof)。gprof 可以为 Linux平台上的程序精确分析性能瓶颈。gprof精确地给出函数被调用的时间和次数,给出函数调用关系。
gprof 用户手册网站 http://sourceware.org/binutils/docs-2.17/gprof/index.html
2 功能
Gprof 是GNU gnu binutils工具之一,默认情况下linux系统当中都带有这个工具。
1. 可以显示“flat profile”,包括每个函数的调用次数,每个函数消耗的处理器时间,
2. 可以显示“Call graph”,包括函数的调用关系,每个函数调用花费了多少时间。
3. 可以显示“注释的源代码”--是程序源代码的一个复本,标记有程序中每行代码的执行次数。
3 原理
4 使用流程
1. 在编译和链接时 加上-pg选项。一般我们可以加在 makefile 中。
3. 在程序运行目录下 生成 gmon.out 文件。如果原来有gmon.out 文件,将会被重写。
5 参数说明
l -p 只输出函数的调用图(Call graph的那部分信息)。
l -e Name 不再输出函数Name 及其子函数的调用图(除非它们有未被限制的其它父函数)。可以给定多个 -e 标志。一个 -e 标志只能指定一个函数。
l -E Name 不再输出函数Name 及其子函数的调用图,此标志类似于 -e 标志,但它在总时间和百分比时间的计算中排除了由函数Name 及其子函数所用的时间。
l -f Name 输出函数Name 及其子函数的调用图。可以指定多个 -f 标志。一个 -f 标志只能指定一个函数。
l -z 显示使用次数为零的例程(按照调用计数和累积时间计算)。
一般用法: gprof –b 二进制程序 gmon.out >report.txt
6 报告说明
%time |
Cumulative seconds |
Self Seconds |
Calls |
Self TS/call |
Total TS/call |
name |
该函数消耗时间占程序所有时间百分比 |
程序的累积执行时间 (只是包括gprof能够监控到的函数) |
该函数本身执行时间 (所有被调用次数的合共时间) |
函数被调用次数 |
函数平均执行时间 (不包括被调用时间) (函数的单次执行时间) |
函数平均执行时间 (包括被调用时间) (函数的单次执行时间) |
函数名 |
Index |
%time |
Self |
Children |
Called |
Name |
索引值 |
函数消耗时间占所有时间百分比 |
函数本身执行时间 |
执行子函数所用时间 |
被调用次数 |
函数名 |
程序的累积执行时间只是包括gprof能够监控到的函数。工作在内核态的函数和没有加-pg编译的第三方库函数是无法被gprof能够监控到的,(如sleep()等)
Gprof 的具体参数可以 通过 man gprof 查询。
7 共享库的支持
对于代码剖析的支持是由编译器增加的,因此如果希望从共享库中获得剖析信息,就需要使用 -pg 来编译这些库。提供已经启用代码剖析支持而编译的 C 库版本(libc_p.a)。
gcc example1.c –pg -lc_p -o example1
注意要用ldd ./example | grep libc来查看程序链接的是libc.so还是libc_p.so
8 用户时间与内核时间
有一个方法可以查看应用程序的运行时间组成,在 time 命令下面执行程序。这个命令会显示一个应用程序的实际运行时间、用户空间运行时间、内核空间运行时间。
9 注意事项
2. 只能使用静态连接libc库,否则在初始化*.so之前就调用profile代码会引起“segmentation fault”,解决办法是编译时加上-static-libgcc或-static。
4. 要监控到第三方库函数的执行时间,第三方库也必须是添加 –pg 选项编译的。
6. 程序不能以demon方式运行。否则采集不到时间。(可采集到调用次数)
7. 首先使用 time 来运行程序从而判断 gprof 是否能产生有用信息是个好方法。
8. 如果 gprof 不适合您的剖析需要,那么还有其他一些工具可以克服 gprof 部分缺陷,包括 OProfile 和 Sysprof。
9. gprof对于代码大部分是用户空间的CPU密集型的程序用处明显。对于大部分时间运行在内核空间或者由于外部因素(例如操作系统的 I/O 子系统过载)而运行得非常慢的程序难以进行优化。
11. gprof只能在程序正常结束退出之后才能生成报告(gmon.out)。
a) 原因: gprof通过在atexit()里注册了一个函数来产生结果信息,任何非正常退出都不会执行atexit()的动作,所以不会产生gmon.out文件。
b) 程序可从main函数中正常退出,或者通过系统调用exit()函数退出。
10 多线程应用
gprof 不支持多线程应用,多线程下只能采集主线程性能数据。原因是gprof采用ITIMER_PROF信号,在多线程内只有主线程才能响应该信号。
采用什么方法才能够分析所有线程呢?关键是能够让各个线程都响应ITIMER_PROF信号。可以通过桩子函数来实现,重写pthread_create函数。
gprof-helper.c#define _GNU_SOURCE#include <sys/time.h>#include <stdio.h>#include <stdlib.h>#include <dlfcn.h>#include <pthread.h>static void * wrapper_routine(void *);/* Original pthread function */static int (*pthread_create_orig)(pthread_t *__restrict,__const pthread_attr_t *__restrict,void *(*)(void *),void *__restrict) = NULL;/* Library initialization function */void wooinit(void) __attribute__((constructor));void wooinit(void){pthread_create_orig = dlsym(RTLD_NEXT, "pthread_create");fprintf(stderr, "pthreads: using profiling hooks for gprof/n");if(pthread_create_orig == NULL){char *error = dlerror();if(error == NULL){error = "pthread_create is NULL";}fprintf(stderr, "%s/n", error);exit(EXIT_FAILURE);}}/* Our data structure passed to the wrapper */typedef struct wrapper_s{void * (*start_routine)(void *);void * arg;pthread_mutex_t lock;pthread_cond_t wait;struct itimerval itimer;} wrapper_t;/* The wrapper function in charge for setting the itimer value */static void * wrapper_routine(void * data){/* Put user data in thread-local variables */void * (*start_routine)(void *) = ((wrapper_t*)data)->;start_routine;void * arg = ((wrapper_t*)data)->;arg;/* Set the profile timer value */setitimer(ITIMER_PROF, &((wrapper_t*)data)->;itimer, NULL);/* Tell the calling thread that we don't need its data anymore */pthread_mutex_lock(&((wrapper_t*)data)->;lock);pthread_cond_signal(&((wrapper_t*)data)->;wait);pthread_mutex_unlock(&((wrapper_t*)data)->;lock);/* Call the real function */return start_routine(arg);}/* Our wrapper function for the real pthread_create() */int pthread_create(pthread_t *__restrict thread,__const pthread_attr_t *__restrict attr,void * (*start_routine)(void *),void *__restrict arg){wrapper_t wrapper_data;int i_return;/* Initialize the wrapper structure */wrapper_data.start_routine = start_routine;wrapper_data.arg = arg;getitimer(ITIMER_PROF, &wrapper_data.itimer);pthread_cond_init(&wrapper_data.wait, NULL);pthread_mutex_init(&wrapper_data.lock, NULL);pthread_mutex_lock(&wrapper_data.lock);/* The real pthread_create call */i_return = pthread_create_orig(thread,attr,&wrapper_routine,&wrapper_data);/* If the thread was successfully spawned, wait for the data* to be released */if(i_return == 0){pthread_cond_wait(&wrapper_data.wait, &wrapper_data.lock);}pthread_mutex_unlock(&wrapper_data.lock);pthread_mutex_destroy(&wrapper_data.lock);pthread_cond_destroy(&wrapper_data.wait);return i_return;}///然后编译成动态库 gcc -shared -fPIC gprof-helper.c -o gprof-helper.so -lpthread -ldl 使用例子:/a.c/#include <stdio.h>;#include <stdlib.h>;#include <unistd.h>;#include <pthread.h>;#include <string.h>;void fun1();void fun2();void* fun(void * argv);int main(){int i =0;int id;pthread_t thread[100];for(i =0 ;i< 100; i++){id = pthread_create(&thread[i], NULL, fun, NULL);printf("thread =%d/n",i);}printf("dsfsd/n");return 0;}void* fun(void * argv){fun1();fun2();return NULL;}void fun1(){int i = 0;while(i<100){i++; printf("fun1/n");} }void fun2(){int i = 0;int b;while(i<50){i++;printf("fun2/n");//b+=i; } }///gcc -pg a.c gprof-helper.so运行程序:./a.out分析gmon.out:gprof -b a.out gmon.out
Linux性能优化gprof使用相关推荐
- 开发人员如何解决Linux性能优化之痛?
这些问题或者场景,你是否曾经遇到过? • 流量高峰期,服务器CPU使用率过高报警,你登录Linux上去top完之后,却不知道怎么进一步定位,到底是系统CPU资源太少,还是程序并发部分写的有问题? • ...
- 如何学习Linux性能优化?
如何学习Linux性能优化? 你是否也曾跟我一样,看了很多书.学了很多 Linux 性能工具,但在面对 Linux 性能问题时,还是束手无策?实际上,性能分析和优化始终是大多数软件工程师的一个痛点.但 ...
- linux性能优化--cpu篇
linux性能优化--cpu篇 前言 负载 CPU使用率 proc perf 一些链接 `perf list` 比较有用的event `perf stat` `perf record` Profili ...
- linux下缓存命中测试,Linux 性能优化实战(倪朋飞)---查看缓存命中情况
cachestat 提供了整个操作系统缓存的读写命中情况. cachetop 提供了每个进程的缓存命中情况.但是,cachetop 并不把直接 I/O 算进来. 安装 cachestat.cachet ...
- Linux性能优化方向及相关工具
1. 考察性能的指标 从应用负载的角度 吞吐 延时 从系统资源的角度 CPU使用率 内存饱和度 2. 定位性能问题的步骤 选择指标评估性能 设置性能优化的目标 进行性能基准测试 分析和定位性能瓶颈 对 ...
- 查看linux内存优化,Linux性能优化和监控系列(三) 分析Memory使用状况
Linux性能优化和监控系列(三) 分析Mem 分析Memory使用状况 内存是影响服务器性能的一个主要因素, 当进程已经驻留内存或者系能够分配给进程足够的内存给它, CPU能顺利自如的运行. 如果发 ...
- 10个问题带你全面理解Linux性能优化
10个问题带你全面理解Linux性能优化 • Feiskyhttps://feisky.xyz/posts/2020-06-06-linux-perf/本文整理自极客时间"10个问题带你全面 ...
- 推荐学习-Linux性能优化实战
学习交流加(可免费帮忙下载CSDN资源): 个人微信: liu1126137994 学习交流资源分享qq群1(已满): 962535112 学习交流资源分享qq群2: 780902027 推荐一个学习 ...
- Linux 性能优化全景指南
大家好 我是坤哥 之前一些朋友觉得奇怪,说你主要做 Java 的,公号怎么时不时地也推送一些 Linux 文章,其实不管你是哪个 xx 语言的工程师,要想进阶,Linux 性能优化是必备知识,举个例子 ...
最新文章
- 5分钟教程,手把手带你安装使用抓包神器:Whistle ,内含精选爬虫资料
- jQuery操作Select
- [原创]WildPackets Omnipeek介绍
- 教程:一起学习Hystrix--服务(依赖)失败场景的表象
- 通过options探测服务器信息,OPTIONS 方法在跨域请求(CORS)中的应用
- Ubuntu 中设置源的几种方法
- 锁屏快捷键_全面屏 iPhone 锁屏快捷键美化,让你的 iPhone 更特别
- 作者:李冰(1989-),女,中国电子技术标准化研究院工程师。
- rsync软件配置和使用教程
- 进程和线程的关系与区别是什么?如何创建多线程?
- Python 06 编码
- 基于LabVIEW的个性化打地鼠游戏设计
- 三菱PLC 闪烁动作 ST语言
- 2018年最有前景的十大行业
- 计算机量子化学计算实验报告物化实验,量子化学计算方试验.doc
- 图benchmark
- 【windows查看电脑属性配置 dxdiag】
- 浅析智慧消防应用中多设备联动火灾报警系统
- 狄拉克δ函数的数学迷思
- HTTP POST 请求工具类