From 1084b4aa3b601ef2ec9912a185358b81792a722d Mon Sep 17 00:00:00 2001 From: MrHua269 Date: Fri, 10 Jul 2026 21:51:55 +0800 Subject: [PATCH] CPU affinity for netty I/O threads --- .../0028-Add-config-for-cpu-affinity.patch | 14 +++++++++++ .../optimizations/CpuAffinityConfig.java | 24 +++++++++++++++++-- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/camellia-server/minecraft-patches/features/0028-Add-config-for-cpu-affinity.patch b/camellia-server/minecraft-patches/features/0028-Add-config-for-cpu-affinity.patch index 03b52e3..b959be1 100644 --- a/camellia-server/minecraft-patches/features/0028-Add-config-for-cpu-affinity.patch +++ b/camellia-server/minecraft-patches/features/0028-Add-config-for-cpu-affinity.patch @@ -17,3 +17,17 @@ index 5a72fa0d72bfdb927293abe921c57f6ae964a6ec..913161732b0affa70fb114dd4087a610 ret.setUncaughtExceptionHandler(TickRegionScheduler.this::uncaughtException); return ret; } +diff --git a/net/minecraft/server/network/EventLoopGroupHolder.java b/net/minecraft/server/network/EventLoopGroupHolder.java +index 9544eaee7e02d00226d957ea0b79cd1a1fb0c4d0..4e138fe36aa0bc519482990b60543b17ee2f388f 100644 +--- a/net/minecraft/server/network/EventLoopGroupHolder.java ++++ b/net/minecraft/server/network/EventLoopGroupHolder.java +@@ -98,7 +98,8 @@ public abstract class EventLoopGroupHolder { + } + + private ThreadFactory createThreadFactory() { +- return new ThreadFactoryBuilder().setNameFormat("Netty " + this.type + " IO #%d").setDaemon(true).setUncaughtExceptionHandler(new net.minecraft.DefaultUncaughtExceptionHandlerWithName(net.minecraft.server.MinecraftServer.LOGGER)).build(); // Paper ++ var origin = new ThreadFactoryBuilder().setNameFormat("Netty " + this.type + " IO #%d").setDaemon(true).setUncaughtExceptionHandler(new net.minecraft.DefaultUncaughtExceptionHandlerWithName(net.minecraft.server.MinecraftServer.LOGGER)).build(); // Paper // Camellia - Add config for cpu affinity ++ return run -> origin.newThread(moe.monnairealms.camellia.config.modules.optimizations.CpuAffinityConfig.wrapForNettyIo(run)); // Camellia - Add config for cpu affinity + } + + protected abstract IoHandlerFactory ioHandlerFactory(); diff --git a/camellia-server/src/main/java/moe/monnairealms/camellia/config/modules/optimizations/CpuAffinityConfig.java b/camellia-server/src/main/java/moe/monnairealms/camellia/config/modules/optimizations/CpuAffinityConfig.java index d22b8f5..3f19ce6 100644 --- a/camellia-server/src/main/java/moe/monnairealms/camellia/config/modules/optimizations/CpuAffinityConfig.java +++ b/camellia-server/src/main/java/moe/monnairealms/camellia/config/modules/optimizations/CpuAffinityConfig.java @@ -30,6 +30,8 @@ public class CpuAffinityConfig implements IConfigModule { @HotReloadUnsupported @ConfigInfo(name = "enable_for_chunksystem_io") public static boolean enabledForChunkSystemIo = false; + @ConfigInfo(name = "enable_for_netty_io") + public static boolean enableForNettyIo = false; @HotReloadUnsupported @ConfigInfo(name = "tickregion_affinity", comments = "The core number you want the tick region threads to bind on") @@ -49,6 +51,12 @@ public class CpuAffinityConfig implements IConfigModule { .stream() .mapToObj(String::valueOf) .toList(); + @HotReloadUnsupported + @ConfigInfo(name = "netty_io_affinity") + public static List nettyIoAffinity = Affinity.getAffinity() + .stream() + .mapToObj(String::valueOf) + .toList(); @DoNotLoad private static boolean inited = false; @@ -60,6 +68,8 @@ public class CpuAffinityConfig implements IConfigModule { public static AffinityRunnableWrapper chunkSystemWorkerRunnableWrapper; @DoNotLoad public static AffinityRunnableWrapper chunkSystemIoRunnableWrapper; + @DoNotLoad + public static AffinityRunnableWrapper nettyIoRunnableWrapper; public static Runnable wrapForTickRegion(Runnable in) { return tickRegionRunnableWrapper == null ? in : tickRegionRunnableWrapper.wrap(in); @@ -73,8 +83,17 @@ public class CpuAffinityConfig implements IConfigModule { return chunkSystemIoRunnableWrapper == null ? in : chunkSystemIoRunnableWrapper.wrap(in); } + public static Runnable wrapForNettyIo(Runnable in) { + return nettyIoRunnableWrapper == null ? in : nettyIoRunnableWrapper.wrap(in); + } + @Override public void onLoaded(CommentedFileConfig configInstance, @Nullable Set e) { + if (inited) { + return; + } + inited = true; + if (enabledForTickRegion) { tickRegionRunnableWrapper = new AffinityRunnableWrapper("tick_region", parseAffinity(tickRegionAffinity)); LOGGER.info("Tick region thread now bound to: {}", tickRegionRunnableWrapper.getAffinity()); @@ -90,8 +109,9 @@ public class CpuAffinityConfig implements IConfigModule { LOGGER.info("Chunk system worker thread now bound to: {}", chunkSystemIoRunnableWrapper.getAffinity()); } - if (!inited) { - inited = true; + if (enableForNettyIo) { + nettyIoRunnableWrapper = new AffinityRunnableWrapper("netty_io", parseAffinity(nettyIoAffinity)); + LOGGER.info("Netty I/O thread now bound to: {}", nettyIoRunnableWrapper.getAffinity()); } }