参考

gprof的简单使用-anthony1983-ChinaUnix博客

Top (GNU gprof) (sourceware.org)

c - Enable and disable gprof at runtime? - Stack Overflow

gprof——GNU性能分析工具 - feisky - 博客园 (cnblogs.com)

Linux性能优化gprof使用 - youxin - 博客园 (cnblogs.com)

gprof介绍

GNU分析工具gprof可以有用的测量程序的性能,它记录了调用每个函数的次数以及在每个函数上花费的时间。

从gprof的输出可以容易的看出占用大量运行时间的函数。提高程序运行速度应该首先集中在那些占据费时的函数上。

使用方式

gprof [可执行文件] [gmon.out文件] [其它参数]

方括号中的内容可以省略。如果省略了“可执行文件”,gprof会在当前目录下搜索a.out文件作为可执行文件;

如果省略了gmon.out文件,gprof也会在当前目录下寻找gmon.out。

其它参数可以控制gprof输出内容的格式等信息,最常用的参数如下:

  • -b:不再输出统计图表中每个字段的详细描述。

  • -p:只输出函数的调用图(Call graph的那部分信息)。

  • -q:只输出函数的时间消耗列表。

  • -e Name:不再输出函数Name 及其子函数的调用图(除非它们有未被限制的其它父函数)。可以给定多个 -e 标志。一个 -e 标志只能指定一个函数。

  • -E Name:不再输出函数Name 及其子函数的调用图,此标志类似于 -e 标志,但它在总时间和百分比时间的计算中排除了由函数Name 及其子函数所用的时间。

  • -f Name:输出函数Name 及其子函数的调用图。可以指定多个 -f 标志。一个 -f 标志只能指定一个函数。

  • -F Name:输出函数Name 及其子函数的调用图,它类似于 -f 标志,但它在总时间和百分比时间计算中仅使用所打印的例程的时间。可以指定多个 -F 标志。一个 -F 标志只能指定一个函数。-F 标志覆盖 -E 标志。

  • -z:显示使用次数为零的例程(按照调用计数和累积时间计算)。

使用步骤

  1. 使用gcc/g++编译时,加参数-pg,比如gcc -pg -o test test.c
  2. 运行编译好的程序test,程序会产生gmon.out文件
  3. 使用gprof工具分析gmon.out文件,gprof ./test gmon.out。

测试代码:

#include <stdio.h>

/* Computes the length of Collatz sequences */
unsigned int step(unsigned int x)
{
if (x % 2 == 0) {
return (x / 2);
} else {
return (3 * x + 1);
}
} unsigned int nseq(unsigned int x0)
{
unsigned int i = 1, x;
if (x0 == 1 || x0 == 0)
return i;
x = step(x0);
while (x != 1 && x != 0) {
x = step(x);
i++;
}
return i;
} int main(void)
{
unsigned int i, m = 0, im = 0;
for (i = 1; i < 500000; i++) {
unsigned int k = nseq(i);
if (k > m) {
m = k;
im = i;
printf("sequence length = %u for %u\n", m, im);
}
}
return 0;
}

编译、运行、测试:

$ gcc -pg -o gprof_test gprof_test.c
$ ./gprof_test
$ gprof ./gprof_test gmon.out -b
Flat profile: Each sample counts as 0.01 seconds.
% cumulative self self total
time seconds seconds calls ns/call ns/call name
75.82 0.30 0.30 62135400 4.88 4.88 step
20.22 0.38 0.08 499999 161.76 768.35 nseq
2.53 0.39 0.01 frame_dummy
2.53 0.40 0.01 main Call graph granularity: each sample hit covers 2 byte(s) for 2.47% of 0.40 seconds index % time self children called name
<spontaneous>
[1] 97.5 0.01 0.38 main [1]
0.08 0.30 499999/499999 nseq [2]
-----------------------------------------------
0.08 0.30 499999/499999 main [1]
[2] 95.0 0.08 0.30 499999 nseq [2]
0.30 0.00 62135400/62135400 step [3]
-----------------------------------------------
0.30 0.00 62135400/62135400 nseq [2]
[3] 75.0 0.30 0.00 62135400 step [3]
-----------------------------------------------
<spontaneous>
[4] 2.5 0.01 0.00 frame_dummy [4]
----------------------------------------------- Index by function name [4] frame_dummy [2] nseq
[1] main [3] step

