编码逻辑上的优化: 重复的代码可以提取出来,做成公共的方法。
数据复用: 缓存Buffer
和缓存Cache
缓冲
: 常见于对数据的暂存,然后批量传输或者写入。多使用顺序方式,用来缓解不同设备之间频繁地、缓慢地随机写,缓冲主要针对的是写操作
。
缓存
: 常见于对已读取数据的复用,通过将它们缓存在相对高速的区域,缓存主要针对的是读操作
。
对象的池化操作: 数据库连接池, 线程池
同步会阻塞, 直到成功, 对于突发的, 时间段倾斜的流量, 问题就特别大, 请求容易失败。
异步支持横向扩展, 缓解瞬时压力, 使请求变得平滑。
就是使用一些常见的设计模式来优化业务,提高体验
单例模式、代理模式等。
举个例子,在绘制 Swing 窗口的时候,如果要显示比较多的图片,就可以先加载一个占位符,然后通过后台线程慢慢加载所需要的资源,这就可以避免窗口的僵死。
xml -> json 的区别
体积变小了, 传输效率和解析效率变高了。
Google的Protobuf, 体积更小了, 虽然可读性低, 但是对于RPC, 效率提升
Nginx,一般都会开启 GZIP 压缩,使得传输的内容保持紧凑。
返回的Sql字段, 保持精简
对于一些对时效性要求不高,但对处理能力有高要求的业务。我们要吸取缓冲区的经验,尽量减少网络连接的交互,采用批量处理的方式,增加处理速度。
结果集有的会二次使用, 加入缓存, 速度会有欠缺, 可以采用索引或Bitmap位图加快数据访问速度。
开发中会有共享资源的数据, 有的是单机的, 比如一个Hashmap, 有的是外部数据, 比如一个数据库行, 有的是单个资源, 比如Redis的某个key的setnx, 有的是多个资源的协调, 比如事务, 分布式。
现实中的性能问题,和锁相关的问题是非常多的。大多数我们会想到数据库的行锁、表锁、Java 中的各种锁等。在更底层,比如 CPU 命令级别的锁、JVM 指令级别的锁、操作系统内部锁等,可以说无处不在。
只有并发,才能产生资源冲突。也就是在同一时刻,只能有一个处理请求能够获取到共享资源。解决资源冲突的方式,就是加锁。再比如事务,在本质上也是一种锁。
对资源的争用,会造成严重的性能问题,所以会有一些针对无锁队列之类的研究,对性能的提升也是巨大的.
算法能够显著提高复杂业务的性能,但在实际的业务中,往往都是变种。由于存储越来越便宜,在一些 CPU 非常紧张的业务中,往往采用空间换取时间的方式,来加快处理速度。
算法属于代码调优了, 代码调优有很多编码技巧, 需要开发者对语言的Api非常熟悉, 对于算法, 数据结构的灵活使用, 也是代码优化的一个重要内容。
比如什么时候用Hashmap, 什么时候用CorrentHashMap, 什么时候用ArrayList, 什么时候用LinkedList, 什么时候用CopyOnWrtieList.
如果通过测试分析,找到了系统的瓶颈点,就要把关键的组件,使用更加高效的组件进行替换。在这种情况下,适配器模式是非常重要的。这也是为什么很多公司喜欢在现有的组件之上,再抽象一层自己的;而当在底层组件进行切换的时候,上层的应用并无感知。
比如性能方面, Netty更优于Mina。
因为 Java 是运行在 JVM 虚拟机之上,它的诸多特性,就要受到 JVM 的制约。对 JVM 虚拟机进行优化,也能在一定程度上能够提升 JAVA 程序的性能。如果参数配置不当,甚至会造成 OOM 等比较严重的后果。
目前被广泛使用的垃圾回收器是 G1,通过很少的参数配置,内存即可高效回收。CMS 垃圾回收器已经在 Java 14 中被移除,由于它的 GC 时间不可控,有条件应该尽量避免使用。
JVM 性能调优涉及方方面面的取舍,往往是牵一发而动全身,需要全盘考虑各方面的影响。所以了解 JVM 内部的一些运行原理,还是特别重要的,它有益于我们加深对代码更深层次的理解,帮助我们书写出更高效的代码。
除了需要了解性能优化的方向. 也需要知道一些性能优化的工具。