Reuse the tick buffer when possible & avoid iteration

Signed-off-by: TheMode <themode@outlook.fr>
This commit is contained in:
TheMode 2021-09-22 23:24:22 +02:00
parent d5d4a97694
commit 68107c9a90

View File

@ -263,46 +263,60 @@ public class PlayerSocketConnection extends PlayerConnection {
@Override @Override
public void flush() { public void flush() {
boolean shouldDisconnect = false; try {
synchronized (bufferLock) { synchronized (bufferLock) {
final BinaryBuffer localBuffer = tickBuffer.getPlain(); final BinaryBuffer localBuffer = tickBuffer.getPlain();
if (localBuffer.readableBytes() == 0 && waitingBuffers.isEmpty()) return; final boolean emptyWaitingList = waitingBuffers.isEmpty();
// Update tick buffer if (localBuffer.readableBytes() == 0 && emptyWaitingList) return;
try { // Update tick buffer
this.tickBuffer.setPlain(PooledBuffers.get()); try {
if (encrypted) { // Encryption support
final Cipher cipher = encryptCipher; if (encrypted) {
// Encrypt data first ByteBuffer cipherInput = localBuffer.asByteBuffer(0, localBuffer.writerOffset());
ByteBuffer cipherInput = localBuffer.asByteBuffer(0, localBuffer.writerOffset()); try {
try { this.encryptCipher.update(cipherInput, cipherInput.duplicate());
cipher.update(cipherInput, cipherInput.duplicate()); } catch (ShortBufferException e) {
} catch (ShortBufferException e) { MinecraftServer.getExceptionManager().handleException(e);
MinecraftServer.getExceptionManager().handleException(e); }
} }
}
this.waitingBuffers.add(localBuffer);
Iterator<BinaryBuffer> iterator = waitingBuffers.iterator();
while (iterator.hasNext()) {
BinaryBuffer waitingBuffer = iterator.next();
try { try {
if (!waitingBuffer.writeChannel(channel)) break; // Try to write the current buffer
iterator.remove(); if (emptyWaitingList && localBuffer.writeChannel(channel)) {
PooledBuffers.add(waitingBuffer); // Can reuse buffer
} catch (ClosedChannelException e) { localBuffer.clear();
shouldDisconnect = true; return;
}
this.tickBuffer.setPlain(PooledBuffers.get());
this.waitingBuffers.add(localBuffer);
if (emptyWaitingList) return;
// Write as much as possible from the waiting list
Iterator<BinaryBuffer> iterator = waitingBuffers.iterator();
while (iterator.hasNext()) {
BinaryBuffer waitingBuffer = iterator.next();
try {
if (!waitingBuffer.writeChannel(channel)) break;
iterator.remove();
PooledBuffers.add(waitingBuffer);
} catch (IOException e) {
MinecraftServer.getExceptionManager().handleException(e);
throw new ClosedChannelException();
}
}
} catch (IOException e) { } catch (IOException e) {
MinecraftServer.getExceptionManager().handleException(e); MinecraftServer.getExceptionManager().handleException(e);
shouldDisconnect = true; throw new ClosedChannelException();
} }
} catch (OutOfMemoryError e) {
this.waitingBuffers.clear();
System.gc(); // Explicit gc forcing buffers to be collected
throw new ClosedChannelException();
} }
} catch (OutOfMemoryError e) {
this.waitingBuffers.clear();
System.gc(); // Explicit gc forcing buffers to be collected
shouldDisconnect = true;
} }
} catch (ClosedChannelException e) {
disconnect();
} }
if (shouldDisconnect) disconnect();
} }
@Override @Override