Add aggressively allocating stress test for GC

This commit is contained in:
Alexander Shabalin
2021-06-09 16:45:30 +03:00
committed by Space
parent 7ae59856cb
commit e3eec33b24
2 changed files with 88 additions and 0 deletions
@@ -2953,6 +2953,11 @@ standaloneTest("leakMemoryWithTestRunner") {
}
}
standaloneTest("stress_gc_allocations") {
source = "runtime/memory/stress_gc_allocations.kt"
flags = ['-tr', '-Xopt-in=kotlin.native.internal.InternalForKotlinNative']
}
standaloneTest("mpp1") {
source = "codegen/mpp/mpp1.kt"
flags = ['-tr', '-Xmulti-platform']
@@ -0,0 +1,83 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
import kotlin.test.*
import kotlin.native.concurrent.*
import kotlin.native.internal.MemoryUsageInfo
object Blackhole {
private val hole = AtomicLong(0)
fun consume(value: Any) {
hole.addAndGet(value.hashCode())
}
fun discharge() {
println(hole.value)
}
}
// Keep a class to ensure we allocate in heap.
// TODO: Protect it from escape analysis.
class MemoryHog(val size: Int, val value: Byte, val stride: Int) {
val data = ByteArray(size)
init {
for (i in 0 until size step stride) {
data[i] = value
}
Blackhole.consume(data)
}
}
val peakRssBytes: Long
get() {
val value = MemoryUsageInfo.peakResidentSetSizeBytes
if (value == 0L) {
fail("Error trying to obtain peak RSS. Check if current platform is supported")
}
return value
}
@Test
fun test() {
// One item is ~10MiB.
val size = 10_000_000
// Total amount is ~1TiB.
val count = 100_000
val value: Byte = 42
// Try to make sure each page is written
val stride = 4096
// Limit memory usage at ~200MiB
val rssDiffLimit: Long = 200_000_000
// Trigger GC after ~100MiB are allocated
val retainLimit: Long = 100_000_000
val progressReportsCount = 100
if (Platform.memoryModel == MemoryModel.EXPERIMENTAL) {
kotlin.native.internal.GC.thresholdAllocations = retainLimit
// Effectively disable trigger on safepoints.
kotlin.native.internal.GC.threshold = Int.MAX_VALUE
}
// On Linux, the child process might immediately commit the same amount of memory as the parent.
// So, measure difference between peak RSS measurements.
val initialPeakRss = peakRssBytes
for (i in 0..count) {
if (i % (count / progressReportsCount) == 0) {
println("Allocating iteration ${i + 1} of $count")
}
MemoryHog(size, value, stride)
val diffPeakRss = peakRssBytes - initialPeakRss
if (diffPeakRss > rssDiffLimit) {
// If GC does not exist, this should eventually fail.
fail("Increased peak RSS by $diffPeakRss which is more than $rssDiffLimit")
}
}
// Make sure `Blackhole` does not get optimized out.
Blackhole.discharge()
}