/*
* Copyright (C) 2014-2021 Daniel Dietsch (dietsch@informatik.uni-freiburg.de)
* Copyright (C) 2015-2021 University of Freiburg
*
* This file is part of the ULTIMATE Util Library.
*
* The ULTIMATE Util Library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The ULTIMATE Util Library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the ULTIMATE Util Library. If not, see .
*
* Additional permission under GNU GPL version 3 section 7:
* If you modify the ULTIMATE Util Library, or any covered work, by linking
* or combining it with Eclipse RCP (or a modified version of Eclipse RCP),
* containing parts covered by the terms of the Eclipse Public License, the
* licensors of the ULTIMATE Util Library grant you additional permission
* to convey the resulting work.
*/
package de.uni_freiburg.informatik.ultimate.util.statistics;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryPoolMXBean;
import java.util.List;
import java.util.concurrent.TimeUnit;
import de.uni_freiburg.informatik.ultimate.util.CoreUtil;
/**
*
* @author Daniel Dietsch (dietsch@informatik.uni-freiburg.de)
*
*/
public final class TimeMemoryTracker {
long mStartTime;
long mElapsedTimeNs;
long mStartMemorySizeBytes;
long mStopMemorySizeBytes;
long mStartMemoryFreeSizeBytes;
long mStopMemoryFreeSizeBytes;
long mStartPeakMemorySizeBytes;
long mPeakMemorySizeBytes;
final String mTitle;
private final long mMaxMemorySizeBytes;
private final List mMemoryPoolBeans;
public TimeMemoryTracker(final String title) {
this(title, Runtime.getRuntime().maxMemory());
}
public TimeMemoryTracker(final String title, final long maxMemorySizeBytes) {
mMaxMemorySizeBytes = maxMemorySizeBytes;
mTitle = title;
mMemoryPoolBeans = ManagementFactory.getMemoryPoolMXBeans();
reset();
}
public void start() {
mStartMemorySizeBytes = Runtime.getRuntime().totalMemory();
mStartMemoryFreeSizeBytes = Runtime.getRuntime().freeMemory();
long startMemoryUsageBytes = 0;
for (final MemoryPoolMXBean bean : mMemoryPoolBeans) {
bean.resetPeakUsage();
if (Benchmark.isHeap(bean.getName())) {
startMemoryUsageBytes = startMemoryUsageBytes + bean.getPeakUsage().getUsed();
}
}
mStartPeakMemorySizeBytes = startMemoryUsageBytes;
mStartTime = System.nanoTime();
}
public void stop(final long stopTime) {
mElapsedTimeNs = stopTime - mStartTime + mElapsedTimeNs;
mStopMemorySizeBytes = Runtime.getRuntime().totalMemory();
mStopMemoryFreeSizeBytes = Runtime.getRuntime().freeMemory();
long stopMemoryUsage = 0;
for (final MemoryPoolMXBean bean : mMemoryPoolBeans) {
if (Benchmark.isHeap(bean.getName())) {
stopMemoryUsage = stopMemoryUsage + bean.getPeakUsage().getUsed();
}
}
mPeakMemorySizeBytes = Math.max(mPeakMemorySizeBytes, Math.max(stopMemoryUsage, mStartPeakMemorySizeBytes));
}
public void reset() {
mStartTime = -1;
mElapsedTimeNs = 0;
mStartMemorySizeBytes = 0;
mStartMemoryFreeSizeBytes = 0;
mStopMemorySizeBytes = 0;
mStopMemoryFreeSizeBytes = 0;
mStartPeakMemorySizeBytes = 0;
mPeakMemorySizeBytes = 0;
}
@Override
public String toString() {
return toString(TimeUnit.MILLISECONDS, 2);
}
private String toString(final TimeUnit timeUnit, final int decimals) {
if (mStartTime == -1) {
return String.format("%s was not measured", mTitle);
}
long memoryDelta = mStopMemorySizeBytes - mStartMemorySizeBytes;
long freeMemoryDelta = mStartMemoryFreeSizeBytes - mStopMemoryFreeSizeBytes;
final String freeMemoryDeltaPrefix = freeMemoryDelta < 0 ? "-" : "";
freeMemoryDelta = Math.abs(freeMemoryDelta);
long peakMemoryDelta = getPeakMemoryDelta();
final String peakMemoryDeltaPrefix = peakMemoryDelta < 0 ? "-" : "";
peakMemoryDelta = Math.abs(peakMemoryDelta);
final StringBuilder sb = new StringBuilder();
final long nanoseconds = mElapsedTimeNs;
sb.append(String.format("%s took %." + decimals + "f%s.", mTitle,
CoreUtil.convertTimeUnit(nanoseconds, TimeUnit.NANOSECONDS, timeUnit),
CoreUtil.getTimeUnitSymbol(timeUnit)));
if (memoryDelta != 0) {
final String heapPrefix = memoryDelta < 0 ? "-" : "";
memoryDelta = Math.abs(memoryDelta);
sb.append(String.format(" Allocated memory was %s in the beginning and %s in the end (delta: %s%s).",
CoreUtil.humanReadableByteCount(mStartMemorySizeBytes, true),
CoreUtil.humanReadableByteCount(mStopMemorySizeBytes, true), heapPrefix,
CoreUtil.humanReadableByteCount(memoryDelta, true)));
} else {
sb.append(String.format(" Allocated memory is still %s.",
CoreUtil.humanReadableByteCount(mStartMemorySizeBytes, true)));
}
if (freeMemoryDelta != 0) {
sb.append(String.format(" Free memory was %s in the beginning and %s in the end (delta: %s%s).",
CoreUtil.humanReadableByteCount(mStartMemoryFreeSizeBytes, true),
CoreUtil.humanReadableByteCount(mStopMemoryFreeSizeBytes, true), freeMemoryDeltaPrefix,
CoreUtil.humanReadableByteCount(freeMemoryDelta, true)));
} else {
sb.append(String.format(" Free memory is still %s.",
CoreUtil.humanReadableByteCount(mStartMemoryFreeSizeBytes, true)));
}
if (peakMemoryDelta != 0) {
sb.append(String.format(" Peak memory consumption was %s%s.", peakMemoryDeltaPrefix,
CoreUtil.humanReadableByteCount(peakMemoryDelta, true)));
} else {
sb.append(" There was no memory consumed.");
}
sb.append(String.format(" Max. memory is %s.", CoreUtil.humanReadableByteCount(mMaxMemorySizeBytes, true)));
return sb.toString();
}
public long getPeakMemoryDelta() {
return mPeakMemorySizeBytes - mStartPeakMemorySizeBytes;
}
}