001package org.cpsolver.ifs.util; 002 003import java.lang.management.ManagementFactory; 004import java.lang.management.ThreadMXBean; 005 006import org.apache.logging.log4j.LogManager; 007 008/** 009 * CPU time measurement. <b>JAVA profiling extension is used. Java needs to be 010 * executed with -Xrunjprof. When the java is executed outside this profiler, 011 * {@link System#currentTimeMillis()} is used.</b> Using {@link ThreadMXBean} 012 * to get the current thread CPU time, if supported. Using {@link System#nanoTime()} 013 * otherwise. 014 * 015 * @version IFS 1.3 (Iterative Forward Search)<br> 016 * Copyright (C) 2006 - 2014 Tomáš Müller<br> 017 * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br> 018 * <a href="http://muller.unitime.org">http://muller.unitime.org</a><br> 019 * <br> 020 * This library is free software; you can redistribute it and/or modify 021 * it under the terms of the GNU Lesser General Public License as 022 * published by the Free Software Foundation; either version 3 of the 023 * License, or (at your option) any later version. <br> 024 * <br> 025 * This library is distributed in the hope that it will be useful, but 026 * WITHOUT ANY WARRANTY; without even the implied warranty of 027 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 028 * Lesser General Public License for more details. <br> 029 * <br> 030 * You should have received a copy of the GNU Lesser General Public 031 * License along with this library; if not see 032 * <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>. 033 */ 034public class JProf { 035 private static Mode sMode = Mode.wall; 036 private static enum Mode { 037 cpu, wall, user 038 } 039 private static boolean sInitialized = false; 040 041 /** Enable / disable the thread CPU timing, if needed */ 042 private synchronized static void init() { 043 if (sInitialized) return; 044 sMode = Mode.valueOf(System.getProperty("jprof", sMode.name())); 045 if (sMode != Mode.wall) { 046 try { 047 ThreadMXBean bean = ManagementFactory.getThreadMXBean(); 048 if (!bean.isCurrentThreadCpuTimeSupported()) { 049 LogManager.getLogger(JProf.class).warn("Measuring " + sMode.name() + " time is not supported, falling back to wall time."); 050 sMode = Mode.wall; 051 } 052 if (!bean.isThreadCpuTimeEnabled()) 053 bean.setThreadCpuTimeEnabled(true); 054 } catch (UnsupportedOperationException e) { 055 LogManager.getLogger(JProf.class).error("Unable to measure " + sMode.name() + " time, falling back to wall time: " + e.getMessage()); 056 sMode = Mode.wall; 057 sMode = Mode.wall; 058 } 059 } 060 LogManager.getLogger(JProf.class).info("Using " + sMode.name() + " time."); 061 sInitialized = true; 062 } 063 064 /** Current CPU time of this thread in seconds 065 * @return CPU time in seconds 066 **/ 067 public static double currentTimeSec() { 068 init(); 069 try { 070 switch (sMode) { 071 case cpu : 072 return ManagementFactory.getThreadMXBean().getCurrentThreadCpuTime() / 1e9; 073 case user : 074 return ManagementFactory.getThreadMXBean().getCurrentThreadUserTime() / 1e9; 075 case wall : 076 default: 077 return System.nanoTime() / 1e9; 078 } 079 } catch (UnsupportedOperationException e) { 080 LogManager.getLogger(JProf.class).error("Unable to measure " + sMode.name() + " time, falling back to wall time: " + e.getMessage()); 081 sMode = Mode.wall; 082 return System.nanoTime() / 1e9; 083 } 084 } 085 086 /** Current CPU time of this thread in milliseconds 087 * @return CPU time in milliseconds 088 **/ 089 public static long currentTimeMillis() { 090 init(); 091 try { 092 switch (sMode) { 093 case cpu : 094 return ManagementFactory.getThreadMXBean().getCurrentThreadCpuTime() / 1000000; 095 case user : 096 return ManagementFactory.getThreadMXBean().getCurrentThreadUserTime() / 1000000; 097 case wall : 098 default: 099 return System.currentTimeMillis(); 100 } 101 } catch (UnsupportedOperationException e) { 102 LogManager.getLogger(JProf.class).error("Unable to measure " + sMode.name() + " time, falling back to wall time: " + e.getMessage()); 103 sMode = Mode.wall; 104 return System.currentTimeMillis(); 105 } 106 } 107}