package org.sef4j.callstack.stats; import java.lang.management.ManagementFactory; import java.lang.management.ThreadMXBean; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class ThreadTimeUtils { private static final Logger LOG = LoggerFactory.getLogger(ThreadTimeUtils.class); private static final ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); static { try { checkThreadCpuEnabled(); } catch(Exception ex) { LOG.error("FAILED to check/activate threadCpuTime! ... ignore, no rethrow!", ex); // ignore, no rethrow! } } public static void checkThreadCpuEnabled() { if (!threadMXBean.isThreadCpuTimeEnabled()) { boolean isSupported = threadMXBean.isThreadCpuTimeSupported(); if (isSupported) { LOG.info("ThreadMXBean.isThreadCpuTimeEnabled(): false => enable"); threadMXBean.setThreadCpuTimeEnabled(true); } else { LOG.warn("ThreadMXBean.isThreadCpuTimeSupported(): false !!"); } } } private static long TIME_OFFSET = System.nanoTime(); public static long getTime() { return System.nanoTime() - TIME_OFFSET; } public static long getCurrentThreadCpuTime() { return threadMXBean.getCurrentThreadCpuTime(); } public static long getCurrentThreadUserTime() { return threadMXBean.getCurrentThreadUserTime(); } private static final long MILLIS_TO_NANOS = 1000000; private static final long APPROX_1M_BIT_SHIFT = 20; public static long nanosToApproxMillis(long nanos) { return nanos >> APPROX_1M_BIT_SHIFT; // nanos >>> 20; //?? } public static long nanosToMillis(long nanos) { return nanos / MILLIS_TO_NANOS; } public static long millisToNanos(long nanos) { return nanos * MILLIS_TO_NANOS; } public static long approxMillisToMillis(long millis) { return // (millis / MILLIS_TO_NANOS) << 20; // may truncate to 0 (millis << 20) / MILLIS_TO_NANOS; // ... may overflow?? // (((millis << 10) / 1000) << 10) / 1000) } public static long approxMillisToNanos(long millis) { return millis << 20; } }