测试结果

  • % time:当前函数占总的运行时间的百分比
  • cumulative seconds:函数和上列函数累计执行的时间,单位秒
  • self seconds:函数本身执行的时间
  • calls:函数被调用次数
  • self ms/call:每一次调用花费在函数的时间
  • total ms/call:每一次调用,花费在函数及其依赖函数的平均时间
  • name:函数名
$ gprof ./gprof_test gmon.out -b
Flat profile: Each sample counts as 0.01 seconds.
% cumulative self self total
time seconds seconds calls ns/call ns/call name
75.82 0.30 0.30 62135400 4.88 4.88 step
20.22 0.38 0.08 499999 161.76 768.35 nseq
2.53 0.39 0.01 frame_dummy
2.53 0.40 0.01 main

Call graph 信息解释:

  • index:索引值
  • % time:函数消耗时间占所有时间百分比
  • Self:函数本身执行时间
  • Children:执行子函数所用时间
  • Called:被调用次数
  • Name:函数名
index % time    self  children    called     name
<spontaneous>
[1] 97.5 0.01 0.38 main [1]
0.08 0.30 499999/499999 nseq [2]
-----------------------------------------------
0.08 0.30 499999/499999 main [1]
[2] 95.0 0.08 0.30 499999 nseq [2]
0.30 0.00 62135400/62135400 step [3]
-----------------------------------------------
0.30 0.00 62135400/62135400 nseq [2]
[3] 75.0 0.30 0.00 62135400 step [3]
-----------------------------------------------
<spontaneous>
[4] 2.5 0.01 0.00 frame_dummy [4]
----------------------------------------------- Index by function name [4] frame_dummy [2] nseq
[1] main [3] step

缺点

  • 只能分析应用程序在运行过程中所消耗掉的用户时间,无法得到程序内核空间的运行时间。

    查看内核空间运行时间的方式,可以使用time命令:

    $ time ./test
    real 0m0.591s 实际运行时间
    user 0m0.498s 用户态运行时间
    sys 0m0.093s 内核态运行时间
  • 分析的执行时间不包括由于挂起和阻塞的时间,所以对于有大量阻塞调用和休眠挂起的程序,使用gprof进行分析,并不能很好的分析出程序瓶颈的所在。gprof以固定的周期对程序运行时间进行采样测量,当程序挂起时,gprof不会对程序进行采样测量。

    解决方式:如果只对某部分代码进行分析,可以在不需要进行分析的代码段调用moncontrol(0)关闭分析,然后在需要分析的代码段调用moncontrol(1)打开分析。

    extern void moncontrol(int);
    moncontrol(0);
    moncontrol(1);
  • 不支持动态库中的函数分析

