diff --git a/src/main/java/com/taobao/profile/Profiler.java b/src/main/java/com/taobao/profile/Profiler.java index 0ad4780..c22065d 100644 --- a/src/main/java/com/taobao/profile/Profiler.java +++ b/src/main/java/com/taobao/profile/Profiler.java @@ -33,6 +33,14 @@ public class Profiler { public static AtomicInteger instrumentMethodCount = new AtomicInteger(0); private final static int size = 65535; + /** + * 缓存当前线程对应的采样槽位,避免每次进入方法都竞争全局数组锁 + */ + private static final ThreadLocal currentThreadIndex = new ThreadLocal(); + /** + * 缓存当前线程的性能数据对象 + */ + private static final ThreadLocal currentThreadData = new ThreadLocal(); /** * 线程数组 */ @@ -43,6 +51,49 @@ public class Profiler { */ public static SlowQueryData[] slowQueryProfile = new SlowQueryData[size]; + /** + * 获取当前线程已存在的性能数据对象 + * + * @param threadIndex + * @return + */ + private static ThreadData getThreadDataIfPresent(int threadIndex) { + Integer cachedIndex = currentThreadIndex.get(); + ThreadData thrData = currentThreadData.get(); + if (cachedIndex != null && cachedIndex.intValue() == threadIndex && thrData != null) { + return thrData; + } + thrData = threadProfile[threadIndex]; + if (thrData != null) { + currentThreadIndex.set(threadIndex); + currentThreadData.set(thrData); + } + return thrData; + } + + /** + * 获取当前线程的性能数据对象,如不存在则初始化 + * + * @param threadIndex + * @return + */ + private static ThreadData getOrCreateThreadData(int threadIndex) { + ThreadData thrData = getThreadDataIfPresent(threadIndex); + if (thrData != null) { + return thrData; + } + synchronized (threadProfile) { + thrData = threadProfile[threadIndex]; + if (thrData == null) { + thrData = new ThreadData(); + threadProfile[threadIndex] = thrData; + } + } + currentThreadIndex.set(threadIndex); + currentThreadData.set(thrData); + return thrData; + } + /** * 方法开始时调用,采集开始时间 * @@ -65,21 +116,14 @@ public static void Start(int methodId) { } try { int threadIndex = (int) threadId; - synchronized (threadProfile) { - ThreadData thrData = threadProfile[threadIndex]; - if (thrData == null) { - thrData = new ThreadData(); - threadProfile[threadIndex] = thrData; - } - - synchronized (thrData) { - long[] frameData = new long[3]; - frameData[0] = methodId; - frameData[1] = thrData.stackNum; - frameData[2] = startTime; - thrData.stackFrame.push(frameData); - thrData.stackNum++; - } + ThreadData thrData = getOrCreateThreadData(threadIndex); + synchronized (thrData) { + long[] frameData = new long[3]; + frameData[0] = methodId; + frameData[1] = thrData.stackNum; + frameData[2] = startTime; + thrData.stackFrame.push(frameData); + thrData.stackNum++; } } catch (Exception e) { e.printStackTrace(); @@ -108,7 +152,7 @@ public static void End(int methodId) { } try { int threadIndex = (int) threadId; - ThreadData thrData = threadProfile[threadIndex]; + ThreadData thrData = getThreadDataIfPresent(threadIndex); if (thrData == null) { return; } diff --git a/src/main/java/com/taobao/profile/thread/SamplerThread.java b/src/main/java/com/taobao/profile/thread/SamplerThread.java index e4aa645..e6c0f6a 100644 --- a/src/main/java/com/taobao/profile/thread/SamplerThread.java +++ b/src/main/java/com/taobao/profile/thread/SamplerThread.java @@ -55,9 +55,9 @@ public void run() { if (Manager.instance().canDump()) { Date date = new Date(); Map map = Thread.getAllStackTraces(); + StringBuilder sb = new StringBuilder(map.size() * 256); for (Map.Entry entry : map.entrySet()) { Thread thread = entry.getKey(); - StringBuilder sb = new StringBuilder(); sb.append("Thread\t"); sb.append(thread.getId()); sb.append("\t"); @@ -67,11 +67,13 @@ public void run() { sb.append("\t"); sb.append(date); sb.append("\n"); - fileWriter.append(sb.toString()); for (StackTraceElement element : entry.getValue()) { - fileWriter.append(element.toString()); - fileWriter.append("\n"); + sb.append(element.toString()); + sb.append("\n"); } + } + if (sb.length() > 0) { + fileWriter.append(sb.toString()); fileWriter.flushAppend(); } }