mirror of
https://github.com/Minestom/Minestom.git
synced 2025-03-09 13:19:05 +01:00
Allow custom Netty thread count
This commit is contained in:
parent
cabdb60370
commit
415bcda6fd
@ -97,6 +97,7 @@ public final class MinecraftServer {
|
|||||||
private static PacketListenerManager packetListenerManager;
|
private static PacketListenerManager packetListenerManager;
|
||||||
private static PacketProcessor packetProcessor;
|
private static PacketProcessor packetProcessor;
|
||||||
private static NettyServer nettyServer;
|
private static NettyServer nettyServer;
|
||||||
|
private static int nettyThreadCount = Runtime.getRuntime().availableProcessors();
|
||||||
private static boolean processNettyErrors = true;
|
private static boolean processNettyErrors = true;
|
||||||
|
|
||||||
// In-Game Manager
|
// In-Game Manager
|
||||||
@ -626,6 +627,28 @@ public final class MinecraftServer {
|
|||||||
return updateManager;
|
return updateManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the number of threads used by Netty.
|
||||||
|
* <p>
|
||||||
|
* Is the number of vCPU by default.
|
||||||
|
*
|
||||||
|
* @return the number of netty threads
|
||||||
|
*/
|
||||||
|
public static int getNettyThreadCount() {
|
||||||
|
return nettyThreadCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes the number of threads used by Netty.
|
||||||
|
*
|
||||||
|
* @param nettyThreadCount the number of threads
|
||||||
|
* @throws IllegalStateException if the server is already started
|
||||||
|
*/
|
||||||
|
public static void setNettyThreadCount(int nettyThreadCount) {
|
||||||
|
Check.stateCondition(started, "Netty thread count can only be changed before the server starts!");
|
||||||
|
MinecraftServer.nettyThreadCount = nettyThreadCount;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets if the server should process netty errors and other unnecessary netty events
|
* Gets if the server should process netty errors and other unnecessary netty events
|
||||||
*
|
*
|
||||||
@ -659,21 +682,27 @@ public final class MinecraftServer {
|
|||||||
Check.stateCondition(!initialized, "#start can only be called after #init");
|
Check.stateCondition(!initialized, "#start can only be called after #init");
|
||||||
Check.stateCondition(started, "The server is already started");
|
Check.stateCondition(started, "The server is already started");
|
||||||
|
|
||||||
|
MinecraftServer.started = true;
|
||||||
|
|
||||||
LOGGER.info("Starting Minestom server.");
|
LOGGER.info("Starting Minestom server.");
|
||||||
MinecraftServer.responseDataConsumer = responseDataConsumer;
|
MinecraftServer.responseDataConsumer = responseDataConsumer;
|
||||||
|
|
||||||
updateManager.start();
|
updateManager.start();
|
||||||
|
|
||||||
|
// Init & start the TCP server
|
||||||
|
nettyServer.init();
|
||||||
nettyServer.start(address, port);
|
nettyServer.start(address, port);
|
||||||
long t1 = -System.nanoTime();
|
|
||||||
|
final long t1 = -System.nanoTime();
|
||||||
// Init extensions
|
// Init extensions
|
||||||
// TODO: Extensions should handle depending on each other and have a load-order.
|
// TODO: Extensions should handle depending on each other and have a load-order.
|
||||||
extensionManager.getExtensions().forEach(Extension::preInitialize);
|
extensionManager.getExtensions().forEach(Extension::preInitialize);
|
||||||
extensionManager.getExtensions().forEach(Extension::initialize);
|
extensionManager.getExtensions().forEach(Extension::initialize);
|
||||||
extensionManager.getExtensions().forEach(Extension::postInitialize);
|
extensionManager.getExtensions().forEach(Extension::postInitialize);
|
||||||
|
|
||||||
MinecraftServer.started = true;
|
|
||||||
|
|
||||||
final double loadTime = MathUtils.round((t1 + System.nanoTime()) / 1_000_000D, 2);
|
final double loadTime = MathUtils.round((t1 + System.nanoTime()) / 1_000_000D, 2);
|
||||||
LOGGER.info("Extensions loaded in " + loadTime + "ms");
|
LOGGER.info("Extensions loaded in " + loadTime + "ms");
|
||||||
|
|
||||||
LOGGER.info("Minestom server started successfully.");
|
LOGGER.info("Minestom server started successfully.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ import net.minestom.server.MinecraftServer;
|
|||||||
import net.minestom.server.network.PacketProcessor;
|
import net.minestom.server.network.PacketProcessor;
|
||||||
import net.minestom.server.network.netty.channel.ClientChannel;
|
import net.minestom.server.network.netty.channel.ClientChannel;
|
||||||
import net.minestom.server.network.netty.codec.*;
|
import net.minestom.server.network.netty.codec.*;
|
||||||
|
import net.minestom.server.utils.validate.Check;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@ -55,15 +56,19 @@ public final class NettyServer {
|
|||||||
public static final String ENCODER_HANDLER_NAME = "encoder"; // Write
|
public static final String ENCODER_HANDLER_NAME = "encoder"; // Write
|
||||||
public static final String CLIENT_CHANNEL_NAME = "handler"; // Read
|
public static final String CLIENT_CHANNEL_NAME = "handler"; // Read
|
||||||
|
|
||||||
private final EventLoopGroup boss, worker;
|
private boolean initialized = false;
|
||||||
private final ServerBootstrap bootstrap;
|
|
||||||
|
private PacketProcessor packetProcessor;
|
||||||
|
|
||||||
|
private EventLoopGroup boss, worker;
|
||||||
|
private ServerBootstrap bootstrap;
|
||||||
|
|
||||||
private ServerSocketChannel serverChannel;
|
private ServerSocketChannel serverChannel;
|
||||||
|
|
||||||
private String address;
|
private String address;
|
||||||
private int port;
|
private int port;
|
||||||
|
|
||||||
private final GlobalChannelTrafficShapingHandler globalTrafficHandler;
|
private GlobalChannelTrafficShapingHandler globalTrafficHandler;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scheduler used by {@code globalTrafficHandler}.
|
* Scheduler used by {@code globalTrafficHandler}.
|
||||||
@ -71,32 +76,48 @@ public final class NettyServer {
|
|||||||
private final ScheduledExecutorService trafficScheduler = Executors.newScheduledThreadPool(1);
|
private final ScheduledExecutorService trafficScheduler = Executors.newScheduledThreadPool(1);
|
||||||
|
|
||||||
public NettyServer(@NotNull PacketProcessor packetProcessor) {
|
public NettyServer(@NotNull PacketProcessor packetProcessor) {
|
||||||
|
this.packetProcessor = packetProcessor;
|
||||||
|
|
||||||
|
this.globalTrafficHandler = new GlobalChannelTrafficShapingHandler(trafficScheduler, 200) {
|
||||||
|
@Override
|
||||||
|
protected void doAccounting(TrafficCounter counter) {
|
||||||
|
// TODO proper monitoring API
|
||||||
|
//System.out.println("data " + counter.lastWriteThroughput() / 1000 + " " + counter.lastReadThroughput() / 1000);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init() {
|
||||||
|
Check.stateCondition(initialized, "Netty server has already been initialized!");
|
||||||
|
initialized = true;
|
||||||
|
|
||||||
Class<? extends ServerChannel> channel;
|
Class<? extends ServerChannel> channel;
|
||||||
|
final int workerThreadCount = MinecraftServer.getNettyThreadCount();
|
||||||
|
|
||||||
if (IOUring.isAvailable()) {
|
if (IOUring.isAvailable()) {
|
||||||
boss = new IOUringEventLoopGroup(2);
|
boss = new IOUringEventLoopGroup(2);
|
||||||
worker = new IOUringEventLoopGroup(); // thread count = core * 2
|
worker = new IOUringEventLoopGroup(workerThreadCount);
|
||||||
|
|
||||||
channel = IOUringServerSocketChannel.class;
|
channel = IOUringServerSocketChannel.class;
|
||||||
|
|
||||||
LOGGER.info("Using io_uring");
|
LOGGER.info("Using io_uring");
|
||||||
} else if (Epoll.isAvailable()) {
|
} else if (Epoll.isAvailable()) {
|
||||||
boss = new EpollEventLoopGroup(2);
|
boss = new EpollEventLoopGroup(2);
|
||||||
worker = new EpollEventLoopGroup(); // thread count = core * 2
|
worker = new EpollEventLoopGroup(workerThreadCount);
|
||||||
|
|
||||||
channel = EpollServerSocketChannel.class;
|
channel = EpollServerSocketChannel.class;
|
||||||
|
|
||||||
LOGGER.info("Using epoll");
|
LOGGER.info("Using epoll");
|
||||||
} else if (KQueue.isAvailable()) {
|
} else if (KQueue.isAvailable()) {
|
||||||
boss = new KQueueEventLoopGroup(2);
|
boss = new KQueueEventLoopGroup(2);
|
||||||
worker = new KQueueEventLoopGroup(); // thread count = core * 2
|
worker = new KQueueEventLoopGroup(workerThreadCount);
|
||||||
|
|
||||||
channel = KQueueServerSocketChannel.class;
|
channel = KQueueServerSocketChannel.class;
|
||||||
|
|
||||||
LOGGER.info("Using kqueue");
|
LOGGER.info("Using kqueue");
|
||||||
} else {
|
} else {
|
||||||
boss = new NioEventLoopGroup(2);
|
boss = new NioEventLoopGroup(2);
|
||||||
worker = new NioEventLoopGroup(); // thread count = core * 2
|
worker = new NioEventLoopGroup(workerThreadCount);
|
||||||
|
|
||||||
channel = NioServerSocketChannel.class;
|
channel = NioServerSocketChannel.class;
|
||||||
|
|
||||||
@ -107,14 +128,6 @@ public final class NettyServer {
|
|||||||
.group(boss, worker)
|
.group(boss, worker)
|
||||||
.channel(channel);
|
.channel(channel);
|
||||||
|
|
||||||
this.globalTrafficHandler = new GlobalChannelTrafficShapingHandler(trafficScheduler, 200) {
|
|
||||||
@Override
|
|
||||||
protected void doAccounting(TrafficCounter counter) {
|
|
||||||
// TODO proper monitoring API
|
|
||||||
//System.out.println("data " + counter.lastWriteThroughput() / 1000 + " " + counter.lastReadThroughput() / 1000);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
|
bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
|
||||||
protected void initChannel(@NotNull SocketChannel ch) {
|
protected void initChannel(@NotNull SocketChannel ch) {
|
||||||
|
Loading…
Reference in New Issue
Block a user