All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.conqat.lib.commons.system.PerformanceMonitor Maven / Gradle / Ivy

There is a newer version: 2024.7.2
Show newest version
/*
 * Copyright (c) CQSE GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.conqat.lib.commons.system;

import org.conqat.lib.commons.filesystem.ByteUnit;

/**
 * Combines a timer and a memory monitor in a simple utility class. Measures both total memory and
 * the delta between {@link PerformanceMonitor#start()} and {@link PerformanceMonitor#stop()}.
 * 

* In order to avoid programming mistakes, the calls to the methods * {@link PerformanceMonitor#start()} and {@link PerformanceMonitor#stop()} must adhere to a simple * protocol:
* The {@link PerformanceMonitor} can be in on of the three states NOT_RUN, RUNNING, FINISHED. *

* {@link PerformanceMonitor#start()} May only be called in state NOT_RUN and * {@link PerformanceMonitor#stop()} may only be called in state RUNNING. *

* All other calls to {@link PerformanceMonitor#start()} and {@link PerformanceMonitor#stop()} * result in {@link IllegalArgumentException}s * * @author Elmar Juergens */ public class PerformanceMonitor { /** The state the {@link PerformanceMonitor} is currently in */ private EPerformanceMonitorState state = EPerformanceMonitorState.NOT_RUN; /** {@link MemoryMonitor} used to measure total memory consumption */ private MemoryMonitor memMonitor; /** * Flag that determines whether a memory monitor (that uses its own thread) should be used to get a * more exact measurement of maximum memory consumption. */ private final boolean useMemoryMonitor; /** * Timestamp the call to the {@link PerformanceMonitor#start()} method occurred */ private long startTimeInMillis; /** * Memory consumption when the call to {@link PerformanceMonitor#start()} occurred. */ private long startMemoryInBytes; /** * The total amount of time spent between {@link #start()} and {@link #stop()} calls. */ private long totalSpentTimeInMillis = 0; /** * The maximum amount of memory used at all {@link #start()} and {@link #stop()} calls. */ private long maxMemoryInBytes = 0; /** * Constructor has package level to allow tests to access it, yet enforce use of factory methods for * public use. */ public PerformanceMonitor(boolean useMemoryMonitor) { this.useMemoryMonitor = useMemoryMonitor; } /** * Convenience factory method: Creates a new {@link PerformanceMonitor} and starts it. * * @param useMemoryMonitor * detemines whether the PerformanceMonitor internally uses a {@link MemoryMonitor} to * measure memory consumption. This requires more resources, since the * {@link MemoryMonitor} runs its own thread, but promises more precise measurement of * maximum memory consumption. */ public static PerformanceMonitor create(boolean useMemoryMonitor) { PerformanceMonitor monitor = new PerformanceMonitor(useMemoryMonitor); monitor.start(); return monitor; } /** * Convenience factory method: Creates a new {@link PerformanceMonitor} and starts it. * PerformanceMonitor does not use a MemoryMonitor internally */ public static PerformanceMonitor create() { return create(false); } /** * Starts the {@link PerformanceMonitor}. It will measure time and maximal memory consumption until * the method {@link PerformanceMonitor#stop()} is called. *

* This method may only be called, if the {@link PerformanceMonitor} is in state NOT_RUN. (i.e., * after it has been created via the constructor). Node: the create() method creates and * starts the monitor. *

* All subsequent calls to this method will result in a {@link IllegalStateException} */ public void start() { long currentMemoryInBytes = Runtime.getRuntime().totalMemory(); if (state == EPerformanceMonitorState.RUNNING) { throw new IllegalStateException("PerformanceMonitor is already running and cannot be restarted"); } else if (state == EPerformanceMonitorState.NOT_RUN) { startMemoryInBytes = currentMemoryInBytes; } state = EPerformanceMonitorState.RUNNING; if (useMemoryMonitor) { memMonitor = new MemoryMonitor(); memMonitor.start(); } maxMemoryInBytes = Math.max(currentMemoryInBytes, maxMemoryInBytes); startTimeInMillis = System.currentTimeMillis(); } /** * Stops the {@link PerformanceMonitor}. *

* This method may only be called, if the {@link PerformanceMonitor} is in state RUNNING. (i.e., * after a call to {@link PerformanceMonitor#start()} ). *

* If the {@link PerformanceMonitor} is in any other state, a call to this method results in an * {@link IllegalStateException} * * @return The elapsed time in milliseconds. */ public long stop() { if (state != EPerformanceMonitorState.RUNNING) { throw new IllegalStateException("PerformanceMonitor can only be stopped if it is running"); } totalSpentTimeInMillis += System.currentTimeMillis() - startTimeInMillis; maxMemoryInBytes = Math.max(Runtime.getRuntime().totalMemory(), maxMemoryInBytes); state = EPerformanceMonitorState.FINISHED; if (useMemoryMonitor) { memMonitor.stop(); } return getMilliseconds(); } /** * Returns whether the PerformanceMonitor is stopped and will return meaningful values. */ public boolean isStopped() { return state == EPerformanceMonitorState.FINISHED; } /** * Gets the measured time in seconds. (Fractions of seconds are discarded) */ public long getSeconds() { return getMilliseconds() / 1000; } /** * Gets the measured time in milliseconds. If measuring is not stopped, returns the time since start * of the measuring. */ public long getMilliseconds() { if (state == EPerformanceMonitorState.RUNNING) { return System.currentTimeMillis() - startTimeInMillis + totalSpentTimeInMillis; } return totalSpentTimeInMillis; } /** Gets the maximal memory consumption in bytes */ public long getMaxMemUsageInBytes() { if (useMemoryMonitor) { return memMonitor.getMaximumMemoryUsage(); } return maxMemoryInBytes; } /** Gets the maximal memory consumption in kilobytes */ public long getMaxMemUsageInKBs() { return ByteUnit.BYTES.toKibiBytes(getMaxMemUsageInBytes()); } /** Gets the delta in memory consumption in bytes */ public long getDeltaMemUsageInBytes() { return getMaxMemUsageInBytes() - startMemoryInBytes; } /** Gets the delta in memory consumption in kilobytes */ public long getDeltaMemUsageInKBs() { return ByteUnit.BYTES.toKibiBytes(getDeltaMemUsageInBytes()); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy