[K/N][tests] Migrate various runtime/ tests ^KT-61259

This commit is contained in:
Alexander Shabalin
2024-03-11 22:48:50 +01:00
committed by Space Team
parent 7ad4e58a7a
commit d88092aa94
99 changed files with 2102 additions and 1905 deletions
@@ -0,0 +1,23 @@
// This test allocs a large array that may make Linux kill any process inlcuding Gradle with OOM-killer
// DISABLE_NATIVE: targetFamily=LINUX
import kotlin.test.*
fun testArrayAllocation(size: Int) {
val arr = IntArray(size)
// Force a write into the memory.
// TODO: How to make sure the optimizer never deletes this write?
arr[size - 1] = 42
assertEquals(42, arr[size - 1])
}
@Test
fun sanity() {
// Should always succeed everywhere
testArrayAllocation(1 shl 10)
}
@Test
fun test() {
// Will fail on 32 bits.
testArrayAllocation(1 shl 30)
}
@@ -0,0 +1,129 @@
// KIND: STANDALONE_NO_TR
// DISABLE_NATIVE: gcType=NOOP
// DISABLE_NATIVE: gcScheduler=AGGRESSIVE
// The test checks GC, we need to allocate everything on the heap.
// FREE_COMPILER_ARGS: -opt-in=kotlin.native.internal.InternalForKotlinNative -Xdisable-phases=EscapeAnalysis
@file:OptIn(kotlin.experimental.ExperimentalNativeApi::class, kotlin.native.runtime.NativeRuntimeApi::class, kotlin.native.concurrent.ObsoleteWorkersApi::class)
import kotlin.concurrent.AtomicInt
import kotlin.concurrent.Volatile
import kotlin.native.concurrent.*
import kotlin.native.identityHashCode
import kotlin.native.internal.MemoryUsageInfo
import kotlin.native.ref.createCleaner
import kotlin.random.Random
// Copying what's done in kotlinx.benchmark
// TODO: Could we benefit, if this was in stdlib, and the compiler just new about it?
object Blackhole {
@Volatile
var i0: Int = Random.nextInt()
var i1 = i0 + 1
fun consume(value: Any?) {
consume(value.identityHashCode())
}
fun consume(i: Int) {
if ((i0 == i) && (i1 == i)) {
i0 = i
}
}
}
class ArrayOfBytes(bytes: Int) {
val data = ByteArray(bytes)
init {
// Write into every OS page.
for (i in 0 until data.size step 4096) {
data[i] = 42
}
Blackhole.consume(data)
}
}
class ArrayOfBytesWithFinalizer(bytes: Int) {
val impl = ArrayOfBytes(bytes)
val cleaner = createCleaner(impl) {
Blackhole.consume(it)
}
}
fun allocateGarbage() {
// Total amount of objects here:
// - 1 big object with finalizer
// - 9 big objects
// - 2490 small objects with finalizers
// - 97500 small objects without finalizers
// And total size is ~50MiB
for (i in 0..100_000) {
val obj: Any = when {
i == 50_000 -> ArrayOfBytesWithFinalizer(1_000_000) // ~1MiB
i % 10_000 == 0 -> ArrayOfBytes(1_000_000) // ~1MiB
i % 40 == 0 -> ArrayOfBytesWithFinalizer(((i / 100) % 10) * 80) // ~1-100 pointers
else -> ArrayOfBytes(((i / 100) % 10) * 80) // ~1-100 pointers
}
Blackhole.consume(obj)
}
}
class PeakRSSChecker(private val rssDiffLimitBytes: Long) {
// On Linux, the child process might immediately commit the same amount of memory as the parent.
// So, measure difference between peak RSS measurements.
private val initialBytes = MemoryUsageInfo.peakResidentSetSizeBytes.also {
check(it != 0L) { "Error trying to obtain peak RSS. Check if current platform is supported" }
}
fun check(): Long {
val diffBytes = MemoryUsageInfo.peakResidentSetSizeBytes - initialBytes
check(diffBytes <= rssDiffLimitBytes) { "Increased peak RSS by $diffBytes bytes which is more than $rssDiffLimitBytes" }
return diffBytes
}
}
fun main() {
// allocateGarbage allocates ~50MiB. Make total amount per mutator ~5GiB.
val count = 100
// Total amount overall is ~20GiB
val threadCount = 4
val progressReportsCount = 10
// Setting the initial boundary to ~50MiB. The scheduler will adapt this value
// dynamically with no upper limit.
kotlin.native.runtime.GC.targetHeapBytes = 50_000_000
kotlin.native.runtime.GC.minHeapBytes = 50_000_000
// Limit memory usage at ~200MiB. 4 times the initial boundary yet still
// way less than total expected allocated amount.
val peakRSSChecker = PeakRSSChecker(200_000_000L)
val workers = Array(threadCount) { Worker.start() }
val globalCount = AtomicInt(0)
val finalGlobalCount = count * workers.size
workers.forEach {
it.executeAfter(0L) {
for (i in 0 until count) {
allocateGarbage()
peakRSSChecker.check()
globalCount.getAndAdd(1)
}
}
}
val reportStep = finalGlobalCount / progressReportsCount
var lastReportCount = -reportStep
while (true) {
val diffPeakRss = peakRSSChecker.check()
val currentCount = globalCount.value
if (currentCount >= finalGlobalCount) {
break
}
if (lastReportCount + reportStep <= currentCount) {
println("Allocating iteration $currentCount of $finalGlobalCount with peak RSS increase: $diffPeakRss bytes")
lastReportCount = currentCount
}
}
workers.forEach {
it.requestTermination().result
}
peakRSSChecker.check()
}
@@ -7,8 +7,10 @@ package org.jetbrains.kotlin.konan.test.blackbox;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.util.KtTestUtil;
import org.jetbrains.kotlin.konan.test.blackbox.support.group.UseStandardTestCaseGroupProvider;
import org.junit.jupiter.api.Tag;
import org.jetbrains.kotlin.konan.test.blackbox.support.EnforcedProperty;
import org.jetbrains.kotlin.konan.test.blackbox.support.ClassLevelProperty;
import org.jetbrains.kotlin.konan.test.blackbox.support.group.UseStandardTestCaseGroupProvider;
import org.jetbrains.kotlin.konan.test.blackbox.support.group.FirPipeline;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.jupiter.api.Test;
@@ -20,6 +22,8 @@ import java.util.regex.Pattern;
@SuppressWarnings("all")
@TestMetadata("native/native.tests/stress/testData")
@TestDataPath("$PROJECT_ROOT")
@Tag("stress")
@EnforcedProperty(property = ClassLevelProperty.EXECUTION_TIMEOUT, propertyValue = "5m")
@UseStandardTestCaseGroupProvider()
@Tag("frontend-fir")
@FirPipeline()
@@ -29,9 +33,21 @@ public class FirNativeStressTestGenerated extends AbstractNativeBlackBoxTest {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("native/native.tests/stress/testData"), Pattern.compile("^(.+)\\.kt$"), null, true);
}
@Test
@TestMetadata("array_out_of_memory.kt")
public void testArray_out_of_memory() {
runTest("native/native.tests/stress/testData/array_out_of_memory.kt");
}
@Test
@TestMetadata("kt63423_dispose_on_main_stress.kt")
public void testKt63423_dispose_on_main_stress() {
runTest("native/native.tests/stress/testData/kt63423_dispose_on_main_stress.kt");
}
@Test
@TestMetadata("stress_gc_allocations.kt")
public void testStress_gc_allocations() {
runTest("native/native.tests/stress/testData/stress_gc_allocations.kt");
}
}
@@ -7,6 +7,9 @@ package org.jetbrains.kotlin.konan.test.blackbox;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.util.KtTestUtil;
import org.junit.jupiter.api.Tag;
import org.jetbrains.kotlin.konan.test.blackbox.support.EnforcedProperty;
import org.jetbrains.kotlin.konan.test.blackbox.support.ClassLevelProperty;
import org.jetbrains.kotlin.konan.test.blackbox.support.group.UseStandardTestCaseGroupProvider;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.jupiter.api.Test;
@@ -18,6 +21,8 @@ import java.util.regex.Pattern;
@SuppressWarnings("all")
@TestMetadata("native/native.tests/stress/testData")
@TestDataPath("$PROJECT_ROOT")
@Tag("stress")
@EnforcedProperty(property = ClassLevelProperty.EXECUTION_TIMEOUT, propertyValue = "5m")
@UseStandardTestCaseGroupProvider()
public class NativeStressTestGenerated extends AbstractNativeBlackBoxTest {
@Test
@@ -25,9 +30,21 @@ public class NativeStressTestGenerated extends AbstractNativeBlackBoxTest {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("native/native.tests/stress/testData"), Pattern.compile("^(.+)\\.kt$"), null, true);
}
@Test
@TestMetadata("array_out_of_memory.kt")
public void testArray_out_of_memory() {
runTest("native/native.tests/stress/testData/array_out_of_memory.kt");
}
@Test
@TestMetadata("kt63423_dispose_on_main_stress.kt")
public void testKt63423_dispose_on_main_stress() {
runTest("native/native.tests/stress/testData/kt63423_dispose_on_main_stress.kt");
}
@Test
@TestMetadata("stress_gc_allocations.kt")
public void testStress_gc_allocations() {
runTest("native/native.tests/stress/testData/stress_gc_allocations.kt");
}
}