From 305255511dd6f25bd363f9ed4447cdd4c1192cfd Mon Sep 17 00:00:00 2001 From: Zoe Gidiere Date: Fri, 11 Oct 2024 18:27:37 -0600 Subject: [PATCH] More cache improvements --- .../dfsek/terra/addons/noise/NoiseAddon.java | 2 +- .../templates/CacheSamplerTemplate.java | 6 +- .../addons/noise/samplers/CacheSampler.java | 68 ++++++++++--------- .../world/biome/generation/BiomeProvider.java | 2 +- .../generation/CachingBiomeProvider.java | 62 +++++++++-------- 5 files changed, 72 insertions(+), 68 deletions(-) diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/NoiseAddon.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/NoiseAddon.java index e4dc09b56..a7ef9a43e 100644 --- a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/NoiseAddon.java +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/NoiseAddon.java @@ -151,7 +151,7 @@ public class NoiseAddon implements AddonInitializer { noiseRegistry.register(addon.key("MAX"), () -> new BinaryArithmeticTemplate<>(MaxSampler::new)); noiseRegistry.register(addon.key("MIN"), () -> new BinaryArithmeticTemplate<>(MinSampler::new)); - noiseRegistry.register(addon.key("CACHE"), () -> new CacheSamplerTemplate(plugin.getGenerationThreads())); + noiseRegistry.register(addon.key("CACHE"), CacheSamplerTemplate::new); Map packSamplers = new LinkedHashMap<>(); diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/CacheSamplerTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/CacheSamplerTemplate.java index 418881ce4..492f9ad5a 100644 --- a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/CacheSamplerTemplate.java +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/CacheSamplerTemplate.java @@ -13,14 +13,12 @@ public class CacheSamplerTemplate extends SamplerTemplate { @Default private NoiseSampler sampler; - private final int generationThreads; + public CacheSamplerTemplate() { - public CacheSamplerTemplate(int generationThreads) { - this.generationThreads = generationThreads; } @Override public NoiseSampler get() { - return new CacheSampler(sampler, getDimensions(), generationThreads); + return new CacheSampler(sampler, getDimensions()); } } diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/CacheSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/CacheSampler.java index 012f077ae..acff3e24c 100644 --- a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/CacheSampler.java +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/CacheSampler.java @@ -3,6 +3,10 @@ package com.dfsek.terra.addons.noise.samplers; import com.dfsek.terra.api.noise.DerivativeNoiseSampler; import com.dfsek.terra.api.noise.NoiseSampler; +import com.dfsek.terra.api.util.generic.pair.Pair; + +import com.dfsek.terra.api.util.generic.pair.Pair.Mutable; + import com.github.benmanes.caffeine.cache.Caffeine; import com.github.benmanes.caffeine.cache.LoadingCache; import com.github.benmanes.caffeine.cache.Scheduler; @@ -13,60 +17,58 @@ import static com.dfsek.terra.api.util.CacheUtils.CACHE_EXECUTOR; public class CacheSampler implements NoiseSampler { private final NoiseSampler sampler; - private final LoadingCache cache2D; - private final LoadingCache cache3D; + private final ThreadLocal>> cache2D; + private final ThreadLocal>> cache3D; - private final ThreadLocal mutable2 = - ThreadLocal.withInitial(() -> new DoubleSeededVector2(0, 0, 0)); - - private final ThreadLocal mutable3 = - ThreadLocal.withInitial(() -> new DoubleSeededVector3(0, 0, 0, 0)); - - public CacheSampler(NoiseSampler sampler, int dimensions, int generationThreads) { + public CacheSampler(NoiseSampler sampler, int dimensions) { this.sampler = sampler; - int size = generationThreads * 256; if (dimensions == 2) { - this.cache2D = Caffeine + LoadingCache cache = Caffeine .newBuilder() .executor(CACHE_EXECUTOR) .scheduler(Scheduler.systemScheduler()) - .initialCapacity(size) - .maximumSize(size) - .build(vec -> { - mutable2.remove(); - return this.sampler.noise(vec.seed, vec.x, vec.z); - }); - cache3D = null; - mutable3.remove(); + .initialCapacity(256) + .maximumSize(256) + .build(this::sampleNoise); + this.cache2D = ThreadLocal.withInitial(() -> Pair.of(new DoubleSeededVector2(0, 0, 0), cache).mutable()); + this.cache3D = null; } else { - int size3D = size * 384; - this.cache3D = Caffeine + LoadingCache cache = Caffeine .newBuilder() .executor(CACHE_EXECUTOR) .scheduler(Scheduler.systemScheduler()) - .initialCapacity(size3D) - .maximumSize(size3D) - .build(vec -> { - mutable3.remove(); - return this.sampler.noise(vec.seed, vec.x, vec.y, vec.z); - }); - cache2D = null; - mutable2.remove(); + .initialCapacity(981504) + .maximumSize(981504) + .build(this::sampleNoise); + this.cache3D = ThreadLocal.withInitial(() -> Pair.of(new DoubleSeededVector3(0, 0, 0, 0), cache).mutable()); + this.cache2D = null; } } + private Double sampleNoise(DoubleSeededVector2 vec) { + this.cache2D.get().setLeft(new DoubleSeededVector2(0, 0, 0)); + return this.sampler.noise(vec.seed, vec.x, vec.z); + } + + private Double sampleNoise(DoubleSeededVector3 vec) { + this.cache3D.get().setLeft(new DoubleSeededVector3(0, 0, 0, 0)); + return this.sampler.noise(vec.seed, vec.x, vec.z); + } + @Override public double noise(long seed, double x, double y) { - DoubleSeededVector2 mutableKey = mutable2.get(); + Mutable> cachePair = cache2D.get(); + DoubleSeededVector2 mutableKey = cachePair.getLeft(); mutableKey.set(x, y, seed); - return cache2D.get(mutableKey); + return cachePair.getRight().get(mutableKey); } @Override public double noise(long seed, double x, double y, double z) { - DoubleSeededVector3 mutableKey = mutable3.get(); + Mutable> cachePair = cache3D.get(); + DoubleSeededVector3 mutableKey = cachePair.getLeft(); mutableKey.set(x, y, z, seed); - return cache3D.get(mutableKey); + return cachePair.getRight().get(mutableKey); } private static class DoubleSeededVector3 { diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java index 743d1d671..29c4531f1 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java +++ b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java @@ -97,7 +97,7 @@ public interface BiomeProvider { if(this instanceof CachingBiomeProvider cachingBiomeProvider) { return cachingBiomeProvider; } - return new CachingBiomeProvider(this, platform.getGenerationThreads()); + return new CachingBiomeProvider(this); } diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java index bdebb0013..3e712b761 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java +++ b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java @@ -1,5 +1,9 @@ package com.dfsek.terra.api.world.biome.generation; +import com.dfsek.terra.api.util.generic.pair.Pair; + +import com.dfsek.terra.api.util.generic.pair.Pair.Mutable; + import com.github.benmanes.caffeine.cache.Caffeine; import com.github.benmanes.caffeine.cache.LoadingCache; import com.github.benmanes.caffeine.cache.Scheduler; @@ -20,47 +24,45 @@ import static com.dfsek.terra.api.util.CacheUtils.CACHE_EXECUTOR; public class CachingBiomeProvider implements BiomeProvider, Handle { protected final BiomeProvider delegate; private final int res; - private final LoadingCache cache; - private final LoadingCache> baseCache; + private final ThreadLocal>> cache; + private final ThreadLocal>>> baseCache; - private final ThreadLocal mutable2 = - ThreadLocal.withInitial(() -> new SeededVector2(0, 0, 0)); - - private final ThreadLocal mutable3 = - ThreadLocal.withInitial(() -> new SeededVector3(0, 0, 0, 0)); - - protected CachingBiomeProvider(BiomeProvider delegate, int generationThreads) { + protected CachingBiomeProvider(BiomeProvider delegate) { this.delegate = delegate; this.res = delegate.resolution(); - int size = generationThreads * 256; - this.baseCache = Caffeine + LoadingCache> cache = Caffeine .newBuilder() .executor(CACHE_EXECUTOR) .scheduler(Scheduler.systemScheduler()) - .initialCapacity(size) - .maximumSize(size) - .build(vec -> { - mutable2.remove(); - return delegate.getBaseBiome(vec.x * res, vec.z * res, vec.seed); - }); + .initialCapacity(256) + .maximumSize(256) + .build(this::sampleBiome); + this.baseCache = ThreadLocal.withInitial(() -> Pair.of(new SeededVector2(0, 0, 0), cache).mutable()); - int size3D = size * 384; - this.cache = Caffeine + LoadingCache cache3D = Caffeine .newBuilder() .executor(CACHE_EXECUTOR) .scheduler(Scheduler.systemScheduler()) - .initialCapacity(size3D) - .maximumSize(size3D) - .build(vec -> { - mutable3.remove(); - return delegate.getBiome(vec.x * res, vec.y * res, vec.z * res, vec.seed); - }); + .initialCapacity(981504) + .maximumSize(981504) + .build(this::sampleBiome); + this.cache = ThreadLocal.withInitial(() -> Pair.of(new SeededVector3(0, 0, 0, 0), cache3D).mutable()); } + private Optional sampleBiome(SeededVector2 vec) { + this.baseCache.get().setLeft(new SeededVector2(0, 0, 0)); + return this.delegate.getBaseBiome(vec.x * res, vec.z * res, vec.seed); + } + + private Biome sampleBiome(SeededVector3 vec) { + this.cache.get().setLeft(new SeededVector3(0, 0, 0, 0)); + return this.delegate.getBiome(vec.x * res, vec.y * res, vec.z * res, vec.seed); + } + @Override public BiomeProvider getHandle() { return delegate; @@ -68,16 +70,18 @@ public class CachingBiomeProvider implements BiomeProvider, Handle { @Override public Biome getBiome(int x, int y, int z, long seed) { - SeededVector3 mutableKey = mutable3.get(); + Mutable> cachePair = cache.get(); + SeededVector3 mutableKey = cachePair.getLeft(); mutableKey.set(x, y, z, seed); - return cache.get(mutableKey); + return cachePair.getRight().get(mutableKey); } @Override public Optional getBaseBiome(int x, int z, long seed) { - SeededVector2 mutableKey = mutable2.get(); + Mutable>> cachePair = baseCache.get(); + SeededVector2 mutableKey = cachePair.getLeft(); mutableKey.set(x, z, seed); - return baseCache.get(mutableKey); + return cachePair.getRight().get(mutableKey); } @Override