From 90a2e481f2f1ae7b2d2d215ca261b64d80212158 Mon Sep 17 00:00:00 2001 From: Intelli Date: Fri, 11 Apr 2025 18:33:33 -0600 Subject: [PATCH] Added CPU handling for Apple Silicon --- .../coreprotect/command/StatusCommand.java | 13 +- .../net/coreprotect/utility/SystemUtils.java | 182 ++++++++++++++++++ 2 files changed, 194 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/coreprotect/command/StatusCommand.java b/src/main/java/net/coreprotect/command/StatusCommand.java index b1968dc..040061f 100755 --- a/src/main/java/net/coreprotect/command/StatusCommand.java +++ b/src/main/java/net/coreprotect/command/StatusCommand.java @@ -17,6 +17,7 @@ import net.coreprotect.patch.Patch; import net.coreprotect.thread.NetworkHandler; import net.coreprotect.utility.Chat; import net.coreprotect.utility.Color; +import net.coreprotect.utility.SystemUtils; import net.coreprotect.utility.VersionUtils; public class StatusCommand { @@ -116,7 +117,17 @@ public class StatusCommand { } String cpuSpeed = String.valueOf(ConfigHandler.processorInfo.getMaxFreq()); - cpuSpeed = String.format("%.2f", Long.valueOf(cpuSpeed) / 1000000000.0); + double speedVal = Long.valueOf(cpuSpeed) / 1000000000.0; + + // Fix for Apple Silicon processors reporting 0 GHz + if (speedVal < 0.01 && SystemUtils.isAppleSilicon()) { + Double appleSiliconSpeed = SystemUtils.getAppleSiliconSpeed(); + if (appleSiliconSpeed != null) { + speedVal = appleSiliconSpeed; + } + } + + cpuSpeed = String.format("%.2f", speedVal); cpuInfo = "x" + Runtime.getRuntime().availableProcessors() + " " + cpuSpeed + "GHz " + modelName + "."; } else { diff --git a/src/main/java/net/coreprotect/utility/SystemUtils.java b/src/main/java/net/coreprotect/utility/SystemUtils.java index 51a4c6e..2f4cb48 100644 --- a/src/main/java/net/coreprotect/utility/SystemUtils.java +++ b/src/main/java/net/coreprotect/utility/SystemUtils.java @@ -1,5 +1,11 @@ package net.coreprotect.utility; +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.util.concurrent.TimeUnit; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + import org.apache.logging.log4j.Level; import org.apache.logging.log4j.core.config.Configurator; @@ -11,6 +17,7 @@ public class SystemUtils { private static boolean testMode = Boolean.getBoolean("net.coreprotect.test"); private static String processorInfo = null; private static boolean log4jInitialized = false; + private static Double appleProcessorSpeed = null; private SystemUtils() { throw new IllegalStateException("Utility class"); @@ -29,6 +36,181 @@ public class SystemUtils { } } + /** + * Check if running on Apple Silicon + * + * @return True if running on Apple Silicon + */ + public static boolean isAppleSilicon() { + String osName = System.getProperty("os.name", "").toLowerCase(); + String osArch = System.getProperty("os.arch", "").toLowerCase(); + + return osName.contains("mac") && (osArch.contains("aarch64") || osArch.contains("arm")); + } + + /** + * Get processor clock speed for Apple Silicon + * + * @return Processor speed in GHz, or null if unavailable + */ + public static Double getAppleSiliconSpeed() { + if (appleProcessorSpeed != null) { + return appleProcessorSpeed; + } + + if (testMode) { + return 3.2; // Default test value + } + + // Try to determine the CPU model first to use for frequency lookup + String modelName = getProcessorModel(); + + // First attempt: Get frequency from machdep.cpu.brand_string if it contains GHz info + if (modelName != null && modelName.contains("GHz")) { + try { + Pattern pattern = Pattern.compile("(\\d+\\.\\d+)GHz"); + Matcher matcher = pattern.matcher(modelName); + if (matcher.find()) { + appleProcessorSpeed = Double.parseDouble(matcher.group(1)); + return appleProcessorSpeed; + } + } + catch (Exception e) { + // Failed to extract frequency from model name + } + } + + // Second attempt: Use sysctl method to detect P-core maximum frequencies + try { + ProcessBuilder pb = new ProcessBuilder("sysctl", "-n", "machdep.cpu.brand_string"); + Process process = pb.start(); + + if (process.waitFor(500, TimeUnit.MILLISECONDS)) { + String appleChipInfo = null; + try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) { + appleChipInfo = reader.readLine(); + } + + if (appleChipInfo != null) { + // Extract M-series info + if (appleChipInfo.contains("M1")) { + return getMSeriesSpeed("M1", appleChipInfo); + } + else if (appleChipInfo.contains("M2")) { + return getMSeriesSpeed("M2", appleChipInfo); + } + else if (appleChipInfo.contains("M3")) { + return getMSeriesSpeed("M3", appleChipInfo); + } + else if (appleChipInfo.contains("M4")) { + return getMSeriesSpeed("M4", appleChipInfo); + } + } + } + } + catch (Exception e) { + // Failed with sysctl method + } + + // Fallback to reasonable defaults based on processor model + if (modelName != null) { + if (modelName.contains("M1")) { + appleProcessorSpeed = 3.2; + } + else if (modelName.contains("M2")) { + appleProcessorSpeed = 3.7; + } + else if (modelName.contains("M3")) { + appleProcessorSpeed = 4.05; + } + else if (modelName.contains("M4")) { + appleProcessorSpeed = 4.5; + } + else { + appleProcessorSpeed = 3.0; // Generic fallback + } + return appleProcessorSpeed; + } + + return 3.2; // Default fallback + } + + /** + * Get the processor speed based on the M-series chip variant + * + * @param series + * The M-series (M1, M2, M3, M4) + * @param chipInfo + * The full chip info string + * @return The processor speed in GHz + */ + private static Double getMSeriesSpeed(String series, String chipInfo) { + switch (series) { + case "M1": + if (chipInfo.contains("Pro") || chipInfo.contains("Max") || chipInfo.contains("Ultra")) { + appleProcessorSpeed = 3.23; // M1 Pro/Max/Ultra P cores + } + else { + appleProcessorSpeed = 3.2; // Base M1 P cores + } + break; + case "M2": + if (chipInfo.contains("Pro") || chipInfo.contains("Max") || chipInfo.contains("Ultra")) { + appleProcessorSpeed = 3.7; // M2 Pro/Max/Ultra P cores + } + else { + appleProcessorSpeed = 3.5; // Base M2 P cores + } + break; + case "M3": + if (chipInfo.contains("Pro") || chipInfo.contains("Max")) { + appleProcessorSpeed = 4.05; // M3 Pro/Max P cores + } + else { + appleProcessorSpeed = 4.0; // Base M3 P cores + } + break; + case "M4": + if (chipInfo.contains("Max")) { + appleProcessorSpeed = 4.5; // M4 Max P cores + } + else if (chipInfo.contains("Pro")) { + appleProcessorSpeed = 4.5; // M4 Pro P cores + } + else { + appleProcessorSpeed = 4.3; // Base M4 P cores + } + break; + default: + appleProcessorSpeed = 3.2; // Default + break; + } + return appleProcessorSpeed; + } + + /** + * Get processor model name for Apple Silicon + * + * @return Processor model name, or null if unavailable + */ + private static String getProcessorModel() { + try { + ProcessBuilder pb = new ProcessBuilder("sysctl", "-n", "machdep.cpu.brand_string"); + Process process = pb.start(); + + if (process.waitFor(500, TimeUnit.MILLISECONDS)) { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) { + return reader.readLine(); + } + } + } + catch (Exception e) { + // Failed to get CPU model + } + + return null; + } + public static CentralProcessor getProcessorInfo() { // In test mode, don't actually try to initialize hardware components if (testMode || isLog4jDisabled()) {