diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/config/NightConfigWatchThrottler.java b/forge/src/main/java/org/embeddedt/modernfix/forge/config/NightConfigWatchThrottler.java new file mode 100644 index 00000000..ae75e00f --- /dev/null +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/config/NightConfigWatchThrottler.java @@ -0,0 +1,56 @@ +package org.embeddedt.modernfix.forge.config; + +import com.electronwill.nightconfig.core.file.FileWatcher; +import com.google.common.collect.ForwardingCollection; +import com.google.common.collect.ForwardingMap; +import net.minecraftforge.fml.common.ObfuscationReflectionHelper; + +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.LockSupport; + +/** + * Throttle NightConfig's file watching. There are reports of this consuming excessive CPU time + * (example) and the spammed iterator calls + * end up being 10% of allocations when testing in a dev environment. + */ +public class NightConfigWatchThrottler { + private static final long DELAY = TimeUnit.MILLISECONDS.toNanos(1000); + + @SuppressWarnings("rawtypes") + public static void throttle() { + Map watchedDirs = ObfuscationReflectionHelper.getPrivateValue(FileWatcher.class, FileWatcher.defaultInstance(), "watchedDirs"); + ObfuscationReflectionHelper.setPrivateValue(FileWatcher.class, FileWatcher.defaultInstance(), new ForwardingMap() { + @Override + protected Map delegate() { + return watchedDirs; + } + + private Collection cachedValues; + + @Override + public Collection values() { + if(cachedValues == null) { + Collection values = super.values(); + cachedValues = new ForwardingCollection() { + @Override + protected Collection delegate() { + return values; + } + + @Override + public Iterator iterator() { + // iterator() is called at the beginning of each iteration of the watch loop, + // so it is a good spot to inject the delay. + LockSupport.parkNanos(DELAY); + return super.iterator(); + } + }; + } + return cachedValues; + } + }, "watchedDirs"); + } +} diff --git a/forge/src/main/java/org/embeddedt/modernfix/platform/forge/ModernFixPlatformHooksImpl.java b/forge/src/main/java/org/embeddedt/modernfix/platform/forge/ModernFixPlatformHooksImpl.java index ce5c373a..01c8f6e0 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/platform/forge/ModernFixPlatformHooksImpl.java +++ b/forge/src/main/java/org/embeddedt/modernfix/platform/forge/ModernFixPlatformHooksImpl.java @@ -27,6 +27,7 @@ import org.embeddedt.modernfix.api.constants.IntegrationConstants; import org.embeddedt.modernfix.forge.classloading.ATInjector; import org.embeddedt.modernfix.forge.classloading.FastAccessTransformerList; import org.embeddedt.modernfix.forge.config.NightConfigFixer; +import org.embeddedt.modernfix.forge.config.NightConfigWatchThrottler; import org.embeddedt.modernfix.forge.init.ModernFixForge; import org.embeddedt.modernfix.forge.packet.PacketHandler; import org.embeddedt.modernfix.platform.ModernFixPlatformHooks; @@ -158,6 +159,7 @@ public class ModernFixPlatformHooksImpl implements ModernFixPlatformHooks { } NightConfigFixer.monitorFileWatcher(); + NightConfigWatchThrottler.throttle(); } public void applyASMTransformers(String mixinClassName, ClassNode targetClass) {