Implement more accurate fix for MC-183518

The game now sleeps precisely till the next tick, rather than still
waking up periodically

Co-authored-by: HaHaWTH <102713261+HaHaWTH@users.noreply.github.com>
This commit is contained in:
embeddedt 2025-05-18 19:10:11 -04:00
parent 82535da861
commit a643170426
No known key found for this signature in database
GPG Key ID: A69433EC199B5613
2 changed files with 48 additions and 23 deletions

View File

@ -1,23 +0,0 @@
package org.embeddedt.modernfix.common.mixin.perf.fix_loop_spin_waiting;
import net.minecraft.util.thread.BlockableEventLoop;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;
// This should fix https://bugs.mojang.com/browse/MC-183518
@Mixin(value = BlockableEventLoop.class, priority = 500)
public class BlockableEventLoopMixin {
private static final long MFIX$TICK_WAIT_TIME = TimeUnit.MILLISECONDS.toNanos(2);
/**
* @author embeddedt
* @reason yielding the thread is pretty pointless if we're about to park anyway
*/
@Overwrite
protected void waitForTasks() {
LockSupport.parkNanos("waiting for tasks", MFIX$TICK_WAIT_TIME);
}
}

View File

@ -0,0 +1,48 @@
package org.embeddedt.modernfix.common.mixin.perf.fix_loop_spin_waiting;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import net.minecraft.Util;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.thread.BlockableEventLoop;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import java.util.concurrent.locks.LockSupport;
import java.util.function.BooleanSupplier;
@Mixin(value = MinecraftServer.class, priority = 500)
public abstract class MinecraftServerMixin extends BlockableEventLoop<Runnable> {
@Shadow private long nextTickTime;
protected MinecraftServerMixin(String name) {
super(name);
}
@Unique
private boolean mfix$isWaitingForNextTick = false;
@WrapOperation(
method = "waitUntilNextTick",
at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;managedBlock(Ljava/util/function/BooleanSupplier;)V")
)
private void managedBlock(MinecraftServer instance, BooleanSupplier isDone, Operation<Void> original) {
try {
this.mfix$isWaitingForNextTick = true;
original.call(instance, isDone);
} finally {
this.mfix$isWaitingForNextTick = false;
}
}
@Override
protected void waitForTasks() {
if (this.mfix$isWaitingForNextTick) {
LockSupport.parkNanos("waiting for tasks", (this.nextTickTime * 1000000L) - Util.getNanos());
} else {
super.waitForTasks();
}
}
}