replace primitive collections with fast util collections

* Improves performance a lot
This commit is contained in:
Bixilon 2022-02-11 12:19:21 +01:00
parent 5ae6a7bc55
commit 3e8f7ba73e
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
15 changed files with 54 additions and 28 deletions

View File

@ -465,5 +465,10 @@
<version>4.1.73.Final</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>it.unimi.dsi</groupId>
<artifactId>fastutil</artifactId>
<version>8.5.6</version>
</dependency>
</dependencies>
</project>

View File

@ -33,6 +33,7 @@ import de.bixilon.minosoft.util.logging.Log
import de.bixilon.minosoft.util.logging.LogLevels
import de.bixilon.minosoft.util.logging.LogMessageType
import glm_.vec3.Vec3i
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
import java.util.*
class EntityData(
@ -105,7 +106,7 @@ class EntityData(
}
}
inner class EntityDataHashMap : HashMap<Int, Any>() {
inner class EntityDataHashMap : Int2ObjectOpenHashMap<Any>() {
operator fun <K> get(field: EntityDataFields): K {
val index: Int = this@EntityData.connection.registries.getEntityMetaDataIndex(field) ?: return field.defaultValue.unsafeCast() // Can not find field.

View File

@ -15,10 +15,11 @@ package de.bixilon.minosoft.data.registries.registries.registry
import de.bixilon.minosoft.data.registries.blocks.BlockState
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
class BlockStateRegistry(var flattened: Boolean) : AbstractRegistry<BlockState?> {
override var parent: AbstractRegistry<BlockState?>? = null
private val idMap: MutableMap<Int, BlockState> = mutableMapOf()
private val idMap: Int2ObjectOpenHashMap<BlockState> = Int2ObjectOpenHashMap()
override val size: Int
get() {

View File

@ -17,6 +17,8 @@ import com.google.gson.JsonPrimitive
import de.bixilon.kutil.cast.CastUtil.unsafeCast
import de.bixilon.kutil.enums.ValuesEnum
import de.bixilon.minosoft.util.collections.Clearable
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap
import java.util.*
class EnumRegistry<T : Enum<*>>(
@ -26,8 +28,8 @@ class EnumRegistry<T : Enum<*>>(
) : Clearable, Parentable<EnumRegistry<T>> {
private var initialized = false
private val idValueMap: MutableMap<Int, T> = mutableMapOf()
private val valueIdMap: MutableMap<T, Int> = mutableMapOf()
private val idValueMap: Int2ObjectOpenHashMap<T> = Int2ObjectOpenHashMap()
private val valueIdMap: Object2IntOpenHashMap<T> = Object2IntOpenHashMap()
operator fun get(id: Int): T? {
return idValueMap[id] ?: parent?.get(id)

View File

@ -17,13 +17,15 @@ import de.bixilon.kutil.json.JsonUtil.asJsonObject
import de.bixilon.kutil.primitive.IntUtil.toInt
import de.bixilon.minosoft.data.registries.registries.Registries
import de.bixilon.minosoft.util.collections.Clearable
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap
class FakeEnumRegistry<T : RegistryFakeEnumerable>(
override var parent: FakeEnumRegistry<T>? = null,
) : Clearable, Parentable<FakeEnumRegistry<T>> {
private var initialized = false
private val idValueMap: MutableMap<Int, T> = mutableMapOf()
private val valueIdMap: MutableMap<T, Int> = mutableMapOf()
private val idValueMap: Int2ObjectOpenHashMap<T> = Int2ObjectOpenHashMap()
private val valueIdMap: Object2IntOpenHashMap<T> = Object2IntOpenHashMap()
private val nameValueMap: MutableMap<String, T> = mutableMapOf()
operator fun get(name: String): T? {

View File

@ -23,13 +23,15 @@ import de.bixilon.minosoft.data.registries.ResourceLocationAble
import de.bixilon.minosoft.data.registries.registries.Registries
import de.bixilon.minosoft.util.KUtil.toResourceLocation
import de.bixilon.minosoft.util.json.ResourceLocationJsonMap.toResourceLocationMap
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap
open class Registry<T : RegistryItem>(
override var parent: AbstractRegistry<T>? = null,
) : AbstractRegistry<T> {
private var initialized = false
protected val idValueMap: MutableMap<Int, T> = mutableMapOf()
protected val valueIdMap: MutableMap<T, Int> = mutableMapOf()
protected val idValueMap: Int2ObjectOpenHashMap<T> = Int2ObjectOpenHashMap()
protected val valueIdMap: Object2IntOpenHashMap<T> = Object2IntOpenHashMap()
protected val resourceLocationMap: MutableMap<ResourceLocation, T> = mutableMapOf()
override val size: Int

View File

@ -16,13 +16,15 @@ package de.bixilon.minosoft.data.registries.registries.registry
import de.bixilon.kutil.primitive.IntUtil.toInt
import de.bixilon.minosoft.data.registries.ResourceLocation
import de.bixilon.minosoft.util.json.ResourceLocationJsonMap.toResourceLocationMap
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap
class ResourceLocationRegistry(
override var parent: AbstractRegistry<ResourceLocation>? = null,
) : AbstractRegistry<ResourceLocation> {
private var initialized = false
private val idValueMap: MutableMap<Int, ResourceLocation> = mutableMapOf()
private val valueIdMap: MutableMap<ResourceLocation, Int> = mutableMapOf()
private val idValueMap: Int2ObjectOpenHashMap<ResourceLocation> = Int2ObjectOpenHashMap()
private val valueIdMap: Object2IntOpenHashMap<ResourceLocation> = Object2IntOpenHashMap()
override val size: Int

View File

@ -28,12 +28,13 @@ import de.bixilon.minosoft.util.KUtil.toResourceLocation
import de.bixilon.minosoft.util.logging.Log
import de.bixilon.minosoft.util.logging.LogLevels
import de.bixilon.minosoft.util.logging.LogMessageType
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
object Versions : Iterable<Version> {
private val VERSIONS_INDEX = "minosoft:mapping/versions.json".toResourceLocation()
private val VERSIONS_BY_NAME: MutableMap<String, Version> = mutableMapOf()
private val VERSIONS_BY_ID: MutableMap<Int, Version> = mutableMapOf()
private val VERSIONS_BY_PROTOCOL: MutableMap<Int, Version> = mutableMapOf()
private val VERSIONS_BY_ID: Int2ObjectOpenHashMap<Version> = Int2ObjectOpenHashMap()
private val VERSIONS_BY_PROTOCOL: Int2ObjectOpenHashMap<Version> = Int2ObjectOpenHashMap()
val AUTOMATIC = Version("Automatic", -1, -1, VersionTypes.RELEASE, mapOf(), mapOf())
private fun addVersion(version: Version) {

View File

@ -19,11 +19,13 @@ import de.bixilon.minosoft.data.abilities.Gamemodes
import de.bixilon.minosoft.data.entities.entities.Entity
import de.bixilon.minosoft.data.entities.entities.player.PlayerEntity
import glm_.vec3.Vec3d
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap
import java.util.*
class WorldEntities : Iterable<Entity> {
private val idEntityMap: MutableMap<Int, Entity> = synchronizedMapOf()
private val entityIdMap: MutableMap<Entity, Int> = synchronizedMapOf()
private val idEntityMap: Int2ObjectOpenHashMap<Entity> = Int2ObjectOpenHashMap()
private val entityIdMap: Object2IntOpenHashMap<Entity> = Object2IntOpenHashMap()
private val entityUUIDMap: MutableMap<Entity, UUID> = synchronizedMapOf()
private val uuidEntityMap: MutableMap<UUID, Entity> = synchronizedMapOf()

View File

@ -16,12 +16,13 @@ package de.bixilon.minosoft.gui.rendering.gui.atlas
import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.AbstractTexture
import glm_.vec2.Vec2
import glm_.vec2.Vec2i
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
class AtlasElement(
override val texture: AbstractTexture,
val start: Vec2i,
val end: Vec2i,
val slots: Map<Int, Vec2iBinding>, // ToDo: Use an array?
val slots: Int2ObjectOpenHashMap<Vec2iBinding>, // ToDo: Use an array?
) : TextureLike {
override val size: Vec2i = end - start
override lateinit var uvStart: Vec2

View File

@ -23,6 +23,7 @@ import de.bixilon.minosoft.gui.rendering.util.vec.vec2.Vec2iUtil.toVec2i
import de.bixilon.minosoft.util.KUtil.toResourceLocation
import glm_.vec2.Vec2
import glm_.vec2.Vec2i
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
class AtlasManager(private val renderWindow: RenderWindow) {
private lateinit var elements: Map<ResourceLocation, AtlasElement>
@ -59,7 +60,7 @@ class AtlasManager(private val renderWindow: RenderWindow) {
val texture = renderWindow.textureManager.staticTextures.createTexture(versionData["texture"].toResourceLocation(), mipmaps = false)
val start = versionData["start"].toVec2i()
val end = versionData["end"].toVec2i()
val slots: MutableMap<Int, Vec2iBinding> = mutableMapOf()
val slots: Int2ObjectOpenHashMap<Vec2iBinding> = Int2ObjectOpenHashMap()
versionData["slots"].toJsonObject()?.let {
for ((slotId, slotData) in it) {

View File

@ -22,11 +22,12 @@ import de.bixilon.minosoft.gui.rendering.gui.elements.Element
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexConsumer
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexOptions
import glm_.vec2.Vec2i
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
class ContainerItemsElement(
guiRenderer: GUIRenderer,
val container: Container,
val slots: Map<Int, Vec2iBinding>, // ToDo: Use an array?
val slots: Int2ObjectOpenHashMap<Vec2iBinding>, // ToDo: Use an array?
) : Element(guiRenderer) {
private val itemElements: MutableMap<Int, ItemElementData> = synchronizedMapOf()
private var revision = -1L

View File

@ -76,6 +76,8 @@ import de.bixilon.minosoft.util.chunk.ChunkUtil.received
import glm_.vec2.Vec2i
import glm_.vec3.Vec3
import glm_.vec3.Vec3i
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
import it.unimi.dsi.fastutil.ints.IntOpenHashSet
class WorldRenderer(
private val connection: PlayConnection,
@ -91,7 +93,7 @@ class WorldRenderer(
private val fluidSectionPreparer: FluidSectionPreparer = FluidCullSectionPreparer(renderWindow)
private val lightMap = LightMap(connection)
private val loadedMeshes: MutableMap<Vec2i, MutableMap<Int, WorldMesh>> = mutableMapOf() // all prepared (and up to date) meshes
private val loadedMeshes: MutableMap<Vec2i, Int2ObjectOpenHashMap<WorldMesh>> = mutableMapOf() // all prepared (and up to date) meshes
private val loadedMeshesLock = ReadWriteLock()
val maxPreparingTasks = maxOf(DefaultThreadPool.threadCount - 1, 1)
@ -100,7 +102,7 @@ class WorldRenderer(
private val queue: MutableList<WorldQueueItem> = synchronizedListOf() // queue, that is visible, and should be rendered
private val queueLock = ReadWriteLock()
private val culledQueue: MutableMap<Vec2i, MutableSet<Int>> = mutableMapOf() // Chunk sections that can be prepared or have changed, but are not required to get rendered yet (i.e. culled chunks)
private val culledQueue: MutableMap<Vec2i, IntOpenHashSet> = mutableMapOf() // Chunk sections that can be prepared or have changed, but are not required to get rendered yet (i.e. culled chunks)
private val culledQueueLock = ReadWriteLock()
// ToDo: Sometimes if you clear the chunk cache a ton of times, the workers are maxed out and nothing happens anymore
@ -189,7 +191,7 @@ class WorldRenderer(
if (!chunk.isFullyLoaded) {
return@of
}
val sectionHeights: MutableMap<Int, BooleanArray> = mutableMapOf()
val sectionHeights: Int2ObjectOpenHashMap<BooleanArray> = Int2ObjectOpenHashMap()
for (blockPosition in it.blocks.keys) {
val neighbours = sectionHeights.getOrPut(blockPosition.sectionHeight) { BooleanArray(Directions.SIZE) }
val inSectionHeight = blockPosition.y.inSectionHeight
@ -542,7 +544,7 @@ class WorldRenderer(
return true
} else {
culledQueueLock.lock()
culledQueue.getOrPut(chunkPosition) { mutableSetOf() } += sectionHeight
culledQueue.getOrPut(chunkPosition) { IntOpenHashSet() } += sectionHeight
culledQueueLock.unlock()
}
return false
@ -606,7 +608,7 @@ class WorldRenderer(
}
loadedMeshesLock.lock()
val meshes = loadedMeshes.getOrPut(item.chunkPosition) { mutableMapOf() }
val meshes = loadedMeshes.getOrPut(item.chunkPosition) { Int2ObjectOpenHashMap() }
meshes.put(item.sectionHeight, mesh)?.let {
this.visible.removeMesh(it)
@ -719,18 +721,18 @@ class WorldRenderer(
loadedMeshesLock.release()
culledQueueLock.acquire()
val queue: MutableMap<Vec2i, MutableSet<Int>> = mutableMapOf() // The queue method needs the full lock of the culledQueue
val queue: MutableMap<Vec2i, IntOpenHashSet> = mutableMapOf() // The queue method needs the full lock of the culledQueue
for ((chunkPosition, sectionHeights) in this.culledQueue) {
if (!isChunkVisible(chunkPosition)) {
continue
}
var chunkQueue: MutableSet<Int>? = null
var chunkQueue: IntOpenHashSet? = null
for (sectionHeight in sectionHeights) {
if (!isSectionVisible(chunkPosition, sectionHeight, Vec3i.EMPTY, Vec3i(16), false)) {
continue
}
if (chunkQueue == null) {
chunkQueue = queue.getOrPut(chunkPosition) { mutableSetOf() }
chunkQueue = queue.getOrPut(chunkPosition) { IntOpenHashSet() }
}
chunkQueue += sectionHeight
}

View File

@ -21,11 +21,12 @@ import de.bixilon.minosoft.util.KUtil.entities
import de.bixilon.minosoft.util.logging.Log
import de.bixilon.minosoft.util.logging.LogLevels
import de.bixilon.minosoft.util.logging.LogMessageType
import it.unimi.dsi.fastutil.ints.IntOpenHashSet
@LoadPacket
class EntityPassengerS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket {
val vehicleEntityId: Int = buffer.readVarInt()
val passengerEntityIds: Set<Int> = buffer.readVarIntArray().toSet()
val passengerEntityIds: IntOpenHashSet = IntOpenHashSet(buffer.readVarIntArray())
override fun handle(connection: PlayConnection) {
val vehicle = connection.world.entities[vehicleEntityId] ?: return

View File

@ -17,12 +17,14 @@ import de.bixilon.minosoft.data.registries.ResourceLocation
import de.bixilon.minosoft.data.registries.ResourceLocationAble
import de.bixilon.minosoft.data.registries.registries.registry.AbstractRegistry
import de.bixilon.minosoft.util.KUtil.toResourceLocation
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap
class RecipeRegistry(
override var parent: AbstractRegistry<Recipe>? = null,
) : AbstractRegistry<Recipe> {
private val idValueMap: MutableMap<Int, Recipe> = mutableMapOf()
private val valueIdMap: MutableMap<Recipe, Int> = mutableMapOf()
private val idValueMap: Int2ObjectOpenHashMap<Recipe> = Int2ObjectOpenHashMap()
private val valueIdMap: Object2IntOpenHashMap<Recipe> = Object2IntOpenHashMap()
private val resourceLocationRecipeMap: MutableMap<ResourceLocation, Recipe> = mutableMapOf()
private val recipeResourceLocationMap: MutableMap<Recipe, ResourceLocation> = mutableMapOf()