Use a concurrent map for viewable packets

This commit is contained in:
themode 2021-10-29 03:02:56 +02:00
parent 107388a37b
commit 484727d02a

View File

@ -1,5 +1,6 @@
package net.minestom.server.utils; package net.minestom.server.utils;
import com.google.common.collect.MapMaker;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.longs.LongArrayList; import it.unimi.dsi.fastutil.longs.LongArrayList;
@ -31,9 +32,8 @@ import org.jetbrains.annotations.Nullable;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.Collection; import java.util.Collection;
import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.WeakHashMap; import java.util.concurrent.ConcurrentMap;
import java.util.zip.Deflater; import java.util.zip.Deflater;
/** /**
@ -53,7 +53,7 @@ public final class PacketUtils {
private static final LocalCache<ByteBuffer> LOCAL_BUFFER = LocalCache.ofBuffer(Server.MAX_PACKET_SIZE); private static final LocalCache<ByteBuffer> LOCAL_BUFFER = LocalCache.ofBuffer(Server.MAX_PACKET_SIZE);
// Viewable packets // Viewable packets
private static final Map<Viewable, ViewableStorage> VIEWABLE_STORAGE_MAP = new WeakHashMap<>(); private static final ConcurrentMap<Viewable, ViewableStorage> VIEWABLE_STORAGE_MAP = new MapMaker().weakKeys().makeMap();
private PacketUtils() { private PacketUtils() {
} }
@ -158,11 +158,12 @@ public final class PacketUtils {
entity.sendPacketToViewers(serverPacket); entity.sendPacketToViewers(serverPacket);
return; return;
} }
ViewableStorage viewableStorage; final Player exception = entity instanceof Player ? (Player) entity : null;
synchronized (VIEWABLE_STORAGE_MAP) { VIEWABLE_STORAGE_MAP.compute(viewable, ((v, storage) -> {
viewableStorage = VIEWABLE_STORAGE_MAP.computeIfAbsent(viewable, v -> new ViewableStorage()); storage = Objects.requireNonNullElseGet(storage, ViewableStorage::new);
} storage.append(v, serverPacket, exception);
viewableStorage.append(viewable, serverPacket, entity instanceof Player ? (Player) entity : null); return storage;
}));
} }
@ApiStatus.Experimental @ApiStatus.Experimental
@ -172,10 +173,8 @@ public final class PacketUtils {
@ApiStatus.Internal @ApiStatus.Internal
public static void flush() { public static void flush() {
synchronized (VIEWABLE_STORAGE_MAP) { VIEWABLE_STORAGE_MAP.entrySet().parallelStream()
VIEWABLE_STORAGE_MAP.entrySet().parallelStream().forEach(entry -> .forEach(entry -> entry.getValue().process(entry.getKey()));
entry.getValue().process(entry.getKey()));
}
} }
public static void writeFramedPacket(@NotNull ByteBuffer buffer, public static void writeFramedPacket(@NotNull ByteBuffer buffer,
@ -246,7 +245,7 @@ public final class PacketUtils {
PooledBuffers.registerBuffer(this, buffer); PooledBuffers.registerBuffer(this, buffer);
} }
private synchronized void append(Viewable viewable, ServerPacket serverPacket, Player player) { private void append(Viewable viewable, ServerPacket serverPacket, Player player) {
final ByteBuffer framedPacket = createFramedPacket(serverPacket); final ByteBuffer framedPacket = createFramedPacket(serverPacket);
final int packetSize = framedPacket.limit(); final int packetSize = framedPacket.limit();
if (packetSize >= buffer.capacity()) { if (packetSize >= buffer.capacity()) {
@ -269,7 +268,7 @@ public final class PacketUtils {
} }
} }
private synchronized void process(Viewable viewable) { private void process(Viewable viewable) {
if (buffer.writerOffset() == 0) return; if (buffer.writerOffset() == 0) return;
viewable.getViewers().forEach(this::processPlayer); viewable.getViewers().forEach(this::processPlayer);
this.buffer.clear(); this.buffer.clear();