1. 性能分析工具

1.1. 必须有足够大的堆来处理数据

1.2. 运行性能分析工具时开启并发GC算法

1.3. 不合时宜的Full GC暂停会导致缓冲区的数据溢出

1.4. 性能分析的一个缺陷就是在应用程序中引入测试会改变其性能

1.5. 在工作时要“附加”到被分析的应用程序上

  • 1.5.1. 通过socket或者被称为JVM工具接口(JVM Tool Interface,JVMTI)的原生Java接口进行的

  • 1.5.2. 目标应用程序和性能分析工具开始交换关于目标应用程序行为的信息

2. 采样分析器

2.1. 性能分析的基本模式

2.2. 想要减小误差,就要延长采样周期并减小采样间隔

2.3. 安全点偏差(safepoint bias)

  • 2.3.1. 只有在线程到安全点之后才可以获取线程的栈轨迹(stack trace)

2.4. 线程自动进入安全点场景

  • 2.4.1. 在同步锁上阻塞

  • 2.4.2. 等待I/O时阻塞

  • 2.4.3. 等待管程时阻塞

  • 2.4.4. 线程挂起

  • 2.4.5. 正在执行Java本地接口(Java Native Interface,JNI)代码(执行GC锁定函数除外)

2.5. 异步分析器(async profiler)

  • 2.5.1. JVM可以在任何时间点提供栈信息,而无须等待线程到达(同步)安全点

  • 2.5.2. 通过AsyncGetCallTrace接口实现的

  • 2.5.3. 异步接口在Java 8被公开,在此之前它是私有接口

  • 2.5.4. 以异步方式收集栈信息的采样分析器引入的测量失真更小

2.6. 火焰图(flame graph)

  • 2.6.1. 一个应用程序调用栈的交互式图表

  • 2.6.2. 自底向上的图表

  • 2.6.3. 开源项目async-profiler

2.7. 自顶向下的调用树(call tree)

3. 探查分析器

3.1. 相对于采样分析器更有侵入性

  • 3.1.1. 会在类加载时更改字节码序列

3.2. 能提供更多关于应用程序内部正在发生什么的有益信息

3.3. 更可能在应用程序中引入性能偏差

  • 3.3.1. 编译器是基于代码的大小来决定是否内联的,而根据代码探查的方式,方法可能不再符合内联的条件

3.4. 最好用于二级分析

  • 3.4.1. 采样分析器将性能问题指向某个包或某段代码,然后探查分析器在需要时深入研究此代码

  • 3.4.2. 用于探查一小部分代码——几个类或包

4. 阻塞方法和线程时间线

4.1. 要知道线程阻塞是不是性能问题的原因,需要检查它们为什么被阻塞

4.2. 通过正在阻塞的方法或者线程时间线分析,可以分辨阻塞的线程

5. 原生分析器

5.1. async-profiler和Oracle Developer Studio的工具

5.2. 可以提供JVM代码和应用程序代码的内部运行信息

5.3. 如果原生分析器显示主要占用CPU资源的是GC时间,那么优化垃圾回收器是正确的选择

5.4. 如果它显示编译线程占用大量时间,那么这通常不会影响应用程序的性能