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