From 084b30e089ae9d1ab893078a1f94e456d568e030 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Wed, 22 Feb 2023 13:07:38 -0500 Subject: [PATCH] Latch JEI and blockstate threads until the world finishes loading These processes are not necessary to get into the game, and so we want to devote all CPU time to essential tasks like logging in and loading chunks. --- .../org/embeddedt/modernfix/ModernFix.java | 24 ++++++++++++++++++ .../embeddedt/modernfix/ModernFixClient.java | 2 ++ .../blockstate/BlockStateCacheHandler.java | 3 +++ .../modernfix/mixin/core/MinecraftMixin.java | 25 +++++++++++++++++++ .../ClientLifecycleHandlerMixin.java | 3 +++ src/main/resources/modernfix.mixins.json | 1 + 6 files changed, 58 insertions(+) create mode 100644 src/main/java/org/embeddedt/modernfix/mixin/core/MinecraftMixin.java diff --git a/src/main/java/org/embeddedt/modernfix/ModernFix.java b/src/main/java/org/embeddedt/modernfix/ModernFix.java index 3e4ee13a..5c455d43 100644 --- a/src/main/java/org/embeddedt/modernfix/ModernFix.java +++ b/src/main/java/org/embeddedt/modernfix/ModernFix.java @@ -21,6 +21,10 @@ import org.embeddedt.modernfix.structure.AsyncLocator; import org.embeddedt.modernfix.util.KubeUtil; import java.lang.management.ManagementFactory; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; +import java.util.function.BooleanSupplier; // The value here should match an entry in the META-INF/mods.toml file @Mod(ModernFix.MODID) @@ -36,6 +40,26 @@ public class ModernFix { // Used to skip computing the blockstate caches twice public static boolean runningFirstInjection = false; + public static CountDownLatch worldLoadSemaphore = null; + + /** + * Simple mechanism used to delay some background processes until the client is actually in-game, to reduce + * launch time. + */ + public static void waitForWorldLoad(BooleanSupplier exitEarly) { + CountDownLatch latch = worldLoadSemaphore; + if(latch != null) { + try { + while(!latch.await(100, TimeUnit.MILLISECONDS)) { + if(exitEarly.getAsBoolean()) + return; + } + } catch(InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + } + public ModernFix() { INSTANCE = this; diff --git a/src/main/java/org/embeddedt/modernfix/ModernFixClient.java b/src/main/java/org/embeddedt/modernfix/ModernFixClient.java index 1ce231d7..2ed3b0c3 100644 --- a/src/main/java/org/embeddedt/modernfix/ModernFixClient.java +++ b/src/main/java/org/embeddedt/modernfix/ModernFixClient.java @@ -48,6 +48,8 @@ public class ModernFixClient { ModernFix.LOGGER.warn("Time from main menu to in-game was " + timeSpentLoading + " seconds"); ModernFix.LOGGER.warn("Total time to load game and open world was " + (timeSpentLoading + gameStartTimeSeconds) + " seconds"); resetWorldLoadStateMachine(); + if(ModernFix.worldLoadSemaphore != null) + ModernFix.worldLoadSemaphore.countDown(); } } } diff --git a/src/main/java/org/embeddedt/modernfix/blockstate/BlockStateCacheHandler.java b/src/main/java/org/embeddedt/modernfix/blockstate/BlockStateCacheHandler.java index 4128d2d9..e9bd7c9f 100644 --- a/src/main/java/org/embeddedt/modernfix/blockstate/BlockStateCacheHandler.java +++ b/src/main/java/org/embeddedt/modernfix/blockstate/BlockStateCacheHandler.java @@ -85,6 +85,9 @@ public class BlockStateCacheHandler { @Override public void run() { + ModernFix.waitForWorldLoad(() -> stopRebuild); + if(stopRebuild) + return; Stopwatch realtimeStopwatch = Stopwatch.createStarted(); rebuildCache(); realtimeStopwatch.stop(); diff --git a/src/main/java/org/embeddedt/modernfix/mixin/core/MinecraftMixin.java b/src/main/java/org/embeddedt/modernfix/mixin/core/MinecraftMixin.java new file mode 100644 index 00000000..7665941d --- /dev/null +++ b/src/main/java/org/embeddedt/modernfix/mixin/core/MinecraftMixin.java @@ -0,0 +1,25 @@ +package org.embeddedt.modernfix.mixin.core; + +import com.mojang.datafixers.util.Function4; +import net.minecraft.client.Minecraft; +import net.minecraft.core.RegistryAccess; +import net.minecraft.server.packs.resources.ResourceManager; +import net.minecraft.world.level.DataPackConfig; +import net.minecraft.world.level.storage.LevelStorageSource; +import net.minecraft.world.level.storage.WorldData; +import org.embeddedt.modernfix.ModernFix; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.concurrent.CountDownLatch; +import java.util.function.Function; + +@Mixin(Minecraft.class) +public class MinecraftMixin { + @Inject(method = "loadWorld", at = @At("HEAD")) + private void setLatch(String string, RegistryAccess.RegistryHolder arg, Function function, Function4 function4, boolean bl, Minecraft.ExperimentalDialogType arg2, boolean creating, CallbackInfo ci) { + ModernFix.worldLoadSemaphore = new CountDownLatch(1); + } +} diff --git a/src/main/java/org/embeddedt/modernfix/mixin/perf/async_jei/ClientLifecycleHandlerMixin.java b/src/main/java/org/embeddedt/modernfix/mixin/perf/async_jei/ClientLifecycleHandlerMixin.java index 6a1d664b..d7708b98 100644 --- a/src/main/java/org/embeddedt/modernfix/mixin/perf/async_jei/ClientLifecycleHandlerMixin.java +++ b/src/main/java/org/embeddedt/modernfix/mixin/perf/async_jei/ClientLifecycleHandlerMixin.java @@ -80,6 +80,9 @@ public class ClientLifecycleHandlerMixin { cancelPreviousStart(); ModernFix.LOGGER.info("Starting new JEI thread."); JEIReloadThread newThread = new JEIReloadThread(() -> { + ModernFix.waitForWorldLoad(() -> ((JEIReloadThread)Thread.currentThread()).isStopRequested()); + if(((JEIReloadThread)Thread.currentThread()).isStopRequested()) + return; try { starter.start( plugins, diff --git a/src/main/resources/modernfix.mixins.json b/src/main/resources/modernfix.mixins.json index f7a43a5a..5dd2746e 100644 --- a/src/main/resources/modernfix.mixins.json +++ b/src/main/resources/modernfix.mixins.json @@ -50,6 +50,7 @@ "perf.kubejs.CustomIngredientMixin" ], "client": [ + "core.MinecraftMixin", "feature.measure_time.MinecraftMixin", "feature.reduce_loading_screen_freezes.ModelBakeryMixin", "perf.skip_first_datapack_reload.MinecraftMixin",