001    package net.sf.cpsolver.ifs.util;
002    
003    import java.lang.management.ManagementFactory;
004    import java.lang.management.ThreadMXBean;
005    
006    import org.apache.log4j.Logger;
007    
008    /**
009     * CPU time measurement. <s>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.</s> Using {@link ThreadMXBean}
012     * to get the current thread CPU time, if supported. Using {@link System#nanoTime()} 
013     * otherwise.
014     * 
015     * @version IFS 1.2 (Iterative Forward Search)<br>
016     *          Copyright (C) 2006 - 2010 Tomas Muller<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     */
034    public 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                        Logger.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                    Logger.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            Logger.getLogger(JProf.class).info("Using " + sMode.name() + " time.");
061            sInitialized = true;
062        }
063        
064        /** Current CPU time of this thread in seconds */
065        public static double currentTimeSec() {
066            init();
067            try {
068                switch (sMode) {
069                    case cpu :
070                        return ManagementFactory.getThreadMXBean().getCurrentThreadCpuTime() / 1e9;
071                    case user :
072                        return ManagementFactory.getThreadMXBean().getCurrentThreadUserTime() / 1e9;
073                    case wall :
074                    default:
075                        return System.nanoTime() / 1e9;
076                }
077            } catch (UnsupportedOperationException e) {
078                Logger.getLogger(JProf.class).error("Unable to measure " + sMode.name() + " time, falling back to wall time: " + e.getMessage());
079                sMode = Mode.wall;
080                return System.nanoTime() / 1e9;
081            }
082        }
083        
084        /** Current CPU time of this thread in milliseconds */
085        public static long currentTimeMillis() {
086            init();
087            try {
088                switch (sMode) {
089                    case cpu :
090                        return ManagementFactory.getThreadMXBean().getCurrentThreadCpuTime() / 1000000;
091                    case user :
092                        return ManagementFactory.getThreadMXBean().getCurrentThreadUserTime() / 1000000;
093                    case wall :
094                    default:
095                        return System.currentTimeMillis();
096                }
097            } catch (UnsupportedOperationException e) {
098                Logger.getLogger(JProf.class).error("Unable to measure " + sMode.name() + " time, falling back to wall time: " + e.getMessage());
099                sMode = Mode.wall;
100                return System.currentTimeMillis();
101            }
102        }
103    }