From 5966cdaa473a57b132f32b52bd4d43ed70fe1324 Mon Sep 17 00:00:00 2001 From: themode Date: Sun, 22 Nov 2020 16:32:15 +0100 Subject: [PATCH] Reduced the number of garbage objects --- .../net/minestom/server/instance/Chunk.java | 1 + .../server/instance/DynamicChunk.java | 2 + .../minestom/server/instance/Instance.java | 8 +++- .../server/instance/InstanceContainer.java | 42 ++++++++++++------- 4 files changed, 37 insertions(+), 16 deletions(-) diff --git a/src/main/java/net/minestom/server/instance/Chunk.java b/src/main/java/net/minestom/server/instance/Chunk.java index c1319ba80..2bceca8c2 100644 --- a/src/main/java/net/minestom/server/instance/Chunk.java +++ b/src/main/java/net/minestom/server/instance/Chunk.java @@ -38,6 +38,7 @@ import java.util.concurrent.CopyOnWriteArraySet; /** * A chunk is a part of an {@link Instance}, limited by a size of 16x256x16 blocks and subdivided in 16 sections of 16 blocks height. * Should contains all the blocks located at those positions and manage their tick updates. + * Be aware that implementations do not need to be thread-safe. *

* Chunks can be serialized using {@link #getSerializedData()} and deserialized back with {@link #readChunk(BinaryReader, ChunkCallback)}, * allowing you to implement your own storage solution if needed. diff --git a/src/main/java/net/minestom/server/instance/DynamicChunk.java b/src/main/java/net/minestom/server/instance/DynamicChunk.java index 37e1b11c9..30c71f310 100644 --- a/src/main/java/net/minestom/server/instance/DynamicChunk.java +++ b/src/main/java/net/minestom/server/instance/DynamicChunk.java @@ -30,6 +30,8 @@ import java.util.Set; /** * Represents a {@link Chunk} which store each individual block in memory. + *

+ * WARNING: not thread-safe */ public class DynamicChunk extends Chunk { diff --git a/src/main/java/net/minestom/server/instance/Instance.java b/src/main/java/net/minestom/server/instance/Instance.java index 80cf4a900..19560c993 100644 --- a/src/main/java/net/minestom/server/instance/Instance.java +++ b/src/main/java/net/minestom/server/instance/Instance.java @@ -1,5 +1,7 @@ package net.minestom.server.instance; +import it.unimi.dsi.fastutil.longs.Long2ObjectMap; +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import net.minestom.server.MinecraftServer; import net.minestom.server.UpdateManager; import net.minestom.server.data.Data; @@ -79,7 +81,7 @@ public abstract class Instance implements BlockModifier, EventHandler, DataConta protected final Set objectEntities = new CopyOnWriteArraySet<>(); protected final Set experienceOrbs = new CopyOnWriteArraySet<>(); // Entities per chunk - protected final Map> chunkEntities = new ConcurrentHashMap<>(); + protected final Long2ObjectMap> chunkEntities = new Long2ObjectOpenHashMap<>(); // the uuid of this instance protected UUID uniqueId; @@ -971,7 +973,9 @@ public abstract class Instance implements BlockModifier, EventHandler, DataConta @NotNull private Set getEntitiesInChunk(long index) { - return chunkEntities.computeIfAbsent(index, i -> new CopyOnWriteArraySet<>()); + synchronized (chunkEntities) { + return chunkEntities.computeIfAbsent(index, i -> new CopyOnWriteArraySet<>()); + } } /** diff --git a/src/main/java/net/minestom/server/instance/InstanceContainer.java b/src/main/java/net/minestom/server/instance/InstanceContainer.java index 5afeb0d12..ae816699f 100644 --- a/src/main/java/net/minestom/server/instance/InstanceContainer.java +++ b/src/main/java/net/minestom/server/instance/InstanceContainer.java @@ -1,5 +1,7 @@ package net.minestom.server.instance; +import it.unimi.dsi.fastutil.longs.Long2ObjectMap; +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import net.minestom.server.MinecraftServer; import net.minestom.server.data.Data; import net.minestom.server.data.SerializableData; @@ -33,7 +35,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.*; -import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; @@ -56,7 +57,7 @@ public class InstanceContainer extends Instance { // the chunk generator used, can be null private ChunkGenerator chunkGenerator; // (chunk index -> chunk) map, contains all the chunks in the instance - private final ConcurrentHashMap chunks = new ConcurrentHashMap<>(); + private final Long2ObjectMap chunks = new Long2ObjectOpenHashMap<>(); // contains all the chunks to remove during the next instance tick protected final Set scheduledChunksToRemove = new HashSet<>(); @@ -450,8 +451,10 @@ public class InstanceContainer extends Instance { @Override public Chunk getChunk(int chunkX, int chunkZ) { final long index = ChunkUtils.getChunkIndex(chunkX, chunkZ); - final Chunk chunk = chunks.get(index); - return ChunkUtils.isLoaded(chunk) ? chunk : null; + synchronized (chunks) { + final Chunk chunk = chunks.get(index); + return ChunkUtils.isLoaded(chunk) ? chunk : null; + } } /** @@ -492,7 +495,10 @@ public class InstanceContainer extends Instance { @Override public void saveChunksToStorage(@Nullable Runnable callback) { - this.chunkLoader.saveChunks(chunks.values(), callback); + synchronized (chunks) { + Collection chunksCollection = chunks.values(); + this.chunkLoader.saveChunks(chunksCollection, callback); + } } @Override @@ -639,14 +645,16 @@ public class InstanceContainer extends Instance { copiedInstance.srcInstance = this; copiedInstance.lastBlockChangeTime = lastBlockChangeTime; - for (Chunk chunk : chunks.values()) { - final int chunkX = chunk.getChunkX(); - final int chunkZ = chunk.getChunkZ(); + synchronized (chunks) { + for (Chunk chunk : chunks.values()) { + final int chunkX = chunk.getChunkX(); + final int chunkZ = chunk.getChunkZ(); - final Chunk copiedChunk = chunk.copy(chunkX, chunkZ); + final Chunk copiedChunk = chunk.copy(chunkX, chunkZ); - copiedInstance.cacheChunk(copiedChunk); - UPDATE_MANAGER.signalChunkLoad(copiedInstance, chunkX, chunkZ); + copiedInstance.cacheChunk(copiedChunk); + UPDATE_MANAGER.signalChunkLoad(copiedInstance, chunkX, chunkZ); + } } return copiedInstance; @@ -693,7 +701,9 @@ public class InstanceContainer extends Instance { */ public void cacheChunk(@NotNull Chunk chunk) { final long index = ChunkUtils.getChunkIndex(chunk.getChunkX(), chunk.getChunkZ()); - this.chunks.put(index, chunk); + synchronized (chunks) { + this.chunks.put(index, chunk); + } } @Override @@ -823,8 +833,12 @@ public class InstanceContainer extends Instance { }); // Clear cache - this.chunks.remove(index); - this.chunkEntities.remove(index); + synchronized (chunks) { + this.chunks.remove(index); + } + synchronized (chunkEntities) { + this.chunkEntities.remove(index); + } chunk.unload();