地址:广东省清远市
电话:0898-08980898
传真:000-000-0000
邮箱:admin@youweb.com
更新时间:2024-06-24 13:51:29
性能优化是coder的比较常见的一项技能,要求开发者有比较全面的知识和比较好的分析能力。这是一个系统性的工程,而不仅仅是针对点的优化,更可能得是优化那个点反而是最容易的。
做任何事情我们都需要一定的指导原则,性能优化也不例外,笔者总结了以下三条:
不要过早优化是性能优化领域的金科玉律,当然了解了原理之后这也不是什么牢不可破的誓言[1]。
深层次的含义是code最关注的是可维护性[2],
而性能优化很多是诘屈聱牙的改动,会破坏程序的结构。
2/8法则提醒我们要关注主次矛盾,将问题聚焦。在性能优化领域我们的2/8法则有以下3个点:
业务资源与物理资源的主次
开发同学在思考性能优化经济收益时大多会比较开发工资和机器价格,这样的思考是线性的。
因为一个平台的工作者的价值并不止是他自身的薪水,也包括了平台的价值赋予。本来一个员工的时间可以用来开拓新的场景业务,他产生的价值可能就大于物理资源的添加了。
问题分析与解决方案的主次
其实无论是性能优化还是其他做事方法,问题定义、分析、验证、取舍都是非常重要环节所花费的时间也应远远大于设计解决方案的时间。在我们设计解决方案过程中,起码我们要校验或者考虑以下的四个问题:
问题的严重性:决定我们是否值得去解决这个问题,有时候鸵鸟策略非常好用。
问题的紧迫性:决定我们通过什么方式去解决问题,有时候时间紧迫的情况下,治标比治本要重要的多。后文我们会有相应的例子。
问题的最终目标:问题的最终目标是我们衡量我们方案效果唯一的标准,不明确目标很多事情很难做成。
问题的根源:方便我们彻底解决问题,很多短期膏药好用,但是长期而言会埋下更多隐患。
方案的投入产出比:这决定我们使用哪种方案,以及解决问题的层次,有时候治本非常难,我们就可以选择先治标,再防止问题蔓延。
很多情况我们知道了优化目标,但是我们难以判断我们的优化对系统是否会起到最用,或者是否已经达到了最佳性能场景, 优化的可能微乎其微。这时候我们就需要找到对应的BenchMark,可以是业内的一份测试报告;也可以是我们的经验值,类似SSD是0.5毫秒,物理磁盘是10ms之类的。
做性能优化的步骤我理解应该是从监控获取性能的大概瓶颈位置,利用对应的工具找到多个痛点位置,按照性价比去进行相应的优化。
首先要明确目标,不做无目标的性能优化。监控是我们发现目标,检验效果非常重要的途径。
无论是压测摸高,还是日常系统出现问题都离不开监控的支撑。
监控我们关注层面最重要的一些指标:
很多监控指标都是相互联系的,问题并不是孤立的。有时候系统CPU高是由于高QPS引起的,但是CPU的飙高同时会影响QPS, 我们问题排查的时候能清楚分析问题非常关键。
系统层:
系统层的工具主要是看四大系统指标: cpu, mem, disk, network:
cpu: top看cpu usage,load,cpu使用率排行; pidstat看CPU上下文切换频率;
mem: free看内存使用率,swap使用率;
disk:iostat看 util%, 写rt,io load 情况;
network: netstat/ss查看系统连接数;
虚拟机层:
虚拟机层主要java 栈的信息,以及GC的一些情况
虚拟机线程和锁:jstack;
JAVA GC:jstat,GCLog;
java 堆内对象: jmap,zprofile, MAT;
java堆外对象:jmap, MAT;
应用层:
应用层主要看的还是系统的接口耗时报错等信息,这里主要依靠trace日志, arthas , 火焰图等工具
首先我们需要通过分析工具找到问题的核心点去进行优化;尽量花最小的力气完成最大的效果能从业务层规避就从业务层规避,能够通过scale out 去横向扩展的就先加物理资源扩容。
根据业务特征重新建模或者优化业务流程,通过业务层去取舍损失一些无关要素来达到优化性能的效果。
平行扩展/硬件升级[3]:
设计系统的初始时就要考虑到能够平行扩展,当我们遇到能平行加机器的架构,加机器就好。
应用层:
针对CPU/QPS/RT的优化:
针对内存的优化:
针对连接数的优化:
1. 更好的GC算法。
2. 调整内存,回收时间等参数。
3. 使用堆外内存,避免GC。
tcp wait time;
tcp delay;
tcp backLog;
tcp listenLog;
tcp 的缓冲区大小