PacketUtils improvement with initial capacity packet + optimize the ChunkDataPacket

This commit is contained in:
themode 2020-08-21 13:16:44 +02:00
parent f2222cfaf2
commit 7ea06cc70b
7 changed files with 64 additions and 131 deletions

View File

@ -86,8 +86,6 @@ dependencies {
api 'io.netty:netty-codec:4.1.51.Final'
implementation 'io.netty:netty-transport-native-epoll:4.1.51.Final:linux-x86_64'
api 'com.github.jhg023:Pbbl:1.0.2'
// https://mvnrepository.com/artifact/it.unimi.dsi/fastutil
api 'it.unimi.dsi:fastutil:8.4.1'

View File

@ -1,5 +1,7 @@
package net.minestom.server.network.packet.server.play;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import net.minestom.server.MinecraftServer;
import net.minestom.server.data.Data;
@ -11,8 +13,6 @@ import net.minestom.server.network.packet.server.ServerPacketIdentifier;
import net.minestom.server.utils.BlockPosition;
import net.minestom.server.utils.Utils;
import net.minestom.server.utils.binary.BinaryWriter;
import net.minestom.server.utils.buffer.BufferUtils;
import net.minestom.server.utils.buffer.BufferWrapper;
import net.minestom.server.utils.chunk.ChunkUtils;
import net.minestom.server.world.biomes.Biome;
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
@ -47,7 +47,7 @@ public class ChunkDataPacket implements ServerPacket {
writer.writeBoolean(fullChunk);
int mask = 0;
BufferWrapper blocks = BufferUtils.getBuffer(MAX_BUFFER_SIZE);
ByteBuf blocks = Unpooled.buffer(MAX_BUFFER_SIZE);
for (byte i = 0; i < CHUNK_SECTION_COUNT; i++) {
if (fullChunk || (sections.length == CHUNK_SECTION_COUNT && sections[i] != 0)) {
short[] section = getSection(i);
@ -91,8 +91,8 @@ public class ChunkDataPacket implements ServerPacket {
}
// Data
writer.writeVarInt(blocks.getSize());
writer.writeBufferAndFree(blocks);
writer.writeVarInt(blocks.writerIndex());
writer.getBuffer().writeBytes(blocks);
// Block entities
writer.writeVarInt(blockEntities.size());

View File

@ -21,11 +21,10 @@ public final class PacketUtils {
* @param packet the packet to write into {@code buf}
*/
public static void writePacket(ByteBuf buf, ServerPacket packet) {
BinaryWriter writer = new BinaryWriter();
Utils.writeVarIntBuf(buf, packet.getId());
packet.write(writer);
buf.writeBytes(writer.toByteArray());
final ByteBuf packetBuffer = getPacketBuffer(packet);
writePacket(buf, packetBuffer, packet.getId());
}
/**
@ -35,11 +34,40 @@ public final class PacketUtils {
* @return a {@link ByteBuf} containing {@code packet}
*/
public static ByteBuf writePacket(ServerPacket packet) {
ByteBuf buffer = Unpooled.buffer();
final ByteBuf packetBuffer = getPacketBuffer(packet);
writePacket(buffer, packet);
// Add 5 for the packet id and for the packet size
final int size = packetBuffer.writerIndex() + 5 + 5;
ByteBuf buffer = Unpooled.buffer(size);
writePacket(buffer, packetBuffer, packet.getId());
return buffer;
}
/**
* Write a packet buffer into {@code buf}
*
* @param buf the buffer which will receive the packet id/data
* @param packetBuffer the buffer containing the raw packet data
* @param packetId the packet id
*/
private static void writePacket(ByteBuf buf, ByteBuf packetBuffer, int packetId) {
Utils.writeVarIntBuf(buf, packetId);
buf.writeBytes(packetBuffer);
}
/**
* Get the buffer representing the raw packet data
*
* @param packet the packet to write
* @return the {@link ByteBuf} containing the raw packet data
*/
private static ByteBuf getPacketBuffer(ServerPacket packet) {
BinaryWriter writer = new BinaryWriter();
packet.write(writer);
return writer.getBuffer();
}
}

View File

@ -3,7 +3,6 @@ package net.minestom.server.utils;
import io.netty.buffer.ByteBuf;
import net.minestom.server.instance.Chunk;
import net.minestom.server.utils.binary.BinaryWriter;
import net.minestom.server.utils.buffer.BufferWrapper;
public final class Utils {
@ -30,17 +29,6 @@ public final class Utils {
} while (value != 0);
}
public static void writeVarIntBuffer(BufferWrapper buffer, int value) {
do {
byte temp = (byte) (value & 0b01111111);
value >>>= 7;
if (value != 0) {
temp |= 0b10000000;
}
buffer.putByte(temp);
} while (value != 0);
}
public static void writeVarInt(BinaryWriter writer, int value) {
do {
byte temp = (byte) (value & 0b01111111);
@ -103,14 +91,14 @@ public final class Utils {
70409299, 70409299, 0, 69273666, 69273666, 0, 68174084, 68174084, 0, Integer.MIN_VALUE,
0, 5};
public static void writeBlocks(BufferWrapper buffer, short[] blocksId, int bitsPerEntry) {
public static void writeBlocks(ByteBuf buffer, short[] blocksId, int bitsPerEntry) {
short count = 0;
for (short id : blocksId)
if (id != 0)
count++;
buffer.putShort(count);
buffer.putByte((byte) bitsPerEntry);
buffer.writeShort(count);
buffer.writeByte((byte) bitsPerEntry);
int[] blocksData = new int[Chunk.CHUNK_SIZE_X * Chunk.CHUNK_SECTION_SIZE * Chunk.CHUNK_SIZE_Z];
for (int y = 0; y < Chunk.CHUNK_SECTION_SIZE; y++) {
for (int x = 0; x < Chunk.CHUNK_SIZE_X; x++) {
@ -121,28 +109,28 @@ public final class Utils {
}
}
}
long[] data = encodeBlocks(blocksData, bitsPerEntry);
buffer.putVarInt(data.length);
final long[] data = encodeBlocks(blocksData, bitsPerEntry);
writeVarIntBuf(buffer, data.length);
for (int i = 0; i < data.length; i++) {
buffer.putLong(data[i]);
buffer.writeLong(data[i]);
}
}
public static long[] encodeBlocks(int[] blocks, int bitsPerEntry) {
long maxEntryValue = (1L << bitsPerEntry) - 1;
char valuesPerLong = (char) (64 / bitsPerEntry);
int magicIndex = 3 * (valuesPerLong - 1);
long divideMul = Integer.toUnsignedLong(MAGIC[magicIndex]);
long divideAdd = Integer.toUnsignedLong(MAGIC[magicIndex + 1]);
int divideShift = MAGIC[magicIndex + 2];
int size = (blocks.length + valuesPerLong - 1) / valuesPerLong;
final long maxEntryValue = (1L << bitsPerEntry) - 1;
final char valuesPerLong = (char) (64 / bitsPerEntry);
final int magicIndex = 3 * (valuesPerLong - 1);
final long divideMul = Integer.toUnsignedLong(MAGIC[magicIndex]);
final long divideAdd = Integer.toUnsignedLong(MAGIC[magicIndex + 1]);
final int divideShift = MAGIC[magicIndex + 2];
final int size = (blocks.length + valuesPerLong - 1) / valuesPerLong;
long[] data = new long[size];
for (int i = 0; i < blocks.length; i++) {
long value = blocks[i];
int cellIndex = (int) (i * divideMul + divideAdd >> 32L >> divideShift);
int bitIndex = (i - cellIndex * valuesPerLong) * bitsPerEntry;
final long value = blocks[i];
final int cellIndex = (int) (i * divideMul + divideAdd >> 32L >> divideShift);
final int bitIndex = (i - cellIndex * valuesPerLong) * bitsPerEntry;
data[cellIndex] = data[cellIndex] & ~(maxEntryValue << bitIndex) | (value & maxEntryValue) << bitIndex;
}

View File

@ -7,13 +7,11 @@ import net.minestom.server.utils.BlockPosition;
import net.minestom.server.utils.NBTUtils;
import net.minestom.server.utils.SerializerUtils;
import net.minestom.server.utils.Utils;
import net.minestom.server.utils.buffer.BufferWrapper;
import org.jglrxavpok.hephaistos.nbt.NBT;
import org.jglrxavpok.hephaistos.nbt.NBTWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.UUID;
import java.util.function.Consumer;
@ -210,15 +208,6 @@ public class BinaryWriter extends OutputStream {
consumer.accept(this);
}
public void writeBufferAndFree(BufferWrapper buffer) {
ByteBuffer byteBuffer = buffer.getByteBuffer();
final int size = buffer.getSize();
byte[] cache = new byte[size];
byteBuffer.position(0).get(cache, 0, size);
writeBytes(cache);
buffer.free();
}
/**
* Write an {@link UUID}
* It is done by writing both long, the most & least significant bits
@ -263,6 +252,15 @@ public class BinaryWriter extends OutputStream {
return bytes;
}
/**
* Get the raw buffer used by this binary writer
*
* @return the raw buffer
*/
public ByteBuf getBuffer() {
return buffer;
}
@Override
public void write(int b) {
writeByte((byte) b);

View File

@ -1,22 +0,0 @@
package net.minestom.server.utils.buffer;
import com.github.pbbl.heap.ByteBufferPool;
import java.nio.ByteBuffer;
public final class BufferUtils {
private static final ByteBufferPool pool = new ByteBufferPool();
private BufferUtils() {
}
public static BufferWrapper getBuffer(int size) {
return new BufferWrapper(pool.take(size));
}
protected static void giveBuffer(ByteBuffer byteBuffer) {
pool.give(byteBuffer);
}
}

View File

@ -1,57 +0,0 @@
package net.minestom.server.utils.buffer;
import net.minestom.server.utils.Utils;
import java.nio.ByteBuffer;
public class BufferWrapper {
private final ByteBuffer byteBuffer;
private int size;
protected BufferWrapper(ByteBuffer byteBuffer) {
this.byteBuffer = byteBuffer;
}
public void putByte(byte b) {
this.byteBuffer.put(b);
size += Byte.BYTES;
}
public void putShort(short s) {
this.byteBuffer.putShort(s);
size += Short.BYTES;
}
public void putInt(int n) {
this.byteBuffer.putInt(n);
size += Integer.BYTES;
}
public void putLong(long l) {
this.byteBuffer.putLong(l);
size += Long.BYTES;
}
public void putVarInt(int n) {
Utils.writeVarIntBuffer(this, n);
size += Utils.getVarIntSize(n);
}
public void putBytes(byte[] bytes) {
this.byteBuffer.put(bytes);
size += Byte.BYTES * bytes.length;
}
public void free() {
BufferUtils.giveBuffer(getByteBuffer());
}
public int getSize() {
return size;
}
public ByteBuffer getByteBuffer() {
return byteBuffer;
}
}