mirror of
https://github.com/Winds-Studio/Leaf.git
synced 2025-12-26 02:19:19 +00:00
Auto resize tracker thread pool (#208)
* Cleanup sort * auto resize * Limit queue size and add RejectedExecutionHandler * Flush queue on task rejection * Move to inner class * Math.max to choose higher one
This commit is contained in:
@@ -14,37 +14,63 @@ import net.minecraft.world.entity.Entity;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
public class MultithreadedTracker {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger("MultithreadedTracker");
|
||||
|
||||
private static long lastWarnMillis = System.currentTimeMillis();
|
||||
|
||||
public static class MultithreadedTrackerThread extends Thread {
|
||||
@Override
|
||||
public void run() {
|
||||
super.run();
|
||||
}
|
||||
}
|
||||
private static final Executor trackerExecutor = new ThreadPoolExecutor(
|
||||
1,
|
||||
org.dreeam.leaf.config.modules.async.MultithreadedTracker.asyncEntityTrackerMaxThreads,
|
||||
org.dreeam.leaf.config.modules.async.MultithreadedTracker.asyncEntityTrackerKeepalive, TimeUnit.SECONDS,
|
||||
new LinkedBlockingQueue<>(),
|
||||
new ThreadFactoryBuilder()
|
||||
.setThreadFactory(
|
||||
r -> new MultithreadedTrackerThread() {
|
||||
@Override
|
||||
public void run() {
|
||||
r.run();
|
||||
}
|
||||
}
|
||||
)
|
||||
.setNameFormat("Leaf Async Tracker Thread - %d")
|
||||
.setPriority(Thread.NORM_PRIORITY - 2)
|
||||
.build());
|
||||
|
||||
static class RejectedTrackingTaskHandler implements RejectedExecutionHandler {
|
||||
@Override
|
||||
public void rejectedExecution(Runnable rejectedTask, ThreadPoolExecutor executor) {
|
||||
BlockingQueue<Runnable> workQueue = executor.getQueue();
|
||||
if (!executor.isShutdown()) {
|
||||
if (!workQueue.isEmpty()) {
|
||||
List<Runnable> pendingTasks = new ArrayList<>(workQueue.size());
|
||||
workQueue.drainTo(pendingTasks);
|
||||
for (Runnable pendingTask : pendingTasks) {
|
||||
pendingTask.run();
|
||||
}
|
||||
}
|
||||
rejectedTask.run();
|
||||
}
|
||||
if (System.currentTimeMillis() - lastWarnMillis > 30000L) {
|
||||
LOGGER.warn("Async entity tracker is busy! Tracking tasks will be done in the server thread. Increasing max-threads in Leaf config may help.");
|
||||
lastWarnMillis = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final ThreadPoolExecutor trackerExecutor = new ThreadPoolExecutor(
|
||||
1,
|
||||
org.dreeam.leaf.config.modules.async.MultithreadedTracker.autoResize ? Integer.MAX_VALUE : org.dreeam.leaf.config.modules.async.MultithreadedTracker.asyncEntityTrackerMaxThreads,
|
||||
org.dreeam.leaf.config.modules.async.MultithreadedTracker.autoResize ? 30L : org.dreeam.leaf.config.modules.async.MultithreadedTracker.asyncEntityTrackerKeepalive, TimeUnit.SECONDS,
|
||||
org.dreeam.leaf.config.modules.async.MultithreadedTracker.autoResize ? new SynchronousQueue<>() : new LinkedBlockingQueue<>(org.dreeam.leaf.config.modules.async.MultithreadedTracker.asyncEntityTrackerMaxThreads * (Math.max(org.dreeam.leaf.config.modules.async.MultithreadedTracker.asyncEntityTrackerMaxThreads, 4))),
|
||||
new ThreadFactoryBuilder()
|
||||
.setThreadFactory(
|
||||
r -> new MultithreadedTrackerThread() {
|
||||
@Override
|
||||
public void run() {
|
||||
r.run();
|
||||
}
|
||||
}
|
||||
)
|
||||
.setNameFormat("Leaf Async Tracker Thread - %d")
|
||||
.setPriority(Thread.NORM_PRIORITY - 2)
|
||||
.build(),
|
||||
new RejectedTrackingTaskHandler()
|
||||
);
|
||||
|
||||
private MultithreadedTracker() {
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ public class MultithreadedTracker extends ConfigModules {
|
||||
|
||||
public static boolean enabled = false;
|
||||
public static boolean compatModeEnabled = false;
|
||||
public static boolean autoResize = false;
|
||||
public static int asyncEntityTrackerMaxThreads = 0;
|
||||
public static int asyncEntityTrackerKeepalive = 60;
|
||||
|
||||
@@ -24,7 +25,7 @@ public class MultithreadedTracker extends ConfigModules {
|
||||
异步实体跟踪,
|
||||
在实体数量多且密集的情况下效果明显.""");
|
||||
|
||||
enabled = config().getBoolean(getBasePath() + ".enabled", enabled);
|
||||
enabled = config.getBoolean(getBasePath() + ".enabled", enabled);
|
||||
compatModeEnabled = config.getBoolean(getBasePath() + ".compat-mode", compatModeEnabled, config.pickStringRegionBased("""
|
||||
Enable compat mode ONLY if Citizens or NPC plugins using real entity has installed,
|
||||
Compat mode fixed visible issue with player type NPCs of Citizens,
|
||||
@@ -32,6 +33,14 @@ public class MultithreadedTracker extends ConfigModules {
|
||||
"""
|
||||
是否启用兼容模式,
|
||||
如果你的服务器安装了 Citizens 或其他类似非发包 NPC 插件, 请开启此项."""));
|
||||
autoResize = config.getBoolean(getBasePath() + ".auto-resize", autoResize, config.pickStringRegionBased("""
|
||||
Auto adjust thread pool size based on server load,
|
||||
This will tweak thread pool size dynamically,
|
||||
overrides max-threads and keepalive.""",
|
||||
"""
|
||||
根据服务器负载自动调整线程池大小,
|
||||
这会使线程池大小动态调整,
|
||||
覆盖设置 max-threads 和 keepalive."""));
|
||||
asyncEntityTrackerMaxThreads = config.getInt(getBasePath() + ".max-threads", asyncEntityTrackerMaxThreads);
|
||||
asyncEntityTrackerKeepalive = config.getInt(getBasePath() + ".keepalive", asyncEntityTrackerKeepalive);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user