Linux C++ 开发9

cnblogs 2024-09-30 16:09:01 阅读 53

  • 1. 什么是gprof?
  • 2. gprof的用法
    • 2.1. 编译程序
    • 2.2. 运行程序
    • 2.3. 生成分析报告
    • 2.4. gprof常用参数说明
    • 2.5. 分析报告解读
      • 2.5.1. <code>Flat profile 各个字段的含义
      • 2.5.2. Call graph 各个字段的含义
  • 3. Demo演示
    • 3.1. demo04.cpp 源码
    • 3.2. 编译、运行和分析
    • 3.3. 查看分析报告

1. 什么是gprof?

gprof 这是一个GNU的性能分析工具,它是GCC(GNU Compiler Collection,GNU编译器套件)的一部分,与GCC编译器紧密集成。可用于分析程序的函数调用关系和每个函数的运行时间。它通过在编译时插入性能分析代码来收集函数调用信息和执行时间,来帮助开发者识别性能瓶颈。

gprof的优点:

  • 可以方便的分析程序的函数调用关系和每个函数的运行时间。
  • gprof对于代码大部分是用户空间的CPU密集型的程序用处明显。

gprof的缺点:

  • 对于大部分时间运行在内核空间或者由于外部因素(例如操作系统的 I/O 子系统过载)而运行得非常慢的程序难以进行优化。
  • gprof默认不支持多线程程序。(gprof采用ITIMER_PROF信号,在多线程内只有主线程才能响应该信号)
  • 默认不支持共享库程序。

2. gprof的用法

2.1. 编译程序

首先,需要使用 -pg 选项编译你的程序:

g++ -pg -o my_program my_program.cpp

除了-pg外,还有一个参数-p,它可以生成适合prof性能分析工具的代码,他们之间的区别如下:

  • -p: 可以生成适合prof性能分析工具的代码。
  • -pg: 可以生成适合gprof性能分析工具的代码,也就是profile information for gprof的含义。

要理解上面描述,又不得不了解profgprof两个工具的关系了。

  • prof是一个较早的性能分析工具,最初在UNIX系统上使用。编译时加上-p选项,生成的可执行文件会在运行时收集性能分析数据。然后通过prof工具再生成性能分析报告。
  • gprof是GNU项目的一部分,是一个更现代的性能分析工具,它的功能与prof类似,但比prof提供了更多的功能和更好的用户体验。而且程序运行时输出的性能分析数据也更丰富、详细。现在gprof几乎取代了prof

2.2. 运行程序

编译完成后,运行你的程序:

./my_program

运行过程中,gprof 会生成一个名为 gmon.out 的文件,其中包含了性能分析数据。

2.3. 生成分析报告

运行完程序后,使用 gprof 工具生成分析报告:

gprof my_program gmon.out > analysis_report.txt

生成的 analysis_report.txt 文件中包含了函数的调用时间、调用次数等详细信息。

2.4. gprof常用参数说明

gprof命令格式:

gprof [options] [executable-file [profile-data-files…]] [> outputfile] Gprof命令行格式 Gprof command line format

options参数说明:

命令 中文解释 英文解释
-b 简洁输出,不显示冗长的解释 Brief output. Do not display verbose explanations
-s 将多个gmon.out文件合并 Summarize: merge several profile data files for cumulative stats
-p 显示程序的每个函数的执行时间统计 Display program’s functions execution time statistics
-q 显示程序的每个函数的调用关系 Display program’s

2.5. 分析报告解读

gprof 生成的报告通常包含以下几个部分:

  • Flat profile: 显示每个函数的执行时间、调用次数等信息。
  • Call graph: 显示函数之间的调用关系和每个函数的执行时间。

2.5.1. Flat profile 各个字段的含义

字段 含义
% time 该函数消耗时间占程序所有时间百分比
Cumulative seconds 程序的累积执行时间(只是包括gprof能够监控到的函数)
Self Seconds 该函数本身执行时间(所有被调用次数的合共时间)
Calls 函数被调用次数
Self TS/call 函数平均执行时间(不包括被调用时间,函数的单次执行时间)
Total TS/call 函数平均执行时间(包括被调用时间,函数的单次执行时间)
name 函数名

