Merge pull request #100 from Kas-tle/feature/performance-improvements

Performance Improvements (Update to JDK 21, Fix Scheduler Excessively Ticking, & Use Virtual Threads)
This commit is contained in:
LOOHP 2025-12-19 00:46:24 +00:00 committed by GitHub
commit bde2c04127
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 76 additions and 70 deletions

59
pom.xml
View File

@ -24,7 +24,7 @@
<groupId>com.loohp</groupId> <groupId>com.loohp</groupId>
<artifactId>Limbo</artifactId> <artifactId>Limbo</artifactId>
<name>Limbo</name> <name>Limbo</name>
<version>0.7.17-ALPHA</version> <version>0.7.18-ALPHA</version>
<description>Standalone Limbo Minecraft Server.</description> <description>Standalone Limbo Minecraft Server.</description>
<url>https://github.com/LOOHP/Limbo</url> <url>https://github.com/LOOHP/Limbo</url>
@ -34,8 +34,8 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.build.number></project.build.number> <project.build.number></project.build.number>
<project.fullVersion>${project.version}</project.fullVersion> <project.fullVersion>${project.version}</project.fullVersion>
<maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target> <maven.compiler.target>21</maven.compiler.target>
</properties> </properties>
<build> <build>
@ -91,17 +91,17 @@
</plugin> </plugin>
<plugin> <plugin>
<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version> <version>3.14.0</version>
<configuration> <configuration>
<source>1.8</source> <source>21</source>
<target>1.8</target> <target>21</target>
<encoding>ISO-8859-1</encoding> <encoding>ISO-8859-1</encoding>
</configuration> </configuration>
</plugin> </plugin>
<plugin> <plugin>
<artifactId>maven-javadoc-plugin</artifactId> <artifactId>maven-javadoc-plugin</artifactId>
<version>3.2.0</version> <version>3.11.2</version>
<configuration> <configuration>
<failOnError>false</failOnError> <failOnError>false</failOnError>
<encoding>ISO-8859-1</encoding> <encoding>ISO-8859-1</encoding>
@ -124,7 +124,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId> <artifactId>maven-source-plugin</artifactId>
<version>3.2.0</version> <version>3.3.1</version>
<executions> <executions>
<execution> <execution>
<id>attach-sources</id> <id>attach-sources</id>
@ -170,7 +170,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId> <artifactId>maven-source-plugin</artifactId>
<version>3.2.1</version> <version>3.3.1</version>
<configuration> <configuration>
<encoding>${project.build.sourceEncoding}</encoding> <encoding>${project.build.sourceEncoding}</encoding>
</configuration> </configuration>
@ -187,7 +187,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId> <artifactId>maven-javadoc-plugin</artifactId>
<version>3.2.0</version> <version>3.11.2</version>
<configuration> <configuration>
<encoding>${project.build.sourceEncoding}</encoding> <encoding>${project.build.sourceEncoding}</encoding>
</configuration> </configuration>
@ -206,47 +206,39 @@
</profiles> </profiles>
<repositories> <repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
<repository>
<id>sonatype-oss-snapshots1</id>
<url>https://s01.oss.sonatype.org/content/repositories/snapshots/</url>
</repository>
<repository>
<id>bungeecord-repo</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</repository>
<repository> <repository>
<id>maven_central</id> <id>maven_central</id>
<name>Maven Central</name> <name>Maven Central</name>
<url>https://repo.maven.apache.org/maven2/</url> <url>https://repo.maven.apache.org/maven2/</url>
</repository> </repository>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories> </repositories>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.apache.commons</groupId> <groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId> <artifactId>commons-lang3</artifactId>
<version>3.14.0</version> <version>3.18.0</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.github.Querz</groupId> <groupId>com.github.Querz</groupId>
<artifactId>NBT</artifactId> <artifactId>NBT</artifactId>
<version>5.5</version> <version>6.1</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.google.code.gson</groupId> <groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId> <artifactId>gson</artifactId>
<version>2.10.1</version> <version>2.13.1</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.yaml</groupId> <groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId> <artifactId>snakeyaml</artifactId>
<version>2.3</version> <version>2.4</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
@ -258,7 +250,14 @@
<dependency> <dependency>
<groupId>net.md-5</groupId> <groupId>net.md-5</groupId>
<artifactId>bungeecord-chat</artifactId> <artifactId>bungeecord-chat</artifactId>
<version>1.18-R0.1-SNAPSHOT</version> <version>1.21-R0.3</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-serializer</artifactId>
<version>1.21-R0.3</version>
<type>jar</type> <type>jar</type>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
@ -295,19 +294,19 @@
<dependency> <dependency>
<groupId>org.fusesource.jansi</groupId> <groupId>org.fusesource.jansi</groupId>
<artifactId>jansi</artifactId> <artifactId>jansi</artifactId>
<version>1.18</version> <version>2.4.2</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.jline</groupId> <groupId>org.jline</groupId>
<artifactId>jline</artifactId> <artifactId>jline</artifactId>
<version>3.16.0</version> <version>3.30.5</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>jline</groupId> <groupId>jline</groupId>
<artifactId>jline</artifactId> <artifactId>jline</artifactId>
<version>2.11</version> <version>2.14.6</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@ -118,7 +118,7 @@ public class Console implements CommandSender {
reader.setExpandEvents(false); reader.setExpandEvents(false);
reader.setHandleUserInterrupt(false); reader.setHandleUserInterrupt(false);
terminal = TerminalBuilder.builder().streams(in, out).system(true).jansi(true).build(); terminal = TerminalBuilder.builder().streams(in, out).jansi(true).build();
tabReader = LineReaderBuilder.builder().terminal(terminal).completer(new Completer() { tabReader = LineReaderBuilder.builder().terminal(terminal).completer(new Completer() {
@Override @Override
public void complete(LineReader reader, ParsedLine line, List<Candidate> candidates) { public void complete(LineReader reader, ParsedLine line, List<Candidate> candidates) {

View File

@ -21,12 +21,12 @@ package com.loohp.limbo.consolegui;
import com.loohp.limbo.Limbo; import com.loohp.limbo.Limbo;
import java.lang.management.ManagementFactory;
import java.text.NumberFormat; import java.text.NumberFormat;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
public class SystemInfo { public class SystemInfo {
@SuppressWarnings("InfiniteLoopStatement")
public static void printInfo() { public static void printInfo() {
if (!Limbo.noGui) { if (!Limbo.noGui) {
while (true) { while (true) {
@ -47,11 +47,11 @@ public class SystemInfo {
try { try {
@SuppressWarnings("restriction") @SuppressWarnings("restriction")
com.sun.management.OperatingSystemMXBean operatingSystemMXBean = (com.sun.management.OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean(); com.sun.management.OperatingSystemMXBean operatingSystemMXBean = (com.sun.management.OperatingSystemMXBean) java.lang.management.ManagementFactory.getOperatingSystemMXBean();
@SuppressWarnings("restriction") @SuppressWarnings("restriction")
double processLoad = operatingSystemMXBean.getProcessCpuLoad(); double processLoad = operatingSystemMXBean.getProcessCpuLoad();
@SuppressWarnings("restriction") @SuppressWarnings("restriction")
double systemLoad = operatingSystemMXBean.getSystemCpuLoad(); double systemLoad = operatingSystemMXBean.getCpuLoad();
int processors = runtime.availableProcessors(); int processors = runtime.availableProcessors();
sb.append("Available Processors: ").append(processors).append("\n"); sb.append("Available Processors: ").append(processors).append("\n");

View File

@ -149,15 +149,18 @@ import java.util.TimerTask;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class ClientConnection extends Thread { public class ClientConnection implements Runnable {
private static final Key DEFAULT_HANDLER_NAMESPACE = Key.key("default"); private static final Key DEFAULT_HANDLER_NAMESPACE = Key.key("default");
private static final String BRAND_ANNOUNCE_CHANNEL = Key.key("brand").toString(); private static final String BRAND_ANNOUNCE_CHANNEL = Key.key("brand").toString();
private final Random random = new Random(); private final Random random = new Random();
private final Socket clientSocket; private final Socket clientSocket;
private final Lock packetSendLock = new ReentrantLock();
protected Channel channel; protected Channel channel;
private boolean running; private boolean running;
private volatile ClientState state; private volatile ClientState state;
@ -239,10 +242,15 @@ public class ClientConnection extends Thread {
sendPacket(packet); sendPacket(packet);
} }
public synchronized void sendPacket(PacketOut packet) throws IOException { public void sendPacket(PacketOut packet) throws IOException {
packetSendLock.lock();
try {
if (channel.writePacket(packet)) { if (channel.writePacket(packet)) {
setLastPacketTimestamp(System.currentTimeMillis()); setLastPacketTimestamp(System.currentTimeMillis());
} }
} finally {
packetSendLock.unlock();
}
} }
public void disconnect(BaseComponent[] reason) { public void disconnect(BaseComponent[] reason) {

View File

@ -27,23 +27,29 @@ import java.net.ServerSocket;
import java.net.Socket; import java.net.Socket;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ServerConnection extends Thread { public class ServerConnection extends Thread {
private final String ip; private final String ip;
private final int port; private final int port;
private final boolean silent; private final boolean silent;
private final ExecutorService executorService;
private final List<ClientConnection> clients;
private ServerSocket serverSocket; private ServerSocket serverSocket;
private List<ClientConnection> clients;
public ServerConnection(String ip, int port, boolean silent) { public ServerConnection(String ip, int port, boolean silent) {
this.clients = new ArrayList<>(); this.clients = new ArrayList<>();
this.ip = ip; this.ip = ip;
this.port = port; this.port = port;
this.silent = silent; this.silent = silent;
this.executorService = Executors.newVirtualThreadPerTaskExecutor();
start(); start();
} }
@SuppressWarnings("InfiniteLoopStatement")
@Override @Override
public void run() { public void run() {
try { try {
@ -53,9 +59,9 @@ public class ServerConnection extends Thread {
} }
while (true) { while (true) {
Socket connection = serverSocket.accept(); Socket connection = serverSocket.accept();
ClientConnection sc = new ClientConnection(connection); ClientConnection clientTask = new ClientConnection(connection);
clients.add(sc); clients.add(clientTask);
sc.start(); executorService.submit(clientTask);
} }
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();

View File

@ -26,8 +26,8 @@ import com.loohp.limbo.scheduler.LimboScheduler.LimboSchedulerTask;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Queue; import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
@ -37,7 +37,7 @@ public class Tick {
private AtomicLong tick = new AtomicLong(0); private AtomicLong tick = new AtomicLong(0);
private List<Thread> threads = new ArrayList<>(); private List<Thread> threads = new ArrayList<>();
private Queue<LimboSchedulerTask> asyncTasksQueue = new ConcurrentLinkedQueue<>(); private BlockingQueue<LimboSchedulerTask> asyncTasksQueue = new LinkedBlockingQueue<>();
public Tick(Limbo instance) { public Tick(Limbo instance) {
new Thread(() -> { new Thread(() -> {
@ -46,14 +46,8 @@ public class Tick {
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
Thread thread = new Thread(() -> { Thread thread = new Thread(() -> {
while (instance.isRunning()) { while (instance.isRunning()) {
LimboSchedulerTask task = asyncTasksQueue.poll();
if (task == null) {
try { try {
TimeUnit.NANOSECONDS.sleep(10000); LimboSchedulerTask task = asyncTasksQueue.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
LimboTask limboTask = task.getTask(); LimboTask limboTask = task.getTask();
try { try {
limboTask.run(); limboTask.run();
@ -61,6 +55,9 @@ public class Tick {
System.err.println("Task " + task.getTaskId() + " threw an exception: " + e.getLocalizedMessage()); System.err.println("Task " + task.getTaskId() + " threw an exception: " + e.getLocalizedMessage());
e.printStackTrace(); e.printStackTrace();
} }
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
e.printStackTrace();
} }
} }
}); });
@ -124,7 +121,6 @@ public class Tick {
return tick.get(); return tick.get();
} }
@SuppressWarnings("deprecation")
public void waitAndKillThreads(long waitTime) { public void waitAndKillThreads(long waitTime) {
long end = System.currentTimeMillis() + waitTime; long end = System.currentTimeMillis() + waitTime;
for (Thread thread : threads) { for (Thread thread : threads) {
@ -133,9 +129,6 @@ public class Tick {
} catch (InterruptedException e) { } catch (InterruptedException e) {
e.printStackTrace(); e.printStackTrace();
} }
if (thread.isAlive()) {
thread.stop();
}
} }
} }

View File

@ -97,7 +97,7 @@ public class Schematic {
CompoundTag heightMap = new CompoundTag(); CompoundTag heightMap = new CompoundTag();
heightMap.putLongArray("MOTION_BLOCKING", new long[] {1371773531765642314L,1389823183635651148L,1371738278539598925L,1389823183635388492L,1353688558756731469L,1389823114781694027L,1317765589597723213L,1371773531899860042L,1389823183635651149L,1371773462911685197L,1389823183635650636L,1353688626805119565L,1371773531900123211L,1335639250618849869L,1371738278674077258L,1389823114781694028L,1353723811310638154L,1371738278674077259L,1335674228429068364L,1335674228429067338L,1335674228698027594L,1317624576693539402L,1335709481520370249L,1299610178184057417L,1335638906349064264L,1299574993811968586L,1299574924958011464L,1299610178184056904L,1299574924958011464L,1299610109330100296L,1299574924958011464L,1299574924823793736L,1299574924958011465L,1281525273222484040L,1299574924958011464L,1281525273222484040L,9548107335L}); heightMap.putLongArray("MOTION_BLOCKING", new long[] {1371773531765642314L,1389823183635651148L,1371738278539598925L,1389823183635388492L,1353688558756731469L,1389823114781694027L,1317765589597723213L,1371773531899860042L,1389823183635651149L,1371773462911685197L,1389823183635650636L,1353688626805119565L,1371773531900123211L,1335639250618849869L,1371738278674077258L,1389823114781694028L,1353723811310638154L,1371738278674077259L,1335674228429068364L,1335674228429067338L,1335674228698027594L,1317624576693539402L,1335709481520370249L,1299610178184057417L,1335638906349064264L,1299574993811968586L,1299574924958011464L,1299610178184056904L,1299574924958011464L,1299610109330100296L,1299574924958011464L,1299574924823793736L,1299574924958011465L,1281525273222484040L,1299574924958011464L,1281525273222484040L,9548107335L});
chunk.setHeightMaps(heightMap); chunk.setHeightMaps(heightMap);
chunk.setBiomes(new int[256]); chunk.setBiomes(new int[1024]);
chunk.cleanupPalettesAndBlockStates(); chunk.cleanupPalettesAndBlockStates();
} }
} }

View File

@ -64,7 +64,7 @@ public class World {
EMPTY_CHUNK.cleanupPalettesAndBlockStates(); EMPTY_CHUNK.cleanupPalettesAndBlockStates();
EMPTY_CHUNK.setHeightMaps(HEIGHT_MAP.clone()); EMPTY_CHUNK.setHeightMaps(HEIGHT_MAP.clone());
EMPTY_CHUNK.setBiomes(new int[256]); EMPTY_CHUNK.setBiomes(new int[1024]);
EMPTY_CHUNK.setTileEntities(new ListTag<>(CompoundTag.class)); EMPTY_CHUNK.setTileEntities(new ListTag<>(CompoundTag.class));
} }
@ -90,7 +90,7 @@ public class World {
Chunk chunk = chunks[x][z]; Chunk chunk = chunks[x][z];
chunk.cleanupPalettesAndBlockStates(); chunk.cleanupPalettesAndBlockStates();
chunk.setHeightMaps(HEIGHT_MAP.clone()); chunk.setHeightMaps(HEIGHT_MAP.clone());
chunk.setBiomes(new int[256]); chunk.setBiomes(new int[1024]);
chunk.setTileEntities(new ListTag<>(CompoundTag.class)); chunk.setTileEntities(new ListTag<>(CompoundTag.class));
} }
} }