性能与可伸缩性(第十一章)

简介:

性能与可伸缩性

性能包括:服务时间、延迟时间、吞吐率、效率、容量等
可伸缩性:当增加计算资源时(例如CPU、内存、存储容量或I/O带宽),程序的吞吐量或者处理能力能相应地增加

    当进行性能调优时,其目的通常是用更小的代价完成相同的工作,例如通过缓存来重用之前计算的结果。
    当进行可伸缩性调优时,其目的是设法将问题的计算并行化,从而能利用更多的计算资源来完成更多的工作。
    

在所有并发程序中都包含一些串行部分,如果你认为在你的程序中不存在串行部分,那么可以再仔细检查一遍。

1. 线程引入的开销

  • 上下文切换
  • 内存同步
  • 阻塞

2. 减少锁的竞争

在并发程序中,对可伸缩性的最主要威胁就是独占方式的资源锁。有两个因素将影响在锁上发生竞争的可能性:锁的请求频率、每次持有该锁的时间。如果二者的乘积很小,那么大多数获取锁的操作都不会发生竞争,因此在该锁上的竞争不会对伸缩性造成严重影响。

    有3种方式可以降低锁的竞争程度:
    1. 减少锁的持有时间
    2. 降低锁的请求频率
    3. 使用带有协调机制的独占锁,这些机制允许更高的并发性
  • 缩小锁的范围(“快进快出”)

降低发生竞争可能性的一种有效方式就是尽可能缩短锁的持有时间。例如可以将一些与锁无关的代码移出同步代码块,尤其是那些开销较大的操作,以及可能被阻塞的操作,例如I/O

  • 减小锁的粒度

降低线程请求锁的频率(从而减小发生竞争的可能性)。这可以通过锁分解和锁分段等技术来实现。在这些技术中将采用多个相互独立的锁来保护独立的状态变量,从而改变这些变量在之前由单个锁来保护的情况。
这些技术能减小锁操作的粒度,并能实现更高的可伸缩性,然而,使用的锁越多,那么发生死锁的风险也就越高。

    如果一个锁需要保护多个相互独立的状态变量,那么可以将这个锁分解为多个锁,并且每个锁只保护一个变量,从而提高可伸缩性,并最终降低每个锁被请求的频率。
    
  • 锁分段

将锁分解技术进一步扩展为对一组独立对象上的锁进行分解,这种情况被称为“锁分段”。例如,在ConcurrentHashMap的实现中使用了一个包含16个锁的数组,每个锁保护所有散列桶的1/16,其中第N个散列桶由第(N mod 16)个锁来保护。

    锁分段的一个劣势在于:与采用单个锁来实现独占访问相比,要获取多个锁来实现独占访问将更加困难并且开销更高(在进行某些操作后,需要获取所有的锁)。
    
  • 避免热点域

当每个操作都请求多个变量时,锁的粒度将很难降低。这是在性能与可伸缩性之间相互制衡的另一个方面。一些常见的优化措施,例如将一些反复计算的结果缓存起来,都会引入一些“热点域(Hot Field)”,而这些热点域往往会限制可伸缩性。

  • 一些代替独占锁的方法

另一种降低锁竞争的技术就是放弃使用独占锁,从而有助于使用一种友好并发的方式来管理共享状态。例如,使用并发容器、读-写锁、不可变对象以及原子变量。

  • 向对象池说“不”

3. 减少上下文切换的开销

在许多任务中都包含一些可能被阻塞的操作。当任务在运行和阻塞这两个状态之间切换时,就相当于一次上下文切换。要提高性能,就要减少这样的切换。

相关文章
|
4月前
|
缓存 监控 前端开发
优化网络应用的性能
【10月更文挑战第21天】优化网络应用的性能
53 2
|
7月前
|
监控 网络协议 Linux
Linux系统管理与优化技巧:提升性能与效率的深度探索
【7月更文挑战第24天】Linux系统管理与优化是一个持续的过程,需要管理员和开发者不断地学习和实践。通过合理的系统监控、内存管理、文件系统优化、进程与任务管理、网络优化以及软件与包管理,可以显著提升Linux系统的性能和效率,确保业务的稳定运行。希望本文的技巧能为广大Linux用户带来帮助,共同推动Linux生态的繁荣发展。
|
7月前
|
存储 自然语言处理 开发者
通用性与灵活性对大模型的影响
通用性与灵活性对大模型的影响
|
8月前
|
SQL 缓存 负载均衡
数据库设计优化:性能提升与扩展性的技术探讨
【6月更文挑战第28天】数据库设计优化聚焦性能与扩展性:SQL优化、索引策略、缓存利用及分库分表、集群技术,旨在平衡处理速度与系统稳定性。通过智能SQL、复合索引、查询缓存减少数据库压力,垂直/水平拆分与集群实现数据分布式处理,提升并发能力。
|
9月前
|
Android开发 开发者 UED
安卓应用开发中的性能优化技巧
在当今移动应用市场竞争激烈的环境中,用户对于应用性能的需求日益增加。因此,在安卓应用开发过程中,如何实现高效的性能优化成为开发者需要关注的重要问题。本文将探讨安卓应用开发中的性能优化技巧,包括减少内存占用、优化界面渲染、提升响应速度等方面的方法,帮助开发者更好地提升应用的用户体验。
82 0
|
9月前
|
移动开发 测试技术 Android开发
构建高效Android应用:从优化用户体验到提升性能表现
【5月更文挑战第15天】 在移动开发领域,一个成功的Android应用不仅需要具备吸引用户的功能,更应提供流畅和高效的用户体验。随着技术的不断进步,开发者面临着将先进技术集成到现有架构中以提高应用性能的挑战。本文将深入探讨如何通过最新的Android框架和工具来优化应用性能,包括对UI的响应性、内存管理以及多线程处理等关键方面的改进,旨在帮助开发者构建出更加强大、快速且稳定的Android应用。
|
9月前
|
存储 算法 Java
内存管理探秘:自动化与性能的完美平衡
内存管理探秘:自动化与性能的完美平衡
76 0
|
9月前
|
缓存 编译器 Go
反射的双刃剑:性能与灵活性权衡
反射的双刃剑:性能与灵活性权衡
76 0
|
算法 小程序
软件复杂性表现,如何计算?
软件复杂性度量的参数很多,主要有: • 规模,即总共的指令数,或源程序行数。 • 难度,通常由程序中出现的操作数的数目所决定的量来表示。 • 结构,通常用于程序结构有关的度量来表示。 • 智能度,即算法的难易程度。
327 0