java性能调优学习笔记

核心

“纸上得来终觉浅,绝知此事要躬行”。

学会透过现象看本质

1. 扎实的计算机基础

我们需要储备计算机组成原理、操作系统、网络协议以及数据库等基础知识。具体的性能问题往往还与传输、计算、存储数据等相关,那我们还需要储备数据结构、算法以及数学等基础知识。

2. 习惯透过源码了解技术本质

我们需要深入源码,通过分析来学习、总结一项技术的实现原理和优缺点,这样我们就能更客观地去学习一项技术,还能透过源码来学习牛人的思维方式,收获更好的编码实现方式。

3. 善于追问和总结

“知其然且知所以然”才是我们积累经验的关键。知道了一项技术背后的实现原理,我们才能在遇到性能问题时,做到触类旁通。

调优政策

  • 分析查找问题是一个复杂而又细致的过程,某个性能问题可能是一个原因导致的,也可能是几个原因共同导致的结果。我们分析查找问题可以采用自下而上的方式,而我们解决系统性能问题,则可以采用自上而下的方式逐级优化。

1. 优化代码

2. 优化设计

3. 优化算法

4. 时间换空间

5. 空间换时间

6. 参数调优

7. 兜底策略,确保系统稳定性

数据结构

数组:采用一段连续的存储单元来存储数据。对于指定下标的查找,时间复杂度为 O(1),但在数组中间以及头部插入数据时,需要复制移动后面的元素。

链表:一种在物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。由于链表不用必须按顺序存储,所以链表在插入的时候可以达到 O(1) 的复杂度,但查找一个结点或者访问特定编号的结点需要 O(n) 的时间。

哈希表:根据关键码值(Key value)直接进行访问的数据结构。通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做哈希函数,存放记录的数组就叫做哈希表。

:由 n(n≥1)个有限结点组成的一个具有层次关系的集合,就像是一棵倒挂的树。

字符串性能优化

MGD7wV.md.jpg

  • 一个 char 字符占 16 位,2 个字节。这个情况下,存储单字节编码内的字符(占一个字节的字符)就显得非常浪费。JDK1.9 的 String 类为了节约内存空间,于是使用了占 8 位,1 个字节的 byte 数组来存放字符串

  • String 对象的不可变性

  • 对象和对象引用

  • 使用 String.intern 来节省内存空间,从而优化 String 对象的存储

    具体做法就是,在每次赋值的时候使用 String 的 intern 方法,如果常量池中有相同值,就会重复使用该对象,返回对象引用,这样一开始的对象就可以被回收掉。这种方式可以使重复性非常高的地址信息存储大小从 20G 降到几百兆。

    如果调用 intern 方法,会去查看字符串常量池中是否有等于该对象的字符串,如果没有,就在常量池中新增该对象,并返回该对象引用;如果有,就返回常量池中的字符串引用。堆内存中原有的对象由于没有引用指向它,将会通过垃圾回收器回收。

    1
    2
    3
    4
    5
    6
    String a =new String("abc").intern();
    String b = new String("abc").intern();

    if(a==b) {// a 和 b 引用的是同一个对象。
    System.out.print("a==b");//正常输出
    }
  • 用 String.indexOf() 方法代替 Split() 方法完成字符串的分割

慎重使用正则表达式

MGDWWQ.md.jpg

正则表达式是一个用正则符号写出的公式,程序对这个公式进行语法分析,建立一个语法分析树,再根据这个分析树结合正则表达式的引擎生成执行程序(这个执行程序我们把它称作状态机,也叫状态自动机),用于字符匹配。

如果使用正则表达式能使你的代码简洁方便,那么在做好性能排查的前提下,可以去使用;如果不能,那么正则表达式能不用就不用,以此避免造成更多的性能问题。

ArrayList VS LinkedList

  • 由于 ArrayList 是数组实现的,而数组是一块连续的内存空间,在添加元素到数组头部的时候,需要对头部以后的数据进行复制重排,所以效率很低;而 LinkedList 是基于链表实现,在添加元素的时候,首先会通过循环查找到添加元素的位置,如果要添加的位置处于 List 的前半段,就从前往后找;若其位置处于后半段,就从后往前找。因此 LinkedList 添加元素到头部是非常高效的。
  • LinkedList 的 for 循环性能是最差的,而 ArrayList 的 for 循环性能是最好的。

Stream

MY0E6A.md.jpg