Improve CachedPacket

Signed-off-by: TheMode <themode@outlook.fr>
This commit is contained in:
TheMode 2021-10-19 12:41:34 +02:00
parent 11d0f82b86
commit 3685bf22b7
2 changed files with 21 additions and 19 deletions

View File

@ -39,6 +39,7 @@ public class DynamicChunk extends Chunk {
protected final Int2ObjectOpenHashMap<Block> entries = new Int2ObjectOpenHashMap<>(); protected final Int2ObjectOpenHashMap<Block> entries = new Int2ObjectOpenHashMap<>();
protected final Int2ObjectOpenHashMap<Block> tickableMap = new Int2ObjectOpenHashMap<>(); protected final Int2ObjectOpenHashMap<Block> tickableMap = new Int2ObjectOpenHashMap<>();
private long lastChange;
private final CachedPacket chunkCache = new CachedPacket(this::createChunkPacket); private final CachedPacket chunkCache = new CachedPacket(this::createChunkPacket);
private final CachedPacket lightCache = new CachedPacket(this::createLightPacket); private final CachedPacket lightCache = new CachedPacket(this::createLightPacket);
@ -48,8 +49,9 @@ public class DynamicChunk extends Chunk {
@Override @Override
public void setBlock(int x, int y, int z, @NotNull Block block) { public void setBlock(int x, int y, int z, @NotNull Block block) {
this.chunkCache.updateTimestamp(); this.lastChange = System.currentTimeMillis();
this.lightCache.updateTimestamp(); this.chunkCache.invalidate();
this.lightCache.invalidate();
// Update pathfinder // Update pathfinder
if (columnarSpace != null) { if (columnarSpace != null) {
final ColumnarOcclusionFieldList columnarOcclusionFieldList = columnarSpace.occlusionFields(); final ColumnarOcclusionFieldList columnarOcclusionFieldList = columnarSpace.occlusionFields();
@ -118,7 +120,7 @@ public class DynamicChunk extends Chunk {
@Override @Override
public long getLastChangeTime() { public long getLastChangeTime() {
return chunkCache.lastChange(); return lastChange;
} }
@Override @Override

View File

@ -3,39 +3,39 @@ package net.minestom.server.network.packet;
import net.minestom.server.network.packet.server.ServerPacket; import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.utils.PacketUtils; import net.minestom.server.utils.PacketUtils;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import java.lang.ref.SoftReference; import java.lang.ref.SoftReference;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
import java.util.function.Supplier; import java.util.function.Supplier;
@ApiStatus.Internal @ApiStatus.Internal
public final class CachedPacket { public final class CachedPacket {
private static final AtomicIntegerFieldUpdater<CachedPacket> UPDATER = AtomicIntegerFieldUpdater.newUpdater(CachedPacket.class, "updated");
private final Supplier<ServerPacket> supplier; private final Supplier<ServerPacket> supplier;
private volatile long lastChange; // 0 means that the reference needs to be updated
private volatile long packetTimestamp; // Anything else (currently 1) means that the packet is up-to-date
private volatile int updated = 0;
private SoftReference<FramedPacket> packet; private SoftReference<FramedPacket> packet;
public CachedPacket(Supplier<ServerPacket> supplier) { public CachedPacket(@NotNull Supplier<@NotNull ServerPacket> supplier) {
this.supplier = supplier; this.supplier = supplier;
} }
public void updateTimestamp() { public void invalidate() {
this.lastChange = System.currentTimeMillis(); this.updated = 0;
} }
public FramedPacket retrieve() { public @NotNull FramedPacket retrieve() {
final long lastChange = this.lastChange; SoftReference<FramedPacket> ref;
final long timestamp = packetTimestamp; FramedPacket cache;
final var ref = packet; if (updated == 0 ||
FramedPacket cache = ref != null ? ref.get() : null; ((ref = packet) == null ||
if (cache == null || lastChange > timestamp) { (cache = ref.get()) == null)) {
cache = PacketUtils.allocateTrimmedPacket(supplier.get()); cache = PacketUtils.allocateTrimmedPacket(supplier.get());
this.packet = new SoftReference<>(cache); this.packet = new SoftReference<>(cache);
this.packetTimestamp = lastChange; UPDATER.compareAndSet(this, 0, 1);
} }
return cache; return cache;
} }
public long lastChange() {
return lastChange;
}
} }