troubleshoot之:使用JFR分析性能问题

简介

java程序的性能问题分析是一个很困难的问题。尤为是对于一个很是复杂的程序来讲,分析起来更是头疼。java

还好JVM引入了JFR,能够经过JFR来监控和分析JVM的各类事件。经过这些事件的分析,咱们能够找出潜在的问题。bootstrap

今天咱们就来介绍一下对java性能分析比较重要的一些JFR事件。多线程

GC性能事件

通常来讲,GC会对java程序的性能操做产生比较重要的影响。咱们可使用jfr监控jdk.GCPhasePause事件。 jvm

下面是一个jdk.GCPhasePause的例子:socket

jfr print --events jdk.GCPhasePause flight_recording_1401comflydeanTestMemoryLeak89268.jfr

输出结果:ide

jdk.GCPhasePause {
  startTime = 19:51:49.798
  duration = 41.1 ms
  gcId = 2
  name = "GC Pause"
}

经过GCPhasePause事件,咱们能够统计总的GC pause时间和平均每一次GC pause的时间。oop

通常来讲GC是在后台执行的,因此GC自己的执行时间咱们并不须要关注,由于这并不会影响到程序的性能。咱们须要关注的是应用程序由于GC暂停的时间。性能

考虑下面两种状况,第一种单独的GC致使GC pause时间过长。第二种是总的GC pause时间过长。spa

若是是第一种状况,那么可能须要考虑换一个GC类型,由于不一样的GC类型在pause时间和吞吐量的平衡直接会有不一样的处理。同时咱们须要减小finalizers的使用。线程

若是是第二种状况,咱们能够从下面几个方面来解决。

  • 增长heap空间大小。heap空间越大,GC的间隔时间就越长。总的GC pause时间就会越短。
  • 尽可能减小tmp对象的分配。咱们知道为了提高多线程的性能,JVM会使用TLAB技术。通常来讲小对象会分配在TLAB中,但若是是大对象,则会直接分配在heap空间中。可是大部分对象都是在TLAB中分配的。因此咱们能够同时关注TLAB和TLAB以外的两个事件:jdk.ObjectAllocationInNewTLAB和dk.ObjectAllocationOutsideTLAB。
  • 减小分配频率。咱们能够经过jdk.ThreadAllocationStatistics来分析。

同步性能

在多线程环境中,由于多线程会竞争共享资源,因此对资源的同步,或者锁的使用都会影响程序的性能。

咱们能够监控jdk.JavaMonitorWait事件。

jfr print --events jdk.JavaMonitorWait flight_recording_1401comflydeanTestMemoryLeak89268.jfr

咱们看一个结果:

jdk.JavaMonitorWait {
  startTime = 19:51:25.395
  duration = 2 m 0 s
  monitorClass = java.util.TaskQueue (classLoader = bootstrap)
  notifier = N/A
  timeout = 2 m 0 s
  timedOut = true
  address = 0x7FFBB7007F08
  eventThread = "JFR Recording Scheduler" (javaThreadId = 17)
  stackTrace = [
    java.lang.Object.wait(long)
    java.util.TimerThread.mainLoop() line: 553
    java.util.TimerThread.run() line: 506
  ]
}

经过分析JavaMonitorWait事件,咱们能够找到竞争最激烈的锁,从而进行更深层次的分析。

IO性能

若是应用程序有不少IO操做,那么IO操做也是会影响性能的关键一环。

咱们能够监控两种IO类型:socket IO和File IO。

相对应的事件有:dk.SocketWrite,jdk.SocketRead,jdk.FileWrite,jdk.FileRead。

代码执行的性能

代码是经过CPU来运行的,若是CPU使用太高,也可能会影响到程序的性能。

咱们能够经过监听jdk.CPULoad事件来对CPULoad进行分析。

jfr print --events jdk.CPULoad flight_recording_1401comflydeanTestMemoryLeak89268.jfr

看下运行结果:

jdk.CPULoad {
  startTime = 19:53:25.519
  jvmUser = 0.63%
  jvmSystem = 0.37%
  machineTotal = 20.54%
}

若是jvm使用的cpu比较少,可是整个machine的CPU使用率比较高,这说明了有其余的程序在占用CPU。

若是JVM本身的CPU使用就很高的话,那么就须要找到这个占用CPU的线程进行进一步分析。

其余有用的event

除了上面提到的event以外,还有一些其余有用的咱们能够关注的event。

好比线程相关的:jdk.ThreadStart,jdk.ThreadEnd,jdk.ThreadSleep,jdk.ThreadPark。

若是你使用JMC,那么能够很直观的查看JFR的各类事件。

因此推荐你们使用JMC。

本文做者:flydean程序那些事

本文连接:http://www.flydean.com/jvm-diagnostic-perform-issue/

本文来源:flydean的博客

欢迎关注个人公众号:程序那些事,更多精彩等着您!

相关文章
相关标签/搜索