From 016fc662934babe4f9dd60d20f797666c1136588 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sat, 13 Dec 2025 16:46:59 -0600 Subject: [PATCH] Print a warning if G1GC is used G1GC is known to cause stuttering --- .../distanthorizons/core/Initializer.java | 7 --- .../core/api/internal/ClientApi.java | 51 ++++++++++++++++++- .../distanthorizons/core/config/Config.java | 9 ++++ .../assets/distanthorizons/lang/en_us.json | 2 + 4 files changed, 60 insertions(+), 9 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/Initializer.java b/core/src/main/java/com/seibel/distanthorizons/core/Initializer.java index 97795fec7..3ff6daabb 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/Initializer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/Initializer.java @@ -25,23 +25,16 @@ import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.render.renderer.generic.GenericRenderObjectFactory; import com.seibel.distanthorizons.core.sql.DatabaseUpdater; import com.seibel.distanthorizons.core.wrapperInterfaces.IWrapperFactory; -import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper; -import com.seibel.distanthorizons.coreapi.ModInfo; import com.seibel.distanthorizons.core.world.DhApiWorldProxy; import com.seibel.distanthorizons.core.api.external.methods.config.DhApiConfig; import com.seibel.distanthorizons.core.api.external.methods.data.DhApiTerrainDataRepo; import com.seibel.distanthorizons.api.DhApi; import com.seibel.distanthorizons.core.render.DhApiRenderProxy; import net.jpountz.lz4.LZ4FrameOutputStream; -import org.apache.logging.log4j.LogManager; import com.seibel.distanthorizons.core.logging.DhLogger; import org.sqlite.SQLiteJDBCLoader; -import org.sqlite.util.OSInfo; import org.tukaani.xz.XZOutputStream; -import java.awt.*; -import java.io.File; - /** Handles first time Core setup. */ public class Initializer { diff --git a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ClientApi.java b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ClientApi.java index fdda74238..7370d52f5 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ClientApi.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ClientApi.java @@ -56,6 +56,8 @@ import org.jetbrains.annotations.Nullable; import org.lwjgl.glfw.GLFW; import java.io.File; +import java.lang.management.GarbageCollectorMXBean; +import java.lang.management.ManagementFactory; import java.util.*; import java.util.concurrent.LinkedBlockingQueue; @@ -93,6 +95,7 @@ public class ClientApi private boolean isDevBuildMessagePrinted = false; private boolean lowMemoryWarningPrinted = false; private boolean highVanillaRenderDistanceWarningPrinted = false; + private boolean g1GarbageCollectorWarningPrinted = false; private long lastStaticWarningMessageSentMsTime = 0L; @@ -645,7 +648,8 @@ public class ClientApi { // dev build if (ModInfo.IS_DEV_BUILD - && !this.isDevBuildMessagePrinted && MC_CLIENT.playerExists()) + && !this.isDevBuildMessagePrinted + && MC_CLIENT.playerExists()) { this.isDevBuildMessagePrinted = true; this.lastStaticWarningMessageSentMsTime = System.currentTimeMillis(); @@ -691,10 +695,11 @@ public class ClientApi if (!this.highVanillaRenderDistanceWarningPrinted && Config.Common.Logging.Warning.showHighVanillaRenderDistanceWarning.get()) { + this.highVanillaRenderDistanceWarningPrinted = true; + // DH generally doesn't need a vanilla render distance above 12 if (MC_RENDER.getRenderDistance() > 12) { - this.highVanillaRenderDistanceWarningPrinted = true; this.lastStaticWarningMessageSentMsTime = System.currentTimeMillis(); String message = @@ -710,6 +715,48 @@ public class ClientApi MC_CLIENT.sendChatMessage(message); } } + + + // print a warning if G1GC is being used + // (this garbage collector is known to cause stuttering) + if (this.staticStartupMessageSentRecently()) return; + if (!this.g1GarbageCollectorWarningPrinted + && Config.Common.Logging.Warning.showGarbageCollectorWarning.get()) + { + this.g1GarbageCollectorWarningPrinted = true; + + try + { + boolean g1GcInUse = false; + + List gcMxBeans = ManagementFactory.getGarbageCollectorMXBeans(); + for (GarbageCollectorMXBean gcMxBean : gcMxBeans) + { + // "G1 Young Generation" // "G1 Concurrent GC" // "G1 Old Generation" + if (gcMxBean.getName().toLowerCase().contains("g1 ")) + { + g1GcInUse = true; + break; + } + } + + if (g1GcInUse) + { + ClientApi.INSTANCE.showChatMessageNextFrame( + // yellow text + "\u00A7e" + "Distant Horizons: G1 Garbage collector detected." + "\u00A7r \n" + + "This garbage collector can cause FPS stuttering. \n" + + "It's recommended to use a concurrent garbage collector \n" + + "like ZGC (Java 21+) for a smoother experience. \n" + + ""); + } + } + catch (Exception re) + { + LOGGER.warn("Unable to determine garbage collector type. If stuttering occurs please try a concurrent garbage collector like ZGC."); + } + } + } /** done to prevent sending a bunch of startup messages all at once, causing some to be missed. */ private boolean staticStartupMessageSentRecently() diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java b/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java index 26178eeaa..65d3fdb02 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java @@ -1629,6 +1629,15 @@ public class Config + "") .build(); + public static ConfigEntry showGarbageCollectorWarning = new ConfigEntry.Builder() + .set(true) + .comment("" + + "If enabled, a chat message will be displayed if the garbage \n" + + "collector Java is currently using is known \n" + + "to cause stutters and/or issues. \n" + + "") + .build(); + public static ConfigEntry showReplayWarningOnStartup = new ConfigEntry.Builder() .set(true) .comment("" diff --git a/core/src/main/resources/assets/distanthorizons/lang/en_us.json b/core/src/main/resources/assets/distanthorizons/lang/en_us.json index 2a048d25d..374d462f7 100644 --- a/core/src/main/resources/assets/distanthorizons/lang/en_us.json +++ b/core/src/main/resources/assets/distanthorizons/lang/en_us.json @@ -725,6 +725,8 @@ "If DH detects that pooled objects are being garbage collected this will send a chat warning.", "distanthorizons.config.common.logging.warning.showHighVanillaRenderDistanceWarning": "Show High Vanilla Render Distance Warning", + "distanthorizons.config.common.logging.warning.showGarbageCollectorWarning": + "Show Garbage Collector Warning", "distanthorizons.config.common.logging.warning.showReplayWarningOnStartup": "Show Replay Warning", "distanthorizons.config.common.logging.warning.showUpdateQueueOverloadedChatWarning":