From 6d9f2f75173adfe08e6c42ea4c628200ae8670e5 Mon Sep 17 00:00:00 2001 From: Georgios Andrianakis Date: Thu, 23 Jan 2025 07:53:46 +0200 Subject: [PATCH] Slightly Make CPU cache interrogation an opt-in feature This feature has a measurable startup performance and for most modern CPUs, the cache line size is 64 anyway, so it doesn't make sense burning cycles to figure it out just for the odd case where the value is different --- .../io/smallrye/common/cpu/CacheInfo.java | 147 ++++++++++-------- 1 file changed, 79 insertions(+), 68 deletions(-) diff --git a/cpu/src/main/java/io/smallrye/common/cpu/CacheInfo.java b/cpu/src/main/java/io/smallrye/common/cpu/CacheInfo.java index a6e1760e..a5da8ac7 100644 --- a/cpu/src/main/java/io/smallrye/common/cpu/CacheInfo.java +++ b/cpu/src/main/java/io/smallrye/common/cpu/CacheInfo.java @@ -78,84 +78,95 @@ public static int getSmallestInstructionCacheLineSize() { } static { - cacheLevels = doPrivileged((PrivilegedAction) () -> { - try { - String osArch = System.getProperty("os.name", "unknown").toLowerCase(Locale.US); - if (osArch.contains("linux")) { - // try to read /sys fs - final File cpu0 = new File("/sys/devices/system/cpu/cpu0/cache"); - if (cpu0.exists()) { - // great! - final File[] files = cpu0.listFiles(); - if (files != null) { - ArrayList indexes = new ArrayList(); - for (File file : files) { - if (file.getName().startsWith("index")) { - indexes.add(file); + cacheLevels = doPrivileged(new PrivilegedAction<>() { + @Override + public CacheLevelInfo[] run() { + if (determineCacheLevel()) { + try { + String osArch = System.getProperty("os.name", "unknown").toLowerCase(Locale.US); + if (osArch.contains("linux")) { + // try to read /sys fs + final File cpu0 = new File("/sys/devices/system/cpu/cpu0/cache"); + if (cpu0.exists()) { + // great! + final File[] files = cpu0.listFiles(); + if (files != null) { + ArrayList indexes = new ArrayList(); + for (File file : files) { + if (file.getName().startsWith("index")) { + indexes.add(file); + } + } + final CacheLevelInfo[] levelInfoArray = new CacheLevelInfo[indexes.size()]; + for (int i = 0; i < indexes.size(); i++) { + File file = indexes.get(i); + int index = parseIntFile(new File(file, "level")); + final CacheType type; + switch (parseStringFile(new File(file, "type"))) { + case "Data": + type = CacheType.DATA; + break; + case "Instruction": + type = CacheType.INSTRUCTION; + break; + case "Unified": + type = CacheType.UNIFIED; + break; + default: + type = CacheType.UNKNOWN; + break; + } + int size = parseIntKBFile(new File(file, "size")); + int lineSize = parseIntFile(new File(file, "coherency_line_size")); + levelInfoArray[i] = new CacheLevelInfo(index, type, size, lineSize); + } + return levelInfoArray; } } - final CacheLevelInfo[] levelInfoArray = new CacheLevelInfo[indexes.size()]; - for (int i = 0; i < indexes.size(); i++) { - File file = indexes.get(i); - int index = parseIntFile(new File(file, "level")); - final CacheType type; - switch (parseStringFile(new File(file, "type"))) { - case "Data": - type = CacheType.DATA; - break; - case "Instruction": - type = CacheType.INSTRUCTION; - break; - case "Unified": - type = CacheType.UNIFIED; - break; - default: - type = CacheType.UNKNOWN; - break; + } else if (osArch.contains("mac os x")) { + // cache line size + final int lineSize = safeParseInt(parseProcessOutput("/usr/sbin/sysctl", "-n", "hw.cachelinesize")); + if (lineSize != 0) { + // cache sizes + final int l1d = safeParseInt(parseProcessOutput("/usr/sbin/sysctl", "-n", "hw.l1dcachesize")); + final int l1i = safeParseInt(parseProcessOutput("/usr/sbin/sysctl", "-n", "hw.l1icachesize")); + final int l2 = safeParseInt(parseProcessOutput("/usr/sbin/sysctl", "-n", "hw.l2cachesize")); + final int l3 = safeParseInt(parseProcessOutput("/usr/sbin/sysctl", "-n", "hw.l3cachesize")); + ArrayList list = new ArrayList(); + if (l1d != 0) { + list.add(new CacheLevelInfo(1, CacheType.DATA, l1d / 1024, lineSize)); + } + if (l1i != 0) { + list.add(new CacheLevelInfo(1, CacheType.INSTRUCTION, l1i / 1024, lineSize)); + } + if (l2 != 0) { + list.add(new CacheLevelInfo(2, CacheType.UNIFIED, l2 / 1024, lineSize)); + } + if (l3 != 0) { + list.add(new CacheLevelInfo(3, CacheType.UNIFIED, l3 / 1024, lineSize)); + } + if (list.size() > 0) { + return list.toArray(new CacheLevelInfo[list.size()]); } - int size = parseIntKBFile(new File(file, "size")); - int lineSize = parseIntFile(new File(file, "coherency_line_size")); - levelInfoArray[i] = new CacheLevelInfo(index, type, size, lineSize); } - return levelInfoArray; + } else if (osArch.contains("windows")) { + // TODO: use the wmic utility to get cache line info } + } catch (Throwable ignored) { } - } else if (osArch.contains("mac os x")) { - // cache line size - final int lineSize = safeParseInt(parseProcessOutput("/usr/sbin/sysctl", "-n", "hw.cachelinesize")); - if (lineSize != 0) { - // cache sizes - final int l1d = safeParseInt(parseProcessOutput("/usr/sbin/sysctl", "-n", "hw.l1dcachesize")); - final int l1i = safeParseInt(parseProcessOutput("/usr/sbin/sysctl", "-n", "hw.l1icachesize")); - final int l2 = safeParseInt(parseProcessOutput("/usr/sbin/sysctl", "-n", "hw.l2cachesize")); - final int l3 = safeParseInt(parseProcessOutput("/usr/sbin/sysctl", "-n", "hw.l3cachesize")); - ArrayList list = new ArrayList(); - if (l1d != 0) { - list.add(new CacheLevelInfo(1, CacheType.DATA, l1d / 1024, lineSize)); - } - if (l1i != 0) { - list.add(new CacheLevelInfo(1, CacheType.INSTRUCTION, l1i / 1024, lineSize)); - } - if (l2 != 0) { - list.add(new CacheLevelInfo(2, CacheType.UNIFIED, l2 / 1024, lineSize)); - } - if (l3 != 0) { - list.add(new CacheLevelInfo(3, CacheType.UNIFIED, l3 / 1024, lineSize)); - } - if (list.size() > 0) { - return list.toArray(new CacheLevelInfo[list.size()]); - } - } - } else if (osArch.contains("windows")) { - // TODO: use the wmic utility to get cache line info + // all has failed + return new CacheLevelInfo[0]; + } else { + return new CacheLevelInfo[] { new CacheLevelInfo(0, CacheType.UNKNOWN, 0, 64) }; } - } catch (Throwable ignored) { } - // all has failed - return new CacheLevelInfo[0]; }); } + private static boolean determineCacheLevel() { + return Boolean.parseBoolean(System.getProperty("smallrye.cpu.determine-cache-level", "false")); + } + static int parseIntFile(final File file) { return safeParseInt(parseStringFile(file)); } @@ -278,4 +289,4 @@ public static void main(String[] args) { Integer.valueOf(levelInfo.getCacheLineSize())); } } -} \ No newline at end of file +}