Massively improve memory usage of world tiles
This commit is contained in:
parent
949ed802ad
commit
064689fc25
@ -116,7 +116,7 @@ fun main() {
|
|||||||
|
|
||||||
val rand = Random()
|
val rand = Random()
|
||||||
|
|
||||||
for (i in 0 .. 128) {
|
for (i in 0 until 0) {
|
||||||
val item = ItemEntity(client.world!!, Registries.items.keys.values.random().value)
|
val item = ItemEntity(client.world!!, Registries.items.keys.values.random().value)
|
||||||
|
|
||||||
item.position = Vector2d(225.0 - i, 785.0)
|
item.position = Vector2d(225.0 - i, 785.0)
|
||||||
|
@ -613,7 +613,7 @@ class StarboundClient : Closeable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val tileRenderers = TileRenderers(this)
|
val tileRenderers = TileRenderers(this)
|
||||||
var world: ClientWorld? = ClientWorld(this, 0L, Vector2i(3000, 2000), true)
|
var world: ClientWorld? = ClientWorld(this, 0L, Vector2i(16000, 8000), true)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
clearColor = RGBAColor.SLATE_GRAY
|
clearColor = RGBAColor.SLATE_GRAY
|
||||||
|
@ -9,11 +9,13 @@ import java.lang.ref.WeakReference
|
|||||||
import java.util.concurrent.locks.LockSupport
|
import java.util.concurrent.locks.LockSupport
|
||||||
import java.util.concurrent.locks.ReentrantLock
|
import java.util.concurrent.locks.ReentrantLock
|
||||||
import kotlin.concurrent.withLock
|
import kotlin.concurrent.withLock
|
||||||
|
import kotlin.math.log
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
// hand-rolled interner, which has similar performance to ConcurrentHashMap
|
// hand-rolled interner, which has similar performance to ConcurrentHashMap
|
||||||
// (given there is no strong congestion, otherwise it performs somewhere above Caffeine interner),
|
// (given there is no strong congestion, otherwise it performs somewhere above Caffeine interner),
|
||||||
// while yielding significantly better memory utilization than both
|
// while yielding significantly better memory utilization than both
|
||||||
class HashTableInterner<T : Any>(private val segmentBits: Int) : Interner<T> {
|
class HashTableInterner<T : Any>(private val segmentBits: Int = log(Runtime.getRuntime().availableProcessors().toDouble(), 2.0).roundToInt().coerceAtLeast(4)) : Interner<T> {
|
||||||
companion object {
|
companion object {
|
||||||
private val interners = ArrayList<WeakReference<HashTableInterner<*>>>()
|
private val interners = ArrayList<WeakReference<HashTableInterner<*>>>()
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package ru.dbotthepony.kstarbound.world.api
|
package ru.dbotthepony.kstarbound.world.api
|
||||||
|
|
||||||
|
import com.github.benmanes.caffeine.cache.Interner
|
||||||
|
import ru.dbotthepony.kstarbound.util.HashTableInterner
|
||||||
import java.io.DataInputStream
|
import java.io.DataInputStream
|
||||||
|
|
||||||
sealed class AbstractCell {
|
sealed class AbstractCell {
|
||||||
@ -23,7 +25,10 @@ sealed class AbstractCell {
|
|||||||
stream.skipNBytes(1 + 2 + 1 + 1 + 1 + 1)
|
stream.skipNBytes(1 + 2 + 1 + 1 + 1 + 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
val EMPTY = ImmutableCell(AbstractTileState.EMPTY, AbstractTileState.EMPTY, AbstractLiquidState.EMPTY, 0, 0, 0, false)
|
@JvmStatic
|
||||||
val NULL = ImmutableCell(AbstractTileState.NULL, AbstractTileState.NULL, AbstractLiquidState.EMPTY, 0, 0, 0, false)
|
protected val POOL: Interner<ImmutableCell> = HashTableInterner()
|
||||||
|
|
||||||
|
val EMPTY: ImmutableCell = POOL.intern(ImmutableCell(AbstractTileState.EMPTY, AbstractTileState.EMPTY, AbstractLiquidState.EMPTY, 0, 0, 0, false))
|
||||||
|
val NULL: ImmutableCell = POOL.intern(ImmutableCell(AbstractTileState.NULL, AbstractTileState.NULL, AbstractLiquidState.EMPTY, 0, 0, 0, false))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
package ru.dbotthepony.kstarbound.world.api
|
package ru.dbotthepony.kstarbound.world.api
|
||||||
|
|
||||||
|
import com.github.benmanes.caffeine.cache.Interner
|
||||||
import ru.dbotthepony.kstarbound.Registry
|
import ru.dbotthepony.kstarbound.Registry
|
||||||
import ru.dbotthepony.kstarbound.defs.tile.BuiltinMetaMaterials
|
import ru.dbotthepony.kstarbound.defs.tile.BuiltinMetaMaterials
|
||||||
import ru.dbotthepony.kstarbound.defs.tile.MaterialModifier
|
import ru.dbotthepony.kstarbound.defs.tile.MaterialModifier
|
||||||
import ru.dbotthepony.kstarbound.defs.tile.TileDefinition
|
import ru.dbotthepony.kstarbound.defs.tile.TileDefinition
|
||||||
|
import ru.dbotthepony.kstarbound.util.HashTableInterner
|
||||||
import java.io.DataInputStream
|
import java.io.DataInputStream
|
||||||
|
|
||||||
sealed class AbstractTileState {
|
sealed class AbstractTileState {
|
||||||
@ -21,7 +23,10 @@ sealed class AbstractTileState {
|
|||||||
stream.skipNBytes(2 + 1 + 1 + 2 + 1)
|
stream.skipNBytes(2 + 1 + 1 + 2 + 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
val EMPTY = ImmutableTileState(BuiltinMetaMaterials.EMPTY)
|
@JvmStatic
|
||||||
val NULL = ImmutableTileState(BuiltinMetaMaterials.NULL)
|
protected val POOL: Interner<ImmutableTileState> = HashTableInterner()
|
||||||
|
|
||||||
|
val EMPTY: ImmutableTileState = POOL.intern(ImmutableTileState(BuiltinMetaMaterials.EMPTY))
|
||||||
|
val NULL: ImmutableTileState = POOL.intern(ImmutableTileState(BuiltinMetaMaterials.NULL))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,10 +29,7 @@ data class MutableCell(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun immutable(): ImmutableCell {
|
override fun immutable(): ImmutableCell {
|
||||||
val result = ImmutableCell(foreground.immutable(), background.immutable(), liquid.immutable(), dungeonId, biome, envBiome, isIndestructible)
|
return POOL.intern(ImmutableCell(foreground.immutable(), background.immutable(), liquid.immutable(), dungeonId, biome, envBiome, isIndestructible))
|
||||||
if (result == NULL) return NULL
|
|
||||||
if (result == EMPTY) return EMPTY
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun mutable(): MutableCell {
|
override fun mutable(): MutableCell {
|
||||||
|
@ -15,10 +15,7 @@ data class MutableTileState(
|
|||||||
override var modifierHueShift: Float = 0f,
|
override var modifierHueShift: Float = 0f,
|
||||||
) : AbstractTileState() {
|
) : AbstractTileState() {
|
||||||
override fun immutable(): ImmutableTileState {
|
override fun immutable(): ImmutableTileState {
|
||||||
val result = ImmutableTileState(material, modifier, color, hueShift, modifierHueShift)
|
return POOL.intern(ImmutableTileState(material, modifier, color, hueShift, modifierHueShift))
|
||||||
if (result == NULL) return NULL
|
|
||||||
if (result == EMPTY) return EMPTY
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun mutable(): MutableTileState {
|
override fun mutable(): MutableTileState {
|
||||||
|
Loading…
Reference in New Issue
Block a user