mirror of
https://github.com/Minestom/Minestom.git
synced 2025-01-02 14:38:26 +01:00
Add experimental local buffer API. Remove allocation when writing chunk packets (should help with startup time)
This commit is contained in:
parent
82602a686e
commit
78126fad6c
@ -10,6 +10,7 @@ import net.minestom.server.instance.palette.Palette;
|
||||
import net.minestom.server.network.packet.server.ServerPacket;
|
||||
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
||||
import net.minestom.server.tag.Tag;
|
||||
import net.minestom.server.utils.PacketUtils;
|
||||
import net.minestom.server.utils.Utils;
|
||||
import net.minestom.server.utils.binary.BinaryReader;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
@ -32,8 +33,7 @@ public class ChunkDataPacket implements ServerPacket {
|
||||
public Map<Integer, Block> entries = new HashMap<>();
|
||||
|
||||
private static final byte CHUNK_SECTION_COUNT = 16;
|
||||
private static final int MAX_BITS_PER_ENTRY = 16;
|
||||
private static final int MAX_BUFFER_SIZE = (Short.BYTES + Byte.BYTES + 5 * Byte.BYTES + (4096 * MAX_BITS_PER_ENTRY / Long.SIZE * Long.BYTES)) * CHUNK_SECTION_COUNT + 256 * Integer.BYTES;
|
||||
private static final PacketUtils.Cache BLOCK_CACHE = PacketUtils.Cache.get("chunk-block-cache", 262_144);
|
||||
|
||||
/**
|
||||
* Heightmaps NBT, as read from raw packet data.
|
||||
@ -49,7 +49,7 @@ public class ChunkDataPacket implements ServerPacket {
|
||||
writer.writeInt(chunkX);
|
||||
writer.writeInt(chunkZ);
|
||||
|
||||
ByteBuffer blocks = ByteBuffer.allocate(MAX_BUFFER_SIZE);
|
||||
ByteBuffer blocks = BLOCK_CACHE.retrieveLocal();
|
||||
|
||||
Int2LongRBTreeMap maskMap = new Int2LongRBTreeMap();
|
||||
|
||||
|
@ -21,6 +21,8 @@ import org.jetbrains.annotations.NotNull;
|
||||
import java.nio.BufferOverflowException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.zip.Deflater;
|
||||
|
||||
/**
|
||||
@ -30,22 +32,12 @@ import java.util.zip.Deflater;
|
||||
public final class PacketUtils {
|
||||
private static final PacketListenerManager PACKET_LISTENER_MANAGER = MinecraftServer.getPacketListenerManager();
|
||||
private static final ThreadLocal<Deflater> COMPRESSOR = ThreadLocal.withInitial(Deflater::new);
|
||||
private static final ThreadLocal<ByteBuffer> PACKET_BUFFER = ThreadLocal.withInitial(() -> ByteBuffer.allocateDirect(Server.SOCKET_BUFFER_SIZE));
|
||||
private static final ThreadLocal<ByteBuffer> COMPRESSION_CACHE = ThreadLocal.withInitial(() -> ByteBuffer.allocateDirect(Server.SOCKET_BUFFER_SIZE));
|
||||
private static final Cache PACKET_BUFFER = Cache.get("packet-buffer", Server.SOCKET_BUFFER_SIZE);
|
||||
private static final Cache COMPRESSION_CACHE = Cache.get("compression-buffer", Server.SOCKET_BUFFER_SIZE);
|
||||
|
||||
private PacketUtils() {
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
static ByteBuffer localBuffer() {
|
||||
return PACKET_BUFFER.get().clear();
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
static ByteBuffer compressionCache() {
|
||||
return COMPRESSION_CACHE.get().clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a packet to an audience. This method performs the following steps in the
|
||||
* following order:
|
||||
@ -162,7 +154,7 @@ public final class PacketUtils {
|
||||
// Packet large enough, compress
|
||||
final int limitCache = buffer.limit();
|
||||
buffer.position(contentStart).limit(contentStart + packetSize);
|
||||
var uncompressedCopy = compressionCache().put(buffer).flip();
|
||||
var uncompressedCopy = COMPRESSION_CACHE.retrieveLocal().put(buffer).flip();
|
||||
buffer.position(contentStart).limit(limitCache);
|
||||
|
||||
var deflater = COMPRESSOR.get();
|
||||
@ -198,15 +190,40 @@ public final class PacketUtils {
|
||||
}
|
||||
|
||||
public static ByteBuffer createFramedPacket(@NotNull ServerPacket packet) {
|
||||
return createFramedPacket(localBuffer(), packet);
|
||||
return createFramedPacket(PACKET_BUFFER.retrieveLocal(), packet);
|
||||
}
|
||||
|
||||
public static ByteBuffer createFramedPacket(@NotNull ServerPacket packet, boolean compression) {
|
||||
return createFramedPacket(localBuffer(), packet, compression);
|
||||
return createFramedPacket(PACKET_BUFFER.retrieveLocal(), packet, compression);
|
||||
}
|
||||
|
||||
public static ByteBuffer allocateTrimmedPacket(@NotNull ServerPacket packet) {
|
||||
final var temp = PacketUtils.createFramedPacket(packet);
|
||||
return ByteBuffer.allocateDirect(temp.position()).put(temp.flip()).asReadOnlyBuffer();
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static final class Cache {
|
||||
private static final Map<String, Cache> CACHES = new ConcurrentHashMap<>();
|
||||
|
||||
private final String name;
|
||||
private final ThreadLocal<ByteBuffer> cache;
|
||||
|
||||
private Cache(String name, int size) {
|
||||
this.name = name;
|
||||
this.cache = ThreadLocal.withInitial(() -> ByteBuffer.allocateDirect(size));
|
||||
}
|
||||
|
||||
public static Cache get(String name, int size) {
|
||||
return CACHES.computeIfAbsent(name, s -> new Cache(name, size));
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public ByteBuffer retrieveLocal() {
|
||||
return cache.get().clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user