mirror of
https://github.com/Minestom/Minestom.git
synced 2025-01-23 16:41:35 +01:00
Overall performance improvement
This commit is contained in:
parent
c2f302ad0e
commit
01d233f7d8
@ -4,8 +4,10 @@ import com.google.common.collect.Queues;
|
|||||||
import net.minestom.server.instance.Instance;
|
import net.minestom.server.instance.Instance;
|
||||||
import net.minestom.server.instance.InstanceManager;
|
import net.minestom.server.instance.InstanceManager;
|
||||||
import net.minestom.server.network.ConnectionManager;
|
import net.minestom.server.network.ConnectionManager;
|
||||||
|
import net.minestom.server.network.player.NettyPlayerConnection;
|
||||||
import net.minestom.server.thread.PerInstanceThreadProvider;
|
import net.minestom.server.thread.PerInstanceThreadProvider;
|
||||||
import net.minestom.server.thread.ThreadProvider;
|
import net.minestom.server.thread.ThreadProvider;
|
||||||
|
import net.minestom.server.utils.async.AsyncUtils;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -80,6 +82,12 @@ public final class UpdateManager {
|
|||||||
// Tick end callbacks
|
// Tick end callbacks
|
||||||
doTickCallback(tickEndCallbacks, tickTime / 1000000L);
|
doTickCallback(tickEndCallbacks, tickTime / 1000000L);
|
||||||
|
|
||||||
|
// Flush all waiting packets
|
||||||
|
AsyncUtils.runAsync(() -> connectionManager.getOnlinePlayers().stream()
|
||||||
|
.filter(player -> player.getPlayerConnection() instanceof NettyPlayerConnection)
|
||||||
|
.map(player -> (NettyPlayerConnection) player.getPlayerConnection())
|
||||||
|
.forEach(NettyPlayerConnection::flush));
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
MinecraftServer.getExceptionManager().handleException(e);
|
MinecraftServer.getExceptionManager().handleException(e);
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,5 @@
|
|||||||
package net.minestom.server.instance;
|
package net.minestom.server.instance;
|
||||||
|
|
||||||
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
|
|
||||||
import it.unimi.dsi.fastutil.longs.Long2ObjectMaps;
|
|
||||||
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
|
||||||
import net.minestom.server.MinecraftServer;
|
import net.minestom.server.MinecraftServer;
|
||||||
import net.minestom.server.data.Data;
|
import net.minestom.server.data.Data;
|
||||||
import net.minestom.server.data.SerializableData;
|
import net.minestom.server.data.SerializableData;
|
||||||
@ -34,6 +31,7 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
import java.util.concurrent.locks.Lock;
|
import java.util.concurrent.locks.Lock;
|
||||||
import java.util.concurrent.locks.ReadWriteLock;
|
import java.util.concurrent.locks.ReadWriteLock;
|
||||||
@ -56,7 +54,7 @@ public class InstanceContainer extends Instance {
|
|||||||
// the chunk generator used, can be null
|
// the chunk generator used, can be null
|
||||||
private ChunkGenerator chunkGenerator;
|
private ChunkGenerator chunkGenerator;
|
||||||
// (chunk index -> chunk) map, contains all the chunks in the instance
|
// (chunk index -> chunk) map, contains all the chunks in the instance
|
||||||
private final Long2ObjectMap<Chunk> chunks = Long2ObjectMaps.synchronize(new Long2ObjectOpenHashMap<>());
|
private final Map<Long, Chunk> chunks = new ConcurrentHashMap<>();
|
||||||
// contains all the chunks to remove during the next instance tick, should be synchronized
|
// contains all the chunks to remove during the next instance tick, should be synchronized
|
||||||
protected final Set<Chunk> scheduledChunksToRemove = new HashSet<>();
|
protected final Set<Chunk> scheduledChunksToRemove = new HashSet<>();
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ import net.minestom.server.utils.binary.BinaryReader;
|
|||||||
import net.minestom.server.utils.binary.BinaryWriter;
|
import net.minestom.server.utils.binary.BinaryWriter;
|
||||||
import net.minestom.server.utils.cache.CacheablePacket;
|
import net.minestom.server.utils.cache.CacheablePacket;
|
||||||
import net.minestom.server.utils.cache.TemporaryCache;
|
import net.minestom.server.utils.cache.TemporaryCache;
|
||||||
|
import net.minestom.server.utils.cache.TemporaryPacketCache;
|
||||||
import net.minestom.server.utils.cache.TimedBuffer;
|
import net.minestom.server.utils.cache.TimedBuffer;
|
||||||
import net.minestom.server.utils.chunk.ChunkUtils;
|
import net.minestom.server.utils.chunk.ChunkUtils;
|
||||||
import net.minestom.server.world.biomes.Biome;
|
import net.minestom.server.world.biomes.Biome;
|
||||||
@ -34,8 +35,7 @@ import java.util.concurrent.TimeUnit;
|
|||||||
public class ChunkDataPacket implements ServerPacket, CacheablePacket {
|
public class ChunkDataPacket implements ServerPacket, CacheablePacket {
|
||||||
|
|
||||||
private static final BlockManager BLOCK_MANAGER = MinecraftServer.getBlockManager();
|
private static final BlockManager BLOCK_MANAGER = MinecraftServer.getBlockManager();
|
||||||
private static final TemporaryCache<TimedBuffer> CACHE = new TemporaryCache<>(5, TimeUnit.MINUTES,
|
private static final TemporaryCache<TimedBuffer> CACHE = new TemporaryPacketCache(5, TimeUnit.MINUTES);
|
||||||
notification -> notification.getValue().getBuffer().release());
|
|
||||||
|
|
||||||
public boolean fullChunk;
|
public boolean fullChunk;
|
||||||
public Biome[] biomes;
|
public Biome[] biomes;
|
||||||
|
@ -6,6 +6,7 @@ import net.minestom.server.utils.binary.BinaryReader;
|
|||||||
import net.minestom.server.utils.binary.BinaryWriter;
|
import net.minestom.server.utils.binary.BinaryWriter;
|
||||||
import net.minestom.server.utils.cache.CacheablePacket;
|
import net.minestom.server.utils.cache.CacheablePacket;
|
||||||
import net.minestom.server.utils.cache.TemporaryCache;
|
import net.minestom.server.utils.cache.TemporaryCache;
|
||||||
|
import net.minestom.server.utils.cache.TemporaryPacketCache;
|
||||||
import net.minestom.server.utils.cache.TimedBuffer;
|
import net.minestom.server.utils.cache.TimedBuffer;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@ -17,8 +18,7 @@ import java.util.concurrent.TimeUnit;
|
|||||||
|
|
||||||
public class UpdateLightPacket implements ServerPacket, CacheablePacket {
|
public class UpdateLightPacket implements ServerPacket, CacheablePacket {
|
||||||
|
|
||||||
private static final TemporaryCache<TimedBuffer> CACHE = new TemporaryCache<>(5, TimeUnit.MINUTES,
|
private static final TemporaryCache<TimedBuffer> CACHE = new TemporaryPacketCache(5, TimeUnit.MINUTES);
|
||||||
notification -> notification.getValue().getBuffer().release());
|
|
||||||
|
|
||||||
public int chunkX;
|
public int chunkX;
|
||||||
public int chunkZ;
|
public int chunkZ;
|
||||||
@ -102,7 +102,7 @@ public class UpdateLightPacket implements ServerPacket, CacheablePacket {
|
|||||||
skyLight.clear();
|
skyLight.clear();
|
||||||
for (int i = 0; i < 14; i++) {
|
for (int i = 0; i < 14; i++) {
|
||||||
int length = reader.readVarInt();
|
int length = reader.readVarInt();
|
||||||
if(length != 2048) {
|
if (length != 2048) {
|
||||||
throw new IllegalStateException("Length must be 2048.");
|
throw new IllegalStateException("Length must be 2048.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,7 +114,7 @@ public class UpdateLightPacket implements ServerPacket, CacheablePacket {
|
|||||||
blockLight.clear();
|
blockLight.clear();
|
||||||
for (int i = 0; i < 6; i++) {
|
for (int i = 0; i < 6; i++) {
|
||||||
int length = reader.readVarInt();
|
int length = reader.readVarInt();
|
||||||
if(length != 2048) {
|
if (length != 2048) {
|
||||||
throw new IllegalStateException("Length must be 2048.");
|
throw new IllegalStateException("Length must be 2048.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,22 +71,6 @@ public class NettyPlayerConnection extends PlayerConnection {
|
|||||||
this.tickBuffer.ensureWritable(INITIAL_BUFFER_SIZE);
|
this.tickBuffer.ensureWritable(INITIAL_BUFFER_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void update() {
|
|
||||||
// Flush
|
|
||||||
final int bufferSize = tickBuffer.writerIndex();
|
|
||||||
if (bufferSize > 0) {
|
|
||||||
this.channel.eventLoop().submit(() -> {
|
|
||||||
if (channel.isActive()) {
|
|
||||||
writeWaitingPackets();
|
|
||||||
channel.flush();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// Network stats
|
|
||||||
super.update();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the encryption key and add the codecs to the pipeline.
|
* Sets the encryption key and add the codecs to the pipeline.
|
||||||
*
|
*
|
||||||
@ -196,7 +180,7 @@ public class NettyPlayerConnection extends PlayerConnection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeWaitingPackets() {
|
public void writeWaitingPackets() {
|
||||||
if (tickBuffer.writerIndex() == 0) {
|
if (tickBuffer.writerIndex() == 0) {
|
||||||
// Nothing to write
|
// Nothing to write
|
||||||
return;
|
return;
|
||||||
@ -221,6 +205,16 @@ public class NettyPlayerConnection extends PlayerConnection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void flush() {
|
||||||
|
final int bufferSize = tickBuffer.writerIndex();
|
||||||
|
if (bufferSize > 0) {
|
||||||
|
if (channel.isActive()) {
|
||||||
|
writeWaitingPackets();
|
||||||
|
channel.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public SocketAddress getRemoteAddress() {
|
public SocketAddress getRemoteAddress() {
|
||||||
|
@ -46,6 +46,9 @@ public interface CacheablePacket {
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
static FramedPacket getCache(@NotNull ServerPacket serverPacket) {
|
static FramedPacket getCache(@NotNull ServerPacket serverPacket) {
|
||||||
|
if (!(serverPacket instanceof CacheablePacket))
|
||||||
|
return null;
|
||||||
|
|
||||||
final CacheablePacket cacheablePacket = (CacheablePacket) serverPacket;
|
final CacheablePacket cacheablePacket = (CacheablePacket) serverPacket;
|
||||||
final UUID identifier = cacheablePacket.getIdentifier();
|
final UUID identifier = cacheablePacket.getIdentifier();
|
||||||
if (identifier == null) {
|
if (identifier == null) {
|
||||||
@ -72,4 +75,20 @@ public interface CacheablePacket {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void writeCache(@NotNull ByteBuf buffer, @NotNull ServerPacket serverPacket) {
|
||||||
|
FramedPacket framedPacket = CacheablePacket.getCache(serverPacket);
|
||||||
|
if (framedPacket == null) {
|
||||||
|
PacketUtils.writeFramedPacket(buffer, serverPacket);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final ByteBuf body = framedPacket.getBody();
|
||||||
|
synchronized (body) {
|
||||||
|
if (framedPacket.getBody().refCnt() != 0) {
|
||||||
|
buffer.writeBytes(body, body.readerIndex(), body.readableBytes());
|
||||||
|
} else {
|
||||||
|
PacketUtils.writeFramedPacket(buffer, serverPacket);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
16
src/main/java/net/minestom/server/utils/cache/TemporaryPacketCache.java
vendored
Normal file
16
src/main/java/net/minestom/server/utils/cache/TemporaryPacketCache.java
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package net.minestom.server.utils.cache;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
public class TemporaryPacketCache extends TemporaryCache<TimedBuffer> {
|
||||||
|
public TemporaryPacketCache(long duration, TimeUnit timeUnit) {
|
||||||
|
super(duration, timeUnit, notification -> {
|
||||||
|
final ByteBuf buffer = notification.getValue().getBuffer();
|
||||||
|
synchronized (buffer) {
|
||||||
|
buffer.release();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -37,6 +37,13 @@ public final class Check {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Contract("true, _, _ -> fail")
|
||||||
|
public static void argCondition(boolean condition, @NotNull String reason, Object... arguments) {
|
||||||
|
if (condition) {
|
||||||
|
throw new IllegalArgumentException(MessageFormat.format(reason, arguments));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Contract("_ -> fail")
|
@Contract("_ -> fail")
|
||||||
public static void fail(@NotNull String reason) {
|
public static void fail(@NotNull String reason) {
|
||||||
throw new IllegalArgumentException(reason);
|
throw new IllegalArgumentException(reason);
|
||||||
|
Loading…
Reference in New Issue
Block a user