`

性能调优学习笔记(转载)

 
阅读更多

1、性能调优的步骤 

1.1、衡量系统现状
包括请求次数、响应时间、资源消耗等;如:A系统目前95%的请求响应为1s。

1.2、设定调优目标
根据用户所能接受的响应速度、系统现有的机器、所支撑的用户量制定出来的,因此通常会设定调优目标:95%的 请求在500ms内返回。

1.3、寻找性能瓶颈
在【2、寻找性能瓶颈】会专门介绍。通常性能瓶颈的表像是:
1.3.1、资源消耗过多(CPU、文件IO、网络IO、内存)
1.3.2、外部系统处理不足(所调用的其他系统提供的功能——多数情况也是资源消耗过多、数据的操作响应速度 不够——根据数据库SQL执行速度、数据库机器的IOPS、数据库的Active Sessions等分析出来的)
1.3.3、程序代码运行效率不够高,未充分使用资源或程序结构不合理。

1.4、性能调优
在后面的【3、性能调优】会专门介绍

1.5、衡量是否达到目标值
优化部署后,达到目标则结束,如果没有则重复1.3、1.4步骤

2、寻找性能瓶颈 

2.1、CPU消耗分析(top、pidstat等方式查看cpu消耗状况;vmstat查看cpu的上下文切换、运行队列、利用率)
在Linux中,CPU消耗主要用于中断、内核以及用户进程的任务处理。优先级为:中断>内核>用户进程。cpu消耗
严重时,主要体现在:
①us—用户进程所占的%
过高的原因:1、线程一直处于可运行(Runnable)状态,通常线程在执行无阻塞、循环、正则或纯粹的计算
等动作引起的。
2、频繁的GC操作引起。如:每次请求需要分配较多内存,当访问量高的时,就不断的进行GC,
系统响应速度下降。进而造成堆积的请求更多,消耗内存更严重,最严重的时候可能导致系统 不断的进行FULL GC。可通过JVM内存的消耗分析来查找原因。
可通过kill -3 [javapid]、jstack [pid] | grep 'nid=0X....' 的方式dump出应用的java线程信息。通过转换
出的十六进制的值就可以找到对应的nid值的线程。该线程即为消耗CPU的线程。在采样时多执行几次上诉过程,
以确保找到真实的消耗CPU的线程。也可以通过intel vtune 这样的商业软件进行分析

②sy—内核线程所占的%
过高的原因:Linux花费更多的时间在进行线程切换。Java应用造成这个原因是:因为启动了的线程比较多,且
这些线程多数都处于不断的阻塞(锁等待、IO等待状态)和执行状态的变化过程,导致了操作系统需要不断的切换
执行的线程。从而产生大量的上下文切换。

可通过kill -3 [javapid]、jstack -1 [javapid] 的方式dump出Java应用线程信息,查看线程的状态、锁信息,
找出等待状态或锁竞争过多的线程。结合vvmstat 查看CPU消耗状况。如cs(上下文切换)、sy等。

③ni—被nice命令改变优先级的任务所占的%
④id—CPU空闲时间所占的%
⑤wa—执行过程中等待io所占的%
⑥hi—硬件中断所占的%
⑦si—软件中断所占的%

2.2、文件IO消耗分析(通过pidstat、iostat命令分析)
Java应用造成io消耗严重主要是:
① 多个线程需要大量内容写入(如频繁的log写入)动作;
② 磁盘设备本身的处理速度慢
③ 文件系统慢
④ 操作的文件本身已经很大

2.3、网络IO消耗分析(通过sar命令,如需跟着TCP/IP通信过程的信息,则可通过tcpdump来进行)
对于分布式Java应用而言,网络IO的消耗非常值得关注,尤其要注意网络中断是不是均衡地分配到各CPU的
(通过cat/proc/interrupts命令查看)。对于网卡只分配到一个CPU的现象采用修改kernle方法(Google使用)、 采用支持MSI-X的网卡进行修复。
由于没办法分析具体每个线程所消耗的网络IO,因此当网络IO消耗高时,对于Java应用而言只能对线程进dump。
查找产生大量网络IO操作的线程,这些线程的特征是读取或写入网络流,在Java网络通信时,通常要对对象进行序列
化为字节流,进行发送,或者读取。并反序列化为对象。这个过程要消耗JVM堆内存,JVM对内存通常是有限的。因此
Java应用一般不会造成网络IO消耗严重。

2.4、内存消耗分析(vmstat、sar、pidstat、top)
目前Java应用只有在创建线程和使用Direct ByteBuffer时才会操作JVM堆意外的内存。对于JVM堆以外的内存方
面消耗,最为值得关注的是swpd的消耗以及物理内存的消耗(可通过vmstat、sar、top、pidstat等方式查看swap
和物理内存的消耗状况)。

2.5、消耗资源不多,在访问量不大的情况。但程序执行慢的原因,主要有3方面
① 锁竞争激烈(如:数据库连接池数,但是请求数多于连接池数)
② 未充分使用硬件资源(如:多核CPU,但程序却采用单线程串行操作。)
③ 数据量增长(如:数据量的海量增长。可对数据库的表拆分、库拆分)


3、性能调优 
3.1JVM调优

3.1.1、代大小调优
① 避免新生代大小设置过小
1、避免频繁进行minor GC;2、可能导致minor GC对象直接进入旧生代,占据旧生代空间,触发FULL GC。
② 避免新生代设置过大
1、导致旧生代变小,可能导致FULL GC频繁执行;2、导致minor GC的耗时大幅度增加。
③ 避免survivor space过小或者过大 
④ 根据具体代码合理设置新生代的存活周期。

3.2.1、GC策略调优
串行GC性能太差,因此实际应用时主要是应用并行和并发GC,
大部分Web应用在处理请求时设置了一个最大可同时处理的请求数,当超出此请求数时,会将之后的请求放 入等待队列中,而这个等待队列也限制了大小。当等待队列满了后,仍然有请求进入,那么这些请求将丢弃,所
有的请求又都是有超时限制度。
在这种情况下如果触发了FULL GC造成应用暂停时间较长的FULL GC,则有可能等这次FULL GC之后,应
用中很多请求就超时或者被丢弃了。
从上面可以看出,Web应用非常需要一个对应用造成暂停时间较短的GC,再加上大部分Web应用的瓶颈都
不在CPU上。因此对于Web应用而言,在G1还不够成熟的情况下,CMS GC是不错的选择。

3.2、程序调优
3.2.1、CPU us高的解决方法
① 执行线程无任何挂起动作,且一直运行,导致CPU没有机会去调度执行其他的线程,造成线程饿死的现象。
解决:对这种线程的动作增加Thread.sleep(int),以释放CPU的执行权,降低CPU的消耗。
原理:以损失单次执行性能为代价,但由于降低了CPU消耗,在多线程的情况下,反而提高了平均性能。

② 状态扫描。如:某线程要等其他线程改变了值才可以继续执行。
解决:改为采用wait/notify机制。

③ 循环次数过多、正则、计算等造成CPU us过高的情况。结合业务需求进行调优。code review是王道。

④ 频繁GC造成us高的情况,通过JVM调优或程序调优,降低GC的执行次数。

3.2.2、CPU sy高的解决方法
① 线程运行状态经常切换
解决:减少线程数,且使用线程池

② 线程之间锁竞争激烈
解决:尽可能降低锁的竞争。
1、使用并发包中的类(java.util.concurrent.*)
2、使用Treiber算法
3、使用Michael-Scott非阻塞队列算法(ConcurrentLinkedQueue就是典型的该算法的非阻塞队列)
4、通常没必要对整个方法加锁,只对需要控制资源的地方做加锁操作。
5、拆分锁,把独占锁拆分为多把锁,如:ConcurrentHashMap。很大程度上可以提高读写速度。
6、去除读写操作的互斥锁

③ 较多网络IO操作或者确实需要一些锁竞争机制(如数据库连接池),但为了能够支持高的并发量,在Java
应用中又只能借助更多的线程来支撑。
解决:采用协程(Coroutine)来支持更高的并发量,避免并发量上涨之后造成CPU sy消耗严重、系统load
迅速上涨和系统性能下降。
Java中目前主要可用于实现协程的框架为Kilim,早使用Kilim执行一项任务,并不创建Thread,而是采用
Task。

3.3、文件IO消耗严重的解决方法
从程序角度看,造成文件IO消耗严重的原因主要是多个线程在写大量的数据到同一文件。导致文件很快变大。
从而写入速度越来越慢,并造成各线程激烈争抢文件锁,对于这种情况解决方法:
1、异步写入文件;2、批量读写;3、限流;4、限制文件大小;5、尽可能采用缓冲区等方式来读取文件内容

3.4、网络IO消耗严重的解决方法
从程序角度而言,造成网络IO消耗严重的主要原因是同时需要发送或接受的包太多。可采用限流。限流通常是
限制发送packet的频率,从而在网络IO消耗可接受的情况下来发送packet。

3.5、内存消耗严重的情况
1、对JVM调优;2、代码调优;
代码调优的方式:
① 释放不必要的引用。如使用ThreadLocal,由于线程复用,ThreadLocal中存放的对象如未主动释放的话,
不会被GC。应该在执行完毕执行ThreadLocal.set把对象清除,避免此有不必要的对象引用。

② 使用对象缓存池(享元模式)

③ 采用合理的缓存失效算法(FIFO、LRU、LFU等)
当缓存池达到最大容量后,如果再加入新对象时采用FIFO、LRU、LFU等失效算法。
④ 对于占据内存但又不是必须存在的对象使用SoftReference、WeakReference的方式进行缓存。
SoftReference在内存不够用的情况进行回收;WeakReference在FULL GC的情况下进行回收。

3.6、对于资源消耗不多,但程序执行慢的情况
3.6.1、锁竞争激烈—见3.2.2②

3.6.2、未充分利用硬件资源。
① 未充分利用CPU
启动多线程,但是单线程演变为多线程要加锁,如:单线程计算,拆分为多线程分别计算,最后合并结果 如:JDK7的fork-join框架。

② 未充分使用内存
数据库缓存、耗时资源缓存(数据库连接的创建、网络连接的创建等)、页面片段的缓存等。

结束语:从纯粹的软件角度调优来讲,充分而不过分的使用硬件资源,合理调整JVM以及合理使用JDK包是调优的三大有效原则,调优没有“银弹”。结合系统现状和多尝试不同的调优策略是找到合适调优方法的唯一途径。

分享到:
评论

相关推荐

    Oracle DBA性能调优学习笔记

    针对“Oracle DBA性能调优学习笔记”这一主题,我们可以提取并解释出以下重点知识。 首先,性能调优是一个多角色参与的过程。不仅DBA需要参与,应用架构师、应用设计师、应用开发人员以及OS和存储系统管理员也同样...

    ORACLE DBA工作笔记 运维数据迁移与性能调优

    标题中提到的“ORACLE DBA工作笔记 运维数据迁移与性能调优”揭示了这本书籍主要围绕着...因此,类似于“ORACLE DBA工作笔记 运维数据迁移与性能调优”这样的专业书籍,是DBA们提升技能、增加实战经验的宝贵学习材料。

    阿里巴巴Java性能调优实战(2021-2022华山版)+Java架构核心宝典+性能优化手册100技巧.rar

    阿里巴巴Java性能调优华山版是一套系统性能调优教程,!通过这份笔记的学习,你将会有一个系统的调优头脑和策略!快了何止100%?需要的朋友可下载试试! 众所周知性能调优可以使系统稳定,用户体验更佳,甚至在...

    linux性能调优.pdf

    本篇学习笔记详细介绍了性能分析的步骤、优化工具、性能指标的概念,并且从应用负载和系统资源两个角度深入探讨了性能优化。 在性能分析中,第一步是要选择合适的性能指标来评估应用和系统的性能。常见的性能指标...

    Oralce 19c执行计划调优学习笔记

    Oralce 19c执行计划调优学习笔记 1_执行计划.pdf 2_explain plan for.pdf 3_dbms_xplan.display_cursor.pdf 4_执行计划顺序.pdf 5_直方图.pdf

    Oracle性能调优笔记

    Oracle性能调优是数据库管理中的关键任务,旨在提高数据库系统的响应速度和整体效率。以下是针对Oracle性能调优的详尽解析: 首先,调优的角色包括系统设计人员、系统开发人员、DBA(数据库管理员)以及操作系统...

    马老师jvm调优实战笔记

    马老师 JVM 调优实战笔记 JVM 调优是 Java 开发者们不可或缺的技能,它直接影响着 Java 应用程序的性能和稳定性。本笔记是马老师的 JVM 调优实战笔记,涵盖了 JVM 的概述、内存结构、堆内存、垃圾回收算法、JVM ...

    windchill交流第十四篇:系统性能调优

    "Windchill性能调优笔记.docx"文件很可能是对以上这些方面的详细记录和指南,包含了具体的步骤和建议。在实际操作中,应根据企业的具体情况进行调整,通过不断的测试和调整,找到最适合自己企业的性能优化方案。记住...

    IOS 性能调优技巧 总结笔记

    在开发过程中总结的ios性能调优技巧,其中有自己实际工程中的总结,也有从网络上的摘抄。

    Oracle DBA调优技术学习笔记

    Oracle 12c-优化 Hint详解.pdf Oracle 12c-优化 Oracle 索引技术.pdf Oracle 12c 执行计划.pdf Oracle 12c锁.pdf Oracle 12c查询优化器.pdf Oracle 12c 使用绑定变量 VS 不使用绑定变量.pdf Oracle 12c 自动工作负载...

    马士兵jvm调优笔记.docx

    ### 马士兵JVM调优笔记知识点梳理 #### 一、Java内存结构 Java程序运行时,其内存被划分为几个不同的区域,包括堆内存(Heap)、方法区(Method Area)、栈(Stack)、程序计数器(Program Counter Register)以及...

    JVM性能调优经典教程

    JVM性能调优是一项关键技术,旨在优化JVM的内存管理、垃圾收集、类加载等方面,以提升程序运行速度、减少内存占用并避免系统崩溃。本教程"JVM性能调优经典教程"由马士兵老师倾力讲解,旨在帮助Java开发者进阶,掌握...

    oracle11g性能优化笔记第五部

    本部分将详细介绍Oracle 11g数据库性能优化笔记的第五部分内容,通过实例调优的步骤来逐步深入理解如何使用Oracle提供的性能视图来改善数据库实例的性能。 首先,确定问题的范围和性能目标是实例调整的起始点。这...

    Go语言学习(五) 高质量编程与性能调优实战-青训营笔记

    在本节"Go语言学习(五)高...记得结合提供的"Go语言学习(五)高质量编程与性能调优实战_青训营笔记.md"和"Go语言学习(五)高质量编程与性能调优实战_青训营笔记.pdf"文档深入学习,以获取更全面的理解和实践指导。

    学习笔记——JVM性能调优之 jstat(csdn)————程序.pdf

    JVM性能调优是Java开发中至关重要的一环,它直接影响应用程序的运行效率和稳定性。jstat(JVM Statistics Monitoring Tool)是Oracle JDK提供的一款强大的命令行工具,用于实时监控Java虚拟机的各种运行状态,包括...

    容量测试和性能调优.zip

    在IT行业中,容量测试和性能调优是两个关键的领域,它们对于确保系统稳定性和高效运行至关重要。容量测试主要是为了评估系统在预期或峰值负载下的处理能力,而性能调优则是通过对系统的各种参数进行调整,以提高其...

    mysql 性能调优 运维

    以上内容涵盖了MySQL性能调优和运维的多个方面,从基础概念到高级技术,每个知识点都值得深入学习和实践。作为一名DBA,理解和掌握这些知识,将有助于优化数据库性能,确保系统的高效稳定运行。

    Java生产环境下性能监控与调优详解课程笔记(完整版)

    在Java生产环境中,性能监控与调优是保证系统稳定、高效运行的关键环节。这份"Java生产环境下性能监控与调优详解课程...通过深入学习和实践,你可以掌握Java生产环境下的性能监控与调优技能,从而提升系统的整体性能。

    Oracle性能调优

    Oracle性能调优是数据库管理员和开发人员关注的重要领域,它涉及到如何优化数据库系统以提高查询速度、减少资源消耗...通过深入学习和实践这些知识点,你可以更好地掌握Oracle性能调优,提升数据库系统的稳定性和效率。

Global site tag (gtag.js) - Google Analytics