中文
注册

示例3:锁频繁抢占

简介

多线程程序,经常会存在锁频繁抢占问题,锁的争抢会导致CPU的资源浪费,可以基于实际的业务减少公共资源的抢占。本示例主要针对这一问题,通过鲲鹏DevKit性能分析工具资源调度和锁与等待分析功能来观测,建议用户分析业务逻辑减少锁的争抢,例如大锁变小锁,减少线程并发数等。

环境准备

  1. 请确认服务器上已安装的操作系统是否为Ubuntu 18.04、CentOS 7.6或openEuler 20.03,GCC版本是否为7.3.0及以上。

    本实例采用openEuler 22.03进行试验。

  2. 请确认服务器上是否已安装鲲鹏DevKit系统性能分析工具。
  3. 请从GithubGitee下载代码样例,执行以下命令赋予所有用户可读、可写和可执行权限。

    样例代码文件为:pthread_atomic.c、pthread_mutex.c、pthread_mutex_long.c和pthread_mutex_long_mod.c。

    chmod 777 pthread_mutex.c pthread_atomic.c pthread_mutex_long.c pthread_mutex_long_mod.c

性能分析过程

  1. 程序准备。
    1. 编译pthread_mutex.c并赋予执行文件所有用户可读、可写和可执行权限。
      gcc -g pthread_mutex.c -o pthread_mutex -lpthread && chmod 777 pthread_mutex
      • demo要求GCC版本在7.3以上,若需要关联源码,建议编译时加上-g参数,如:gcc -g pthreadd_mutex.c -o pthread_mutex -lpthread。
      • 本实践除了锁与等待的分析对象为应用级外,其他模块均为系统级调优,进程和资源调度任务为了分析锁抢占情况,锁与等待任务定位优化锁抢占。
    2. 后台运行程序,nohup命令使得即使退出账户之后会继续运行相应的进程,防止任务中断。
      nohup taskset -c 0-1 ./pthread_mutex >>pthread_mutex.out 2>&1 &

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

      该程序一般运行时间为20秒左右,若已运行完成,启动采集任务将无法采集到该程序数据,可修改pthread_mutex.c源码中count参数增加对应运行时间或运行该程序后立即启动采集任务。

    3. 优化后程序pthread_atomic.c使用1.a一致的编译方式。
  2. 采用进程/线程性能分析,查看造成CPU消耗的进程。

    创建进程/线程分析任务,并启动分析。

    表1 任务参数配置说明

    参数

    说明

    分析类型

    进程/线程性能分析

    分析对象

    系统

    采样时长

    10秒

    采样类型

    全选

    其他参数

    默认

  3. 查看采集分析结果。
    图1 进程/线程分析结果总览

    默认排序是按照PID/TID升序排列,为便于观察CPU消耗的进程详情,请点击%CPU列旁边的按钮进行降序排列,可发现pthread_mutex程序在消耗大量的CPU资源,实际结果将根据实际运行情况显示,同图1略有差别。

  4. 选择“上下文切换”页签,点击筛选按钮选择pthread_mutex程序所对应的PID。
    图2 上下文切换分析结果

    发现pthread_mutex对应进程及线程的上下文切换比较多,可推测该进程存在较多的切换。

  5. 采用系统资源调度分析,查看pthread_mutex程序进程和线程的切换次数及抢占情况。

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

    表2 任务参数配置说明

    参数

    说明

    分析对象

    应用

    模式

    选择“Launch application”

    分析类型

    资源调度分析

    应用路径

    输入示例应用路径,如:/opt/testdemo/pthread_mutex。

    采样时长

    30秒

    其他参数

    默认

  6. 查看“CPU/进程统计”页签。
    图3 CPU/进程统计

    可观察到pthread_mutex两个线程之间存在频繁交替抢占的情况,此情况最大可能是锁等互斥量操作。

  7. 采用锁与等待分析,得到锁的调用情况。

    创建锁与等待分析任务,并启动分析。

    表3 任务配置参数说明

    参数

    说明

    分析对象

    应用

    模式

    Attach to process

    分析类型

    锁与等待分析

    采样时长

    20秒

    其他参数

    默认

  8. 查看采集分析结果。
    图4 锁与等待分析结果总览
    图5 锁快照信息

    在“锁实例分析”页签,发现函数“__pthread_mutex_lock”被两个线程调用次数很多;在“锁快照”页签点,查看对应的锁的持有等待时间。

锁抢占优化

实际功能代码的执行速度较快,多线程使用锁的方案会将大量的资源开销花费在锁竞争上,为减少公共资源的的抢占,可通过原子变量无锁的编程方式优化代码。

  1. 再次创建锁与等待分析任务(pthread_atomic.c应用)。
    表4 任务配置参数说明

    参数

    说明

    分析对象

    应用

    模式

    Attach to process

    分析类型

    锁与等待分析

    其他参数

    默认

    图6 优化后锁与等待任务

    发现没有锁函数的调用存在。

  2. 再次创建资源调度分析任务。
    表5 任务参数配置说明

    参数

    说明

    分析对象

    应用

    模式

    选择“Launch application”

    分析类型

    资源调度分析

    应用路径

    输入示例应用路径,如:/opt/testdemo/pthread_atomic。

    采样时长

    30秒

    其他参数

    默认

    图7 CPU/进程统计

    发现优化后的应用不存在频繁交替抢占,等待时间已被优化。

搜索结果
找到“0”个结果

当前产品无相关内容

未找到相关内容,请尝试其他搜索词