mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-10-20 07:24:16 +00:00
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:
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))
|
||||
|
||||
Reference in new issue
Block a user