探讨互斥锁锁定非临界区带来多少性能消耗

2024-04-12 02:32

本文主要是介绍探讨互斥锁锁定非临界区带来多少性能消耗,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

概述

本次主要是测试使用互斥锁,锁定非临界区带来的性能消耗。

在我们写代码时,有时候通过逻辑的设计,可以使代码中临界区在80%以上不会同时访问。但是从理论上来说,在极端或者概率很低的情况下它是可能成为临界区的。处于程序的稳定性考虑,同样是需要加锁的。

但是最近在看disruptor文档[1]时,文献提到:

即使不是临界资源,只要调用了锁就会大幅度的降低性能。
而我之前在项目中的代码,总是会考虑逻辑上减少多线程去竞争同一个锁,这难道是在做无用功?

文中采用的是简单的做5亿次++操作,考虑到其是用Java实现的,因此此处采用C来实现,实践来检验一下结果

 

如果有资源竞争,肯定会导致性能下降。因此我们主要对比进入“假临界区"的场景。

 

测试代码:

 

点击(此处)折叠或打开

  1. #include<stdio.h>
  2. #include<time.h>
  3. #include<sys/time.h>
  4. #include<unistd.h>
  5. #include<string.h>
  6.  
  7. #include<pthread.h>
  8.  
  9.  
  10. unsigned long gtimes = 2 * 1000 * 1000 * 1000;
  11. unsigned long i;
  12.  
  13. struct timeval startTime, endTime;
  14.  
  15. pthread_mutex_t gmutex; //ensure not a stack varible;
  16.  
  17. void start_time()
  18. {
  19.     gettimeofday(&startTime, NULL);
  20. }
  21.  
  22. void end_time()
  23. {
  24.     gettimeofday(&endTime, NULL);
  25. }
  26.  
  27. double spend_time()
  28. {
  29.     return 1000 * (endTime.tv_sec - startTime.tv_sec) +
  30.         (endTime.tv_usec - startTime.tv_usec) / 1000.0f;
  31. }
  32.  
  33. void* test_thread(void* argv)
  34. {
  35.     i = gtimes;
  36.  
  37.     start_time();
  38.     while(i--);
  39.     end_time();
  40.  
  41.     printf(" a thread cost time: %.2f ms\n", spend_time());
  42.  
  43.     return NULL;
  44. }
  45.  
  46. void* test_lockthread(void* argv)
  47. {
  48.     i = gtimes;
  49.     pthread_mutex_init(&gmutex,NULL);
  50.  
  51.     start_time();
  52.  
  53.     pthread_mutex_lock(&gmutex);
  54.     while(i--);
  55.     pthread_mutex_unlock(&gmutex);
  56.  
  57.     end_time();
  58.  
  59.     pthread_mutex_destroy(&gmutex);
  60.     printf(" a thread with a pthread_mutex, cost time: %.2f ms\n", spend_time());
  61.  
  62.     return NULL;
  63. }
  64. int main(int argc, char *argv[])
  65. {
  66.     pthread_t pid;
  67.  
  68.     //pthread_create(&pid, NULL, test_thread, NULL);
  69.     pthread_create(&pid, NULL, test_lockthread, NULL);
  70.  
  71.     pthread_join(pid, NULL);
  72.  
  73.     test_thread(NULL);
  74.     test_lockthread(NULL);
  75.  
  76.     return 0;
  77. }


测试结果:

 不加锁加锁效率对比绝对值加锁在不同线程
1990.861007.291.66%16.43987.79
2996.13997.040.09%0.911001.21
3988.47989.190.07%0.72982.72
4993.6992.02-0.16%-1.58986.94
5984.85984.57-0.03%-0.28989.66
6991.59986.75-0.49%-4.84992.94
7986.68986.720.00%0.04983.4
8989.16991.170.20%2.01987.69
9987.221001.311.43%14.09985.03
10986.27984.09-0.22%-2.18987.14

 

从上表可以看出:
如果两个场景在不同的线程中,没有可比性:两者差值不同。
再考虑到进程调度。理论上偏差也比较大

如果是同一个线程中,除了第1和第9组数据,差距都不是很大:
最大偏差<2ms,偏差率<0.5%.
多数偏差<1ms,偏差率<0.1%.

那么另外两组误差在哪里呢?同样是时间片。Linux中时间片是10ms。
在程序中,两个函数是挨着执行的,如果第一个函数执行完成之后,在执行第二个函数的start_time后时间片到期,此时就会多消耗一个时间片。
那么我们将后一个函数减去时间片,则基本上可以在接收的范围内——实际上还会有至少两次线程切换

1990.86997.290.65%6.43987.79
9987.22991.310.41%4.09985.03

 

结论:

C 中的锁即使进入临界区,实际没有发生资源争用,基本上等同于进入非临界区。

