Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make CPU cache interrogation an opt-in feature #389

Merged
merged 1 commit into from
Jan 23, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
147 changes: 79 additions & 68 deletions cpu/src/main/java/io/smallrye/common/cpu/CacheInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -78,84 +78,95 @@ public static int getSmallestInstructionCacheLineSize() {
}

static {
cacheLevels = doPrivileged((PrivilegedAction<CacheLevelInfo[]>) () -> {
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<File> indexes = new ArrayList<File>();
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<File> indexes = new ArrayList<File>();
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<CacheLevelInfo> list = new ArrayList<CacheLevelInfo>();
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<CacheLevelInfo> list = new ArrayList<CacheLevelInfo>();
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"));
dmlloyd marked this conversation as resolved.
Show resolved Hide resolved
}

static int parseIntFile(final File file) {
return safeParseInt(parseStringFile(file));
}
Expand Down Expand Up @@ -278,4 +289,4 @@ public static void main(String[] args) {
Integer.valueOf(levelInfo.getCacheLineSize()));
}
}
}
}
Loading