    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}