2.5.2. Call graph 各个字段的含义

字段 含义
Index 索引值
%time 函数消耗时间占所有时间百分比
Self 函数本身执行时间
Children 执行子函数所用时间
Called 被调用次数
Name 函数名

3. Demo演示

3.1. demo04.cpp 源码

#include <iostream>

int64_t add(int64_t a, int64_t b)

{

return a + b;

}

void func1()

{

int sum = 0;

for (int i = 0; i < 1000000; ++i)

{

sum = add(sum, i);

}

std::cout << "Sum of 0 to 999999 is " << sum << std::endl;

}

void func2()

{

int sum = 0;

for (int i = 0; i < 500000; ++i)

{

sum = add(sum, i);

}

std::cout << "Sum of 0 to 499999 is " << sum << std::endl;

}

int main()

{

func1();

func2();

return 0;

}

3.2. 编译、运行和分析

# 编译程序

g++ -pg ./demo04.cpp -o ./demo04.out

# 运行程序

./demo04.out

# 生成分析报告

gprof ./demo04.out ./gmon.out > analysis_report04.txt

# 也可以使用下面的命令,生成的报告更加简洁,没有冗余信息

gprof -b ./demo04.out ./gmon.out > analysis_report04.txt

3.3. 查看分析报告

打开analysis_report04.txt,可以看到类似如下的输出:

Flat profile:

Each sample counts as 0.01 seconds.

no time accumulated

% cumulative self self total

time seconds seconds calls Ts/call Ts/call name

0.00 0.00 0.00 1500000 0.00 0.00 add(long, long)

0.00 0.00 0.00 1 0.00 0.00 func1()

0.00 0.00 0.00 1 0.00 0.00 func2()

...

Call graph (explanation follows)

granularity: each sample hit covers 4 byte(s) no time propagated

index % time self children called name

0.00 0.00 500000/1500000 func2() [10]

0.00 0.00 1000000/1500000 func1() [9]

[8] 0.0 0.00 0.00 1500000 add(long, long) [8]

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

0.00 0.00 1/1 main [6]

[9] 0.0 0.00 0.00 1 func1() [9]

0.00 0.00 1000000/1500000 add(long, long) [8]

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

0.00 0.00 1/1 main [6]

[10] 0.0 0.00 0.00 1 func2() [10]

0.00 0.00 500000/1500000 add(long, long) [8]

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

...

Index by function name

[8] add(long, long) [9] func1() [10] func2()

通过这些信息,可以清楚地看到 func1 和 func2 的执行时间和调用次数,从而进行针对性的优化。

历史文章推荐:

  • Linux C++ 开发10 - 手把手教你使用valgrind性能分析工具

  • Linux C++ 开发9 - 手把手教你使用gprof性能分析工具

  • Linux C++ 开发8 - 性能分析工具汇总

  • Linux C++ 开发7 - GDB常用命令汇总

  • Linux C++ 开发6 - GDB调试入门指南

  • Linux C++ 开发5 - 一文了解CMake构建

  • Linux C++ 开发4 - 入门makefile一篇文章就够了

  • Linux C++ 开发3 - 你写的Hello world经过哪些过程才被计算机理解和执行?

  • Linux C++ 开发2 - 编写、编译、执行第一个程序

  • VSCode系列2 - 如何用VSCode搭建C++高效开发环境?

  • Linux C++ 开发1 - 搭建C++开发环境


大家好,我是陌尘。

IT从业10年+, 北漂过也深漂过,目前暂定居于杭州,未来不知还会飘向何方。

搞了8年C++,也干过2年前端;用Python写过书,也玩过一点PHP,未来还会折腾更多东西,不死不休。

感谢大家的关注,期待与你一起成长。



【SunLogging】

扫码二维码,关注微信公众号,阅读更多精彩内容


上一篇: Python学习路线

下一篇: Linux C++ 开发10

本文标签

gprof    分析    时间    函数    程序   


声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。