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.core.config.ModernFixEarlyConfig;
|
||||
import org.embeddedt.modernfix.core.config.Option;
|
||||
import org.embeddedt.modernfix.load.ModWorkManagerQueue;
|
||||
import org.embeddedt.modernfix.util.DummyList;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.tree.*;
|
||||
|
|
@ -83,6 +84,7 @@ public class ModernFixMixinPlugin implements IMixinConfigPlugin {
|
|||
}
|
||||
|
||||
FastAccessTransformerList.attemptReplace();
|
||||
ModWorkManagerQueue.replace();
|
||||
|
||||
/* https://github.com/FabricMC/Mixin/pull/99 */
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -56,7 +56,6 @@ public class ModernFixEarlyConfig {
|
|||
this.addMixinRule("perf.async_jei", modPresent("jei"));
|
||||
this.addMixinRule("perf.thread_priorities", true);
|
||||
this.addMixinRule("perf.preload_block_classes", false);
|
||||
this.addMixinRule("perf.sync_executor_sleep", true);
|
||||
this.addMixinRule("perf.scan_cache", true);
|
||||
this.addMixinRule("perf.compress_biome_container", 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.BlockStateBaseMixin",
|
||||
"perf.deduplicate_location.MixinResourceLocation",
|
||||
"perf.sync_executor_sleep.SyncExecutorMixin",
|
||||
"perf.compress_biome_container.MixinBiomeContainer",
|
||||
"perf.nuke_empty_chunk_sections.MixinChunk",
|
||||
"perf.cache_blockstate_cache_arrays.AbstractBlockStateCacheMixin",
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user