diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/TlabSupport.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/TlabSupport.java index 1c672aff3671..504d39982867 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/TlabSupport.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/TlabSupport.java @@ -409,10 +409,10 @@ public static void resize(IsolateThread thread) { if (SerialAndEpsilonGCOptions.PrintTLAB.getValue()) { Log.log().string("TLAB new size: thread ").zhex(thread) - .string(" target refills: ").unsigned(targetRefills) - .string(" alloc avg.: ").unsigned(allocatedAvg) - .string(" desired size: ").hex(desiredSize.get(thread)) - .string(" -> ").hex(alignedNewSize).newline(); + .string(", target refills: ").unsigned(targetRefills) + .string(", alloc avg.: ").unsigned(allocatedAvg) + .string(", desired size: ").unsigned(desiredSize.get(thread)) + .string(" -> ").unsigned(alignedNewSize).newline(); } desiredSize.set(thread, alignedNewSize); @@ -498,13 +498,13 @@ private static void printStats(IsolateThread thread, UnsignedWord allocatedBytes long waste = gcWaste.get(thread) + refillWaste.get(thread); Log.log().string("TLAB: thread: ").zhex(thread) - .string(" slow allocs: ").unsigned(slowAllocations.get(thread)) - .string(" refills: ").unsigned(numberOfRefills.get(thread)) - .string(" alloc bytes: ").unsigned(allocatedBytesSinceLastGC) - .string(" alloc avg.: ").unsigned((long) allocatedBytesAvg.getAddress(thread).getAverage()) - .string(" waste bytes: ").zhex(waste) - .string(" GC waste: ").unsigned(gcWaste.get(thread)) - .string(" refill waste: ").unsigned(refillWaste.get(thread)).newline(); + .string(", slow allocs: ").unsigned(slowAllocations.get(thread)) + .string(", refills: ").unsigned(numberOfRefills.get(thread)) + .string(", alloc bytes: ").unsigned(allocatedBytesSinceLastGC) + .string(", alloc avg.: ").unsigned((long) allocatedBytesAvg.getAddress(thread).getAverage()) + .string(", waste bytes: ").unsigned(waste) + .string(", GC waste: ").unsigned(gcWaste.get(thread)) + .string(", refill waste: ").unsigned(refillWaste.get(thread)).newline(); } static void logTlabChunks(Log log, IsolateThread thread, String shortSpaceName) { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/events/JfrAllocationEvents.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/events/JfrAllocationEvents.java index a57cd05cff20..ae97227a0625 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/events/JfrAllocationEvents.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/events/JfrAllocationEvents.java @@ -59,7 +59,6 @@ public static void reset() { @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true) public static void emit(long startTicks, DynamicHub hub, UnsignedWord allocationSize, UnsignedWord tlabSize, boolean allocatedOutsideTlab) { if (HasJfrSupport.get()) { - if (allocatedOutsideTlab) { emitObjectAllocationOutsideTLAB(startTicks, hub, allocationSize); } else if (tlabSize.notEqual(0)) { diff --git a/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/TestObjectAllocationOutsideTLABEvent.java b/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/TestObjectAllocationOutsideTLABEvent.java index e08dc3fc31c7..ea607e29cb23 100644 --- a/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/TestObjectAllocationOutsideTLABEvent.java +++ b/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/jfr/TestObjectAllocationOutsideTLABEvent.java @@ -56,27 +56,28 @@ public void test() throws Throwable { String[] events = new String[]{JfrEvent.ObjectAllocationOutsideTLAB.getName()}; Recording recording = startRecording(events); + /* Do a GC before the allocations to avoid that the GC interferes with the test. */ + System.gc(); + /* * Use a separate thread for allocating the objects, to have better control over the TLAB * and to make sure the objects are actually allocated outside the TLAB. */ Thread testThread = new Thread(() -> { - final long largeObjectThreshold = SerialAndEpsilonGCOptions.LargeArrayThreshold.getValue(); - final int arraySize = NumUtil.safeToInt(largeObjectThreshold - 1024); + int arrayDataSize = arrayDataSizeForOutOfTLABAllocation(); - // Allocate a small object to make sure we have a TLAB. - Object o = new Object(); - GraalDirectives.blackhole(o); + /* Allocate a small object to make sure we have a TLAB. */ + GraalDirectives.blackhole(new Object()); - allocateByteArray(arraySize / Byte.BYTES); - allocateCharArray(arraySize / Character.BYTES); + /* Allocate large arrays that don't fit into the TLAB. */ + GraalDirectives.blackhole(allocateByteArray(arrayDataSize / Byte.BYTES)); + GraalDirectives.blackhole(allocateCharArray(arrayDataSize / Character.BYTES)); }, TEST_THREAD_NAME); testThread.start(); testThread.join(); stopRecording(recording, TestObjectAllocationOutsideTLABEvent::validateEvents); - } @NeverInline("Prevent escape analysis.") @@ -89,9 +90,17 @@ private static char[] allocateCharArray(int length) { return new char[length]; } + /** + * Returns the required array data size in bytes such that an array is too large to be allocated + * in the TLAB, yet still small enough to fit within an aligned heap chunk. + */ + private static int arrayDataSizeForOutOfTLABAllocation() { + long largeObjectThreshold = SerialAndEpsilonGCOptions.LargeArrayThreshold.getValue(); + return NumUtil.safeToInt(largeObjectThreshold - 512); + } + private static void validateEvents(List events) { - final long largeObjectThreshold = SerialAndEpsilonGCOptions.LargeArrayThreshold.getValue(); - final int arrayLength = NumUtil.safeToInt(largeObjectThreshold - 1024); + int arrayDataSize = arrayDataSizeForOutOfTLABAllocation(); boolean foundByteArray = false; boolean foundCharArray = false; @@ -105,7 +114,7 @@ private static void validateEvents(List events) { long allocationSize = event. getValue("allocationSize"); String className = event. getValue("objectClass").getName(); - if (allocationSize >= arrayLength) { + if (allocationSize >= arrayDataSize) { if (className.equals(char[].class.getName())) { foundCharArray = true; } else if (className.equals(byte[].class.getName())) { @@ -119,5 +128,4 @@ private static void validateEvents(List events) { assertTrue(foundByteArray); assertTrue(foundCharArray); } - }