diff --git a/src/java.base/share/classes/com/alibaba/wisp/engine/ScheduledWispEngine.java b/src/java.base/share/classes/com/alibaba/wisp/engine/ScheduledWispEngine.java index afb36effef1..87cb922c1b0 100644 --- a/src/java.base/share/classes/com/alibaba/wisp/engine/ScheduledWispEngine.java +++ b/src/java.base/share/classes/com/alibaba/wisp/engine/ScheduledWispEngine.java @@ -587,6 +587,7 @@ protected void closeEngineSelector() { @Override public void shutdown() { hasBeenShutdown = true; + deRegisterPerfCounter(); if (WispEngine.current().current == threadTask) { doShutdown(); } else { diff --git a/src/java.base/share/classes/com/alibaba/wisp/engine/Wisp2Engine.java b/src/java.base/share/classes/com/alibaba/wisp/engine/Wisp2Engine.java index 7442d28f13b..8d8c9d29fc9 100644 --- a/src/java.base/share/classes/com/alibaba/wisp/engine/Wisp2Engine.java +++ b/src/java.base/share/classes/com/alibaba/wisp/engine/Wisp2Engine.java @@ -252,6 +252,7 @@ public void shutdown() { return; } hasBeenShutdown = true; + deRegisterPerfCounter(); group.scheduler.executeWithCarrierThread(new StealAwareRunnable() { @Override public void run() { diff --git a/src/java.base/share/classes/com/alibaba/wisp/engine/Wisp2Scheduler.java b/src/java.base/share/classes/com/alibaba/wisp/engine/Wisp2Scheduler.java index fdc4bf1b969..ee6f3093ed0 100644 --- a/src/java.base/share/classes/com/alibaba/wisp/engine/Wisp2Scheduler.java +++ b/src/java.base/share/classes/com/alibaba/wisp/engine/Wisp2Scheduler.java @@ -111,6 +111,7 @@ public void run() { engine.group = group; engine.carrier = this; group.carrierEngines.add(engine); + engine.registerPerfCounter(); runCarrier(engine); } finally { WispEngine.carrierThreads.remove(thread); @@ -461,6 +462,8 @@ public void run() { last = cs[i]; } carriers = cs; + Wisp2Engine engine = (Wisp2Engine) JLA.getWispEngine(thread); + engine.deRegisterPerfCounter(); } } diff --git a/src/java.base/share/classes/com/alibaba/wisp/engine/WispCounter.java b/src/java.base/share/classes/com/alibaba/wisp/engine/WispCounter.java index 80e0b0988d1..fa44ec566c4 100644 --- a/src/java.base/share/classes/com/alibaba/wisp/engine/WispCounter.java +++ b/src/java.base/share/classes/com/alibaba/wisp/engine/WispCounter.java @@ -1,6 +1,6 @@ package com.alibaba.wisp.engine; -final class WispCounter { +final public class WispCounter { private long switchCount = 0; @@ -8,7 +8,7 @@ final class WispCounter { private long runningTimeTotal = 0; - private long completeTaskCount = 0; + private long completedTaskCount = 0; private long createTaskCount = 0; @@ -26,18 +26,26 @@ final class WispCounter { private long totalEnqueueTime = 0; + private long maxEnqueueTime = 0; + private long enqueueCount = 0; private long totalExecutionTime = 0; + private long maxExecutionTime = 0; + private long executionCount = 0; private long totalWaitSocketIOTime = 0; + private long maxWaitSocketIOTime = 0; + private long waitSocketIOCount = 0; private long totalBlockingTime = 0; + private long maxBlockingTime = 0; + private long unparkFromJvmCount = 0; WispEngine engine; @@ -46,27 +54,28 @@ private WispCounter(WispEngine engine) { this.engine = engine; } - boolean getRunningState() { - return engine.isRunning(); + public boolean getRunningState() { + WispEngine e = engine; + return e != null ? e.isRunning() : false; } void incrementSwitchCount() { switchCount++; } - long getSwitchCount() { + public long getSwitchCount() { return switchCount; } void incrementCompleteTaskCount() { - completeTaskCount++; + completedTaskCount++; } void incrementRunningTimeTotal(long value) { runningTimeTotal += value; } - long getRunningTimeTotal() { + public long getRunningTimeTotal() { return runningTimeTotal; } @@ -74,19 +83,19 @@ void incrementWaitTime(long value) { waitTimeTotal += value; } - long getWaitTimeTotal() { + public long getWaitTimeTotal() { return waitTimeTotal; } - long getCompleteTaskCount() { - return completeTaskCount; + public long getCompletedTaskCount() { + return completedTaskCount; } void incrementCreateTaskCount() { createTaskCount++; } - long getCreateTaskCount() { + public long getCreateTaskCount() { return createTaskCount; } @@ -94,7 +103,7 @@ void incrementParkCount() { parkCount++; } - long getParkCount() { + public long getParkCount() { return parkCount; } @@ -103,7 +112,7 @@ void incrementUnparkInterruptSelectorCount() { unparkInterruptSelectorCount++; } - long getUnparkInterruptSelectorCount() { + public long getUnparkInterruptSelectorCount() { return unparkInterruptSelectorCount; } @@ -111,7 +120,7 @@ void incrementSelectableIOCount() { selectableIOCount++; } - long getSelectableIOCount() { + public long getSelectableIOCount() { return selectableIOCount; } @@ -119,7 +128,7 @@ void incrementTimeOutCount() { timeOutCount++; } - long getTimeOutCount() { + public long getTimeOutCount() { return timeOutCount; } @@ -127,96 +136,141 @@ void incrementEventLoopCount() { eventLoopCount++; } - long getEventLoopCount() { + public long getEventLoopCount() { return eventLoopCount; } void incrementTotalEnqueueTime(long value) { totalEnqueueTime += value; enqueueCount++; + if (value > maxEnqueueTime) { + maxEnqueueTime = value; + } } - long getTotalEnqueueTime() { + public long getTotalEnqueueTime() { return totalEnqueueTime; } - long getEnqueueCount() { + public long getEnqueueCount() { return enqueueCount; } void incrementTotalExecutionTime(long value) { totalExecutionTime += value; executionCount++; + if (value > maxExecutionTime) { + maxExecutionTime = value; + } } - long getTotalExecutionTime() { + public long getTotalExecutionTime() { return totalExecutionTime; } - long getExecutionCount() { + public long getExecutionCount() { return executionCount; } void incrementTotalWaitSocketIOTime(long value) { totalWaitSocketIOTime += value; waitSocketIOCount++; + if (value > maxWaitSocketIOTime) { + maxWaitSocketIOTime = value; + } } - long getTotalWaitSocketIOTime() { + public long getTotalWaitSocketIOTime() { return totalWaitSocketIOTime; } - long getWaitSocketIOCount() { + public long getWaitSocketIOCount() { return waitSocketIOCount; } void incrementTotalBlockingTime(long value) { totalBlockingTime += value; unparkCount++; + if (value > maxBlockingTime) { + maxBlockingTime = value; + } } - long getTotalBlockingTime() { + public long getTotalBlockingTime() { return totalBlockingTime; } - long getUnparkCount() { + public long getUnparkCount() { return unparkCount; } - public long getQueueLength() { - return engine.getTaskQueueLength(); + public long getTaskQueueLength() { + WispEngine e = engine; + return e != null ? e.getTaskQueueLength() : 0; } - long getNumberOfRunningTasks() { - return engine.getRunningTaskCount(); + public long getRunningTaskCount() { + WispEngine e = engine; + return e != null ? e.getRunningTaskCount() : 0; } void incrementUnparkFromJvmCount() { unparkFromJvmCount++; } - long getUnparkFromJvmCount() { + public long getUnparkFromJvmCount() { return unparkFromJvmCount; } + public long getMaxEnqueueTime() { + return maxEnqueueTime; + } + + public long getMaxExecutionTime() { + return maxExecutionTime; + } + + public long getMaxWaitSocketIOTime() { + return maxWaitSocketIOTime; + } + + public long getMaxBlockingTime() { + return maxBlockingTime; + } + WispCounter() {} void assign(WispCounter counter) { - createTaskCount = counter.createTaskCount; - completeTaskCount = counter.completeTaskCount; + createTaskCount = counter.createTaskCount; + completedTaskCount = counter.completedTaskCount; totalEnqueueTime = counter.totalEnqueueTime; enqueueCount = counter.enqueueCount; + maxEnqueueTime = counter.maxEnqueueTime; totalExecutionTime = counter.totalExecutionTime; executionCount = counter.executionCount; + maxExecutionTime = counter.maxExecutionTime; totalBlockingTime = counter.totalBlockingTime; unparkCount = counter.unparkCount; + maxBlockingTime = counter.maxBlockingTime; totalWaitSocketIOTime = counter.totalWaitSocketIOTime; waitSocketIOCount = counter.waitSocketIOCount; + maxWaitSocketIOTime = counter.maxWaitSocketIOTime; switchCount = counter.switchCount; unparkFromJvmCount = counter.unparkFromJvmCount; } - public static WispCounter create(WispEngine engine) { + void resetMaxValue() { + maxEnqueueTime = 0; + maxExecutionTime = 0; + maxWaitSocketIOTime = 0; + maxBlockingTime = 0; + } + + void cleanup() { + engine = null; + } + + static WispCounter create(WispEngine engine) { return new WispCounter(engine); } } diff --git a/src/java.base/share/classes/com/alibaba/wisp/engine/WispEngine.java b/src/java.base/share/classes/com/alibaba/wisp/engine/WispEngine.java index 798eb32615e..53e322e5c3b 100644 --- a/src/java.base/share/classes/com/alibaba/wisp/engine/WispEngine.java +++ b/src/java.base/share/classes/com/alibaba/wisp/engine/WispEngine.java @@ -16,6 +16,7 @@ import java.util.concurrent.AbstractExecutorService; import java.util.concurrent.ConcurrentSkipListSet; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; import java.util.concurrent.atomic.AtomicReference; @@ -73,6 +74,7 @@ public static boolean isShiftThreadModel() { static Set carrierThreads; private static Thread pollerThread; + static Map managedEngineCounters; static { registerNatives(); @@ -132,6 +134,9 @@ public void run() { pollerThread.setDaemon(true); pollerThread.start(); } + if (WispConfiguration.WISP_PROFILE_LOG_ENABLED) { + WispPerfCounterMonitor.INSTANCE.startDaemon(); + } } } @@ -335,6 +340,10 @@ private static void initializeClasses() { if (WispConfiguration.GLOBAL_POLLER) { Class.forName(WispEventPump.class.getName()); } + managedEngineCounters = new ConcurrentHashMap<>(100); + if (WispConfiguration.WISP_PROFILE) { + Class.forName(WispPerfCounterMonitor.class.getName()); + } WispEngine.current().preloadClasses(); // It will load configuration files and trigger // CleanerFactory.cleaner() when run thread as wisp firstly. But @@ -492,6 +501,10 @@ public long getId() { return thread.getId(); } + public static Map getManagedEngineCounters() { + return managedEngineCounters; + } + /** * Create WispTask to run task code *

@@ -504,6 +517,35 @@ public static void dispatch(Runnable target) { engine.dispatchTask(target, "dispatch task", null); } + public static WispCounter getWispCounter(long id) { + if (WispConfiguration.WISP_PROFILE) { + return WispPerfCounterMonitor.INSTANCE.getWispCounter(id); + } else { + return null; + } + } + + public void registerPerfCounter() { + SharedSecrets.getWispEngineAccess().runInCritical(() -> { + if (WispConfiguration.WISP_PROFILE) { + WispPerfCounterMonitor.INSTANCE.register(counter); + } + managedEngineCounters.put(getId(), counter); + return null; + }); + } + + void deRegisterPerfCounter() { + SharedSecrets.getWispEngineAccess().runInCritical(() -> { + if (WispConfiguration.WISP_PROFILE) { + WispPerfCounterMonitor.INSTANCE.deRegister(counter); + } + managedEngineCounters.remove(getId()); + counter.cleanup(); + return null; + }); + } + final WispTask runTaskInternal(Runnable target, String name, Thread thread, ClassLoader ctxLoader) { if (hasBeenShutdown && !WispTask.SHUTDOWN_TASK_NAME.equals(name)) { return null; diff --git a/src/java.base/share/classes/com/alibaba/wisp/engine/WispPerfCounterMonitor.java b/src/java.base/share/classes/com/alibaba/wisp/engine/WispPerfCounterMonitor.java new file mode 100644 index 00000000000..33f31b22af1 --- /dev/null +++ b/src/java.base/share/classes/com/alibaba/wisp/engine/WispPerfCounterMonitor.java @@ -0,0 +1,177 @@ +package com.alibaba.wisp.engine; + +import java.io.File; +import java.io.IOException; +import java.io.PrintStream; +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.Map.Entry; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentSkipListSet; +import java.util.function.Function; +import jdk.internal.access.SharedSecrets; +import jdk.internal.access.WispEngineAccess; + +enum WispPerfCounterMonitor { + INSTANCE; + + private boolean fileHandleEnable = false; + private Map managedEngineCounters; + private PrintStream printStream; + private SimpleDateFormat localDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + + private WispEngineAccess WEA; + + WispPerfCounterMonitor() { + WEA = SharedSecrets.getWispEngineAccess(); + if (WispConfiguration.WISP_PROFILE) { + managedEngineCounters = new ConcurrentHashMap<>(100); + } + if (WispConfiguration.WISP_PROFILE_LOG_ENABLED) { + String logPath = WispConfiguration.WISP_PROFILE_LOG_PATH; + try { + if (logPath == null) { + printStream = new PrintStream(new File("wisplog.log")); + } else { + printStream = new PrintStream(new File(logPath + File.separator + "wisplog%g.log")); + } + fileHandleEnable = true; + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + void startDaemon() { + Thread thread = new Thread(WispEngine.daemonThreadGroup, this::perfCounterLoop, "Wisp-Monitor"); + thread.setDaemon(true); + thread.start(); + } + + void register(WispCounter counter) { + if (WispConfiguration.WISP_PROFILE) { + WispPerfCounter wispPerfCounter = new WispPerfCounter(counter); + managedEngineCounters.put(counter.engine.getId(), wispPerfCounter); + } + } + + void deRegister(WispCounter counter) { + if (WispConfiguration.WISP_PROFILE) { + long id = counter.engine.getId(); + WispPerfCounter perfCounter = managedEngineCounters.get(id); + managedEngineCounters.remove(counter.engine.getId()); + } + } + + WispCounter getWispCounter(long id) { + WispPerfCounter perfCounter; + perfCounter = WEA.runInCritical(() -> { + return managedEngineCounters.get(id); + }); + if (perfCounter == null) { + return null; + } + perfCounter.storeCurrentWispCounter(); + return perfCounter.prevCounterValue; + } + + private void perfCounterLoop() { + while (true) { + try { + Thread.sleep((long)WispConfiguration.WISP_PROFILE_LOG_INTERVAL_MS); + } catch (InterruptedException e) { + // pass + } + dumpCounter(); + } + } + + private void appendLogString(StringBuilder strb, String dateTime, String item, int workerID, long data) { + strb.append(dateTime) + .append("\t" + item + "\t\t") + .append("worker" + workerID) + .append("\t\t") + .append(data) + .append("\n"); + } + + private void dumpCounter() { + if (!fileHandleEnable) { + return; + } + + StringBuilder strb = new StringBuilder(); + long currentTime = System.currentTimeMillis(); + String dateTime = localDateFormat.format(new Date(currentTime)); + int worker = 0; + /* dump Wisp monitor information */ + WispPerfCounter perfCounter; + for (Entry entry : managedEngineCounters.entrySet()) { + perfCounter = entry.getValue(); + appendLogString(strb, dateTime, "completedTaskCount", worker, perfCounter.getCompletedTaskCount()); + appendLogString(strb, dateTime, "unparkFromJvmCount", worker, perfCounter.getUnparkFromJvmCount()); + appendLogString(strb, dateTime, "averageEnqueueTime", worker, perfCounter.getAverageEnqueueTime()); + appendLogString(strb, dateTime, "averageExecutionTime", worker, perfCounter.getAverageExecutionTime()); + appendLogString(strb, dateTime, "averageWaitSocketIOTime", worker, perfCounter.getAverageWaitSocketIOTime()); + appendLogString(strb, dateTime, "averageBlockingTime", worker, perfCounter.getAverageBlockingTime()); + perfCounter.storeCurrentWispCounter(); + worker++; + } + printStream.print(strb.toString()); + printStream.println(); + printStream.flush(); + } + + private class WispPerfCounter { + WispCounter counter; + + WispCounter prevCounterValue; + + long getCompletedTaskCount() { + return counter.getCompletedTaskCount() - prevCounterValue.getCompletedTaskCount(); + } + + long getUnparkFromJvmCount() { + return counter.getUnparkFromJvmCount() - prevCounterValue.getUnparkFromJvmCount(); + } + + long getAverageTime(Function timeFunc, Function countFunc) { + long count = countFunc.apply(counter) - countFunc.apply(prevCounterValue); + if (count == 0) { + return 0; + } + long totalNanos = timeFunc.apply(counter) - timeFunc.apply(prevCounterValue); + return totalNanos/count; + } + + long getAverageEnqueueTime() { + return getAverageTime(WispCounter::getTotalEnqueueTime, WispCounter::getEnqueueCount); + } + + long getAverageExecutionTime() { + return getAverageTime(WispCounter::getTotalExecutionTime, WispCounter::getExecutionCount); + } + + long getAverageWaitSocketIOTime() { + return getAverageTime(WispCounter::getTotalWaitSocketIOTime, WispCounter::getWaitSocketIOCount); + } + + long getAverageBlockingTime() { + return getAverageTime(WispCounter::getTotalBlockingTime, WispCounter::getUnparkCount); + } + + void storeCurrentWispCounter() { + if (counter == null) { + return; + } + prevCounterValue.assign(counter); + counter.resetMaxValue(); + } + + public WispPerfCounter(WispCounter counter) { + this.counter = counter; + this.prevCounterValue = new WispCounter(); + this.prevCounterValue.assign(counter); + } + } +} diff --git a/src/java.base/share/classes/com/alibaba/wisp/engine/WispWorkerContainer.java b/src/java.base/share/classes/com/alibaba/wisp/engine/WispWorkerContainer.java index 6e31f6cfd72..3ae2bc0a109 100644 --- a/src/java.base/share/classes/com/alibaba/wisp/engine/WispWorkerContainer.java +++ b/src/java.base/share/classes/com/alibaba/wisp/engine/WispWorkerContainer.java @@ -39,6 +39,7 @@ public List getWorkers() { @Override public void run() { WispEngine engine = WispEngine.current(); // create engine + engine.registerPerfCounter(); countDownLatch.countDown(); engine.schedule(); // wait task submit diff --git a/src/jdk.management/share/classes/com/alibaba/management/WispCounterData.java b/src/jdk.management/share/classes/com/alibaba/management/WispCounterData.java new file mode 100644 index 00000000000..f036db21ead --- /dev/null +++ b/src/jdk.management/share/classes/com/alibaba/management/WispCounterData.java @@ -0,0 +1,141 @@ +package com.alibaba.management; + +import com.alibaba.wisp.engine.WispCounter; +import javax.management.ConstructorParameters; + +public class WispCounterData { + private long completedTaskCount = 0; + + private long unparkCount = 0; + + private long totalEnqueueTime = 0; + + private long maxEnqueueTime = 0; + + private long enqueueCount = 0; + + private long totalExecutionTime = 0; + + private long maxExecutionTime = 0; + + private long executionCount = 0; + + private long totalWaitSocketIOTime = 0; + + private long maxWaitSocketIOTime = 0; + + private long waitSocketIOCount = 0; + + private long totalBlockingTime = 0; + + private long maxBlockingTime = 0; + + private long runningTaskCount = 0; + + private long taskQueueLength = 0; + + public long getCompletedTaskCount() { + return completedTaskCount; + } + + public long getTotalEnqueueTime() { + return totalEnqueueTime; + } + + public long getEnqueueCount() { + return enqueueCount; + } + + public long getTotalExecutionTime() { + return totalExecutionTime; + } + + public long getExecutionCount() { + return executionCount; + } + + public long getTotalWaitSocketIOTime() { + return totalWaitSocketIOTime; + } + + public long getWaitSocketIOCount() { + return waitSocketIOCount; + } + + public long getTotalBlockingTime() { + return totalBlockingTime; + } + + public long getUnparkCount() { + return unparkCount; + } + + public long getMaxEnqueueTime() { + return maxEnqueueTime; + } + + public long getMaxExecutionTime() { + return maxExecutionTime; + } + + public long getMaxWaitSocketIOTime() { + return maxWaitSocketIOTime; + } + + public long getMaxBlockingTime() { + return maxBlockingTime; + } + + public long getTaskQueueLength() { + return taskQueueLength; + } + + public long getRunningTaskCount() { + return runningTaskCount; + } + + @ConstructorParameters({"completedTaskCount", "totalEnqueueTime", "maxEnqueueTime", "enqueueCount", + "totalExecutionTime", "maxExecutionTime", "executionCount", + "totalWaitSocketIOTime", "maxWaitSocketIOTime", "waitSocketIOCount", + "totalBlockingTime", "maxBlockingTime", "unparkCount", + "runningTaskCount", "taskQueueLength"}) + public WispCounterData(long completedTaskCount, long totalEnqueueTime, long maxEnqueueTime, long enqueueCount, + long totalExecutionTime, long maxExecutionTime, long executionCount, + long totalWaitSocketIOTime, long maxWaitSocketIOTime, long waitSocketIOCount, + long totalBlockingTime, long maxBlockingTime, long unparkCount, + long runningTaskCount, long taskQueueLength) { + this.completedTaskCount = completedTaskCount; + this.totalEnqueueTime = totalEnqueueTime; + this.maxEnqueueTime = maxEnqueueTime; + this.enqueueCount = enqueueCount; + this.totalExecutionTime = totalExecutionTime; + this.maxExecutionTime = maxExecutionTime; + this.executionCount = executionCount; + this.totalWaitSocketIOTime = totalWaitSocketIOTime; + this.maxWaitSocketIOTime = maxWaitSocketIOTime; + this.waitSocketIOCount = waitSocketIOCount; + this.totalBlockingTime = totalBlockingTime; + this.maxBlockingTime = maxBlockingTime; + this.unparkCount = unparkCount; + this.runningTaskCount = runningTaskCount; + this.taskQueueLength = taskQueueLength; + } + + public WispCounterData(WispCounter counter) { + completedTaskCount = counter.getCompletedTaskCount(); + totalEnqueueTime = counter.getTotalEnqueueTime(); + enqueueCount = counter.getEnqueueCount(); + maxEnqueueTime = counter.getMaxEnqueueTime(); + totalExecutionTime = counter.getTotalExecutionTime(); + executionCount = counter.getExecutionCount(); + maxExecutionTime = counter.getMaxExecutionTime(); + totalBlockingTime = counter.getTotalBlockingTime(); + unparkCount = counter.getUnparkCount(); + maxBlockingTime = counter.getMaxBlockingTime(); + totalWaitSocketIOTime = counter.getTotalWaitSocketIOTime(); + waitSocketIOCount = counter.getWaitSocketIOCount(); + maxWaitSocketIOTime = counter.getMaxWaitSocketIOTime(); + runningTaskCount = counter.getRunningTaskCount(); + taskQueueLength = counter.getTaskQueueLength(); + } +} diff --git a/src/jdk.management/share/classes/com/alibaba/management/WispCounterMXBean.java b/src/jdk.management/share/classes/com/alibaba/management/WispCounterMXBean.java new file mode 100644 index 00000000000..3e9450ef460 --- /dev/null +++ b/src/jdk.management/share/classes/com/alibaba/management/WispCounterMXBean.java @@ -0,0 +1,125 @@ +package com.alibaba.management; + +import com.alibaba.wisp.engine.WispCounter; + +import java.lang.management.PlatformManagedObject; +import java.util.List; + +public interface WispCounterMXBean extends PlatformManagedObject { + + /** + * @return list of managed wisp worker running state + */ + List getRunningStates(); + + /** + * @return list of managed wisp worker switch count + */ + List getSwitchCount(); + + /** + * @return list of managed wisp worker wait time total, unit ns + */ + List getWaitTimeTotal(); + + /** + * @return list of managed wisp worker running time total, unit ns + */ + List getRunningTimeTotal(); + + /** + * @return list of managed wisp worker complete task count + */ + List getCompleteTaskCount(); + + /** + * @return list of managed wisp worker create task count + */ + List getCreateTaskCount(); + + /** + * @return list of managed wisp worker park count + */ + List getParkCount(); + + /** + * @return list of managed wisp worker unpark count + */ + List getUnparkCount(); + + /** + * @return list of managed wisp worker lazy unpark count + */ + List getLazyUnparkCount(); + + /** + * @return list of managed wisp worker unpark interrupt selector count + */ + List getUnparkInterruptSelectorCount(); + + /** + * @return list of managed wisp worker do IO count + */ + List getSelectableIOCount(); + + /** + * @return list of managed wisp worker timeout count + */ + List getTimeOutCount(); + + /** + * @return list of managed wisp worker do event loop count + */ + List getEventLoopCount(); + + /** + * @return list of managed wisp worker task queue length + */ + List getQueueLength(); + + /** + * @return list of number of running tasks from managed wisp workers + */ + List getNumberOfRunningTasks(); + + /** + * @return list of total blocking time in nanos from managed wisp workers + */ + List getTotalBlockingTime(); + + /** + * @return list of total execution time in nanos from managed wisp workers + */ + List getTotalExecutionTime(); + + /** + * @return list of execution count from managed wisp workers + */ + List getExecutionCount(); + + /** + * @return list of total enqueue time in nanos from managed wisp workers + */ + List getTotalEnqueueTime(); + + /** + * @return list of enqueue count from managed wisp workers + */ + List getEnqueueCount(); + + /** + * @return list of total wait socket io time in nanos from managed wisp workers + */ + List getTotalWaitSocketIOTime(); + + /** + * @return list of wait socket io event count from managed wisp workers + */ + List getWaitSocketIOCount(); + + /** + * @param id WispEngine id + * @return WispCounterData + */ + WispCounterData getWispCounterData(long id); +} diff --git a/src/jdk.management/share/classes/com/alibaba/management/internal/WispCounterMXBeanImpl.java b/src/jdk.management/share/classes/com/alibaba/management/internal/WispCounterMXBeanImpl.java new file mode 100644 index 00000000000..d18f7d90131 --- /dev/null +++ b/src/jdk.management/share/classes/com/alibaba/management/internal/WispCounterMXBeanImpl.java @@ -0,0 +1,157 @@ +package com.alibaba.management.internal; + +import com.alibaba.management.WispCounterMXBean; +import com.alibaba.management.WispCounterData; +import com.alibaba.wisp.engine.WispCounter; +import com.alibaba.wisp.engine.WispEngine; +import sun.management.Util; + +import javax.management.ObjectName; +import java.util.*; +import java.util.function.Function; +import java.util.Map.Entry; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Implementation class for WispCounterMXBean. + */ +public class WispCounterMXBeanImpl implements com.alibaba.management.WispCounterMXBean { + + private final static String WISP_COUNTER_MXBEAN_NAME = "com.alibaba.management:type=WispCounter"; + + @Override + public List getRunningStates() { + return aggregate(WispCounter::getRunningState); + } + + @Override + public List getSwitchCount() { + return aggregate(WispCounter::getSwitchCount); + } + + @Override + public List getWaitTimeTotal() { + return aggregate(WispCounter::getWaitTimeTotal); + } + + @Override + public List getRunningTimeTotal() { + return aggregate(WispCounter::getRunningTimeTotal); + } + + @Override + public List getCompleteTaskCount() { + return aggregate(WispCounter::getCompletedTaskCount); + } + + @Override + public List getCreateTaskCount() { + return aggregate(WispCounter::getCreateTaskCount); + } + + @Override + public List getParkCount() { + return aggregate(WispCounter::getParkCount); + } + + @Override + public List getUnparkCount() { + return aggregate(WispCounter::getUnparkCount); + } + + @Override + public List getLazyUnparkCount() { + return aggregate(w -> 0L); + } + + @Override + public List getUnparkInterruptSelectorCount() { + return aggregate(WispCounter::getUnparkInterruptSelectorCount); + } + + @Override + public List getSelectableIOCount() { + return aggregate(WispCounter::getSelectableIOCount); + } + + @Override + public List getTimeOutCount() { + return aggregate(WispCounter::getTimeOutCount); + } + + @Override + public List getEventLoopCount() { + return aggregate(WispCounter::getEventLoopCount); + } + + @Override + public List getQueueLength() { + return aggregate(WispCounter::getTaskQueueLength); + } + + @Override + public List getNumberOfRunningTasks() { + return aggregate(WispCounter::getRunningTaskCount); + } + + @Override + public List getTotalEnqueueTime() { + return aggregate(WispCounter::getTotalEnqueueTime); + } + + @Override + public List getEnqueueCount() { + return aggregate(WispCounter::getEnqueueCount); + } + + @Override + public List getTotalExecutionTime() { + return aggregate(WispCounter::getTotalExecutionTime); + } + + @Override + public List getExecutionCount() { + return aggregate(WispCounter::getExecutionCount); + } + + @Override + public List getTotalWaitSocketIOTime() { + return aggregate(WispCounter::getTotalWaitSocketIOTime); + } + + @Override + public List getWaitSocketIOCount() { + return aggregate(WispCounter::getWaitSocketIOCount); + } + + @Override + public List getTotalBlockingTime() { + return aggregate(WispCounter::getTotalBlockingTime); + } + + /** + * @param id WispEngine id + * @return WispCounterData + */ + @Override + public WispCounterData getWispCounterData(long id) { + WispCounter counter = WispEngine.getWispCounter(id); + return new WispCounterData(counter); + } + + private List aggregate(Function getter) { + if (!WispEngine.transparentWispSwitch()) { + return null; + } + List result = new ArrayList<>(WispEngine.getManagedEngineCounters().size()); + for (Entry entry : WispEngine.getManagedEngineCounters().entrySet()) { + result.add(getter.apply(entry.getValue())); + } + return result; + } + + @Override + public ObjectName getObjectName() { + return Util.newObjectName(WISP_COUNTER_MXBEAN_NAME); + } +} diff --git a/src/jdk.management/share/classes/com/sun/management/internal/PlatformMBeanProviderImpl.java b/src/jdk.management/share/classes/com/sun/management/internal/PlatformMBeanProviderImpl.java index 97c31ddc401..c27d7e38148 100644 --- a/src/jdk.management/share/classes/com/sun/management/internal/PlatformMBeanProviderImpl.java +++ b/src/jdk.management/share/classes/com/sun/management/internal/PlatformMBeanProviderImpl.java @@ -24,6 +24,8 @@ */ package com.sun.management.internal; +import com.alibaba.management.WispCounterMXBean; +import com.alibaba.management.internal.WispCounterMXBeanImpl; import com.sun.management.DiagnosticCommandMBean; import com.sun.management.HotSpotDiagnosticMXBean; import com.sun.management.ThreadMXBean; @@ -52,6 +54,7 @@ public final class PlatformMBeanProviderImpl extends PlatformMBeanProvider { private final List> mxbeanList; private static HotSpotDiagnostic hsDiagMBean = null; private static OperatingSystemMXBean osMBean = null; + private static WispCounterMXBean wispCounterMBean = null; static { AccessController.doPrivileged((PrivilegedAction) () -> { @@ -264,6 +267,38 @@ public Map nameToMBeanMap() { }); } + /** + * Wisp-Counter support. + */ + initMBeanList.add(new PlatformComponent() { + private final Set wispCounterMXBeanInterfaceNames = + Collections.unmodifiableSet(Collections.singleton( + "com.alibaba.management.WispCounterMXBean")); + + @Override + public Set> mbeanInterfaces() { + return Collections.singleton(com.alibaba.management.WispCounterMXBean.class); + } + + @Override + public Set mbeanInterfaceNames() { + return wispCounterMXBeanInterfaceNames; + } + + @Override + public String getObjectNamePattern() { + return "com.alibaba.management:type=WispCounter"; + } + + @Override + public Map nameToMBeanMap() { + return Collections.singletonMap( + "com.alibaba.management:type=WispCounter", + getWispCounterMXBean()); + } + }); + + initMBeanList.trimToSize(); return initMBeanList; } @@ -281,4 +316,11 @@ private static synchronized OperatingSystemMXBean getOperatingSystemMXBean() { } return osMBean; } + + private static synchronized WispCounterMXBean getWispCounterMXBean() { + if (wispCounterMBean == null) { + wispCounterMBean = new WispCounterMXBeanImpl(); + } + return wispCounterMBean; + } } diff --git a/src/jdk.management/share/classes/module-info.java b/src/jdk.management/share/classes/module-info.java index 092480de9e5..c0d7ec3a02a 100644 --- a/src/jdk.management/share/classes/module-info.java +++ b/src/jdk.management/share/classes/module-info.java @@ -33,6 +33,7 @@ requires transitive java.management; exports com.sun.management; + exports com.alibaba.management; provides sun.management.spi.PlatformMBeanProvider with com.sun.management.internal.PlatformMBeanProviderImpl; diff --git a/test/jdk/com/alibaba/wisp/TestWispCounter.java b/test/jdk/com/alibaba/wisp/TestWispCounter.java new file mode 100644 index 00000000000..32f797b643a --- /dev/null +++ b/test/jdk/com/alibaba/wisp/TestWispCounter.java @@ -0,0 +1,128 @@ +import com.alibaba.management.WispCounterMXBean; + +import javax.management.MBeanServer; +import java.io.*; +import java.lang.management.ManagementFactory; +import java.lang.management.RuntimeMXBean; +import java.lang.reflect.Method; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import static jdk.test.lib.Asserts.assertTrue; + +/* @test + * @summary WispCounterMXBean unit test + * @library /test/lib + * @modules java.base/com.alibaba.wisp.engine:+open + * @run main/othervm/timeout=2000 -XX:ActiveProcessorCount=4 -XX:+EnableCoroutine -XX:+UseWispMonitor -Dcom.alibaba.transparentAsync=true -Dcom.alibaba.shiftThreadModel=true -Dcom.alibaba.wisp.config=/tmp/wisp.config TestWispCounter + */ + +public class TestWispCounter { + + public static void main(String[] args) throws Exception { + + startNetServer(); + File f = new File("/tmp/wisp.config"); + f.deleteOnExit(); + FileWriter writer = new FileWriter(f); + writer.write("com.alibaba.wisp.biz.manage=TestWispCounter::main\n"); + writer.close(); + + // WispBizSniffer has already been loaded; + // reload WispBizSniffer's config from file. + Method m = Class.forName("com.alibaba.wisp.engine.WispConfiguration").getDeclaredMethod("loadBizConfig"); + m.setAccessible(true); + m.invoke(null); + + MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); + WispCounterMXBean mbean = null; + try { + + mbean = ManagementFactory.newPlatformMXBeanProxy(mbs, + "com.alibaba.management:type=WispCounter", WispCounterMXBean.class); + } catch (IOException e) { + e.printStackTrace(); + } + + ExecutorService es = Executors.newFixedThreadPool(20); + int taskTotal = 40; + for (int i = 0; i < taskTotal; i++) { + // submit task + es.submit(() -> { + // do park/unpark + synchronized (TestWispCounter.class) { + // do sleep + try { + Thread.sleep(10L); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + // do net IO + doNetIO(); + }); + } + + System.out.println(mbean.getRunningStates()); + System.out.println(mbean.getQueueLength()); + // wait task complete + Thread.sleep(10_000L); + System.out.println(mbean.getSwitchCount()); + assertTrue(mbean.getSwitchCount().stream().mapToLong(Long::longValue).sum() >= taskTotal); + System.out.println(mbean.getSelectableIOCount()); + assertTrue(mbean.getSwitchCount().stream().mapToLong(Long::longValue).sum() > 0); + System.out.println(mbean.getParkCount()); + assertTrue(mbean.getParkCount().stream().mapToLong(Long::longValue).sum() > 0); + System.out.println(mbean.getCreateTaskCount()); + System.out.println(mbean.getCompleteTaskCount()); + System.out.println(mbean.getEventLoopCount()); + assertTrue(mbean.getEventLoopCount().stream().mapToLong(Long::longValue).sum() > 0); + System.out.println(mbean.getUnparkInterruptSelectorCount()); + assertTrue(mbean.getTimeOutCount().stream().mapToLong(Long::longValue).sum() > 0); + System.out.println(mbean.getTimeOutCount()); + assertTrue(mbean.getTimeOutCount().stream().mapToLong(Long::longValue).sum() > 0); + System.out.println(mbean.getWaitTimeTotal()); + assertTrue(mbean.getWaitTimeTotal().stream().mapToLong(Long::longValue).sum() > 0); + System.out.println(mbean.getRunningTimeTotal()); + assertTrue(mbean.getRunningTimeTotal().stream().mapToLong(Long::longValue).sum() > 0); + } + + private static ServerSocket ss; + private static final int PORT = 23000; + private static final int BUFFER_SIZE = 1024; + + private static void startNetServer() throws IOException { + ss = new ServerSocket(PORT); + Thread t = new Thread(() -> { + try { + while (true) { + Socket cs = ss.accept(); + InputStream is = cs.getInputStream(); + int r = is.read(new byte[BUFFER_SIZE]); + is.close(); + cs.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + }); + t.setDaemon(true); + t.start(); + } + + private static void doNetIO() { + try { + Socket so = new Socket("localhost", PORT); + OutputStream os = so.getOutputStream(); + os.write(new byte[BUFFER_SIZE]); + os.flush(); + os.close(); + } catch (IOException e) { + e.printStackTrace(); + throw new Error(e); + } + } +} diff --git a/test/jdk/com/alibaba/wisp/TestWispDetailCounter.java b/test/jdk/com/alibaba/wisp/TestWispDetailCounter.java new file mode 100644 index 00000000000..25d4448ce7c --- /dev/null +++ b/test/jdk/com/alibaba/wisp/TestWispDetailCounter.java @@ -0,0 +1,134 @@ +import com.alibaba.management.WispCounterMXBean; + +import javax.management.MBeanServer; +import java.io.*; +import java.lang.management.ManagementFactory; +import java.lang.reflect.Method; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import static jdk.test.lib.Asserts.assertTrue; + +/* @test + * @summary WispCounterMXBean unit test for Detail profile data + * @library /test/lib + * @modules java.base/com.alibaba.wisp.engine:+open + * @run main/othervm/timeout=2000 -XX:+EnableCoroutine -XX:+UseWispMonitor -XX:ActiveProcessorCount=4 -Dcom.alibaba.transparentAsync=true -Dcom.alibaba.shiftThreadModel=true -Dcom.alibaba.wisp.config=/tmp/wisp.config -Dcom.alibaba.wisp.profile=true -Dcom.alibaba.wisp.enableProfileLog=true -Dcom.alibaba.wisp.logTimeInternalMillis=3000 TestWispDetailCounter + * @run main/othervm/timeout=2000 -XX:+EnableCoroutine -XX:+UseWispMonitor -XX:ActiveProcessorCount=4 -Dcom.alibaba.wisp.version=2 -Dcom.alibaba.transparentAsync=true -Dcom.alibaba.shiftThreadModel=true -Dcom.alibaba.wisp.config=/tmp/wisp.config -Dcom.alibaba.wisp.profile=true -Dcom.alibaba.wisp.enableProfileLog=true -Dcom.alibaba.wisp.logTimeInternalMillis=3000 TestWispDetailCounter + */ + +public class TestWispDetailCounter { + + public static void main(String[] args) throws Exception { + + startNetServer(); + File f = new File("/tmp/wisp.config"); + f.deleteOnExit(); + FileWriter writer = new FileWriter(f); + writer.write("com.alibaba.wisp.biz.manage=TestWispDetailCounter::main\n"); + writer.close(); + + // reload WispBizSniffer's config from file. + Method m = Class.forName("com.alibaba.wisp.engine.WispConfiguration").getDeclaredMethod("loadBizConfig"); + m.setAccessible(true); + m.invoke(null); + + MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); + WispCounterMXBean mbean = null; + try { + mbean = ManagementFactory.newPlatformMXBeanProxy(mbs, + "com.alibaba.management:type=WispCounter", WispCounterMXBean.class); + } catch (IOException e) { + e.printStackTrace(); + } + + ExecutorService es = Executors.newFixedThreadPool(20); + int taskTotal = 40; + for (int i = 0; i < taskTotal; i++) { + // submit task + es.submit(() -> { + // do park/unpark + synchronized (TestWispDetailCounter.class) { + // do sleep + try { + Thread.sleep(10L); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + // do net IO + doNetIO(); + }); + } + + System.out.println(mbean.getRunningStates()); + System.out.println(mbean.getQueueLength()); + System.out.println(mbean.getNumberOfRunningTasks()); + // wait task complete + Thread.sleep(10_000L); + System.out.println(mbean.getCreateTaskCount()); + System.out.println(mbean.getCompleteTaskCount()); + System.out.println(mbean.getUnparkCount()); + assertTrue(mbean.getUnparkCount().stream().mapToLong(Long::longValue).sum() > 0); + System.out.println(mbean.getTotalBlockingTime()); + assertTrue(mbean.getTotalBlockingTime().stream().mapToLong(Long::longValue).sum() > 0); + System.out.println(mbean.getWaitSocketIOCount()); + System.out.println(mbean.getTotalWaitSocketIOTime()); + System.out.println(mbean.getEnqueueCount()); + assertTrue(mbean.getEnqueueCount().stream().mapToLong(Long::longValue).sum() > 0); + System.out.println(mbean.getTotalEnqueueTime()); + assertTrue(mbean.getTotalEnqueueTime().stream().mapToLong(Long::longValue).sum() > 0); + System.out.println(mbean.getExecutionCount()); + assertTrue(mbean.getExecutionCount().stream().mapToLong(Long::longValue).sum() > 0); + System.out.println(mbean.getTotalExecutionTime()); + assertTrue(mbean.getTotalExecutionTime().stream().mapToLong(Long::longValue).sum() > 0); + + es.submit(() -> { try {Thread.sleep(1000);} catch (Exception e){} }); + System.out.println(mbean.getNumberOfRunningTasks()); + assertTrue(mbean.getNumberOfRunningTasks().stream().mapToLong(Long::longValue).sum() > 0); + + // check log file exist + File file = new File("wisplog.log"); + if (!file.exists()) { + assertTrue(false, "log file isn't generated"); + } + } + + private static ServerSocket ss; + private static final int PORT = 23000; + private static final int BUFFER_SIZE = 1024; + + private static void startNetServer() throws IOException { + ss = new ServerSocket(PORT); + Thread t = new Thread(() -> { + try { + while (true) { + Socket cs = ss.accept(); + InputStream is = cs.getInputStream(); + int r = is.read(new byte[BUFFER_SIZE]); + is.close(); + cs.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + }); + t.setDaemon(true); + t.start(); + } + + private static void doNetIO() { + try { + Socket so = new Socket("localhost", PORT); + OutputStream os = so.getOutputStream(); + os.write(new byte[BUFFER_SIZE]); + os.flush(); + os.close(); + } catch (IOException e) { + e.printStackTrace(); + throw new Error(e); + } + } +} diff --git a/test/jdk/com/alibaba/wisp/TestWispMonitorData.java b/test/jdk/com/alibaba/wisp/TestWispMonitorData.java new file mode 100644 index 00000000000..3c0fb88abb6 --- /dev/null +++ b/test/jdk/com/alibaba/wisp/TestWispMonitorData.java @@ -0,0 +1,130 @@ +import com.alibaba.management.WispCounterMXBean; +import com.alibaba.management.WispCounterData; +import com.alibaba.wisp.engine.WispCounter; +import com.alibaba.wisp.engine.WispEngine; + +import javax.management.MBeanServer; +import java.io.*; +import java.lang.management.ManagementFactory; +import java.lang.reflect.Method; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.*; +import jdk.internal.access.JavaLangAccess; +import jdk.internal.access.SharedSecrets; + +import java.lang.reflect.Field; +import static jdk.test.lib.Asserts.assertTrue; + +/* @test + * @summary WispCounterMXBean unit test for Detail profile data using the API with the specified WispEngine + * @library /test/lib + * @modules java.base/jdk.internal.access + * @modules java.base/com.alibaba.wisp.engine:+open + * @run main/othervm/timeout=2000 -XX:+EnableCoroutine -XX:+UseWispMonitor -XX:ActiveProcessorCount=4 -Dcom.alibaba.transparentAsync=true -Dcom.alibaba.shiftThreadModel=true -Dcom.alibaba.wisp.config=/tmp/wisp.config -Dcom.alibaba.wisp.profile=true TestWispMonitorData + * @run main/othervm/timeout=2000 -XX:+EnableCoroutine -XX:+UseWispMonitor -XX:ActiveProcessorCount=4 -Dcom.alibaba.wisp.version=2 -Dcom.alibaba.transparentAsync=true -Dcom.alibaba.shiftThreadModel=true -Dcom.alibaba.wisp.config=/tmp/wisp.config -Dcom.alibaba.wisp.profile=true TestWispMonitorData + */ + +public class TestWispMonitorData { + + public static void main(String[] args) throws Exception { + + startNetServer(); + File f = new File("/tmp/wisp.config"); + f.deleteOnExit(); + FileWriter writer = new FileWriter(f); + writer.write("com.alibaba.wisp.biz.manage=TestWispMonitorData::main\n"); + writer.close(); + + // reload WispBizSniffer's config from file. + Method m = Class.forName("com.alibaba.wisp.engine.WispConfiguration").getDeclaredMethod("loadBizConfig"); + m.setAccessible(true); + m.invoke(null); + + MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); + WispCounterMXBean mbean = null; + try { + mbean = ManagementFactory.newPlatformMXBeanProxy(mbs, + "com.alibaba.management:type=WispCounter", WispCounterMXBean.class); + } catch (IOException e) { + e.printStackTrace(); + } + + ExecutorService es = Executors.newFixedThreadPool(20); + int taskTotal = 40; + for (int i = 0; i < taskTotal; i++) { + // submit task + es.submit(() -> { + // do park/unpark + synchronized (TestWispDetailCounter.class) { + // do sleep + try { + Thread.sleep(10L); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + // do net IO + doNetIO(); + }); + } + Thread.sleep(5_000L); + + Class clazz = Class.forName("com.alibaba.wisp.engine.WispEngine"); + Field field = clazz.getDeclaredField("carrierThreads"); + field.setAccessible(true); + Set set = (Set)field.get(null); + JavaLangAccess JLA = SharedSecrets.getJavaLangAccess(); + + for (Thread thread : set) { + WispEngine engine = JLA.getWispEngine(thread); + WispCounterData wispdata = mbean.getWispCounterData(engine.getId()); + if (wispdata != null) { + System.out.println("WispTask is " + engine.getId()); + System.out.println(wispdata.getCompletedTaskCount()); + System.out.println(wispdata.getTotalExecutionTime()); + System.out.println(wispdata.getExecutionCount()); + System.out.println(wispdata.getTotalEnqueueTime()); + System.out.println(wispdata.getEnqueueCount()); + } + } + } + + private static ServerSocket ss; + private static final int PORT = 23000; + private static final int BUFFER_SIZE = 1024; + + private static void startNetServer() throws IOException { + ss = new ServerSocket(PORT); + Thread t = new Thread(() -> { + try { + while (true) { + Socket cs = ss.accept(); + InputStream is = cs.getInputStream(); + int r = is.read(new byte[BUFFER_SIZE]); + is.close(); + cs.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + }); + t.setDaemon(true); + t.start(); + } + + private static void doNetIO() { + try { + Socket so = new Socket("localhost", PORT); + OutputStream os = so.getOutputStream(); + os.write(new byte[BUFFER_SIZE]); + os.flush(); + os.close(); + } catch (IOException e) { + e.printStackTrace(); + throw new Error(e); + } + } +} diff --git a/test/jdk/com/alibaba/wisp2/TestProfileWithHandOff.java b/test/jdk/com/alibaba/wisp2/TestProfileWithHandOff.java new file mode 100644 index 00000000000..15d918bc425 --- /dev/null +++ b/test/jdk/com/alibaba/wisp2/TestProfileWithHandOff.java @@ -0,0 +1,66 @@ +/* + * @test + * @library /test/lib + * @modules java.base/jdk.internal.access + * @summary test after long running or blocking syscall task could be retaken, the new carrier thread can be profiled. + * @run main/othervm -Dcom.alibaba.wisp.carrierEngines=1 -XX:-UseBiasedLocking -XX:+EnableCoroutine -XX:+UseWispMonitor -Dcom.alibaba.wisp.transparentWispSwitch=true -Dcom.alibaba.wisp.version=2 -Dcom.alibaba.wisp.enableHandOff=true -Dcom.alibaba.wisp.handoffPolicy=ADAPTIVE -Dcom.alibaba.wisp.enablePerfLog=true -Dcom.alibaba.wisp.logTimeInternalMillis=1000 TestProfileWithHandOff + */ + +import com.alibaba.wisp.engine.WispEngine; +import com.alibaba.management.WispCounterMXBean; +import jdk.internal.access.SharedSecrets; + +import javax.management.MBeanServer; +import java.io.IOException; +import java.lang.management.ManagementFactory; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import static jdk.test.lib.Asserts.assertTrue; + +public class TestProfileWithHandOff { + public static void main(String[] args) throws Exception { + CountDownLatch cl = new CountDownLatch(10); + AtomicInteger cnt = new AtomicInteger(); + for (int i = 0; i < 10; i++) { + WispEngine.dispatch(() -> { + try { + Thread.sleep(1000); + cnt.incrementAndGet(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + cl.countDown(); + }); + } + + WispEngine.dispatch(() -> { + try { + for(int j = 0; j < 30; j++) { + int i = System.in.read(); + System.out.println("your input: " + i); + } + } catch (IOException e) { + e.printStackTrace(); + } + }); + + MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); + WispCounterMXBean mbean = null; + try { + mbean = ManagementFactory.newPlatformMXBeanProxy(mbs, + "com.alibaba.management:type=WispCounter", WispCounterMXBean.class); + } catch (IOException e) { + e.printStackTrace(); + } + + System.out.println(mbean.getRunningStates()); + System.out.println(mbean.getQueueLength()); + System.out.println(mbean.getNumberOfRunningTasks()); + assertTrue(cl.await(5, TimeUnit.SECONDS)); + + System.out.println(mbean.getCreateTaskCount()); + System.out.println(mbean.getCompleteTaskCount()); + } +}