8217338: [Containers] Improve systemd slice memory limit support

Use hierachical memory limit in addition to memory_limits_in_bytes

Reviewed-by: bobv, dholmes
This commit is contained in:
Severin Gehwolf 2019-03-12 10:43:27 +01:00
parent b1ae2d0bf1
commit 73d7e8f86c
4 changed files with 207 additions and 26 deletions

View file

@ -25,15 +25,16 @@
package jdk.internal.platform.cgroupv1;
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Stream;
import jdk.internal.platform.cgroupv1.SubSystem.MemorySubSystem;
public class Metrics implements jdk.internal.platform.Metrics {
private SubSystem memory;
private MemorySubSystem memory;
private SubSystem cpu;
private SubSystem cpuacct;
private SubSystem cpuset;
@ -133,7 +134,7 @@ public class Metrics implements jdk.internal.platform.Metrics {
for (String subsystemName: subsystemNames) {
switch (subsystemName) {
case "memory":
metric.setMemorySubSystem(new SubSystem(mountentry[3], mountentry[4]));
metric.setMemorySubSystem(new MemorySubSystem(mountentry[3], mountentry[4]));
break;
case "cpuset":
metric.setCpuSetSubSystem(new SubSystem(mountentry[3], mountentry[4]));
@ -195,6 +196,11 @@ public class Metrics implements jdk.internal.platform.Metrics {
if (subsystem != null) {
subsystem.setPath(base);
if (subsystem instanceof MemorySubSystem) {
MemorySubSystem memorySubSystem = (MemorySubSystem)subsystem;
boolean isHierarchial = getHierarchical(memorySubSystem);
memorySubSystem.setHierarchical(isHierarchial);
}
metric.setActiveSubSystems();
}
if (subsystem2 != null) {
@ -203,6 +209,11 @@ public class Metrics implements jdk.internal.platform.Metrics {
}
private static boolean getHierarchical(MemorySubSystem subsystem) {
long hierarchical = SubSystem.getLongValue(subsystem, "memory.use_hierarchy");
return hierarchical > 0;
}
private void setActiveSubSystems() {
activeSubSystems = true;
}
@ -211,7 +222,7 @@ public class Metrics implements jdk.internal.platform.Metrics {
return activeSubSystems;
}
private void setMemorySubSystem(SubSystem memory) {
private void setMemorySubSystem(MemorySubSystem memory) {
this.memory = memory;
}
@ -366,9 +377,29 @@ public class Metrics implements jdk.internal.platform.Metrics {
public long getMemoryLimit() {
long retval = SubSystem.getLongValue(memory, "memory.limit_in_bytes");
if (retval > unlimited_minimum) {
if (memory.isHierarchical()) {
// memory.limit_in_bytes returned unlimited, attempt
// hierarchical memory limit
String match = "hierarchical_memory_limit";
retval = SubSystem.getLongValueMatchingLine(memory,
"memory.stat",
match,
Metrics::convertHierachicalLimitLine);
}
}
return retval > unlimited_minimum ? -1L : retval;
}
public static long convertHierachicalLimitLine(String line) {
String[] tokens = line.split("\\s");
if (tokens.length == 2) {
String strVal = tokens[1];
return SubSystem.convertStringToLong(strVal);
}
return unlimited_minimum + 1; // unlimited
}
public long getMemoryMaxUsage() {
return SubSystem.getLongValue(memory, "memory.max_usage_in_bytes");
}
@ -417,6 +448,17 @@ public class Metrics implements jdk.internal.platform.Metrics {
public long getMemoryAndSwapLimit() {
long retval = SubSystem.getLongValue(memory, "memory.memsw.limit_in_bytes");
if (retval > unlimited_minimum) {
if (memory.isHierarchical()) {
// memory.memsw.limit_in_bytes returned unlimited, attempt
// hierarchical memory limit
String match = "hierarchical_memsw_limit";
retval = SubSystem.getLongValueMatchingLine(memory,
"memory.stat",
match,
Metrics::convertHierachicalLimitLine);
}
}
return retval > unlimited_minimum ? -1L : retval;
}

View file

@ -29,10 +29,11 @@ import java.io.BufferedReader;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Stream;
public class SubSystem {
@ -99,10 +100,32 @@ public class SubSystem {
}
public static long getLongValueMatchingLine(SubSystem subsystem,
String param,
String match,
Function<String, Long> conversion) {
long retval = Metrics.unlimited_minimum + 1; // default unlimited
try {
List<String> lines = Files.readAllLines(Paths.get(subsystem.path(), param));
for (String line: lines) {
if (line.contains(match)) {
retval = conversion.apply(line);
break;
}
}
} catch (IOException e) {
// Ignore. Default is unlimited.
}
return retval;
}
public static long getLongValue(SubSystem subsystem, String parm) {
String strval = getStringValue(subsystem, parm);
long retval = 0;
return convertStringToLong(strval);
}
public static long convertStringToLong(String strval) {
long retval = 0;
if (strval == null) return 0L;
try {
@ -215,4 +238,22 @@ public class SubSystem {
return ints;
}
public static class MemorySubSystem extends SubSystem {
private boolean hierarchical;
public MemorySubSystem(String root, String mountPoint) {
super(root, mountPoint);
}
boolean isHierarchical() {
return hierarchical;
}
void setHierarchical(boolean hierarchical) {
this.hierarchical = hierarchical;
}
}
}