GNU gprof分析C性能的更多相关文章

  1. C/C++性能测试工具GNU gprof

    代码剖析(Code profiling)程序员在优化软件性能时要注意应尽量优化软件中被频繁调用的部分,这样才能对程序进行有效优化.使用真实的数据,精确的分析应用程序在时间上的花费的行为就成为_代码剖析 ...

  2. GNU Linux高并发性能优化方案

    /*********************************************************** * Author : Samson * Date : 07/14/2015 * ...

  3. 使用show profiles分析SQL性能

    如何查看执行SQL的耗时 使用show profiles分析sql性能. Show profiles是5.0.37之后添加的,要想使用此功能,要确保版本在5.0.37之后. 查看数据库版本 mysql ...

  4. google perftools分析程序性能

    Google perftools 1.功能简介 它的主要功能就是通过采样的方式,给程序中cpu的使用情况进行“画像”,通过它所输出的结果,我们可以对程序中各个函数(得到函数之间的调用关系)耗时情况一目 ...

  5. 【MS SQL】通过执行计划来分析SQL性能

    原文:[MS SQL]通过执行计划来分析SQL性能 如何知道一句SQL语句的执行效率呢,只知道下面3种: 1.通过SQL语句执行时磁盘的活动量(IO)信息来分析:SET STATISTICS IO O ...

  6. 用 CPI 火焰图分析 Linux 性能问题

    https://yq.aliyun.com/articles/465499 用 CPI 火焰图分析 Linux 性能问题   yangoliver 2018-02-11 16:05:53 浏览1076 ...

  7. 【PHP】善用php-fpm的慢执行日志slow log,分析php性能问题

    (转)善用php-fpm的慢执行日志slow log,分析php性能问题  众所周知,mysql有slow query log,根据慢查询日志,我们可以知道那些sql语句有性能问题.作为mysql的好 ...

  8. 大数据学习--day14(String--StringBuffer--StringBuilder 源码分析、性能比较)

    String--StringBuffer--StringBuilder 源码分析.性能比较 站在优秀博客的肩上看问题:https://www.cnblogs.com/dolphin0520/p/377 ...

  9. Nginx 日志分析及性能排查

    Nginx 日志分析及性能排查 2017-03-04 Linux爱好者 (点击上方公众号,可快速关注) 作者:-外星人- my.oschina.net/362228416/blog/844713 如有 ...

  10. mysql show profiles使用分析sql性能

    mysql show profiles使用分析sql性能 Show profiles是5.0.37之后添加的,要想使用此功能,要确保版本在5.0.37之后. 查看一下我的数据库版本 mysql> ...

随机推荐

  1. ImageJ使用教程(一):开始使用

    目录 简介 界面介绍 Edit->Options 开始使用 打开图片 放大拖拽 图片信息 色彩分析 保存图片 总结 参考文章 ImageJ软件 简介 ImageJ是一个基于java的公共的图像处 ...

  2. Ajax 原理是什么?如何实现?

    一.是什么 AJAX全称(Asynchronous Javascript And XML) 即异步的JavaScript 和XML,是一种创建交互式网页应用的网页开发技术,可以在不重新加载整个网页的情 ...

  3. pid算法函数实现,c语言版

    #include <stdio.h> float pid(float setpoint, float process_variable, float kp, float ki, float ...

  4. 深入了解PBKDF2:密码学中的关键推导函数

    title: 深入了解PBKDF2:密码学中的关键推导函数 date: 2024/4/20 20:37:35 updated: 2024/4/20 20:37:35 tags: 密码学 对称加密 哈希 ...

  5. 前端直接获取用户IP的方法

    前端直接获取用户IP的方法 简单来说就是使用两个接口 一个是太平洋网 <script src="//whois.pconline.com.cn/ipJson.jsp?callback= ...

  6. 力扣196(MySQL)-删除重复的电子邮箱(简单)

    题目: 表: Person 编写一个 SQL 删除语句来 删除 所有重复的电子邮件,只保留一个id最小的唯一电子邮件. 以 任意顺序 返回结果表. (注意: 仅需要写删除语句,将自动对剩余结果进行查询 ...

  7. 力扣553(java)-最优除法(中等)

    题目: 给定一组正整数,相邻的整数之间将会进行浮点除法操作.例如, [2,3,4] -> 2 / 3 / 4 . 但是,你可以在任意位置添加任意数目的括号,来改变算数的优先级.你需要找出怎么添加 ...

  8. 阿里云全站加速DCDN重磅发布!打造新一代加速引擎

    简介: 新一代的加速引擎DCDN,安全.高效.可计算 在数字化转型变革逐步深入的当下,安全高效成为企业上云.全球化部署的关键需求. 随着应用场景复杂度不断提升.业务需求差异化发展,为了给企业提供更完善 ...

  9. Helm Chart 多环境、多集群交付实践,透视资源拓扑和差异

    简介: 在本文中,我们将介绍如何通过 KubeVela解决多集群环境下 Helm Chart 的部署问题.如果你手里没有多集群也不要紧,我们将介绍一种仅依赖于 Docker 或者 Linux 系统的轻 ...

  10. WPF 更改 DrawingVisual 的 RenderOpen 用到的对象的内容将持续影响渲染效果

    在 WPF 里面,可以通过 DrawingVisual 来进行使用底层的绘制方法,此方法需要调用 DrawingVisual 的 RenderOpen 拿到 DrawingContext 类型的对象, ...