replace dumb caches with guava caches

This commit is contained in:
dfsek 2021-01-14 00:34:23 -07:00
parent 8fd3530653
commit cbc2885c16
7 changed files with 81 additions and 113 deletions

View File

@ -32,21 +32,21 @@ import com.dfsek.terra.debug.Debug;
import com.dfsek.terra.generation.math.SamplerCache;
import com.dfsek.terra.registry.LootRegistry;
import com.dfsek.terra.registry.ScriptRegistry;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import net.jafama.FastMath;
import org.apache.commons.io.IOUtils;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ExecutionException;
public class StructureScript {
private final Block block;
private final String id;
String tempID;
private final Map<Location, StructureBuffer> cache;
private final Cache<Location, StructureBuffer> cache;
private final TerraPlugin main;
public StructureScript(InputStream inputStream, TerraPlugin main, ScriptRegistry registry, LootRegistry lootRegistry, SamplerCache cache) throws ParseException {
@ -88,12 +88,7 @@ public class StructureScript {
this.id = parser.getID();
tempID = id;
this.main = main;
this.cache = Collections.synchronizedMap(new LinkedHashMap<Location, StructureBuffer>() {
@Override
protected boolean removeEldestEntry(Map.Entry<Location, StructureBuffer> eldest) {
return this.size() > main.getTerraConfig().getStructureCache();
}
});
this.cache = CacheBuilder.newBuilder().maximumSize(main.getTerraConfig().getStructureCache()).build();
}
/**
@ -122,12 +117,14 @@ public class StructureScript {
}
private StructureBuffer computeBuffer(Location location, Random random, Rotation rotation) {
synchronized(cache) {
return cache.computeIfAbsent(location, loc -> {
StructureBuffer buf = new StructureBuffer(loc);
try {
return cache.get(location, () -> {
StructureBuffer buf = new StructureBuffer(location);
buf.setSucceeded(applyBlock(new TerraImplementationArguments(buf, rotation, random, 0)));
return buf;
});
} catch(ExecutionException e) {
throw new RuntimeException(e);
}
}

View File

@ -1,25 +0,0 @@
package com.dfsek.terra.biome;
import com.dfsek.terra.api.math.vector.Vector2;
import com.dfsek.terra.biome.pipeline.BiomeHolder;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import org.jetbrains.annotations.NotNull;
public class BiomeCache {
LoadingCache<Vector2, BiomeHolder> cache;
public BiomeCache() {
cache = CacheBuilder.newBuilder()
.maximumSize(1024)
.build(
new CacheLoader<Vector2, BiomeHolder>() {
@Override
public BiomeHolder load(@NotNull Vector2 key) throws Exception {
return null;
}
}
);
}
}

View File

@ -50,11 +50,7 @@ public class StandardBiomeProvider implements BiomeProvider {
@Override
public TerraBiome getBiome(int x, int z) {
try {
return biomeCache.get(new Vector2(x, z));
} catch(ExecutionException e) {
throw new RuntimeException(e);
}
return biomeCache.getUnchecked(new Vector2(x, z));
}
public int getResolution() {

View File

@ -10,44 +10,38 @@ import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.carving.Worm;
import com.dfsek.terra.biome.BiomeProvider;
import com.dfsek.terra.biome.UserDefinedBiome;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
public class CarverCache {
private final World w;
private final Map<Long, List<Worm.WormPoint>> carvers;
private final TerraPlugin main;
private final LoadingCache<Long, List<Worm.WormPoint>> cache;
private final UserDefinedCarver carver;
public CarverCache(World w, TerraPlugin main) {
this.w = w;
this.main = main;
carvers = Collections.synchronizedMap(new LinkedHashMap<Long, List<Worm.WormPoint>>() {
public CarverCache(World w, TerraPlugin main, UserDefinedCarver carver) {
this.carver = carver;
cache = CacheBuilder.newBuilder().maximumSize(main.getTerraConfig().getCarverCacheSize())
.build(new CacheLoader<Long, List<Worm.WormPoint>>() {
@Override
protected boolean removeEldestEntry(Map.Entry eldest) {
return this.size() > main.getTerraConfig().getCarverCacheSize();
}
});
}
public List<Worm.WormPoint> getPoints(int chunkX, int chunkZ, UserDefinedCarver carver) {
synchronized(carvers) {
return carvers.computeIfAbsent(MathUtil.squash(chunkX, chunkZ), key -> {
public List<Worm.WormPoint> load(@NotNull Long key) {
int chunkX = (int) (key >> 32);
int chunkZ = (int) key.longValue();
BiomeProvider provider = main.getWorld(w).getBiomeProvider();
if(carver.isChunkCarved(w, chunkX, chunkZ, new FastRandom(MathUtil.getCarverChunkSeed(chunkX, chunkZ, w.getSeed() + carver.hashCode())))) {
if(CarverCache.this.carver.isChunkCarved(w, chunkX, chunkZ, new FastRandom(MathUtil.getCarverChunkSeed(chunkX, chunkZ, w.getSeed() + CarverCache.this.carver.hashCode())))) {
long seed = MathUtil.getCarverChunkSeed(chunkX, chunkZ, w.getSeed());
carver.getSeedVar().setValue(seed);
CarverCache.this.carver.getSeedVar().setValue(seed);
Random r = new FastRandom(seed);
Worm carving = carver.getWorm(seed, new Vector3((chunkX << 4) + r.nextInt(16), carver.getConfig().getHeight().get(r), (chunkZ << 4) + r.nextInt(16)));
Worm carving = CarverCache.this.carver.getWorm(seed, new Vector3((chunkX << 4) + r.nextInt(16), CarverCache.this.carver.getConfig().getHeight().get(r), (chunkZ << 4) + r.nextInt(16)));
List<Worm.WormPoint> points = new GlueList<>();
for(int i = 0; i < carving.getLength(); i++) {
carving.step();
TerraBiome biome = provider.getBiome(carving.getRunning().toLocation(w));
if(!((UserDefinedBiome) biome).getConfig().getCarvers().containsKey(carver)) { // Stop if we enter a biome this carver is not present in
if(!((UserDefinedBiome) biome).getConfig().getCarvers().containsKey(CarverCache.this.carver)) { // Stop if we enter a biome this carver is not present in
return new GlueList<>();
}
points.add(carving.getPoint());
@ -55,7 +49,11 @@ public class CarverCache {
return points;
}
return new GlueList<>();
}
});
}
public List<Worm.WormPoint> getPoints(int chunkX, int chunkZ) {
return cache.getUnchecked(MathUtil.squash(chunkX, chunkZ));
}
}

View File

@ -11,6 +11,7 @@ import com.dfsek.terra.api.world.carving.Worm;
import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.config.templates.BiomeTemplate;
import com.dfsek.terra.config.templates.CarverTemplate;
import com.dfsek.terra.debug.Debug;
import net.jafama.FastMath;
import parsii.eval.Expression;
import parsii.eval.Parser;
@ -100,11 +101,12 @@ public class UserDefinedCarver extends Carver {
@Override
public void carve(int chunkX, int chunkZ, World w, BiConsumer<Vector3, CarvingType> consumer) {
CarverCache cache = cacheMap.computeIfAbsent(w, world -> new CarverCache(world, main));
CarverCache cache = cacheMap.computeIfAbsent(w, world -> new CarverCache(world, main, this));
if(cacheMap.size() > 1) Debug.info("Map size: " + cacheMap.size());
int carvingRadius = getCarvingRadius();
for(int x = chunkX - carvingRadius; x <= chunkX + carvingRadius; x++) {
for(int z = chunkZ - carvingRadius; z <= chunkZ + carvingRadius; z++) {
cache.getPoints(x, z, this).forEach(point -> {
cache.getPoints(x, z).forEach(point -> {
Vector3 origin = point.getOrigin();
if(FastMath.floorDiv(origin.getBlockX(), 16) != chunkX && FastMath.floorDiv(origin.getBlockZ(), 16) != chunkZ) // We only want to carve this chunk.
return;

View File

@ -4,11 +4,13 @@ import com.dfsek.terra.TerraWorld;
import com.dfsek.terra.api.math.MathUtil;
import com.dfsek.terra.api.platform.TerraPlugin;
import com.dfsek.terra.api.platform.world.World;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import net.jafama.FastMath;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
public class SamplerCache {
@ -35,14 +37,18 @@ public class SamplerCache {
private class Container {
private final World world;
private final TerraWorld terraWorld;
private final Map<Long, Sampler> cache = Collections.synchronizedMap(new LinkedHashMap<Long, Sampler>() {
@Override
protected boolean removeEldestEntry(Map.Entry<Long, Sampler> eldest) {
return this.size() > main.getTerraConfig().getSamplerCache();
}
});
private final LoadingCache<Long, Sampler> cache;
private Container(World world) {
cache = CacheBuilder.newBuilder().maximumSize(main.getTerraConfig().getSamplerCache())
.build(new CacheLoader<Long, Sampler>() {
@Override
public Sampler load(@NotNull Long key) {
int cx = (int) (key >> 32);
int cz = (int) key.longValue();
return new Sampler(cx, cz, terraWorld.getBiomeProvider(), world, terraWorld.getConfig().getTemplate().getBaseBlend(), terraWorld.getConfig().getTemplate().getElevationBlend());
}
});
this.world = world;
terraWorld = main.getWorld(world);
}
@ -55,9 +61,7 @@ public class SamplerCache {
public Sampler getChunk(int cx, int cz) {
long key = MathUtil.squash(cx, cz);
synchronized(cache) {
return cache.computeIfAbsent(key, k -> new Sampler(cx, cz, terraWorld.getBiomeProvider(), world, terraWorld.getConfig().getTemplate().getBaseBlend(), terraWorld.getConfig().getTemplate().getElevationBlend()));
}
return cache.getUnchecked(key);
}
}
}

View File

@ -61,8 +61,7 @@ public class BiomeTest {
BiomeSource source = new RandomSource(climate, sourceSampler);
BiomeProvider provider = new StandardBiomeProvider.StandardBiomeProviderBuilder((seed) -> {
BiomePipeline pipeline = new BiomePipeline.BiomePipelineBuilder(2)
BiomeProvider provider = new StandardBiomeProvider.StandardBiomeProviderBuilder((seed) -> new BiomePipeline.BiomePipelineBuilder(2)
.addStage(new ExpanderStage(new FractalExpander(whiteNoise(1))))
.addStage(new MutatorStage(new ReplaceMutator("OCEAN_TEMP", oceanBiomes, whiteNoise(243))))
.addStage(new MutatorStage(new ReplaceMutator("LAND_TEMP", landBiomes, whiteNoise(243))))
@ -76,10 +75,7 @@ public class BiomeTest {
.addStage(new MutatorStage(new BorderMutator("OCEAN", "LAND", whiteNoise(1234), beachBiomes)))
.addStage(new MutatorStage(new SmoothMutator(whiteNoise(6))))
.addStage(new MutatorStage(new SmoothMutator(whiteNoise(6))))
.build(source);
System.out.println("Size: " + pipeline.getSize());
return pipeline;
}, null).build(0);
.build(source), null).build(0);
int size = 1000;