利用JVM的MXBean找到blocked的点
当你发现JVM占用的cpu很高,而且响应时间比较慢,很可能是被IO或者网络等慢速设备拖住了。也有可能是你的方法中某个同步点(同步方法或者对象)成为性能的瓶颈。这时候你可以利用JVM提供的monitor API来监控:
- <%@ page import="java.lang.management.*, java.util.*" %>
- <%!
- Map cpuTimes = new HashMap();
- Map cpuTimeFetch = new HashMap();
- %>
-
- <%
- out.println("Threads Monitoring");
- long cpus = Runtime.getRuntime().availableProcessors();
- ThreadMXBean threads = ManagementFactory.getThreadMXBean();
- threads.setThreadContentionMonitoringEnabled(true);
- long now = System.currentTimeMillis();
- ThreadInfo[] t = threads.dumpAllThreads(false, false);
- for (int i = 0; i < t.length; i++) {
- long id = t[i].getThreadId();
- Long idObj = new Long(id);
- long current = 0;
- if (cpuTimes.get(idObj) != null) {
- long prev = ((Long) cpuTimes.get(idObj)).longValue();
- current = threads.getThreadCpuTime(t[i].getThreadId());
- long catchTime = ((Long) cpuTimeFetch.get(idObj)).longValue();
- double percent = (double)(current - prev) / (double)((now - catchTime) * cpus * 1000);
- if (percent > 0 && prev > 0) {
- out.println("<li>" + t[i].getThreadName()+"#"+t[i].getThreadId() + " Time: " + percent + " (" + prev + ", " + current + ") ");
- String locked = t[i].getLockInfo()==null?"":t[i].getLockInfo().getClassName();
- out.println(" Blocked: (" + t[i].getBlockedTime() + ", " + t[i].getBlockedCount() + ", " + locked + ")</li>");
- }
- }
- cpuTimes.put(idObj, new Long(current));
- cpuTimeFetch.put(idObj, new Long(now));
- }
- %>
|
同步是性能的一大瓶颈
通过监控发现,大量线程block在一个同步方法上,这样cpu也使不上劲。当你发现性能上不去,IO和网络等慢速设备也不是问题的时候,你就得检查一下是否在某个关键点上使用了同步(synchronizae)。有时候也许是你应用的第三方的jar里面的某个方法是同步的,这种情况下,你就很难找到问题所在。只能在编写代码的时候看一下你引用的方法是否是同步的。