《锁长期等待》项目大作业解析

举报
Tianyi_Li 发表于 2022/11/28 17:11:16 2022/11/28
【摘要】 通过性能分析工具找出程序中加锁范围不合理的地方并解决。多线程程序,经常存在锁不合理长期占用的问题。这次主要针对这一问题,通过鲲鹏性能分析工具资源调度功能来观测,建议在分析业务逻辑将不需要锁的计算移出互斥量加锁操作。

锁长期等待》项目大作业解析

一、作业题目

通过性能分析工具找出程序中加锁范围不合理的地方并解决。

多线程程序,经常存在锁不合理长期占用的问题。这次主要针对这一问题,通过鲲鹏性能分析工具资源调度功能来观测,建议在分析业务逻辑将不需要锁的计算移出互斥量加锁操作。

二、操作前提

1)认真观看迁移工具的实战视频。

2)在鲲鹏社区申请远程实验室,操作系统选择OpenEuler。

https://www.hikunpeng.com/zh/developer/devkit

3)这里选择远程服务器,具体配置和信息如下图所示。


申请之后,会收到一封邮件,里面会有详细的环境配置信息。

三、准备工作

1. 登录服务器,并准备代码

a. 使用MobaXterm工具,以root用户登录服务器。

b. 将文件pthread_mutex_long.c上传到home目录,并赋予所有用户只读、只写、可执行权限。

pthread_mutex_long.c可从如下GitHub仓库获取https://github.com/kunpengcompute/devkitdemo/tree/main/Hyper_tuner/testdemo/lock  

赋予所有用户只读、只写、可执行权限命令如下:

chmod 777 pthread_mutex_long.c

c.编译pthread_mutex_long.c并赋予执行文件所有用户只读、只写、可执行权限

gcc -g pthread_mutex_long.c -o pthread_mutex_long -lpthread -lm && chmod 777 pthread_mutex_long

d.绑核到CPU 0,1,使用后台运行程序,需要确定0-1核上没有其他程序正在绑核运行nohup命令使得即使退出账户之后会继续运行相应的进程,防止任务中断。

nohup taskset -c 0-1 ./pthread_mutex_long >>pthread_mutex_long.out 2>&1 &

程序运行的输出(标准输出(1))将会保存到pthread_mutex_long.out文件,错误信息(2)会重定向到pthread_mutex_long.out文件。

操作步骤截图

1. 登录鲲鹏性能分析工具Web界面

具体登录信息可在邮件中查看,注意需要登录VPN。

登录后,自动跳转到如下界面:


2. 利用鲲鹏性能分析工具创建系统全景分析任务,分析当前程序

选择系统性能分析,首先要新建一个工程,具体如下图:

a. 创建系统全景分析任务,启动分析。

具体配置如上图所示点击开始分析分析完成后,会进入如下界面

如下为一些具体的截图:

系统全景分析结果总

 系统全景性能分析结果(系统性能

从上图可以看出,当前有CPU01的使用率(%user的数值)偏高,两者相加在100%左右。

系统全景性能分析结果(进程性能

3. 采用进程/线程性能分析,找到是哪个进程造成的CPU消耗。

a. 创建进程/线程分析任务,并启动分析,具体配置如下图

b. 查看采集分析结果。

进程/线程分析结果总截图如下所示,图中默认排序是按照PID/TID升序排列

为了观察哪个进程造成了CPU消耗,需要点击%CPU列旁边按钮,进行降序排列,如下图所示,可以看到pthread_mutex_l程序在消耗大量的CPU

3. 采用系统资源调度分析,确定看出pthread_mutex_l程序进程及线程的切换次数及抢占情况。

a创建资源调度分析任务,并启动分析。

b查看采集分析结果

资源调度分析结果总截图:


在“总览”页签中,点击线程名、PID或者TID旁边的过滤按钮,可以选择想要观察的线程,从以上两个步骤的分析得知pthread_mutex_l程序存在问题,所以我们直接找这个程序所对应的PID,通过PID旁边的过滤按钮,过滤出pthread_mutex_l进程,如下图所示。

在“进程/线程调度”的页签中,可以看到pthread_mutex_l两个线程之间情况。绿色代表当前线程处于运行状态,橙色代表当前线程处于等待状态,观察可以发现pthread_mutex_l两个进程之间存在一个线程长期占用(绿色部分)而另一个线程长期等待状态(橙色部分),而没有平衡的相互交替运行(橙色绿色在两个线程中的长度相等)。如下图所示。将鼠标或者使用触摸板放在调度图上,滑动鼠标滚轮,可以放大、缩小图片,可以更清楚地看到等待运行的分布情况。

由此,我们可以推断两个线程在频繁抢占,最有可能就是有锁等互斥量操作。其中一个线程长期占用锁,导致另一个线程无法得到锁而长期等待。

4. 热点函数分析

a创建热点函数分析任务,并启动分析。


b查看采集分析结果

如下图所示为热点函数分析任务结果-总。我们可以看到这个模块/home/pthread_mutex_long时钟周期百分比在88%以上,符合我们的预期




通过对热点函数的源码分析,发现其中有一段业务逻辑并不涉及并发的场景,并且这块业务逻辑是Func函数中热度最高的,如下图所示,理论上完全可以移到锁的范围之外去。


下面开始优化代码,将不需要互斥的操作移到pthread_mutex_unlock()之后。优化前后对比如下图所示。

好了,代码优化后,我们重新启动验证一下。不过,我们先结束当前程序,通过jobs -l查看pthread_mutex_long程序运行pid(如果程序尚未结束,可以看到后台运行的程序),通过kill -9结束进程。

jobs -l

kill -9 <pthread_mutex_long程序pid>

操作截图如下:


5. 重新运行程序

a. 重新编译pthread_mutex_long.c并赋予执行文件所有用户只读、只写、可执行权限。

gcc -g pthread_mutex_long.c -o pthread_mutex_long -lpthread -lm && chmod 777 pthread_mutex_long

b.绑核到CPU 0,1,使用后台运行程序,需要确定0-1核上没有其他程序正在绑核运行。

nohup taskset -c 0-1 ./pthread_mutex_long >>pthread_mutex_long.out 2>&1 &

操作截图如下图所示:

c.采用系统资源调度分析。

创建系统资源调度分析任务,并启动运行,如下图所示:


查看分析结果,在“总览”页签中,点击线程名、PID或者TID旁边的过滤按钮,可以选择pthread_mutex_l,可以发现切换次数相较优化前大幅减少。如下图所示。


“进程/线程调度”页签中,可以看到pthread_mutex_l两个线程之间情况。如下图所示,可以看出,此时,两个线程切换时等待时间很短(橙色部分),这段时间用于计算需要互斥的全局变量,除此之外,两个线程可以并发运行不需要互斥操作的计算(绿色部分),大幅度提升了计算性能。

最后不要忘记结束样例程序。

通过jobs -l查看pthread_mutex_long_mod程序运行pid(如果程序尚未结束,可以看到后台运行的程序),通过kill -9结束进程。具体命令如下:

jobs -l

kill -9 <pthread_mutex_long_mod程序pid>

操作截图如下所示:

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。