mirror of
https://github.com/Winds-Studio/Leaf.git
synced 2025-12-29 03:49:21 +00:00
reduce unparking on AsyncGoalThread
This commit is contained in:
@@ -18,6 +18,7 @@ public class AsyncGoalExecutor {
|
||||
private final ServerLevel serverLevel;
|
||||
private boolean dirty = false;
|
||||
private long tickCount = 0L;
|
||||
private static final int SPIN_LIMIT = 100;
|
||||
|
||||
public AsyncGoalExecutor(AsyncGoalThread thread, ServerLevel serverLevel) {
|
||||
this.serverLevel = serverLevel;
|
||||
@@ -38,8 +39,14 @@ public class AsyncGoalExecutor {
|
||||
|
||||
public final void submit(int entityId) {
|
||||
if (!this.queue.send(entityId)) {
|
||||
LockSupport.unpark(thread);
|
||||
int spinCount = 0;
|
||||
while (!this.queue.send(entityId)) {
|
||||
spinCount++;
|
||||
// Unpark thread after some spinning to help clear the queue
|
||||
if (spinCount > SPIN_LIMIT) {
|
||||
unpark();
|
||||
spinCount = 0;
|
||||
}
|
||||
Thread.onSpinWait();
|
||||
}
|
||||
}
|
||||
@@ -52,15 +59,18 @@ public class AsyncGoalExecutor {
|
||||
}
|
||||
|
||||
public final void midTick() {
|
||||
boolean didWork = false;
|
||||
while (true) {
|
||||
int id = this.wake.recv();
|
||||
if (id == Integer.MAX_VALUE) {
|
||||
break;
|
||||
}
|
||||
didWork = true;
|
||||
Entity entity = this.serverLevel.getEntities().get(id);
|
||||
if (entity == null || !entity.isAlive() || !(entity instanceof Mob mob)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
mob.tickingTarget = true;
|
||||
boolean a = mob.targetSelector.poll();
|
||||
mob.tickingTarget = false;
|
||||
@@ -69,8 +79,7 @@ public class AsyncGoalExecutor {
|
||||
submit(id);
|
||||
}
|
||||
}
|
||||
if ((tickCount & 3L) == 0L) unpark();
|
||||
if (didWork || (tickCount & 15L) == 0L) unpark();
|
||||
tickCount += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@ import net.minecraft.server.level.ServerLevel;
|
||||
import java.util.concurrent.locks.LockSupport;
|
||||
|
||||
public class AsyncGoalThread extends Thread {
|
||||
private static final int SPIN_TRIES = 1000;
|
||||
|
||||
public AsyncGoalThread(final MinecraftServer server) {
|
||||
super(() -> run(server), "Leaf Async Goal Thread");
|
||||
this.setDaemon(true);
|
||||
@@ -16,21 +18,38 @@ public class AsyncGoalThread extends Thread {
|
||||
}
|
||||
|
||||
private static void run(MinecraftServer server) {
|
||||
int emptySpins = 0;
|
||||
|
||||
while (server.isRunning()) {
|
||||
LockSupport.park();
|
||||
boolean didWork = false;
|
||||
for (ServerLevel level : server.getAllLevels()) {
|
||||
var exec = level.asyncGoalExecutor;
|
||||
boolean levelWork = false;
|
||||
while (true) {
|
||||
int id = exec.queue.recv();
|
||||
if (id == Integer.MAX_VALUE) {
|
||||
break;
|
||||
}
|
||||
levelWork = true;
|
||||
if (exec.wake(id)) {
|
||||
while (!exec.wake.send(id)) {
|
||||
Thread.onSpinWait();
|
||||
}
|
||||
}
|
||||
}
|
||||
didWork |= levelWork;
|
||||
}
|
||||
// Adaptive parking
|
||||
if (didWork) {
|
||||
emptySpins = 0; // Reset counter when work was done
|
||||
} else {
|
||||
emptySpins++;
|
||||
if (emptySpins > SPIN_TRIES) {
|
||||
LockSupport.park(); // Only park after several empty spins
|
||||
emptySpins = 0;
|
||||
} else {
|
||||
Thread.onSpinWait(); // Yield to other threads but don't park
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user