From 7a5a9791699968c05383f97b105870149b425169 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Wed, 26 Mar 2025 13:15:26 +0700 Subject: [PATCH] Improve enhanced placed feature performance --- .../mc/otm/worldgen/EnhancedPlacedFeature.kt | 28 +++++++++++++------ 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/EnhancedPlacedFeature.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/EnhancedPlacedFeature.kt index dc9c245a4..3f9483e91 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/EnhancedPlacedFeature.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/worldgen/EnhancedPlacedFeature.kt @@ -3,13 +3,11 @@ package ru.dbotthepony.mc.otm.worldgen import com.github.benmanes.caffeine.cache.Cache import com.github.benmanes.caffeine.cache.Caffeine 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.DataResult -import com.mojang.serialization.DynamicOps 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.objects.ObjectArrayList import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet import net.minecraft.Util 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.configurations.FeatureConfiguration 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.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.data.codec.minRange import ru.dbotthepony.mc.otm.worldgen.feature.EnhancedFeature import ru.dbotthepony.mc.otm.worldgen.placement.EnhancedPlacement import java.io.DataOutputStream import java.time.Duration -import java.util.LinkedList +import java.util.* import kotlin.math.sqrt object EnhancedPlacedFeature : Feature( @@ -137,7 +136,7 @@ object EnhancedPlacedFeature : Feature( fun place(context: FeaturePlaceContext<*>): Boolean { val cache = getCache(context.level()) val chunkPos = ChunkPos(context.origin()) - val instances = ArrayList() + val chunkPositions = ArrayList() for (x in -chunkScanRange .. chunkScanRange) { for (z in -chunkScanRange .. chunkScanRange) { @@ -146,13 +145,24 @@ object EnhancedPlacedFeature : Feature( if (radius <= chunkScanRange) { 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() + + withIndex.forEach { (i, it) -> + instances.put(i, cache.get(it) { evaluate(context, it) }) + } + var any = false - instances.forEach { any = it.place(context) } + instances.values.forEach { any = it.place(context) } return any } }