diff options
Diffstat (limited to 'spark-common/src/main/java/me')
3 files changed, 148 insertions, 22 deletions
diff --git a/spark-common/src/main/java/me/lucko/spark/common/monitor/cpu/CpuInfo.java b/spark-common/src/main/java/me/lucko/spark/common/monitor/cpu/CpuInfo.java index a179904..9bbe0f8 100644 --- a/spark-common/src/main/java/me/lucko/spark/common/monitor/cpu/CpuInfo.java +++ b/spark-common/src/main/java/me/lucko/spark/common/monitor/cpu/CpuInfo.java @@ -20,13 +20,8 @@ package me.lucko.spark.common.monitor.cpu; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.List; +import me.lucko.spark.common.util.LinuxProc; + import java.util.regex.Pattern; /** @@ -43,8 +38,7 @@ public enum CpuInfo { * @return the cpu model */ public static String queryCpuModel() { - List<String> cpuInfo = readFile("/proc/cpuinfo"); - for (String line : cpuInfo) { + for (String line : LinuxProc.CPUINFO.read()) { String[] splitLine = SPACE_COLON_SPACE_PATTERN.split(line); if (splitLine[0].equals("model name") || splitLine[0].equals("Processor")) { @@ -54,16 +48,4 @@ public enum CpuInfo { return ""; } - private static List<String> readFile(String file) { - Path path = Paths.get(file); - if (Files.isReadable(path)) { - try { - return Files.readAllLines(path, StandardCharsets.UTF_8); - } catch (IOException e) { - // ignore - } - } - return new ArrayList<>(); - } - } diff --git a/spark-common/src/main/java/me/lucko/spark/common/monitor/memory/MemoryInfo.java b/spark-common/src/main/java/me/lucko/spark/common/monitor/memory/MemoryInfo.java index 4ed9b1c..4aa52f4 100644 --- a/spark-common/src/main/java/me/lucko/spark/common/monitor/memory/MemoryInfo.java +++ b/spark-common/src/main/java/me/lucko/spark/common/monitor/memory/MemoryInfo.java @@ -20,12 +20,19 @@ package me.lucko.spark.common.monitor.memory; +import me.lucko.spark.common.util.LinuxProc; + import java.lang.management.ManagementFactory; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import javax.management.JMX; import javax.management.MBeanServer; import javax.management.ObjectName; +/** + * Utility to query information about system memory usage. + */ public enum MemoryInfo { ; @@ -34,6 +41,9 @@ public enum MemoryInfo { /** The OperatingSystemMXBean instance */ private static final OperatingSystemMXBean BEAN; + /** The format used by entries in /proc/meminfo */ + private static final Pattern PROC_MEMINFO_VALUE = Pattern.compile("^(\\w+):\\s*(\\d+) kB$"); + static { try { MBeanServer beanServer = ManagementFactory.getPlatformMBeanServer(); @@ -44,6 +54,8 @@ public enum MemoryInfo { } } + /* Swap */ + public static long getUsedSwap() { return BEAN.getTotalSwapSpaceSize() - BEAN.getFreeSwapSpaceSize(); } @@ -52,14 +64,67 @@ public enum MemoryInfo { return BEAN.getTotalSwapSpaceSize(); } + /* Physical Memory */ + public static long getUsedPhysicalMemory() { - return BEAN.getTotalPhysicalMemorySize() - BEAN.getFreePhysicalMemorySize(); + return BEAN.getTotalPhysicalMemorySize() - getAvailablePhysicalMemory(); } public static long getTotalPhysicalMemory() { return BEAN.getTotalPhysicalMemorySize(); } + public static long getAvailablePhysicalMemory() { + boolean present = false; + long free = 0, buffers = 0, cached = 0, sReclaimable = 0; + + for (String line : LinuxProc.MEMINFO.read()) { + Matcher matcher = PROC_MEMINFO_VALUE.matcher(line); + if (matcher.matches()) { + present = true; + + String label = matcher.group(1); + long value = Long.parseLong(matcher.group(2)) * 1024; // kB -> B + + // if MemAvailable is set, just return that + if (label.equals("MemAvailable")) { + return value; + } + + // otherwise, record MemFree, Buffers, Cached and SReclaimable + switch (label) { + case "MemFree": + free = value; + break; + case "Buffers": + buffers = value; + break; + case "Cached": + cached = value; + break; + case "SReclaimable": + sReclaimable = value; + break; + } + } + } + + // estimate how much is "available" - not exact but this is probably good enough. + // most Linux systems (assuming they have been updated in the last ~8 years) will + // have MemAvailable set, and we return that instead if present + // + // useful ref: https://www.linuxatemyram.com/ + if (present) { + return free + buffers + cached + sReclaimable; + } + + // fallback to what the JVM understands as "free" + // on non-linux systems, this is probably good enough to estimate what's available + return BEAN.getFreePhysicalMemorySize(); + } + + /* Virtual Memory */ + public static long getTotalVirtualMemory() { return BEAN.getCommittedVirtualMemorySize(); } diff --git a/spark-common/src/main/java/me/lucko/spark/common/util/LinuxProc.java b/spark-common/src/main/java/me/lucko/spark/common/util/LinuxProc.java new file mode 100644 index 0000000..0926ae7 --- /dev/null +++ b/spark-common/src/main/java/me/lucko/spark/common/util/LinuxProc.java @@ -0,0 +1,79 @@ +/* + * This file is part of spark. + * + * Copyright (c) lucko (Luck) <luck@lucko.me> + * Copyright (c) contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package me.lucko.spark.common.util; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Collections; +import java.util.List; + +/** + * Utility for reading from /proc/ on Linux systems. + */ +public enum LinuxProc { + + /** + * Information about the system CPU. + */ + CPUINFO("/proc/cpuinfo"), + + /** + * Information about the system memory. + */ + MEMINFO("/proc/meminfo"); + + private final Path path; + + LinuxProc(String path) { + this.path = resolvePath(path); + } + + private static @Nullable Path resolvePath(String path) { + try { + Path p = Paths.get(path); + if (Files.isReadable(p)) { + return p; + } + } catch (Exception e) { + // ignore + } + return null; + } + + public @NonNull List<String> read() { + if (this.path != null) { + try { + return Files.readAllLines(this.path, StandardCharsets.UTF_8); + } catch (IOException e) { + // ignore + } + } + + return Collections.emptyList(); + } + +} |