GDB
- bt: 当前运行的堆栈列表
- print: 输出或者修改指定变量或者表达式的值
- info thread: 显示所有线程信息
- info program: 来查看程序的是否在运行,进程号,被暂停的原因
- run(简写r): 运行程序,当遇到断点后,程序会在断点处停止运行,等待用户输入下一步的命令。
- continue(简写c): 继续执行,到下一个断点处(或运行结束)
- next(简写n): 单步跟踪程序,当遇到函数调用时,直接调用,不进入此函数体;
- step(简写s): 单步调试如果有函数调用,则进入函数;与命令n不同,n是不进入调用的函数的
- until: 运行程序直到退出循环体; / until+行号: 运行至某行
- finish: 运行程序,直到当前函数完成返回,并打印函数返回时的堆栈地址和返回值及参数值等信息
- list 函数名: 将显示“函数名”所在函数的源代码,如: list main
Benchmark
Benchmark是Goole的一个开源基准测试框架,主要用于比较不同代码实现的性能和效率。Benchmak提供了丰富的测试功能,包括时、统计和分析等,可以帮助开发人员优化程序的性能和效率。
- 安装Benchmark
可以使用包管理器或者源代码安装Benchmark。安装sudo apt-get install libbenchmark-dev1
- 编写测试用例
首先,我们需要编写一个简单的测试函数,用于对比不同实现的性能。以计算数组元素之和为例,我们可以编写以下函数.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
static void BM_accumulate(benchmark::State& state)
{
std::vector<int> vec(state.range(0));
std::iota(vec.begin(), vec.end(), 0);
for (auto _ : state) {
int sum = std::accumulate(vec.begin(), vec.end(), 0);
benchmark::DoNotOptimize(sum);
}
}
BENCHMARK(BM_accumulate)->Arg(100)->Arg(1000)->Arg(10000);
这个函数使用了Benchmark提供的 tate 对象,该对象可以帮助我们迭代多次测试,并记录每次测试的结果。在函数中,我们先使用std::vector 生成一个指定大小的数组,并用 std::iota 填数组元素。然后,我们使用 std::accumulate 计算数组元素之和,并调用benchmark::DoNotoptimize 来确保这个计算不会被优化掉,最后,我们使用 BENCHMARK 宏将这个函数注册为基准测试用例,并使用Arg 方法指定测试用例的参数。
- 运行测试
编写测试用例后,我们可以使用 benchmark::RunSpecifiedBenchmarks 函数来运行所有注册的基准测试用例,并生成测试报告。代码如下:1
2
3
4
5int main(int argc, char** argv)
{
::benchmark::Initialize(&argc, argv);
::benchmark::RunSpecifiedBenchmarks();
}
运行后1
2
3
4
5
6
7
8
9
10
11
12
13Run on (8 X 2200 MHz CPU s)
CPU Caches:
L1 Data 32 KiB (x8)
L1 Instruction 32 KiB (x8)
L2 Unified 256 KiB (x8)
L3 Unified 8192 KiB (x1)
Load Average: 1.20, 1.33, 1.18
-------------------------------------------------------------------------
Benchmark Time CPU Iterations
-------------------------------------------------------------------------
BM_accumulate/100 208 ns 208 ns 3251616
BM_accumulate/1000 2236 ns 2236 ns 313125
BM_accumulate/10000 22563 ns 22561 ns 31189
这个报告显示了每个测试用例的执行时间、吞吐量和标准差,以及与其他测试的比较。同时,也会显示出每个测试函数的代码行数和CPU 循环数等重详细的信息。除了默认的报告格式外,Goodle Benchmak 还提供了其他输出格式,例如 JSON、CSV 和 console等可以使用相应的命令行选项进行设置。
Goocle Benchmak 是一个基于 C++ 的高性能基准测试库,可以对代码的运行时间、内存使用和 CPU 循环等方面进行准确的测量和分析,帮助开发者优化代码性能。使用 Google Benchmark,可以轻松编写测试用例,自定义测试参数和运行选项,并生成详细的测试报告,方便分析和比较测试结果。
perf
在Nano上安装perf,参考这里,我下载的页面是
先用ps aux
找到进程的PID,再观察进程内各个函数的CPU使用情况:sudo perf top -p <pid>
记录采样结果,以供后续分析,加上-g会记录调用链:sudo perf record -g -p <pid>
在当前终端读取采样结果:sudo perf report
,会自动读取perf.data
core dump
如果进程在运行期间发生奔溃,操作系统会为进程生成一个快照文件,这个文件就叫做 core dump。之后我们可以对 core dump 文件进行分析,弄清楚进程为什么会奔溃。默认情况下,Linux 不允许生成 core dump 文件。
- 如果执行
ulimit -c
的结果是0,说明还未开启。命令ulimit -c unlimited
只能在当前终端生效,所以加入~/.bashrc
。
指定core dump文件的路径: 修改
/etc/sysctl.conf
,在最后添加kernel.core_pattern=/home/user/coredump_%e_%p_%s_%t
,命名格式为命令名_PID_导致core的信号_UNIX时间
。cat /proc/sys/kernel/core_pattern
可以查看设置的格式。执行
sysctl -p
遇到程序非正常阻塞不运行时,在另一个终端查看其PID,然后使用
kill -s SIGSEGV <pid>
产生 core dump 文件,这样就可以快速重启程序,然后慢慢分析 core dump 文件。
- 执行
gdb ./exec /path/coredump_file
,就可以回放core dump