Inceptum/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/util/Memory.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
}
}
}