Use reflection instead of mixins for SyncExecutor patch
This commit is contained in:
parent
9443c41273
commit
c4fbde015e
|
|
@ -13,6 +13,7 @@ import org.embeddedt.modernfix.classloading.FastAccessTransformerList;
|
||||||
import org.embeddedt.modernfix.classloading.ModernFixResourceFinder;
|
import org.embeddedt.modernfix.classloading.ModernFixResourceFinder;
|
||||||
import org.embeddedt.modernfix.core.config.ModernFixEarlyConfig;
|
import org.embeddedt.modernfix.core.config.ModernFixEarlyConfig;
|
||||||
import org.embeddedt.modernfix.core.config.Option;
|
import org.embeddedt.modernfix.core.config.Option;
|
||||||
|
import org.embeddedt.modernfix.load.ModWorkManagerQueue;
|
||||||
import org.embeddedt.modernfix.util.DummyList;
|
import org.embeddedt.modernfix.util.DummyList;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
import org.objectweb.asm.tree.*;
|
import org.objectweb.asm.tree.*;
|
||||||
|
|
@ -83,6 +84,7 @@ public class ModernFixMixinPlugin implements IMixinConfigPlugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
FastAccessTransformerList.attemptReplace();
|
FastAccessTransformerList.attemptReplace();
|
||||||
|
ModWorkManagerQueue.replace();
|
||||||
|
|
||||||
/* https://github.com/FabricMC/Mixin/pull/99 */
|
/* https://github.com/FabricMC/Mixin/pull/99 */
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,6 @@ public class ModernFixEarlyConfig {
|
||||||
this.addMixinRule("perf.async_jei", modPresent("jei"));
|
this.addMixinRule("perf.async_jei", modPresent("jei"));
|
||||||
this.addMixinRule("perf.thread_priorities", true);
|
this.addMixinRule("perf.thread_priorities", true);
|
||||||
this.addMixinRule("perf.preload_block_classes", false);
|
this.addMixinRule("perf.preload_block_classes", false);
|
||||||
this.addMixinRule("perf.sync_executor_sleep", true);
|
|
||||||
this.addMixinRule("perf.scan_cache", true);
|
this.addMixinRule("perf.scan_cache", true);
|
||||||
this.addMixinRule("perf.compress_biome_container", true);
|
this.addMixinRule("perf.compress_biome_container", true);
|
||||||
this.addMixinRule("perf.nuke_empty_chunk_sections", true);
|
this.addMixinRule("perf.nuke_empty_chunk_sections", true);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
package org.embeddedt.modernfix.load;
|
||||||
|
|
||||||
|
import net.minecraftforge.fml.ModWorkManager;
|
||||||
|
import net.minecraftforge.fml.common.ObfuscationReflectionHelper;
|
||||||
|
|
||||||
|
import java.util.concurrent.ConcurrentLinkedDeque;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.concurrent.locks.LockSupport;
|
||||||
|
|
||||||
|
public class ModWorkManagerQueue extends ConcurrentLinkedDeque<Runnable> {
|
||||||
|
private static final long PARK_TIME = TimeUnit.MILLISECONDS.toNanos(25);
|
||||||
|
|
||||||
|
private static final Runnable DUMMY_TASK = () -> {};
|
||||||
|
|
||||||
|
private boolean shouldReturnDummyTask = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sleep for a bit if there are no tasks.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Runnable pollFirst() {
|
||||||
|
Runnable r = super.pollFirst();
|
||||||
|
if(r == null) {
|
||||||
|
LockSupport.parkNanos(PARK_TIME);
|
||||||
|
boolean isReturning = shouldReturnDummyTask;
|
||||||
|
shouldReturnDummyTask = !shouldReturnDummyTask;
|
||||||
|
/*
|
||||||
|
* We need to kick FML to redraw the loading screen periodically,
|
||||||
|
* but also allow actually exiting the executor loop, so that
|
||||||
|
* loading can complete if async work is done.
|
||||||
|
*
|
||||||
|
* This is accomplished by alternating between returning a dummy
|
||||||
|
* task and nothing.
|
||||||
|
*/
|
||||||
|
return isReturning ? DUMMY_TASK : null;
|
||||||
|
} else {
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||||
|
public static void replace() {
|
||||||
|
try {
|
||||||
|
Class<?> syncExecutorClass = Class.forName("net.minecraftforge.fml.ModWorkManager$SyncExecutor");
|
||||||
|
ConcurrentLinkedDeque<Runnable> taskQueue = (ConcurrentLinkedDeque<Runnable>)ObfuscationReflectionHelper.getPrivateValue((Class)syncExecutorClass, (Object)ModWorkManager.syncExecutor(), "tasks");
|
||||||
|
ModWorkManagerQueue q = new ModWorkManagerQueue();
|
||||||
|
Runnable task;
|
||||||
|
do {
|
||||||
|
task = taskQueue.pollFirst();
|
||||||
|
if(task != null)
|
||||||
|
q.push(task);
|
||||||
|
} while(task != null);
|
||||||
|
ObfuscationReflectionHelper.setPrivateValue((Class)syncExecutorClass, (Object)ModWorkManager.syncExecutor(), q, "tasks");
|
||||||
|
} catch(ReflectiveOperationException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,38 +0,0 @@
|
||||||
package org.embeddedt.modernfix.mixin.perf.sync_executor_sleep;
|
|
||||||
|
|
||||||
import net.minecraftforge.fml.ModWorkManager;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
|
||||||
import org.spongepowered.asm.mixin.Overwrite;
|
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
|
||||||
|
|
||||||
import java.util.concurrent.ConcurrentLinkedDeque;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.concurrent.locks.LockSupport;
|
|
||||||
|
|
||||||
@Mixin(targets = "net/minecraftforge/fml/ModWorkManager$SyncExecutor")
|
|
||||||
public abstract class SyncExecutorMixin {
|
|
||||||
@Shadow(remap = false) public abstract boolean driveOne();
|
|
||||||
|
|
||||||
private static final long PARK_TIME = TimeUnit.MILLISECONDS.toNanos(50);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Currently FML spins in driveOne while waiting for the modloading workers. We can improve this
|
|
||||||
* by sleeping for 50ms at a time.
|
|
||||||
*
|
|
||||||
* Also, render FML splash screen regardless of task availability.
|
|
||||||
* @author embeddedt
|
|
||||||
* @reason improve CPU efficiency
|
|
||||||
*/
|
|
||||||
public void drive(Runnable ticker) {
|
|
||||||
int executions = 0;
|
|
||||||
do {
|
|
||||||
executions++;
|
|
||||||
ticker.run();
|
|
||||||
} while(driveOne());
|
|
||||||
if(executions < 2)
|
|
||||||
LockSupport.parkNanos(PARK_TIME);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -30,7 +30,6 @@
|
||||||
"perf.reduce_blockstate_cache_rebuilds.BlocksMixin",
|
"perf.reduce_blockstate_cache_rebuilds.BlocksMixin",
|
||||||
"perf.reduce_blockstate_cache_rebuilds.BlockStateBaseMixin",
|
"perf.reduce_blockstate_cache_rebuilds.BlockStateBaseMixin",
|
||||||
"perf.deduplicate_location.MixinResourceLocation",
|
"perf.deduplicate_location.MixinResourceLocation",
|
||||||
"perf.sync_executor_sleep.SyncExecutorMixin",
|
|
||||||
"perf.compress_biome_container.MixinBiomeContainer",
|
"perf.compress_biome_container.MixinBiomeContainer",
|
||||||
"perf.nuke_empty_chunk_sections.MixinChunk",
|
"perf.nuke_empty_chunk_sections.MixinChunk",
|
||||||
"perf.cache_blockstate_cache_arrays.AbstractBlockStateCacheMixin",
|
"perf.cache_blockstate_cache_arrays.AbstractBlockStateCacheMixin",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user