mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-10-28 23:10:32 +00:00
Fixed container memory pressure
- Container pressure excludes committed heap the JVM is not using - Reclaim, pregen gating and status text use the adjusted figure - Tests cover the committed heap subtraction
This commit is contained in:
1 parent
3dc958edcf
commit
300ecbfc8b
2 files changed
+61
-7
No files matched your search
@@ -65,7 +65,8 @@ public final class MantleHeapPressure {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static double usedFraction() {
|
public static double usedFraction() {
|
||||||
return pressureFraction(heapUsedFraction(), ContainerMemory.snapshot().pressureFraction());
|
MemoryUsage heap = heapUsage();
|
||||||
|
return pressureFraction(heapUsedFraction(heap), containerPressureFraction(ContainerMemory.snapshot(), heap));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static long memoryBudgetBytes() {
|
public static long memoryBudgetBytes() {
|
||||||
@@ -76,6 +77,14 @@ public final class MantleHeapPressure {
|
|||||||
return Math.min(heapBytes, containerBytes - containerBytes / 4L);
|
return Math.min(heapBytes, containerBytes - containerBytes / 4L);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static double containerPressureFraction(ContainerMemory.Snapshot container, long heapCommittedBytes, long heapUsedBytes) {
|
||||||
|
if (!container.supported()) {
|
||||||
|
return 0D;
|
||||||
|
}
|
||||||
|
long freeCommittedHeap = Math.max(0L, heapCommittedBytes - heapUsedBytes);
|
||||||
|
return Math.max(0D, container.pressureFraction() - (double) freeCommittedHeap / (double) container.limitBytes());
|
||||||
|
}
|
||||||
|
|
||||||
static double pressureFraction(double heapFraction, double containerFraction) {
|
static double pressureFraction(double heapFraction, double containerFraction) {
|
||||||
if (containerFraction >= CONTAINER_HIGH_WATER) {
|
if (containerFraction >= CONTAINER_HIGH_WATER) {
|
||||||
return Math.max(heapFraction, HIGH_WATER + (containerFraction - CONTAINER_HIGH_WATER));
|
return Math.max(heapFraction, HIGH_WATER + (containerFraction - CONTAINER_HIGH_WATER));
|
||||||
@@ -88,14 +97,22 @@ public final class MantleHeapPressure {
|
|||||||
|
|
||||||
public static String describe() {
|
public static String describe() {
|
||||||
ContainerMemory.Snapshot container = ContainerMemory.snapshot();
|
ContainerMemory.Snapshot container = ContainerMemory.snapshot();
|
||||||
String heap = Math.round(heapUsedFraction() * 100D) + "% heap";
|
MemoryUsage heapUsage = heapUsage();
|
||||||
|
String heap = Math.round(heapUsedFraction(heapUsage) * 100D) + "% heap";
|
||||||
return container.supported()
|
return container.supported()
|
||||||
? heap + ", " + Math.round(container.pressureFraction() * 100D) + "% container working memory"
|
? heap + ", " + Math.round(containerPressureFraction(container, heapUsage) * 100D) + "% container working memory"
|
||||||
: heap;
|
: heap;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static double heapUsedFraction() {
|
private static MemoryUsage heapUsage() {
|
||||||
MemoryUsage heap = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
|
return ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double containerPressureFraction(ContainerMemory.Snapshot container, MemoryUsage heap) {
|
||||||
|
return containerPressureFraction(container, heap.getCommitted(), heap.getUsed());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double heapUsedFraction(MemoryUsage heap) {
|
||||||
long max = heap.getMax();
|
long max = heap.getMax();
|
||||||
if (max <= 0L) {
|
if (max <= 0L) {
|
||||||
Runtime runtime = Runtime.getRuntime();
|
Runtime runtime = Runtime.getRuntime();
|
||||||
@@ -110,8 +127,9 @@ public final class MantleHeapPressure {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean overHighWater() {
|
public static boolean overHighWater() {
|
||||||
boolean heapPressure = PRESSURE_GATE.update(heapUsedFraction());
|
MemoryUsage heap = heapUsage();
|
||||||
boolean containerPressure = CONTAINER_PRESSURE_GATE.update(ContainerMemory.snapshot().pressureFraction());
|
boolean heapPressure = PRESSURE_GATE.update(heapUsedFraction(heap));
|
||||||
|
boolean containerPressure = CONTAINER_PRESSURE_GATE.update(containerPressureFraction(ContainerMemory.snapshot(), heap));
|
||||||
return heapPressure || containerPressure;
|
return heapPressure || containerPressure;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package art.arcane.iris.world.pregen;
|
package art.arcane.iris.world.pregen;
|
||||||
|
|
||||||
|
import art.arcane.volmlib.util.diagnostics.ContainerMemory;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
@@ -9,6 +10,8 @@ import static org.junit.Assert.assertFalse;
|
|||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
public class MantleContainerPressureTest {
|
public class MantleContainerPressureTest {
|
||||||
|
private static final long MIB = 1L << 20;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void containerPressureReclaimsEvenWhenTheHeapHasHeadroom() {
|
public void containerPressureReclaimsEvenWhenTheHeapHasHeadroom() {
|
||||||
double pressure = MantleHeapPressure.pressureFraction(0.45D, 0.90D);
|
double pressure = MantleHeapPressure.pressureFraction(0.45D, 0.90D);
|
||||||
@@ -39,4 +42,37 @@ public class MantleContainerPressureTest {
|
|||||||
assertTrue(gate.update(0.85D));
|
assertTrue(gate.update(0.85D));
|
||||||
assertFalse(gate.update(0.80D));
|
assertFalse(gate.update(0.80D));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void freeCommittedHeapDoesNotCountAsContainerPressure() {
|
||||||
|
ContainerMemory.Snapshot container = containerAt(8_601L * MIB, 8_240L * MIB);
|
||||||
|
double containerPressure = MantleHeapPressure.containerPressureFraction(container, 7_388L * MIB, 2_355L * MIB);
|
||||||
|
assertEquals((8_240D - 5_033D) / 8_601D, containerPressure, 1E-9D);
|
||||||
|
assertEquals(0D, MantleHeapPressure.reclaimUrgency(MantleHeapPressure.pressureFraction(0.31D, containerPressure)), 0D);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void heapFillingItsCommittedSpaceStillRaisesContainerPressure() {
|
||||||
|
ContainerMemory.Snapshot container = containerAt(8_601L * MIB, 8_240L * MIB);
|
||||||
|
double containerPressure = MantleHeapPressure.containerPressureFraction(container, 7_388L * MIB, 7_200L * MIB);
|
||||||
|
assertTrue(containerPressure >= 0.90D);
|
||||||
|
assertEquals(1D, MantleHeapPressure.reclaimUrgency(MantleHeapPressure.pressureFraction(0.94D, containerPressure)), 0D);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void containerPressureNeverDropsBelowZero() {
|
||||||
|
ContainerMemory.Snapshot container = containerAt(4_096L * MIB, 1_024L * MIB);
|
||||||
|
assertEquals(0D, MantleHeapPressure.containerPressureFraction(container, 3_072L * MIB, 512L * MIB), 0D);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void unlimitedContainersReportNoContainerPressure() {
|
||||||
|
ContainerMemory.Snapshot container = new ContainerMemory.Snapshot(Long.MAX_VALUE, 0L, 0L, 0D, Long.MAX_VALUE);
|
||||||
|
assertEquals(0D, MantleHeapPressure.containerPressureFraction(container, 7_388L * MIB, 2_355L * MIB), 0D);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ContainerMemory.Snapshot containerAt(long limitBytes, long workingSetBytes) {
|
||||||
|
return new ContainerMemory.Snapshot(limitBytes, workingSetBytes, workingSetBytes,
|
||||||
|
workingSetBytes / (double) limitBytes, limitBytes - workingSetBytes);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user