但是性能消耗肯定是有的,应该是锁底层实现的首先自旋的时候会识别出来资源可用!

 

[1] disruptor原文地址:https://mechanitis.blogspot.jp/2011/07/dissecting-disruptor-why-its-so-fast.html

http://blog.chinaunix.net/uid-28993794-id-5779757.html

这篇关于探讨互斥锁锁定非临界区带来多少性能消耗的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/895857

相关文章

Vue3 的 shallowRef 和 shallowReactive:优化性能

大家对 Vue3 的 ref 和 reactive 都很熟悉,那么对 shallowRef 和 shallowReactive 是否了解呢? 在编程和数据结构中,“shallow”(浅层)通常指对数据结构的最外层进行操作,而不递归地处理其内部或嵌套的数据。这种处理方式关注的是数据结构的第一层属性或元素,而忽略更深层次的嵌套内容。 1. 浅层与深层的对比 1.1 浅层(Shallow) 定义

性能测试介绍

性能测试是一种测试方法,旨在评估系统、应用程序或组件在现实场景中的性能表现和可靠性。它通常用于衡量系统在不同负载条件下的响应时间、吞吐量、资源利用率、稳定性和可扩展性等关键指标。 为什么要进行性能测试 通过性能测试,可以确定系统是否能够满足预期的性能要求,找出性能瓶颈和潜在的问题,并进行优化和调整。 发现性能瓶颈:性能测试可以帮助发现系统的性能瓶颈,即系统在高负载或高并发情况下可能出现的问题

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

黑神话,XSKY 星飞全闪单卷性能突破310万

当下,云计算仍然是企业主要的基础架构,随着关键业务的逐步虚拟化和云化,对于块存储的性能要求也日益提高。企业对于低延迟、高稳定性的存储解决方案的需求日益迫切。为了满足这些日益增长的 IO 密集型应用场景,众多云服务提供商正在不断推陈出新,推出具有更低时延和更高 IOPS 性能的云硬盘产品。 8 月 22 日 2024 DTCC 大会上(第十五届中国数据库技术大会),XSKY星辰天合正式公布了基于星

从状态管理到性能优化:全面解析 Android Compose

文章目录 引言一、Android Compose基本概念1.1 什么是Android Compose?1.2 Compose的优势1.3 如何在项目中使用Compose 二、Compose中的状态管理2.1 状态管理的重要性2.2 Compose中的状态和数据流2.3 使用State和MutableState处理状态2.4 通过ViewModel进行状态管理 三、Compose中的列表和滚动

PR曲线——一个更敏感的性能评估工具

在不均衡数据集的情况下,精确率-召回率(Precision-Recall, PR)曲线是一种非常有用的工具,因为它提供了比传统的ROC曲线更准确的性能评估。以下是PR曲线在不均衡数据情况下的一些作用: 关注少数类:在不均衡数据集中,少数类的样本数量远少于多数类。PR曲线通过关注少数类(通常是正类)的性能来弥补这一点,因为它直接评估模型在识别正类方面的能力。 精确率与召回率的平衡:精确率(Pr

java线程深度解析(二)——线程互斥技术与线程间通信

http://blog.csdn.net/daybreak1209/article/details/51307679      在java多线程——线程同步问题中,对于多线程下程序启动时出现的线程安全问题的背景和初步解决方案已经有了详细的介绍。本文将再度深入解析对线程代码块和方法的同步控制和多线程间通信的实例。 一、再现多线程下安全问题 先看开启两条线程,分别按序打印字符串的

MySQL中一致性非锁定读

一致性非锁定读(consistent nonlocking read)是指InnoDB存储引擎通过多版本控制(multi versionning)的方式来读取当前执行时间数据库中行的数据,如果读取的行正在执行DELETE或UPDATE操作,这是读取操作不会因此等待行上锁的释放。相反的,InnoDB会去读取行的一个快照数据 上面展示了InnoDB存储引擎一致性的非锁定读。之所以称为非锁定读,因

FreeRTOS学习笔记(四)Freertos的中断管理及临界保护

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、Cortex-M 中断管理1.1 中断优先级分组1.2 相关寄存器1.3 相关宏定义1.4 FreeRTOS 开关中断 二、临界段及其保护2.1 taskENTER_CRITICAL( ) 和 taskEXIT_CRITICAL( )2.2 taskENTER_CRITICAL_FROM_ISR( )

SQL2005 性能监视器计数器错误解决方法

【系统环境】 windows 2003 +sql2005 【问题状况】 用户在不正当删除SQL2005后会造成SQL2005 性能监视器计数器错误,如下图 【解决办法】 1、在 “开始” --> “运行”中输入 regedit,开启注册表编辑器,定位到 [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVer