gdb 基础用法:https://www.daodaodao123.com/?p=665
1.gdb 与多线程
案例代码:
#include <stdio.h>
#include <pthread.h>
#include <sys/types.h>
#include <signal.h>
struct thread_param
{
char info;
int num;
int delay;
};
void* thread_fun(void* param)
{
struct thread_param* p;
p=(struct thread_param*)param;
int i;
printf("thread pid:%d, tid:%lu\n",getpid(), pthread_self());
for(i=0;i<p->num;i++){
#if 0 /* change to #if 1 for debugging high cpu-loading issues */
while(1);
#else
sleep(p->delay);
#endif
printf("%i: %c\n",i,p->info);
}
return NULL;
}
int main(void)
{
pthread_t tid1,tid2;
struct thread_param info1;
struct thread_param info2;
int ret;
printf("main pid:%d, tid:%lu\n",getpid(), pthread_self());
info1.info='T';
info1.num=2000000;
info1.delay=1;
ret=pthread_create(&tid1,NULL,thread_fun,&info1);
if(ret==-1){perror("cannot create new thread");
return 1;
}
info2.info='S';
info2.num=300000;
info2.delay=2;
ret=pthread_create(&tid2,NULL,thread_fun,&info2);
if(ret==-1){perror("cannot create new thread");
return 1;
}
if(pthread_join(tid1,NULL)!=0){perror("call pthread_join function fail");
return 1;
}
if(pthread_join(tid2,NULL)!=0){perror("call pthread_join function fail");
return 1;
}
return 0;
}
1.1 查看指定线程信息
i threads
查看所有线程的 backtrace, 针对 coredump 文件,用该命令查看程序宕机时,每个线程具体执行到那个地方;
thread apply all bt
查看线程 1 的 backtrace
thread apply 1 bt
1.2 设置断点
(1) 默认情况下,断点对所有线程有效
b 28
(2) 设定断点读特定线程有效
b 28 thread 2
1.3 单独运行某个线程
thread 2
set scheduler-locking on
#取消锁定
set scheduler-locking off
性能分析源码:
#include <pthread.h>
func_d()
{
int i;
for(i=0;i<50000;i++);
}
func_a()
{
int i;
for(i=0;i<100000;i++);
func_d();}
func_b()
{
int i;
for(i=0;i<200000;i++);
}
func_c()
{
int i;
for(i=0;i<300000;i++);
}
void* thread_fun1(void* param)
{while(1) {
int i;
for(i=0;i<100000;i++);
func_a();
func_b();
func_c();}
}
void* thread_fun2(void* param)
{while(1) {
int i;
for(i=0;i<100000;i++);
func_a();
func_b();
func_c();}
}
int main(void)
{
pthread_t tid1,tid2;
int ret;
ret=pthread_create(&tid1,NULL,thread_fun1,NULL);
if(ret==-1){perror("cannot create new thread");
return 1;
}
ret=pthread_create(&tid2,NULL,thread_fun2,NULL);
if(ret==-1){perror("cannot create new thread");
return 1;
}
if(pthread_join(tid1,NULL)!=0){perror("call pthread_join function fail");
return 1;
}
if(pthread_join(tid2,NULL)!=0){perror("call pthread_join function fail");
return 1;
}
return 0;
}
编译
$ gcc -g test.c -lpthread
2.Intel 平台多线程性能分析工具:Intel VTune Profiler
https://www.intel.com/content/www/us/en/developer/tools/oneapi/vtune-profiler.html#gs.qcqcrv
3.perf
(1) 采样
sudo perf recored -s ./a.out // 生成 perf.data 文件
(2) 分析采样数据
sudo perf report -n -T // 分析采样数据,包括所有线程
sudo perf report -n -T --tid xxxx // 分析指定线程 xxxx cpu 消耗
(3)perf 录制,生成火焰图
perf recore -F 99 -a -g -- ./a.out
perf script | ../stackcollapse-perf.pl > out.perf-folded
../flamegraph.pl out.perf-fouded > perf-kernel.svg
firefox perf-kernel.svg
4.valgrind
(1) 采集数据
valgrind --tool=callgrind --separate-threads=yes ./a.out
生成如下文件:
callgrind.out.4427 进程级的数据,包括所有线程
callgrind.out.4427-01 // 特定线程的数据
callgrind.out.4427-02
callgrind.out.4427-03
(2) 用图形化工具 kcachegrinkcache 查看分析数据
查看整个进程级数据
kcachegrinkcache callgrind.out.4427
查看线程 2 数据
注:在嵌入式中,可以在设备端用 valgrind 采集数据,在 PC 端用 kcachegrinkcache 图像化工具查看分析;
5 top 命令
(1)top 进程视角
(2)top -H 线程视角
按 1, 显示多个核信息
(3) 只查看指定线程信息
top -H -p `pidof a.out`
(4) 按“f”可以配置显示信息
(5)htop 增强型的线程视角
htop -p `pidof a.out`
(6) 用 perf 录像
sudo perf sched record -a sleep 20
生成 perf.data
sudo perf timechart
生成矢量图, 用 firefox 查看
firefox output.svg
正文完