< prev index next >

src/java.base/linux/classes/jdk/internal/platform/cgroupv2/CgroupV2Subsystem.java

Print this page
@  rev 57586 : Review changes
|
o  rev 57585 : 8231111: Cgroups v2: Rework Metrics in java.base so as to recognize unified hierarchy
|  Reviewed-by: bobv
~
o  rev 56863 : 8231111: Cgroups v2: Rework Metrics in java.base so as to recognize unified hierarchy
|  Reviewed-by: bobv
~

*** 1,7 **** /* ! * Copyright (c) 2019, Red Hat Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this --- 1,7 ---- /* ! * Copyright (c) 2020, Red Hat Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this
*** 23,47 **** * questions. */ package jdk.internal.platform.cgroupv2; import java.util.concurrent.TimeUnit; import jdk.internal.platform.CgroupSubsystem; import jdk.internal.platform.CgroupSubsystemController; public class CgroupV2Subsystem implements CgroupSubsystem { private final CgroupSubsystemController unified; private static final String PROVIDER_NAME = "cgroupv2"; private static final int PER_CPU_SHARES = 1024; private static final String MAX_VAL = "max"; private static final Object EMPTY_STR = ""; - private volatile long memoryMaxUsage = Long.MIN_VALUE; - public CgroupV2Subsystem(CgroupSubsystemController unified) { this.unified = unified; } private long getLongVal(String file) { --- 23,51 ---- * questions. */ package jdk.internal.platform.cgroupv2; + import java.io.IOException; + import java.nio.file.Paths; import java.util.concurrent.TimeUnit; + import java.util.function.Function; + import java.util.stream.Collectors; import jdk.internal.platform.CgroupSubsystem; import jdk.internal.platform.CgroupSubsystemController; + import jdk.internal.platform.CgroupUtil; + import jdk.internal.platform.Metrics; public class CgroupV2Subsystem implements CgroupSubsystem { private final CgroupSubsystemController unified; private static final String PROVIDER_NAME = "cgroupv2"; private static final int PER_CPU_SHARES = 1024; private static final String MAX_VAL = "max"; private static final Object EMPTY_STR = ""; public CgroupV2Subsystem(CgroupSubsystemController unified) { this.unified = unified; } private long getLongVal(String file) {
*** 61,72 **** return TimeUnit.MICROSECONDS.toNanos(micros); } @Override public long[] getPerCpuUsage() { ! // Not supported ! return new long[0]; } @Override public long getCpuUserUsage() { long micros = CgroupSubsystemController.getLongEntry(unified, "cpu.stat", "user_usec"); --- 65,75 ---- return TimeUnit.MICROSECONDS.toNanos(micros); } @Override public long[] getPerCpuUsage() { ! return null; // Not supported. } @Override public long getCpuUserUsage() { long micros = CgroupSubsystemController.getLongEntry(unified, "cpu.stat", "user_usec");
*** 91,123 **** private long getFromCpuMax(int tokenIdx) { String cpuMaxRaw = CgroupSubsystemController.getStringValue(unified, "cpu.max"); if (cpuMaxRaw == null) { // likely file not found ! return CgroupSubsystemController.RETVAL_UNLIMITED; } // $MAX $PERIOD String[] tokens = cpuMaxRaw.split("\\s+"); if (tokens.length != 2) { ! return CgroupSubsystemController.RETVAL_ERROR; } String quota = tokens[tokenIdx]; return limitFromString(quota); } private long limitFromString(String strVal) { if (MAX_VAL.equals(strVal)) { ! return CgroupSubsystemController.RETVAL_UNLIMITED; } return Long.parseLong(strVal); } @Override public long getCpuShares() { long sharesRaw = getLongVal("cpu.weight"); if (sharesRaw == 100 || sharesRaw == 0) { ! return CgroupSubsystemController.RETVAL_UNLIMITED; } int shares = (int)sharesRaw; // CPU shares (OCI) value needs to get translated into // a proper Cgroups v2 value. See: // https://github.com/containers/crun/blob/master/crun.1.md#cpu-controller --- 94,126 ---- private long getFromCpuMax(int tokenIdx) { String cpuMaxRaw = CgroupSubsystemController.getStringValue(unified, "cpu.max"); if (cpuMaxRaw == null) { // likely file not found ! return Metrics.LONG_RETVAL_UNLIMITED; } // $MAX $PERIOD String[] tokens = cpuMaxRaw.split("\\s+"); if (tokens.length != 2) { ! return Metrics.LONG_RETVAL_UNLIMITED; } String quota = tokens[tokenIdx]; return limitFromString(quota); } private long limitFromString(String strVal) { if (MAX_VAL.equals(strVal)) { ! return Metrics.LONG_RETVAL_UNLIMITED; } return Long.parseLong(strVal); } @Override public long getCpuShares() { long sharesRaw = getLongVal("cpu.weight"); if (sharesRaw == 100 || sharesRaw == 0) { ! return Metrics.LONG_RETVAL_UNLIMITED; } int shares = (int)sharesRaw; // CPU shares (OCI) value needs to get translated into // a proper Cgroups v2 value. See: // https://github.com/containers/crun/blob/master/crun.1.md#cpu-controller
*** 163,182 **** @Override public int[] getCpuSetCpus() { String cpuSetVal = CgroupSubsystemController.getStringValue(unified, "cpuset.cpus"); if (cpuSetVal == null || EMPTY_STR.equals(cpuSetVal)) { ! return new int[0]; // not available } return CgroupSubsystemController.stringRangeToIntArray(cpuSetVal); } @Override public int[] getEffectiveCpuSetCpus() { String effCpuSetVal = CgroupSubsystemController.getStringValue(unified, "cpuset.cpus.effective"); if (effCpuSetVal == null || EMPTY_STR.equals(effCpuSetVal)) { ! return new int[0]; // not available } return CgroupSubsystemController.stringRangeToIntArray(effCpuSetVal); } @Override --- 166,185 ---- @Override public int[] getCpuSetCpus() { String cpuSetVal = CgroupSubsystemController.getStringValue(unified, "cpuset.cpus"); if (cpuSetVal == null || EMPTY_STR.equals(cpuSetVal)) { ! return null; // not available } return CgroupSubsystemController.stringRangeToIntArray(cpuSetVal); } @Override public int[] getEffectiveCpuSetCpus() { String effCpuSetVal = CgroupSubsystemController.getStringValue(unified, "cpuset.cpus.effective"); if (effCpuSetVal == null || EMPTY_STR.equals(effCpuSetVal)) { ! return null; // not available } return CgroupSubsystemController.stringRangeToIntArray(effCpuSetVal); } @Override
*** 189,204 **** return CgroupSubsystemController.stringRangeToIntArray(CgroupSubsystemController.getStringValue(unified, "cpuset.mems.effective")); } @Override public double getCpuSetMemoryPressure() { ! return CgroupSubsystemController.RETVAL_NOT_SUPPORTED; } @Override ! public boolean isCpuSetMemoryPressureEnabled() { ! return false; // not supported } @Override public long getMemoryFailCount() { return CgroupSubsystemController.getLongEntry(unified, "memory.events", "max"); --- 192,207 ---- return CgroupSubsystemController.stringRangeToIntArray(CgroupSubsystemController.getStringValue(unified, "cpuset.mems.effective")); } @Override public double getCpuSetMemoryPressure() { ! return Metrics.DOUBLE_RETVAL_NOT_SUPPORTED; } @Override ! public Boolean isCpuSetMemoryPressureEnabled() { ! return Metrics.BOOL_RETVAL_NOT_SUPPORTED; } @Override public long getMemoryFailCount() { return CgroupSubsystemController.getLongEntry(unified, "memory.events", "max");
*** 210,309 **** return limitFromString(strVal); } @Override public long getMemoryMaxUsage() { ! return memoryMaxUsage; } @Override public long getMemoryUsage() { ! long memUsage = getLongVal("memory.current"); ! // synthesize memory max usage by piggy-backing on current usage ! if (memoryMaxUsage < memUsage) { ! memoryMaxUsage = memUsage; ! } ! return memUsage; } @Override public long getKernelMemoryFailCount() { ! return CgroupSubsystemController.RETVAL_NOT_SUPPORTED; } @Override public long getKernelMemoryLimit() { ! return CgroupSubsystemController.RETVAL_NOT_SUPPORTED; } @Override public long getKernelMemoryMaxUsage() { ! return CgroupSubsystemController.RETVAL_NOT_SUPPORTED; } @Override public long getKernelMemoryUsage() { ! return CgroupSubsystemController.RETVAL_NOT_SUPPORTED; } @Override public long getTcpMemoryFailCount() { ! return CgroupSubsystemController.RETVAL_NOT_SUPPORTED; } @Override public long getTcpMemoryLimit() { ! return CgroupSubsystemController.RETVAL_NOT_SUPPORTED; } @Override public long getTcpMemoryMaxUsage() { ! return CgroupSubsystemController.RETVAL_NOT_SUPPORTED; } @Override public long getTcpMemoryUsage() { ! return CgroupSubsystemController.RETVAL_NOT_SUPPORTED; } @Override public long getMemoryAndSwapFailCount() { ! return CgroupSubsystemController.RETVAL_NOT_SUPPORTED; } @Override public long getMemoryAndSwapLimit() { String strVal = CgroupSubsystemController.getStringValue(unified, "memory.swap.max"); return limitFromString(strVal); } @Override public long getMemoryAndSwapMaxUsage() { ! return CgroupSubsystemController.RETVAL_NOT_SUPPORTED; } @Override public long getMemoryAndSwapUsage() { return getLongVal("memory.swap.current"); } @Override ! public boolean isMemoryOOMKillEnabled() { ! return false; // Not supported. } @Override public long getMemorySoftLimit() { String softLimitStr = CgroupSubsystemController.getStringValue(unified, "memory.high"); return limitFromString(softLimitStr); } @Override public long getBlkIOServiceCount() { ! return CgroupSubsystemController.RETVAL_NOT_SUPPORTED; } @Override public long getBlkIOServiced() { ! return CgroupSubsystemController.RETVAL_NOT_SUPPORTED; } } --- 213,367 ---- return limitFromString(strVal); } @Override public long getMemoryMaxUsage() { ! return Metrics.LONG_RETVAL_NOT_SUPPORTED; } @Override public long getMemoryUsage() { ! return getLongVal("memory.current"); } @Override public long getKernelMemoryFailCount() { ! return Metrics.LONG_RETVAL_NOT_SUPPORTED; } @Override public long getKernelMemoryLimit() { ! return Metrics.LONG_RETVAL_NOT_SUPPORTED; } @Override public long getKernelMemoryMaxUsage() { ! return Metrics.LONG_RETVAL_NOT_SUPPORTED; } @Override public long getKernelMemoryUsage() { ! return Metrics.LONG_RETVAL_NOT_SUPPORTED; } @Override public long getTcpMemoryFailCount() { ! return Metrics.LONG_RETVAL_NOT_SUPPORTED; } @Override public long getTcpMemoryLimit() { ! return Metrics.LONG_RETVAL_NOT_SUPPORTED; } @Override public long getTcpMemoryMaxUsage() { ! return Metrics.LONG_RETVAL_NOT_SUPPORTED; } @Override public long getTcpMemoryUsage() { ! return CgroupSubsystemController.getLongEntry(unified, "memory.stat", "sock"); } @Override public long getMemoryAndSwapFailCount() { ! return Metrics.LONG_RETVAL_NOT_SUPPORTED; } @Override public long getMemoryAndSwapLimit() { String strVal = CgroupSubsystemController.getStringValue(unified, "memory.swap.max"); return limitFromString(strVal); } @Override public long getMemoryAndSwapMaxUsage() { ! return Metrics.LONG_RETVAL_NOT_SUPPORTED; } @Override public long getMemoryAndSwapUsage() { return getLongVal("memory.swap.current"); } @Override ! public Boolean isMemoryOOMKillEnabled() { ! return Metrics.BOOL_RETVAL_NOT_SUPPORTED; } @Override public long getMemorySoftLimit() { String softLimitStr = CgroupSubsystemController.getStringValue(unified, "memory.high"); return limitFromString(softLimitStr); } @Override public long getBlkIOServiceCount() { ! return sumTokensIOStat(CgroupV2Subsystem::lineToRandWIOs); } + @Override public long getBlkIOServiced() { ! return sumTokensIOStat(CgroupV2Subsystem::lineToRBytesAndWBytesIO); ! } ! ! private long sumTokensIOStat(Function<String, Long> mapFunc) { ! try { ! return CgroupUtil.readFilePrivileged(Paths.get(unified.path(), "io.stat")) ! .map(mapFunc) ! .collect(Collectors.summingLong(e -> e)); ! } catch (IOException e) { ! return Metrics.LONG_RETVAL_NOT_SUPPORTED; ! } ! } ! ! private static String[] getRWIOMatchTokenNames() { ! return new String[] { "rios", "wios" }; ! } ! ! private static String[] getRWBytesIOMatchTokenNames() { ! return new String[] { "rbytes", "wbytes" }; ! } ! ! public static Long lineToRandWIOs(String line) { ! String[] matchNames = getRWIOMatchTokenNames(); ! return ioStatLineToLong(line, matchNames); ! } ! ! public static Long lineToRBytesAndWBytesIO(String line) { ! String[] matchNames = getRWBytesIOMatchTokenNames(); ! return ioStatLineToLong(line, matchNames); ! } ! ! private static Long ioStatLineToLong(String line, String[] matchNames) { ! if (line == null || EMPTY_STR.equals(line)) { ! return Long.valueOf(0); ! } ! String[] tokens = line.split("\\s+"); ! long retval = 0; ! for (String t: tokens) { ! String[] valKeys = t.split("="); ! if (valKeys.length != 2) { ! // ignore device ids $MAJ:$MIN ! continue; ! } ! for (String match: matchNames) { ! if (match.equals(valKeys[0])) { ! retval += longOrZero(valKeys[1]); ! } ! } ! } ! return Long.valueOf(retval); ! } ! ! private static long longOrZero(String val) { ! long lVal = 0; ! try { ! lVal = Long.parseLong(val); ! } catch (NumberFormatException e) { ! // keep at 0 ! } ! return lVal; } }
< prev index next >