Simplify acquisition, reduce overhead

This commit is contained in:
TheMode 2021-04-17 14:22:47 +02:00
parent a5df2376cf
commit 23664292de
6 changed files with 59 additions and 93 deletions

View File

@ -121,18 +121,10 @@ public final class UpdateManager {
final CountDownLatch countDownLatch = threadProvider.update(tickStart);
// Wait tick end
while (countDownLatch.getCount() != 0) {
this.threadProvider.getThreads().forEach(batchThread -> {
BatchThread waitingOn = batchThread.waitingOn;
if (waitingOn != null && !waitingOn.getMainRunnable().isInTick()) {
BatchThread waitingOn2 = waitingOn.waitingOn;
if(waitingOn2 != null){
Acquisition.processMonitored(waitingOn2);
}else{
Acquisition.processMonitored(waitingOn);
}
}
});
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
// Clear removed entities & update threads

View File

@ -488,9 +488,6 @@ public class Entity implements Viewable, Tickable, LockedElement, EventHandler,
}
}
// Acquisition
getAcquiredElement().getHandler().acquisitionTick();
final boolean isNettyClient = PlayerUtils.isNettyClient(this);
// Synchronization with updated fields in #getPosition()

View File

@ -44,6 +44,8 @@ import net.minestom.server.item.ItemStack;
import net.minestom.server.item.Material;
import net.minestom.server.item.metadata.WrittenBookMeta;
import net.minestom.server.listener.PlayerDiggingListener;
import net.minestom.server.lock.Acquirable;
import net.minestom.server.lock.AcquirableCollection;
import net.minestom.server.network.ConnectionManager;
import net.minestom.server.network.ConnectionState;
import net.minestom.server.network.PlayerProvider;
@ -325,13 +327,22 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
packet.process(this);
}
Collection<Acquirable<Player>> players = new ArrayList<>();
//if (username.equals("TheMode911"))
for (Player p1 : MinecraftServer.getConnectionManager().getOnlinePlayers()) {
p1.getAcquiredElement().acquire(o -> {
//for (Player p2 : MinecraftServer.getConnectionManager().getOnlinePlayers())
// p2.getAcquiredElement().acquire(o2 -> { });
});
}
for (Player p1 : MinecraftServer.getConnectionManager().getOnlinePlayers()) {
//players.add(p1.getAcquiredElement());
p1.getAcquiredElement().acquire(o -> {
for (Player p2 : MinecraftServer.getConnectionManager().getOnlinePlayers())
p2.getAcquiredElement().acquire(o2 -> {});
});
}
/*AcquirableCollection<Player> players1 = new AcquirableCollection<>(players);
players1.forEach(player -> {
players1.forEach(player2 -> {
});
});*/
super.update(time); // Super update (item pickup/fire management)

View File

@ -8,7 +8,6 @@ import org.jetbrains.annotations.NotNull;
import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.CountDownLatch;
import java.util.function.Consumer;
/**
@ -78,19 +77,6 @@ public interface Acquirable<T> {
this.batchThread = batchThread;
this.batchChunk = batchChunk;
}
/**
* Executed during this element tick to empty the current thread acquisition queue.
*/
public void acquisitionTick() {
if (batchThread == null)
return;
Acquisition.process(batchThread);
}
}
class Request {
public CountDownLatch localLatch, processLatch;
}
}

View File

