Allow a single low-priority worker thread when cause_lag_by_disabling_threads is enabled
On a system with few cores, we should still benefit from using one low-priority background thread for worldgen, because it avoids the server thread stopping to handle it itself. The thread will be blocked from progressing while higher-priority work (e.g. rendering or server ticking) is in progress.
This commit is contained in:
parent
db13f39b30
commit
4ff7d4c554
|
|
@ -1,7 +1,7 @@
|
||||||
package org.embeddedt.modernfix.common.mixin.feature.cause_lag_by_disabling_threads;
|
package org.embeddedt.modernfix.common.mixin.feature.cause_lag_by_disabling_threads;
|
||||||
|
|
||||||
import net.minecraft.Util;
|
import net.minecraft.Util;
|
||||||
import org.embeddedt.modernfix.util.DirectExecutorService;
|
import org.embeddedt.modernfix.util.SingleThreadedWorkerService;
|
||||||
import org.spongepowered.asm.mixin.Final;
|
import org.spongepowered.asm.mixin.Final;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Mutable;
|
import org.spongepowered.asm.mixin.Mutable;
|
||||||
|
|
@ -12,5 +12,5 @@ import java.util.concurrent.ExecutorService;
|
||||||
@Mixin(Util.class)
|
@Mixin(Util.class)
|
||||||
public class UtilMixin {
|
public class UtilMixin {
|
||||||
@Shadow @Final @Mutable
|
@Shadow @Final @Mutable
|
||||||
private static final ExecutorService BACKGROUND_EXECUTOR = new DirectExecutorService();
|
private static final ExecutorService BACKGROUND_EXECUTOR = new SingleThreadedWorkerService();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,43 +0,0 @@
|
||||||
package org.embeddedt.modernfix.util;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.AbstractExecutorService;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
public class DirectExecutorService extends AbstractExecutorService {
|
|
||||||
private boolean isShutdown;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void shutdown() {
|
|
||||||
isShutdown = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public List<Runnable> shutdownNow() {
|
|
||||||
isShutdown = true;
|
|
||||||
return List.of();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isShutdown() {
|
|
||||||
return isShutdown;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isTerminated() {
|
|
||||||
return isShutdown;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean awaitTermination(long timeout, @NotNull TimeUnit unit) throws InterruptedException {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(@NotNull Runnable command) {
|
|
||||||
command.run();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
package org.embeddedt.modernfix.util;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.AbstractExecutorService;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Like {@link Executors#newSingleThreadExecutor()}, but handles the case where the background executor schedules
|
||||||
|
* a task to itself and waits for it the way a direct executor would.
|
||||||
|
*/
|
||||||
|
public class SingleThreadedWorkerService extends AbstractExecutorService {
|
||||||
|
private final AtomicReference<Thread> thread = new AtomicReference<>();
|
||||||
|
private final ExecutorService executorService;
|
||||||
|
|
||||||
|
public SingleThreadedWorkerService() {
|
||||||
|
this.executorService = Executors.newSingleThreadExecutor(r -> {
|
||||||
|
Thread t = new Thread(r, "Worker-Main");
|
||||||
|
t.setPriority(Thread.MIN_PRIORITY);
|
||||||
|
thread.set(t);
|
||||||
|
return t;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void shutdown() {
|
||||||
|
executorService.shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public List<Runnable> shutdownNow() {
|
||||||
|
return executorService.shutdownNow();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isShutdown() {
|
||||||
|
return executorService.isShutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isTerminated() {
|
||||||
|
return executorService.isTerminated();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean awaitTermination(long timeout, @NotNull TimeUnit unit) throws InterruptedException {
|
||||||
|
return executorService.awaitTermination(timeout, unit);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(@NotNull Runnable command) {
|
||||||
|
if (Thread.currentThread() == thread.get()) {
|
||||||
|
command.run();
|
||||||
|
} else {
|
||||||
|
executorService.execute(command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user