Add idle timer to prevent chunks from suspending too quickly
This commit is contained in:
parent
e34a99b38c
commit
9692da12b4
|
|
@ -3,9 +3,8 @@ package org.embeddedt.modernfix.common.mixin.perf.release_protochunks;
|
||||||
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
|
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
|
||||||
import com.llamalad7.mixinextras.sugar.Local;
|
import com.llamalad7.mixinextras.sugar.Local;
|
||||||
import com.mojang.datafixers.util.Either;
|
import com.mojang.datafixers.util.Either;
|
||||||
|
import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap;
|
||||||
import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap;
|
import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap;
|
||||||
import it.unimi.dsi.fastutil.longs.LongIterator;
|
|
||||||
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
|
|
||||||
import net.minecraft.server.level.ChunkHolder;
|
import net.minecraft.server.level.ChunkHolder;
|
||||||
import net.minecraft.server.level.ChunkLevel;
|
import net.minecraft.server.level.ChunkLevel;
|
||||||
import net.minecraft.server.level.ChunkMap;
|
import net.minecraft.server.level.ChunkMap;
|
||||||
|
|
@ -30,6 +29,9 @@ import java.util.function.BooleanSupplier;
|
||||||
|
|
||||||
@Mixin(ChunkMap.class)
|
@Mixin(ChunkMap.class)
|
||||||
public abstract class ChunkMapMixin implements ISuspendedHolderTrackingChunkMap {
|
public abstract class ChunkMapMixin implements ISuspendedHolderTrackingChunkMap {
|
||||||
|
|
||||||
|
private static final int MFIX$TICKS_TO_WAIT_BEFORE_SUSPENDING = 100;
|
||||||
|
|
||||||
@Shadow
|
@Shadow
|
||||||
@Final
|
@Final
|
||||||
public Long2ObjectLinkedOpenHashMap<ChunkHolder> updatingChunkMap;
|
public Long2ObjectLinkedOpenHashMap<ChunkHolder> updatingChunkMap;
|
||||||
|
|
@ -44,7 +46,10 @@ public abstract class ChunkMapMixin implements ISuspendedHolderTrackingChunkMap
|
||||||
@Shadow
|
@Shadow
|
||||||
@Final
|
@Final
|
||||||
public Long2ObjectLinkedOpenHashMap<ChunkHolder> pendingUnloads;
|
public Long2ObjectLinkedOpenHashMap<ChunkHolder> pendingUnloads;
|
||||||
private final LongOpenHashSet mfix$protoChunksToDrop = new LongOpenHashSet();
|
|
||||||
|
private final Long2IntOpenHashMap mfix$protoChunksToDrop = new Long2IntOpenHashMap();
|
||||||
|
|
||||||
|
private int mfix$dropTickCounter = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author embeddedt
|
* @author embeddedt
|
||||||
|
|
@ -55,10 +60,12 @@ public abstract class ChunkMapMixin implements ISuspendedHolderTrackingChunkMap
|
||||||
private void dropProtoChunks(BooleanSupplier hasMoreTime, CallbackInfo ci) {
|
private void dropProtoChunks(BooleanSupplier hasMoreTime, CallbackInfo ci) {
|
||||||
int suspended = 0;
|
int suspended = 0;
|
||||||
int iterations = 0;
|
int iterations = 0;
|
||||||
LongIterator dropIterator = mfix$protoChunksToDrop.longIterator();
|
mfix$dropTickCounter++;
|
||||||
|
var dropIterator = mfix$protoChunksToDrop.long2IntEntrySet().fastIterator();
|
||||||
while (dropIterator.hasNext() && suspended < 50 && iterations < 500 && (hasMoreTime.getAsBoolean() || mfix$protoChunksToDrop.size() > 1000)) {
|
while (dropIterator.hasNext() && suspended < 50 && iterations < 500 && (hasMoreTime.getAsBoolean() || mfix$protoChunksToDrop.size() > 1000)) {
|
||||||
iterations++;
|
iterations++;
|
||||||
long pos = dropIterator.nextLong();
|
var entry = dropIterator.next();
|
||||||
|
long pos = entry.getLongKey();
|
||||||
ChunkHolder holder = this.updatingChunkMap.get(pos);
|
ChunkHolder holder = this.updatingChunkMap.get(pos);
|
||||||
if (holder == null // already removed
|
if (holder == null // already removed
|
||||||
|| ChunkLevel.fullStatus(holder.getTicketLevel()).isOrAfter(FullChunkStatus.FULL) // promoted to FULL
|
|| ChunkLevel.fullStatus(holder.getTicketLevel()).isOrAfter(FullChunkStatus.FULL) // promoted to FULL
|
||||||
|
|
@ -68,10 +75,16 @@ public abstract class ChunkMapMixin implements ISuspendedHolderTrackingChunkMap
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!holder.getChunkToSave().isDone()
|
if (!holder.getChunkToSave().isDone() // chunkToSave dependencies have not completed
|
||||||
|| ((IClearableChunkHolder)holder).mfix$getGenerationRefCount().get() != 0) {
|
|| ((IClearableChunkHolder)holder).mfix$getGenerationRefCount().get() != 0 // chunk is still being referenced by another chunk for generation
|
||||||
// Not safe to suspend yet; either the chunkToSave chain is still pending, or a neighbor's
|
) {
|
||||||
// generation task is still actively using this chunk's sections
|
// Not safe to suspend yet, reset timer
|
||||||
|
entry.setValue(mfix$dropTickCounter);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((mfix$dropTickCounter - entry.getIntValue()) < MFIX$TICKS_TO_WAIT_BEFORE_SUSPENDING) {
|
||||||
|
// Chunk has not been idle for long enough, wait
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -135,7 +148,7 @@ public abstract class ChunkMapMixin implements ISuspendedHolderTrackingChunkMap
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mfix$markForSuspensionCheck(ChunkPos pos) {
|
public void mfix$markForSuspensionCheck(ChunkPos pos) {
|
||||||
this.mfix$protoChunksToDrop.add(pos.toLong());
|
this.mfix$protoChunksToDrop.put(pos.toLong(), this.mfix$dropTickCounter);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user