【总结】性能优化

发布于: 9 小时前

性能测试

作用与重要性

性能测试是性能优化的前提和基础,也是性能优化结果的检查和度量标准

不同视角下的网站性能有不同的指标,也有不同的优化手段

主观视角:用户感受到的性能

客观视角:性能指标衡量的性能

性能测试指标

响应时间

从发出请求开始到收到最后响应数据所需要的时间

并发数

系统能够同时处理请求的数目,即系统并发用户数

吞吐量

指单位时间内系统处理的请求的数量,体现系统的处理能力,可用“请求数/秒”、“页面数/秒”、“访问人数/天”、“处理业务数/小时”、TPS每秒事务数、HPS每秒HTTP请求数、QPS每秒查询数。

吞吐量=(1000/响应时间ms)*并发数

性能计数器

是描述服务器或操作系统性能的一些数据指标,如System Load、对象与线程数、内存使用、CPU使用、磁盘与网络I/O等指标。这些指标是系统监控的重要指标,对这些指标设置阀值,当监控系统发现性能计数器超过阀值时,就向运维和开发人员报警,及时发现和处理系统异常。

性能测试方法

性能测试

以系统设计初期规划的性能指标为预期目标,对系统不断施加压力,验证系统在资源可接受范围内,是否能达到性能预期。

负载测试

对系统不断增加并发请求以增加系统压力,直到系统的某项或多项指标达到安全临界值,如某种资源已经呈饱和状态,这时候继续对系统施加压力,系统的处理能力不但不能提高,反而会下降。

压力测试

超过安全负载的情况下,对系统继续施加压力,直到系统崩溃或不能再处理任何请求,以此获得系统最大压力承受能力。

稳定性测试

被测试系统在特定硬件、软件、网络环境条件下,给系统加载一些业务压力,使系统运行一段较长时间,以此检查系统是否稳定。在生产环境,请求压力是不均匀的,呈波浪特性,因此为了更好的模拟生产环境,稳定性测试也应不均匀地对系统施加压力。

全链路测试

是指在特定的业务场景下,将相关的链路完整的串联起来同时施压,尽可能模拟出真实的用户行为,当系统的整站流量都被打上来的时候,必定会暴露出性能瓶颈,才能够探测出系统整体的真实处理能力,以及有指导的在大促前进行容量规划和性能优化,这便是线上实施全链路压测的真正目的。

全链路压测的调整

数据构造

数据隔离

逻辑隔离:直接把测试数据和正常数据写到一起,通过特殊的标识能够区分开

  • 可能污染线上数据,破话线上数据安全性

虚拟隔离:在所有写数据的地方做mock,并不真正的写进去

  • 不会对线上数据产生污染,但是mock对压测结果的准确性会产生干扰

物理隔离:所有写数据的地方对压测的流量进行识别,判断一旦是压测流量的写,就写到隔离的位置,包括存储、缓存、搜索引擎等等。

流量构造

性能优化

基本原则

  • 你不能优化一个没有测试的软件

  • 你不能优化一个你不了解的软件

性能测试的主要指标

响应时间:完成一次任务花费的时间

并发数:同时处理的任务数

吞吐量:单位时间完成的任务数据

性能计数器:System Load、线程数、进程数、CPU、内存、磁盘、网络使用率

性能优化的一般方法

  1. 性能测试,获得性能指标

  2. 指标分析,发现性能与资源瓶颈点

  3. 架构与代码分析,寻找性能与资源瓶颈关键所在

  4. 架构与代码优化,优化关键技术点,平衡资源利用

  5. 性能测试,进入性能优化闭环

性能优化的分层思想

机房与骨干网络性能优化

异地多活的多机房架构

专线网络与自主CDN建设

服务器与硬件性能优化

使用更优的CPU、磁盘、内存、网卡,对软件性能优化可能是数量级的,有时候远远超过代码和架构的性能优化

案例:如spark作业过程需要传输大量数据,进行资源瓶颈分析,发现大量时间消耗在网络传输上

优化方案:升级网卡,10G网卡替代1G网卡

操作系统性能优化

虚拟机性能优化

基础组件性能优化

例如Jetty7.1.5替代JBoss4.0.5,性能大幅提升

软件架构性能优化

缓存

从内存获取数据,减少响应时间

减少数据库访问,降低存储设备负载压力

缓存对象结果,而不是原始数据,减少CPU计算

缓存主要优化读操作

异步

即时响应,更好的用户体验

控制消费速度,合适的负载压力

异步主要优化写操作

集群

通过增加更多的服务器来支持更多用户访问所需要消耗的计算资源

使多台服务器对使用者而言看起来像是一台服务器

软件代码性能优化

遵循面向对象的设计原则和设计模式编程

并发编程,多线程与锁

资源复用,线程池与对象池

异步编程,生产者与消费者

数据结构,数组、链表、hash表、树

锁原语CAS

CAS(V,E,N)

V表示要更新的变量

E表示预期值

N表示新值

如果V值等于E值,则将V的值设为N,若V值与E值不同,什么都不做。

CAS是一种系统原语,原语的执行必须是连续的,在执行过程中不允许被打断。

JAVA通过CAS原语在对象头中修改Mark Word实现加锁

总线锁与缓存锁

总线锁:使用处理器的LOCK信号,当一个处理器在内存总线上输出此信号的时候,其他处理器的请求江北阻塞,该处理器独占内存

缓存锁:是指内存区域如果被缓存在处理器的缓存行中,通过缓存一致性机制来保证操作的原子性,阻止同时修改两个以上处理器缓存的内存区域数据

偏向锁 轻量级锁 重量级锁

偏向锁:指一段同步代码一直被一个线程所访问,那么该线程会自动获取锁,降低获取锁的代价

轻量级锁:指当锁是偏向锁时,被另一个线程所访问,偏向锁就会升级为轻量级锁,其他线程会通过自旋的形式尝试获取锁,不会阻塞,提高性能

重量级锁:指当锁是轻量级锁时,另一个线程虽然自旋,但是自旋不会一直持续下去,当自旋到一定次数时,还没获取到锁,就会进入阻塞,该锁膨胀为重量级锁,重量级锁会让其他申请的线程进入阻塞,性能降低

公平锁 非公平锁

公平锁:多个线程按照申请的顺序来获取锁

非公平锁:有可能后申请的线程比先申请的线程优先获取锁

可重入锁

某个线程已经获得某个锁,可以再次获取锁而不会出现死锁

独享锁/互斥锁 共享锁 读写锁

独享锁/互斥锁:该锁一次只能被一个线程所持有

共享锁:该锁可以被多个线程所持有

读写锁:多个读线程之间并不互斥,而写线程则要求与任何线程互斥

乐观锁 悲观锁

悲观锁:认为对于同一数据的并发操作,一定会发生修改,采取加锁的形式。悲观的认为,不加锁的并发操锁的并发操作一定会出问题

乐观锁:认为对于同一数据的并发操作,是不会发生修改。在更新数据的时候,检查是否已经被修改过,如果修改过,就放弃

分段锁

细化锁的颗粒度,仅对数据的一段进行加锁操作。

如JDK ConcurrentHashMap通过分段锁的形式来实现高效并发操作

自旋锁

是指尝试获取锁的线程不会立即阻塞,而是采用循环的方式去尝试获取锁,这样的好处是减少线程上下文切换的消耗,缺点是循环会消耗CPU

文件与硬盘IO

RAID独立硬盘冗余阵列

分布式文件系统HDFS

用户头像

小胖子

关注

还未添加个人签名 2018.02.04 加入

还未添加个人简介

评论

发布
暂无评论
【总结】性能优化