Avoid unnecessary thread local lookup for acquirable entities

Signed-off-by: TheMode <themode@outlook.fr>
This commit is contained in:
TheMode 2021-09-15 14:41:01 +02:00
parent 2ecd10a4ec
commit a0c38b94c6
4 changed files with 26 additions and 24 deletions

View File

@ -7,7 +7,6 @@ import net.minestom.server.utils.async.AsyncUtils;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.stream.Stream;
@ -25,19 +24,12 @@ public interface Acquirable<T> {
* @return the entities ticked in the current thread
*/
static @NotNull Stream<@NotNull Entity> currentEntities() {
return AcquirableImpl.ENTRIES.get().stream()
.flatMap(chunkEntry -> chunkEntry.getEntities().stream());
}
/**
* Mostly for internal use, external calls are unrecommended as they could lead
* to unexpected behavior.
*
* @param entries the new chunk entries
*/
@ApiStatus.Internal
static void refreshEntries(@NotNull Collection<ThreadDispatcher.ChunkEntry> entries) {
AcquirableImpl.ENTRIES.set(entries);
final Thread currentThread = Thread.currentThread();
if (currentThread instanceof TickThread) {
return ((TickThread) currentThread).entries().stream()
.flatMap(chunkEntry -> chunkEntry.getEntities().stream());
}
return Stream.empty();
}
/**

View File

@ -1,17 +1,13 @@
package net.minestom.server.acquirable;
import net.minestom.server.thread.ThreadDispatcher;
import net.minestom.server.thread.TickThread;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReentrantLock;
final class AcquirableImpl<T> implements Acquirable<T> {
static final ThreadLocal<Collection<ThreadDispatcher.ChunkEntry>> ENTRIES = ThreadLocal.withInitial(Collections::emptySet);
static final AtomicLong WAIT_COUNTER_NANO = new AtomicLong();
/**
@ -40,8 +36,8 @@ final class AcquirableImpl<T> implements Acquirable<T> {
static @Nullable ReentrantLock enter(@NotNull Thread currentThread, @Nullable TickThread elementThread) {
if (elementThread == null) return null;
if (currentThread == elementThread) return null;
final ReentrantLock currentLock = currentThread instanceof TickThread ? ((TickThread) currentThread).getLock() : null;
final ReentrantLock targetLock = elementThread.getLock();
final ReentrantLock currentLock = currentThread instanceof TickThread ? ((TickThread) currentThread).lock() : null;
final ReentrantLock targetLock = elementThread.lock();
if (targetLock.isHeldByCurrentThread()) return null;
// Monitoring

View File

@ -1,7 +1,6 @@
package net.minestom.server.thread;
import net.minestom.server.MinecraftServer;
import net.minestom.server.acquirable.Acquirable;
import net.minestom.server.entity.Entity;
import net.minestom.server.instance.Chunk;
import net.minestom.server.instance.Instance;
@ -98,9 +97,9 @@ public final class ThreadDispatcher {
// Execute tick
this.phaser.register();
thread.startTick(() -> {
Acquirable.refreshEntries(chunkEntries);
thread.updateEntries(chunkEntries);
final ReentrantLock lock = thread.getLock();
final ReentrantLock lock = thread.lock();
lock.lock();
for (ChunkEntry chunkEntry : chunkEntries) {
final Chunk chunk = chunkEntry.chunk;

View File

@ -3,6 +3,8 @@ package net.minestom.server.thread;
import net.minestom.server.MinecraftServer;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.Phaser;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;
@ -18,6 +20,9 @@ public final class TickThread extends Thread {
private volatile boolean stop;
private Runnable tickRunnable;
private boolean isTicking;
private Collection<ThreadDispatcher.ChunkEntry> entries;
public TickThread(Phaser phaser, int number) {
super(MinecraftServer.THREAD_NAME_TICK + "-" + number);
this.phaser = phaser;
@ -27,7 +32,9 @@ public final class TickThread extends Thread {
public void run() {
LockSupport.park(this);
while (!stop) {
this.isTicking = true;
this.tickRunnable.run();
this.isTicking = false;
this.phaser.arriveAndDeregister();
LockSupport.park(this);
}
@ -38,12 +45,20 @@ public final class TickThread extends Thread {
LockSupport.unpark(this);
}
public Collection<ThreadDispatcher.ChunkEntry> entries() {
return isTicking ? entries : Collections.emptyList();
}
void updateEntries(Collection<ThreadDispatcher.ChunkEntry> entries) {
this.entries = entries;
}
/**
* Gets the lock used to ensure the safety of entity acquisition.
*
* @return the thread lock
*/
public @NotNull ReentrantLock getLock() {
public @NotNull ReentrantLock lock() {
return lock;
}