性能优化的7类技术手段
复用优化
写代码时会发现有很多重复的代码可以提取出来做成公共的方法。
谈到数据复用,首先想到的就是缓冲和缓存,两者意义是完全不同的。
缓冲(Buffer):常见于对数据的暂存,然后批量传输或者写入多使用顺序方式,用来缓解不同设备之间频繁地、缓慢地随机写。
缓存(Cache):常见于对已读取数据的复用
通过将它们缓存在相对高速的区域,缓存主要针对的是读操作。
计算优化
1. 并行执行:
现在的CPU发展速度很快,绝大多数硬件,都是多核。
要想加快某个任务的执行,最快最优的解决方式,就是让它并行执行。
2. 变同步为异步
通常涉及编程模型的改变。
请求会一直阻塞,直到有成功,或者失败结果的返回。
虽然编程模型简单,但应对突发的、时间段倾斜的流量,问题就特别大,请求很容易失败。
3. 惰性加载
使用一些常见的设计模式来优化业务,提高体验,比如单例模式、代理模式等。
比如在绘制Swing窗口时,如果要显示比较多的图片,就可以先加载一个占位符。
然后通过后台线程慢慢加载所需要的资源,这就可以避免窗口的僵死。
结果集优化
XML的表现形式是非常好的,那为什么还有JSON呢?
一个重要的原因就是体积变小,传输效率和解析效率变高。
像Google的Protobuf,体积更小。
虽然可读性降低,但在一些高并发场景下(如RPC), 能够显著提高效率。
这是典型的对结果集的优化。
像Nginx,一般都会开启GZIP压缩,使得传输的内容保持紧凑。
客户端只需要一小部分计算能力,就可以方便解压。
由于这个操作是分散的,所以性能损失是固定的。
对于一些对时效性要求不高,但对处理能力有高要求的业务。
要吸取缓冲区的经验,尽量减少网络连接的交互。
采用批量处理的方式,增加处理速度。
资源冲突优化
在平常的开发中,会涉及很多共享资源:
- 单机的,比如一个HashMap
- 外部存储,比如一个数据库行
- 单个资源,比如Redis某个key的Setnx
- 多个资源的协调,比如事务、分布式事务等
按照锁级别,锁可分为乐观锁和悲观锁,乐观锁在效率上更高。
按照锁类型,锁又分为公平锁和非公平锁,在对任务的调度上,有一些细微的差别。
算法优化
算法能够显著提高复杂业务的性能。
但在实际的业务中,往往都是变种。
由于存储越来越便宜,在一些CPU非常紧张的业务中,往往采用空间换取时间的方式,来加快处理速度。
算法属于代码调优,代码调优涉及很多编码技巧,需要使用者对所使用语言的AP!也非常熟悉。
有时对算法、数据结构的灵活使用,也是代码优化的一个重要内容。
比如常用的降低时间复杂度的方式,就有递归、二分、排序、动态规划等。
在平时的编程中,尽量使用一些设计理念良好、性能优越的组件。
比如有了Netty,就不用再选择比较老的Mina组件,而在设计系统时,从性能因素考虑,就不要选SOAP这样比较耗时的协议。
比如一个好的语法分析器(比如使用JavaCC), 其效率会比正则表达式高很多。
JVM优化
因为Java是运行在JVM虚拟机之上,它的诸多特性,就要受到JVM的制约。
对JVM虚拟机进行优化,也能在一定程度上能够提升JAVA程序的性能。
如果参数配置不当,甚至会造成OOM等比较严重的后果。
目前被广泛使用的垃圾回收器是G1。
通过很少的参数配置,内存即可高效回收。
CMS垃圾回收器已经在Java14中被移除,因为它的GC时间不可控。
总结
当然性能优化还包含数据库优化、操作系统优化、架构优化等其他一些内容,但不是重点。
参考资料:性能优化的切入点