【系列三:DevKit性能分析工具】第三讲:《锁长期等待》项目大作业解析
【系列三:DevKit性能分析工具】第三讲:《锁长期等待》项目大作业解析
准备工作
这里,我们使用的环境是鲲鹏社区提供的远程实验室,因为已经安装好了工具,所以可以直接使用。下面是一些步骤:
下面是更为详细的记录:
1、打开网页,找到测试程序 :pthread_mutex_long.c
,复制里面的内容到本地同名的文件里:
这里我是直接在远程实验室的服务器上创建了一个同名文件,之后从GitHub复制代码到创建的文件,保存。主要用到的命令如下:
创建文件:
touch pthread_mutex_long.c
保存文件:
:wq!
因此,下面第二步可以不做了。
2、本地电脑通过ssh工具(如:MobalXtem)将pthread_mutex_long.c
上传到远程实验室的服务器上,如 /home目录下
3、授权文件:chmod 777 pthread_mutex_long.c
4、编译程序:gcc -g pthread_mutex_long.c -o pthread_mutex_long -lpthread -lm && chmod 777 pthread_mutex_long
运行截图:
5、绑核启动:taskset -c 0-1 ./pthread_mutex_long
运行截图如下:
程序一直在运行,不断打印。
程序性能分析
首先,还是先登录,登录界面如下图所示:
登录成功后,就来到了上一讲所介绍的四个子工具界面,如下图所示,具体功能之前介绍过了。
创建工程
这次我们主要用的是系统性能分析,点击去,先来建个工程:
工程创建好后,就是创建采集任务,新建一个分析任务,如下图所示:
查看分析
等分析完成后,进入总览页,可以看到优化建议,还是很详细的,同时附加了修改方法,可以作为参考,如下图所示:
从上图可以看到,展示了非常详尽的信息,受篇幅限制,不方便全部展示,其实实际页面展示的更多,可以很有效帮助我们掌握系统情况。如上图所示,“总览”页签上方会显示“检测到CPU利用率高”的优化建议。其实,从“性能”页签的CPU利用率可以看到图形化界面的top5 %cpu对应的CPU核在采集时间内的利用率变化。而从系统全景性能分析结果(时序图),可以看到当前有CPU核0,1的使用率(“性能”页签下%cpu的数值)偏高,两者相加在100%左右。
下面来到性能界面,使用表格模式查看,如下图所示。这里,我们看看用户态利用率,这里说的是我们自己的程序本身的使用情况。此外,还要看内核态,内核态和用户态综合考虑,才能判断程序的情况。
比如,我们对用户态使用率排序,可以发现CPU 0的用户态利用情况在78%以上,这一点和我们在总览界面看到的相吻合。通过进程/线程性能分析,找到是哪个进程造成的CPU消耗。
这里可以注意下NUMA内存统计情况,特别注意跨节点访问内存的情况,这种情况一般是很费时间的,应注重优化。
这里经过分析发现,主要是CPU的负载情况待优化,而内存、存储、网络等没什么问题。接下来就该主要针对CPU分析,具体来说就是对进程和线程分析了。我们进一步分析,可以得到优化建议,可以看到一个技巧,就是减少NUMA访间内存,不同NUMA内的CPU core访间同一个位置的内存,性能不同,内存访问延时从高到低为:跨CPU > 跨NUMA不跨CPU > NUMA内,这一点我们前面也提到了。
运行完成后,查看采集分析结果。我们先来看看下图的进程/线程分析结果总览:
默认排序是按照PID/TID升序排列,为了观察哪个进程造成了CPU消耗,需要点击CPU列旁边的按钮进行降序排列,如下图所示,可以看到pthread_mutex_l程序在消耗大量的CPU,这个正好也是我们启动的测试程序。
而采用系统资源调度分析,确定看出pthread_mutex_l程序进程及线程的切换次数及抢占情况。下面来创建资源调度分析任务,并启动分析。具体配置截图如下所示:
在“总览”页签中,点击线程名、PID或者TID旁边的过滤按钮 ,可以选择想要观察的线程,从以上两个步骤的分析得知pthread_mutex_l程序存在问题,所以我们直接找这个程序所对应的PID,通过PID旁边的过滤按钮 ,过滤出pthread_mutex_l进程,如下图所示,资源调度分析任务结果-总览。
如下图所示,在“进程/线程调度”的页签中,可以看到pthread_mutex_l两个线程之间情况。绿色代表当前线程处于运行状态,橙色代表当前线程处于等待状态,观察可以发现pthread_mutex_l两个进程之间存在一个线程长期占用(绿色部分)而另一个线程长期等待状态(橙色部分),而没有平衡的相互交替运行(橙色绿色在两个线程中的长度相等)。这也是关键截图四: 资源分析任务结果-进程/线程调度。
我们发现在采样期间两个线程之间的调度没有交集,没有平衡的相互交替运行,我们可以推断两个线程可能在抢占某个资源,最有可能就是有锁等互斥量操作。其中一个线程长期占用锁,导致另一个线程无法得到锁而长期等待。注意,如果环境的性能较好,等待时间会相对较短并且交替会相对平衡,所以在整个时间段上两个线程都显示绿色,可以通过放大图片,观察到具体等待与运行时间的分布,橙色和绿色的分布差异不会特别大。
对了,如果将鼠标放在调度图上,滑动鼠标滚轮,可以放大、缩小图片,可以更清楚地看到等待运行的分布情况。
如果进行热点函数分析的话,发现其中有一段业务逻辑并不涉及并发的场景,并且这块业务逻辑是Func函数中热度最高的,完全可以移到锁的范围之外去。
接下来优化代码,将不需要互斥的操作移到pthread_mutex_unlock()之后。优化之前代码:
优化之后的代码:
之后编译运行,会发现测试程序的两个线程会平稳的进行,不会存在长时间的等待。
- 点赞
- 收藏
- 关注作者
评论(0)