@ -1,6 +1,7 @@
package net.minestom.server.lock;
import com.google.common.util.concurrent.Monitor;
import net.minestom.server.MinecraftServer;
import net.minestom.server.thread.BatchThread;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@ -13,7 +14,7 @@ import java.util.function.Consumer;
public final class Acquisition {
private static final Map<BatchThread, Collection<Acquirable.Request>> REQUEST_MAP = new ConcurrentHashMap<>();
private static final Map<BatchThread, Collection<Request>> REQUEST_MAP = new ConcurrentHashMap<>();
private static final ThreadLocal<ScheduledAcquisition> SCHEDULED_ACQUISITION = ThreadLocal.withInitial(ScheduledAcquisition::new);
private static final Monitor GLOBAL_MONITOR = new Monitor();
@ -68,53 +69,41 @@ public final class Acquisition {
if (elementThread == null || elementThread == currentThread) {
callback.run();
} else {
final BatchThread currentBatch = currentThread instanceof BatchThread ? ((BatchThread) currentThread) : null;
final Monitor currentMonitor = currentBatch != null ? currentBatch.monitor : null;
boolean enter = false;
if (currentMonitor != null && currentMonitor.isOccupiedByCurrentThread()) {
process((BatchThread) currentThread);
currentMonitor.leave();
enter = true;
// Monitoring
final boolean monitoring = MinecraftServer.hasWaitMonitoring();
long time = 0;
if (monitoring) {
time = System.nanoTime();
}
Monitor monitor = elementThread.monitor;
BatchThread current = (BatchThread) currentThread;
Monitor currentMonitor = current.monitor;
final boolean currentAcquired = currentMonitor.isOccupiedByCurrentThread();
if (currentAcquired)
current.monitor.leave();
if (monitor.isOccupiedByCurrentThread() || GLOBAL_MONITOR.isOccupiedByCurrentThread()) {
// We already have access to the thread
callback.run();
} else if (monitor.tryEnter()) {
// Acquire the thread
callback.run();
GLOBAL_MONITOR.enter();
final var monitor = elementThread.monitor;
final boolean acquired = monitor.isOccupiedByCurrentThread();
if (!acquired) {
monitor.enter();
}
// Monitoring
if (monitoring) {
time = System.nanoTime() - time;
WAIT_COUNTER_NANO.addAndGet(time);
}
callback.run();
if (!acquired) {
monitor.leave();
} else {
// Thread is not available, forward request to be executed later
while (!GLOBAL_MONITOR.tryEnter())
processMonitored(currentBatch);
var requests = getRequests(elementThread);
Acquirable.Request request = new Acquirable.Request();
request.localLatch = new CountDownLatch(1);
request.processLatch = new CountDownLatch(1);
requests.add(request);
try {
currentBatch.waitingOn = elementThread;
request.localLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
currentBatch.waitingOn = null;
callback.run();
request.processLatch.countDown();
GLOBAL_MONITOR.leave();
}
if (currentMonitor != null && enter) {
currentMonitor.enter();
}
GLOBAL_MONITOR.leave();
if (currentAcquired)
current.monitor.enter();
}
}
@ -131,13 +120,7 @@ public final class Acquisition {
});
}
public static void processMonitored(@NotNull BatchThread thread) {
thread.monitor.enter();
process(thread);
thread.monitor.leave();
}
private static @NotNull Collection<Acquirable.Request> getRequests(@NotNull BatchThread thread) {
private static @NotNull Collection<Request> getRequests(@NotNull BatchThread thread) {
return REQUEST_MAP.computeIfAbsent(thread, batchThread -> ConcurrentHashMap.newKeySet());
}
@ -179,6 +162,11 @@ public final class Acquisition {
WAIT_COUNTER_NANO.set(0);
}
private static class Request {
public CountDownLatch localLatch, processLatch;
public Runnable runnable;
}
private static class ScheduledAcquisition {
private final List<Acquirable<Object>> acquirableElements = new ArrayList<>();
private final Map<Object, List<Consumer<Object>>> callbacks = new HashMap<>();

View File

@ -2,8 +2,6 @@ package net.minestom.server.thread;
import com.google.common.util.concurrent.Monitor;
import net.minestom.server.MinecraftServer;
import net.minestom.server.lock.Acquirable;
import net.minestom.server.lock.Acquisition;
import net.minestom.server.utils.validate.Check;
import org.jetbrains.annotations.NotNull;
@ -17,8 +15,7 @@ public class BatchThread extends Thread {
private final BatchRunnable runnable;
public final Monitor monitor = new Monitor();
public volatile BatchThread waitingOn;
public volatile Monitor monitor = new Monitor();
public BatchThread(@NotNull BatchRunnable runnable, int number) {
super(runnable, MinecraftServer.THREAD_NAME_TICK + "-" + number);
@ -69,11 +66,6 @@ public class BatchThread extends Thread {
runnable.run();
}
// Execute waiting acquisition
{
Acquisition.processMonitored(batchThread);
}
localCountDownLatch.countDown();
this.countDownLatch.compareAndSet(localCountDownLatch, null);