性能参考指标:
执行时间: 程序从开始到结束的执行时间。
CPU时间: 函数或者线程占用的cpu时间。
内存分配: 程序运行期间所占内存。
磁盘吞吐量: 硬盘I/O使用情况。
网络吞吐量: 网络使用情况。
响应时间:用户行为做出的响应时间,越短性能越好。
短板原理:
一直木桶能装多少水取决于桶壁最短的那个木板。
产生短板的资源有:
磁盘I/O:很多应用大部分瓶颈在硬盘的I/O,硬盘比内存慢很多。如果等待磁盘读写完成会浪费大量CPU时间,拖累整个系统。
网络请求:由于网络不稳定或拥塞控制等都会降低网络请求效率,如果等待网络请求结束或者超时时间设置过长会浪费大量CPU时间,拖累整个系统。
CPU:一些运算对CPU直接或者不间断占用很大,CPU密集型应用会在CPU上产生瓶颈。
程序异常:对于java应用,异常产生构造异常栈并加以处理是很耗费资源的,高频率出现异常会拖垮整个系统。
数据库:关系型数据库在存盘读盘操作(即磁盘I/O操作),更新索引、锁等待和竞争都会产生瓶颈。
锁竞争:高并发应用线程之间互相锁的竞争,线程上下文切换都是很大的开销。
内存:内存使用nand flash读写速度很快,但如果应用程序和操作系统把内存占满,会导致交换分区的使用,内存数据与硬盘交换分区交换数据会产生(即磁盘I/O)瓶颈。
上述瓶颈基本解决方案:
磁盘I/O:使用NIO、零拷贝、mmap映射等技术,尽量异步读写硬盘,使用缓存和缓冲区技术。使用SSD硬盘,使用RAID技术提高写入性能。
网络请求:CDN或PCDN加速、缓存、合并请求、压缩报文,尽量异步网络请求(消息队列服务、master-worker等),使用NIO。加大带宽、升级网卡。
CPU:持续优化代码,利用好多线程或多进程,设计合理架构,拆分业务,减少单机复杂运算,避免复杂运算和业务请求掺杂在一起。
异常:处理好边界、缓冲区等,尤其需要注意避免出现NullPointException,测试时间大于开发时间减少bug出现几率。
数据库:优化sql语句,注意执行计划,使用缓存代替数据库部分功能,根据情景使用合理的存储引擎,注意锁,使用连接池,使用PrepareStatment。
锁竞争:尽量减少锁竞争,可以使用无锁的copy-on-write、重入锁等技术。
内存:优化代码,分析内存占用情况,合理配置gc。增大物理内存。
Amdahl定律:
加速比公式:加速比=优化前耗时/优化后耗时
Speedup ≤ 1/(F+(1-F)/N)
- Speedup:加速比
- F:串行化比重
- N:CPU数量
根据Amdahl定律,优化的效果取决于CPU数量以及系统中串行化程序比重,CPU数量越多,串行比越低,优化效果越好。
性能调优层次
设计调优:对整体架构进行梳理,找出短板进行优化,适当使用设计模式和以往经验。详细进行系统设计。
代码调优:熟悉基本API、第三方类库的原理,选择最适当和最优秀的算法,精简实现,面向接口。
JVM调优:熟悉jvm内存模型,字节码等深层技术,使用常用监控工具如:visualVM、Jconsole等。进行压测,调节gc和堆栈大小。
数据库调优:对sql语句进行调优,分析执行计划,对数据库系统配置调优(缓冲区、共享区、连接池等),对数据库设计进行调优(冗余、索引、分库分表、读写分离等)
操作系统调优:调节句柄数、关闭没用服务和端口、调节共享内存、调节交换分区大小等。
最后需要注意:不要因为优化而优化!