From d6285a59011dce482455fd5741145c2ba252717c Mon Sep 17 00:00:00 2001 From: Zoe Gidiere Date: Wed, 10 Dec 2025 22:33:49 -0700 Subject: [PATCH] Improve TriStateintCache with Unsafe --- .../extrusions/ReplaceExtrusion.java | 3 +- .../terra/addons/biome/UserDefinedBiome.java | 1 - .../api/util/collection/TriStateIntCache.java | 50 +++++++++++-------- .../dfsek/terra/api/world/biome/Biome.java | 2 + 4 files changed, 32 insertions(+), 24 deletions(-) diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/extrusions/ReplaceExtrusion.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/extrusions/ReplaceExtrusion.java index 9e31a8009..cd7eb034f 100644 --- a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/extrusions/ReplaceExtrusion.java +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/extrusions/ReplaceExtrusion.java @@ -33,8 +33,7 @@ public class ReplaceExtrusion implements Extrusion { this.range = range; this.biomes = biomes; this.hasTag = BiomeQueries.has(tag); - - this.cache = new TriStateIntCache(65536); + this.cache = new TriStateIntCache(Math.max(512, Biome.INT_ID_COUNTER.get())); } @Override diff --git a/common/addons/config-biome/src/main/java/com/dfsek/terra/addons/biome/UserDefinedBiome.java b/common/addons/config-biome/src/main/java/com/dfsek/terra/addons/biome/UserDefinedBiome.java index 86b878f08..4729f60df 100644 --- a/common/addons/config-biome/src/main/java/com/dfsek/terra/addons/biome/UserDefinedBiome.java +++ b/common/addons/config-biome/src/main/java/com/dfsek/terra/addons/biome/UserDefinedBiome.java @@ -19,7 +19,6 @@ import com.dfsek.terra.api.world.biome.PlatformBiome; * Class representing a config-defined biome */ public class UserDefinedBiome implements Biome { - private final static AtomicInteger INT_ID_COUNTER = new AtomicInteger(0); private final PlatformBiome vanilla; private final String id; private final BiomeTemplate config; diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/collection/TriStateIntCache.java b/common/api/src/main/java/com/dfsek/terra/api/util/collection/TriStateIntCache.java index cc4baf11a..1dd005fcc 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/util/collection/TriStateIntCache.java +++ b/common/api/src/main/java/com/dfsek/terra/api/util/collection/TriStateIntCache.java @@ -1,7 +1,11 @@ package com.dfsek.terra.api.util.collection; -import java.util.concurrent.atomic.AtomicLongArray; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.VarHandle; +import java.lang.reflect.Field; +import com.dfsek.seismic.util.UnsafeUtils; +import sun.misc.Unsafe; public class TriStateIntCache { public static final long STATE_UNSET = 0L; @@ -9,10 +13,19 @@ public class TriStateIntCache { public static final long STATE_TRUE = 2L; private static final long BIT_MASK = 3L; - private final AtomicLongArray data; + private final long[] data; + + private static final VarHandle ARRAY_HANDLE = MethodHandles.arrayElementVarHandle(long[].class); + + private static final long ARRAY_BASE_OFFSET; + + static { + assert UnsafeUtils.UNSAFE != null; + ARRAY_BASE_OFFSET = UnsafeUtils.UNSAFE.arrayBaseOffset(long[].class); + } public TriStateIntCache(int maxKeySize) { - this.data = new AtomicLongArray((maxKeySize + 31) >>> 5); + this.data = new long[(maxKeySize + 31) >>> 5]; } /** @@ -21,33 +34,28 @@ public class TriStateIntCache { * @return STATE_UNSET (0), STATE_FALSE (1), or STATE_TRUE (2) */ public long get(int key) { - int arrayIndex = key >>> 5; - int bitShift = (key & 31) << 1; - long currentWord = data.get(arrayIndex); - return (currentWord >>> bitShift) & BIT_MASK; + long offset = ARRAY_BASE_OFFSET + ((long)(key >>> 5) << 3); + long currentWord = UnsafeUtils.UNSAFE.getLong(data, offset); + return (currentWord >>> ((key << 1) & 63)) & BIT_MASK; } /** * Sets the value safely. Handles race conditions internally. */ public void set(int key, boolean value) { - int arrayIndex = key >>> 5; - int bitShift = (key & 31) << 1; - long targetState = value ? STATE_TRUE : STATE_FALSE; + int index = key >>> 5; + int shift = (key << 1) & 63; - long currentWord, newWord; + long targetWord = (value ? STATE_TRUE : STATE_FALSE) << shift; + + long current; do { - currentWord = data.get(arrayIndex); + current = (long) ARRAY_HANDLE.getVolatile(data, index); - // Race condition check: - long existingState = (currentWord >>> bitShift) & BIT_MASK; - if(existingState != STATE_UNSET) { - return; // Already set, abort our update + if (((current >>> shift) & BIT_MASK) != STATE_UNSET) { + return; } - // Create new word with our bit set - newWord = (currentWord & ~(BIT_MASK << bitShift)) | (targetState << bitShift); - - } while(!data.compareAndSet(arrayIndex, currentWord, newWord)); + } while (!ARRAY_HANDLE.compareAndSet(data, index, current, current | targetWord)); } -} \ No newline at end of file +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/biome/Biome.java b/common/api/src/main/java/com/dfsek/terra/api/world/biome/Biome.java index 009b71a68..e43a4d2ff 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/world/biome/Biome.java +++ b/common/api/src/main/java/com/dfsek/terra/api/world/biome/Biome.java @@ -9,6 +9,7 @@ package com.dfsek.terra.api.world.biome; import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; import com.dfsek.terra.api.properties.PropertyHolder; import com.dfsek.terra.api.registry.key.StringIdentifiable; @@ -18,6 +19,7 @@ import com.dfsek.terra.api.registry.key.StringIdentifiable; * Represents a Terra biome */ public interface Biome extends PropertyHolder, StringIdentifiable { + AtomicInteger INT_ID_COUNTER = new AtomicInteger(0); /** * Gets the platform biome this custom biome delegates to.