Create mantle chunk flag locks only when a flag needs one

Every mantle chunk allocated a coroutine mutex for all 256 possible flag
ordinals up front, about 66 KB of locks per chunk, although only a few
flags are ever raised under a lock. During a pregen those locks took
well over a gigabyte of heap and ran 3 GB servers out of memory. Each
lock is now created when its flag is first raised.

Model used: Claude Opus 5.5
This commit is contained in:
piexel committed 2026-10-15 00:26:21 +02:00
1 parent 8a0fd9b9fc
commit 6a85cb53a9
1 file changed
+13 -4
@@ -12,6 +12,7 @@ import java.io.DataInput
import java.io.DataOutput
import java.io.IOException
import java.lang.Byte
import java.util.concurrent.atomic.AtomicReferenceArray
import kotlin.Boolean
import kotlin.IllegalStateException
import kotlin.Int
@@ -21,14 +22,16 @@ import kotlin.Unit
abstract class FlaggedChunk() {
private val flags = AtomicBooleanArray(MantleFlag.MAX_ORDINAL + 1)
private val locks = 0.rangeUntil(flags.length()).map { Mutex() }.toTypedArray()
// Created per flag on first use: a mutex for every possible ordinal cost ~66 KB per chunk, which made the mantle
// the largest consumer of heap during generation.
private val locks = AtomicReferenceArray<Mutex>(flags.length())
abstract fun isClosed(): Boolean
protected fun copyFrom(other: FlaggedChunk, action: Runnable) = runBlocking {
coroutineScope {
for (i in 0 until flags.length()) {
launch { locks[i].lock() }.start()
launch { lockFor(i).lock() }.start()
}
}
@@ -39,10 +42,16 @@ abstract class FlaggedChunk() {
}
for (i in 0 until flags.length()) {
locks[i].unlock()
lockFor(i).unlock()
}
}
private fun lockFor(index: Int): Mutex {
locks.get(index)?.let { return it }
val created = Mutex()
return if (locks.compareAndSet(index, null, created)) created else locks.get(index)
}
fun isFlagged(flag: MantleFlag) = flags.get(flag.ordinal())
fun flag(flag: MantleFlag, value: Boolean) {
if (isClosed()) throw IllegalStateException("Chunk is closed!")
@@ -53,7 +62,7 @@ abstract class FlaggedChunk() {
if (isClosed()) throw IllegalStateException("Chunk is closed!")
if (isFlagged(flag)) return
locks[flag.ordinal()].withLock {
lockFor(flag.ordinal()).withLock {
if (isFlagged(flag)) return
task()
if (flags.getAndSet(flag.ordinal(), true))