    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}