104 lines
3.7 KiB
Java
104 lines
3.7 KiB
Java
package io.gitlab.jfronny.inceptum.gtk.util;
|
|
|
|
import io.gitlab.jfronny.commons.LazySupplier;
|
|
import io.gitlab.jfronny.commons.OSUtils;
|
|
import io.gitlab.jfronny.inceptum.common.Utils;
|
|
|
|
import java.io.IOException;
|
|
import java.nio.file.Files;
|
|
import java.nio.file.Path;
|
|
import java.util.regex.Matcher;
|
|
import java.util.regex.Pattern;
|
|
import java.util.stream.Stream;
|
|
|
|
public class Memory {
|
|
public static final long KB = 1024;
|
|
public static final long MB = KB * 1024;
|
|
public static final long GB = MB * 1024;
|
|
private static final MI impl = switch (OSUtils.TYPE) {
|
|
case LINUX -> new LinuxMI();
|
|
case WINDOWS -> new WindowsMI();
|
|
case MAC_OS -> new MacOsMI();
|
|
};
|
|
|
|
private static final LazySupplier<Long> totalMemory = new LazySupplier<>(impl::getTotalMemory);
|
|
|
|
public static long getMaxMBForInstance() {
|
|
return Math.max(totalMemory.get() / MB - 1024, 1024);
|
|
}
|
|
|
|
private interface MI {
|
|
long getTotalMemory();
|
|
}
|
|
|
|
private static class LinuxMI implements MI {
|
|
@Override
|
|
public long getTotalMemory() {
|
|
try (Stream<String> stream = Files.lines(Path.of("/proc/meminfo"))) {
|
|
var memTotal = stream
|
|
.filter(s -> s.startsWith("MemTotal:"))
|
|
.map(s -> s.substring("MemTotal:".length()))
|
|
.map(String::trim)
|
|
.findFirst();
|
|
if (memTotal.isPresent()) {
|
|
return parseDecimalMemorySizeToBinary(memTotal.get());
|
|
} else {
|
|
Utils.LOGGER.error("Could not find total memory");
|
|
return 32 * GB;
|
|
}
|
|
} catch (IOException e) {
|
|
Utils.LOGGER.error("Could not get total memory", e);
|
|
return 32 * GB;
|
|
}
|
|
}
|
|
|
|
// Taken from oshi
|
|
private static final Pattern BYTES_PATTERN = Pattern.compile("(\\d+) ?([kKMGT]?B?).*");
|
|
private static final Pattern WHITESPACES = Pattern.compile("\\s+");
|
|
private static long parseDecimalMemorySizeToBinary(String size) {
|
|
String[] mem = WHITESPACES.split(size);
|
|
if (mem.length < 2) {
|
|
// If no spaces, use regexp
|
|
Matcher matcher = BYTES_PATTERN.matcher(size.trim());
|
|
if (matcher.find() && matcher.groupCount() == 2) {
|
|
mem = new String[2];
|
|
mem[0] = matcher.group(1);
|
|
mem[1] = matcher.group(2);
|
|
}
|
|
}
|
|
long capacity = parseLongOrDefault(mem[0], 0L);
|
|
if (mem.length == 2 && mem[1].length() > 1) {
|
|
switch (mem[1].charAt(0)) {
|
|
case 'T' -> capacity <<= 40;
|
|
case 'G' -> capacity <<= 30;
|
|
case 'M' -> capacity <<= 20;
|
|
case 'K', 'k' -> capacity <<= 10;
|
|
default -> {}
|
|
}
|
|
}
|
|
return capacity;
|
|
}
|
|
private static long parseLongOrDefault(String s, long defaultLong) {
|
|
try {
|
|
return Long.parseLong(s);
|
|
} catch (NumberFormatException e) {
|
|
return defaultLong;
|
|
}
|
|
}
|
|
}
|
|
|
|
private static class WindowsMI implements MI {
|
|
@Override
|
|
public long getTotalMemory() {
|
|
return 32 * GB; // This is currently unsupported, but any implementations by Windows user using panama are welcome
|
|
}
|
|
}
|
|
|
|
private static class MacOsMI implements MI {
|
|
@Override
|
|
public long getTotalMemory() {
|
|
return 32 * GB; // This is currently unsupported, but any implementations by MacOS user using panama are welcome
|
|
}
|
|
}
|
|
}
|