Improve enhanced placed feature performance

This commit is contained in:
DBotThePony 2025-03-26 13:15:26 +07:00
parent e2369b3a24
commit 7a5a979169
Signed by: DBot
GPG Key ID: DCC23B5715498507

View File

@ -3,13 +3,11 @@ package ru.dbotthepony.mc.otm.worldgen
import com.github.benmanes.caffeine.cache.Cache import com.github.benmanes.caffeine.cache.Cache
import com.github.benmanes.caffeine.cache.Caffeine import com.github.benmanes.caffeine.cache.Caffeine
import com.github.benmanes.caffeine.cache.Scheduler import com.github.benmanes.caffeine.cache.Scheduler
import com.mojang.datafixers.util.Either
import com.mojang.datafixers.util.Pair
import com.mojang.serialization.Codec import com.mojang.serialization.Codec
import com.mojang.serialization.DataResult
import com.mojang.serialization.DynamicOps
import com.mojang.serialization.codecs.RecordCodecBuilder import com.mojang.serialization.codecs.RecordCodecBuilder
import it.unimi.dsi.fastutil.ints.Int2ObjectRBTreeMap
import it.unimi.dsi.fastutil.io.FastByteArrayOutputStream import it.unimi.dsi.fastutil.io.FastByteArrayOutputStream
import it.unimi.dsi.fastutil.objects.ObjectArrayList
import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet
import net.minecraft.Util import net.minecraft.Util
import net.minecraft.core.BlockPos import net.minecraft.core.BlockPos
@ -23,15 +21,16 @@ import net.minecraft.world.level.levelgen.feature.Feature
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration
import net.minecraft.world.level.levelgen.placement.PlacedFeature import net.minecraft.world.level.levelgen.placement.PlacedFeature
import net.minecraft.world.level.levelgen.placement.PlacementModifier
import ru.dbotthepony.kommons.util.XXHash64 import ru.dbotthepony.kommons.util.XXHash64
import ru.dbotthepony.mc.otm.THREAD_LOCAL_RANDOM
import ru.dbotthepony.mc.otm.core.shuffle
import ru.dbotthepony.mc.otm.core.util.GJRAND64RandomSource import ru.dbotthepony.mc.otm.core.util.GJRAND64RandomSource
import ru.dbotthepony.mc.otm.data.codec.minRange import ru.dbotthepony.mc.otm.data.codec.minRange
import ru.dbotthepony.mc.otm.worldgen.feature.EnhancedFeature import ru.dbotthepony.mc.otm.worldgen.feature.EnhancedFeature
import ru.dbotthepony.mc.otm.worldgen.placement.EnhancedPlacement import ru.dbotthepony.mc.otm.worldgen.placement.EnhancedPlacement
import java.io.DataOutputStream import java.io.DataOutputStream
import java.time.Duration import java.time.Duration
import java.util.LinkedList import java.util.*
import kotlin.math.sqrt import kotlin.math.sqrt
object EnhancedPlacedFeature : Feature<EnhancedPlacedFeature.Config>( object EnhancedPlacedFeature : Feature<EnhancedPlacedFeature.Config>(
@ -137,7 +136,7 @@ object EnhancedPlacedFeature : Feature<EnhancedPlacedFeature.Config>(
fun place(context: FeaturePlaceContext<*>): Boolean { fun place(context: FeaturePlaceContext<*>): Boolean {
val cache = getCache(context.level()) val cache = getCache(context.level())
val chunkPos = ChunkPos(context.origin()) val chunkPos = ChunkPos(context.origin())
val instances = ArrayList<GeneratedChunk>() val chunkPositions = ArrayList<ChunkPos>()
for (x in -chunkScanRange .. chunkScanRange) { for (x in -chunkScanRange .. chunkScanRange) {
for (z in -chunkScanRange .. chunkScanRange) { for (z in -chunkScanRange .. chunkScanRange) {
@ -146,13 +145,24 @@ object EnhancedPlacedFeature : Feature<EnhancedPlacedFeature.Config>(
if (radius <= chunkScanRange) { if (radius <= chunkScanRange) {
val thisPos = ChunkPos(chunkPos.x + x, chunkPos.z + z) val thisPos = ChunkPos(chunkPos.x + x, chunkPos.z + z)
instances.add(cache.get(thisPos) { evaluate(context, thisPos) }) chunkPositions.add(thisPos)
} }
} }
} }
val withIndex = ObjectArrayList(chunkPositions.withIndex().iterator())
// evaluate chunks in random order, so in multithreaded environments we experience less congestion
// between threads which lookup cache while it is being populated on neighbouring chunks
withIndex.shuffle(THREAD_LOCAL_RANDOM)
val instances = Int2ObjectRBTreeMap<GeneratedChunk>()
withIndex.forEach { (i, it) ->
instances.put(i, cache.get(it) { evaluate(context, it) })
}
var any = false var any = false
instances.forEach { any = it.place(context) } instances.values.forEach { any = it.place(context) }
return any return any
} }
} }