001package co.codewizards.cloudstore.core.util;
002
003import org.slf4j.Logger;
004import org.slf4j.LoggerFactory;
005
006public final class DebugUtil {
007
008        private static final Logger logger = LoggerFactory.getLogger(DebugUtil.class);
009
010        private static final long KIB = 1024L;
011        private static final long MIB = KIB * 1024;
012        private static final long GIB = MIB * 1024;
013        private static final long TIB = GIB * 1024;
014
015        private DebugUtil() {
016        }
017
018        public static void logMemoryStats(Logger logger) {
019                if (logger == null)
020                        logger = DebugUtil.logger;
021
022                if (! logger.isInfoEnabled())
023                        return;
024
025                final Runtime runtime = Runtime.getRuntime();
026
027                runtime.gc();
028
029                // max: limit of maximum allocatable memory allowed to the VM. Likely specified by -Xmx...
030                final long max = runtime.maxMemory();
031
032                // allocated: memory currently allocated by the VM (requested from and granted by the OS). Might be less than 'max'.
033                final long allocated = runtime.totalMemory();
034
035                // used: memory in use by Java objects (hence we invoke gc() above, otherwise this doesn't say anything useful).
036                final long used = allocated - runtime.freeMemory();
037
038                // available: how much this JVM can still use for future objects -- with or without the need to allocate more from the OS.
039                final long available = max - used;
040
041                logger.info("logMemoryStats: max={}, allocated={}, used={}, available={}",
042                                getHumanReadableSize(max),
043                                getHumanReadableSize(allocated),
044                                getHumanReadableSize(used),
045                                getHumanReadableSize(available));
046        }
047
048        private static String getHumanReadableSize(final long size) {
049                if (size >= TIB)
050                        return String.format("%.1f TiB", (double) size / TIB);
051
052                if (size >= GIB)
053                        return String.format("%.1f GiB", (double) size / GIB);
054
055                if (size >= MIB)
056                        return String.format("%.1f MiB", (double) size / MIB);
057
058                if (size >= KIB)
059                        return String.format("%.1f KiB", (double) size / KIB);
060
061                return String.format("%d B", size);
062        }
063}