From 3a1e723a51407a7b3886223c2cc9919e87f429c5 Mon Sep 17 00:00:00 2001 From: "Lukas Rieger (Blue)" Date: Fri, 23 Feb 2024 00:55:11 +0100 Subject: [PATCH] Improve linear region efficiency by caching the whole region-file data --- .../bluemap/core/world/mca/MCAWorld.java | 4 +- .../core/world/mca/region/LinearRegion.java | 40 ++++++++++++------- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/mca/MCAWorld.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/mca/MCAWorld.java index b4a70032..992d80c5 100644 --- a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/mca/MCAWorld.java +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/mca/MCAWorld.java @@ -56,7 +56,7 @@ public class MCAWorld implements World { private final ChunkLoader chunkLoader = new ChunkLoader(this); private final LoadingCache regionCache = Caffeine.newBuilder() .executor(BlueMap.THREAD_POOL) - .maximumSize(64) + .maximumSize(32) .expireAfterWrite(10, TimeUnit.MINUTES) .build(this::loadRegion); private final LoadingCache chunkCache = Caffeine.newBuilder() @@ -176,11 +176,13 @@ public class MCAWorld implements World { @Override public void invalidateChunkCache() { + regionCache.invalidateAll(); chunkCache.invalidateAll(); } @Override public void invalidateChunkCache(int x, int z) { + regionCache.invalidate(VECTOR_2_I_CACHE.get(x >> 5, z >> 5)); chunkCache.invalidate(VECTOR_2_I_CACHE.get(x, z)); } diff --git a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/mca/region/LinearRegion.java b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/mca/region/LinearRegion.java index 9ff42c3d..1d79a4e1 100644 --- a/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/mca/region/LinearRegion.java +++ b/BlueMapCore/src/main/java/de/bluecolored/bluemap/core/world/mca/region/LinearRegion.java @@ -69,6 +69,16 @@ public class LinearRegion implements Region { private final Path regionFile; private final Vector2i regionPos; + private boolean initialized = false; + + private byte version; + private long newestTimestamp; + private byte compressionLevel; + private short chunkCount; + private int dataLength; + private long dataHash; + private byte[] compressedData; + public LinearRegion(MCAWorld world, Path regionFile) throws IllegalArgumentException { this.world = world; this.regionFile = regionFile; @@ -86,26 +96,14 @@ public class LinearRegion implements Region { this.regionFile = world.getRegionFolder().resolve(getRegionFileName(regionPos.getX(), regionPos.getY())); } - @Override - public void iterateAllChunks(ChunkConsumer consumer) throws IOException { + private synchronized void init() throws IOException { + if (initialized) return; + if (Files.notExists(regionFile)) return; long fileLength = Files.size(regionFile); if (fileLength == 0) return; - int chunkStartX = regionPos.getX() * 32; - int chunkStartZ = regionPos.getY() * 32; - - byte[] chunkDataBuffer = null; - byte[] compressedData; - - byte version; - long newestTimestamp; - byte compressionLevel; - short chunkCount; - int dataLength; - long dataHash; - try ( InputStream in = Files.newInputStream(regionFile, StandardOpenOption.READ); BufferedInputStream bIn = new BufferedInputStream(in); @@ -136,6 +134,18 @@ public class LinearRegion implements Region { } + initialized = true; + } + + @Override + public void iterateAllChunks(ChunkConsumer consumer) throws IOException { + if (!initialized) init(); + + int chunkStartX = regionPos.getX() * 32; + int chunkStartZ = regionPos.getY() * 32; + + byte[] chunkDataBuffer = null; + try ( InputStream in = new ZstdInputStream(new ByteArrayInputStream(compressedData)); BufferedInputStream bIn = new BufferedInputStream(in);