怎么统计c的代码执行中每个步骤的耗时并且生成易读的报告

怎么统计c的代码执行中每个步骤的耗时并且生成易读的报告,最好简单点,不要大量报错,类似perf,但perf可能因为权限问题无法执行下去,手动在代码里面插桩不用考虑了,需要统计很广的范围

如果你想统计 C 代码中各个步骤的耗时,并生成易读的报告,同时避免手动插桩和 perf 的权限问题,可以考虑以下几种 轻量级、自动化 的方案:

使用perf

1. 记录函数耗时(采样)

perf record -F 99 -g ./your_program

2. 生成报告(火焰图或文本)

perf report -n --stdio # 文本模式

git clone https://github.com/brendangregg/FlameGraph.git
cd FlameGraph

方案 1:使用 gcc 的 -finstrument-functions 自动插桩
GCC 和 Clang 支持 编译时自动插桩,可以在每个函数入口/出口插入计时代码,无需手动修改源码。

2. 生成火焰图(确保在 FlameGraph 目录或指定完整路径)

perf script | ./FlameGraph/stackcollapse-perf.pl | ./FlameGraph/flamegraph.pl > flamegraph.svg

步骤
编译时启用插桩
在编译时添加 -finstrument-functions 选项:

bash
复制
gcc -finstrument-functions -o my_program my_program.c
定义插桩回调函数
在你的代码中添加以下函数,它们会在每个函数调用前后自动执行:

c
复制
#include <stdio.h>
#include <time.h>

void __cyg_profile_func_enter(void *func, void *caller) {
printf(“Enter: %p\n”, func);
}

void __cyg_profile_func_exit(void *func, void *caller) {
printf(“Exit: %p\n”, func);
}
运行程序并生成日志

bash
复制
./my_program > trace.log
解析日志生成报告
使用 addr2line 或自定义脚本将函数地址转换为函数名:

bash
复制
addr2line -e my_program -f < trace.log
优点
无需手动插桩,自动记录所有函数调用。

低侵入性,只需添加两个回调函数。

缺点
输出较原始,需要额外解析日志。

可能影响性能,频繁的函数调用会增加开销。

方案 2:使用 ltrace 跟踪库函数调用
ltrace 可以动态跟踪程序调用的库函数,并统计耗时。

步骤
安装 ltrace

bash
复制
sudo apt install ltrace # Ubuntu/Debian
sudo yum install ltrace # CentOS/RHEL
运行程序并记录耗时

bash
复制
ltrace -T -c ./my_program
-T:显示每个调用的耗时。

-c:生成汇总报告。

示例输出
复制
% time seconds usecs/call calls function


30.00 0.300000 300 1000 malloc
20.00 0.200000 200 1000 free
10.00 0.100000 100 1000 printf
优点
无需修改代码,直接运行即可。

统计库函数调用,适合分析标准库/第三方库。

缺点
只能跟踪动态库调用,无法统计内部函数。

可能影响性能,特别是高频调用的函数。

方案 3:使用 strace 跟踪系统调用
strace 可以统计系统调用的耗时,适合分析 I/O、进程等底层操作。

步骤
安装 strace

bash
复制
sudo apt install strace # Ubuntu/Debian
sudo yum install strace # CentOS/RHEL
运行程序并记录耗时

bash
复制
strace -c ./my_program
示例输出
复制
% time seconds usecs/call calls errors syscall


50.00 0.500000 500 1000 read
30.00 0.300000 300 1000 write
20.00 0.200000 200 1000 open
优点
无需修改代码,直接运行即可。

统计系统调用,适合分析文件、网络等操作。

缺点
仅限系统调用,无法统计用户态函数。

方案 4:使用 time 命令统计总耗时
如果只需要粗略统计整个程序的运行时间,可以使用 time 命令:

bash
复制
time ./my_program
输出示例:

复制
real 0m1.234s # 实际运行时间
user 0m0.987s # 用户态时间
sys 0m0.123s # 内核态时间
优点
最简单,无需任何额外工具。

适合快速评估 整体性能。

缺点
无法细化到函数级别。

方案 5:使用 gprof 生成函数级性能报告
gprof 是 GNU 的性能分析工具,可以统计函数调用关系和耗时。

步骤
编译时启用 -pg

bash
复制
gcc -pg -o my_program my_program.c
运行程序生成 gmon.out

bash
复制
./my_program
生成报告

bash
复制
gprof my_program gmon.out > report.txt
示例输出
复制
Flat profile:
Each sample counts as 0.01 seconds.
% cumulative self self total
time seconds seconds calls ms/call ms/call name
50.00 0.50 0.50 1000 0.50 0.50 foo
30.00 0.80 0.30 1000 0.30 0.30 bar
20.00 1.00 0.20 1000 0.20 0.20 baz
优点
函数级统计,适合分析热点函数。

无需额外运行时依赖。

缺点
需要重新编译(-pg 选项)。

不支持多线程程序(可能不准确)。

总结对比
方案 适用场景 是否需要改代码 统计粒度 易用性
-finstrument-functions 函数级统计 需添加回调函数 函数级 ⭐⭐⭐
ltrace 库函数调用统计 无需改代码 库函数级 ⭐⭐⭐⭐
strace 系统调用统计 无需改代码 系统调用级 ⭐⭐⭐⭐
time 整体耗时 无需改代码 进程级 ⭐⭐⭐⭐⭐
gprof 函数级耗时 需 -pg 编译 函数级 ⭐⭐⭐
推荐选择
如果想自动统计所有函数调用 → -finstrument-functions

如果想统计库函数调用 → ltrace

如果想统计系统调用 → strace

如果想快速查看整体耗时 → time

如果想生成函数级报告 → gprof

这些方法都不需要 perf 的高权限,且适用于大多数 Linux 环境。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值