Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add max-chunk-lifetime setting used by chunk gc (#3167) - fixed #3206

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@ public interface ChunkBridge {

boolean bridge$isQueuedForUnload();

long bridge$getLastSaveTime();

boolean bridge$isChunkDirty();

void bridge$markChunkDirty();

boolean bridge$isActive();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,22 @@ public class WorldCategory extends ConfigCategory {

@Setting(value = "max-chunk-unloads-per-tick", comment = ""
+ "The maximum number of queued unloaded chunks that will be unloaded in a single tick.\n"
+ "Note: With the chunk gc enabled, this setting only applies to the ticks\n"
+ "where the gc runs (controlled by 'chunk-gc-tick-interval')\n"
+ "Note: this setting only controls the amount chunk gc is allowed to save\n"
+ "(controlled by 'chunk-gc-tick-interval' and 'chunk-gc-load-threshold')\n"
+ "Note: If the maximum unloads is too low, too many chunks may remain loaded on the world\n"
+ "and increases the chance for a drop in tps. (Default: 100)")
private int maxChunkUnloads = 100;

@Setting(value = "max-chunk-lifetime", comment = ""
+ "The number of ticks a chunk will stay in memory without saving.\n"
+ "Note: this setting only applies to chunks gc forcibly saving chunks\n"
+ "(controlled by 'chunk-gc-tick-interval' and 'chunk-gc-load-threshold')\n"
+ "Note: Useless if 'auto-save-interval' is enabled and less than this value\n"
+ "Note: 'auto-save-interval' becomes mostly useless if both are enabled and\n"
+ "it is bigger than this value\n"
+ "(Default: 0)")
private int maxChunkLifetime = 0;

@Setting(value = "chunk-gc-load-threshold", comment = ""
+ "The number of newly loaded chunks before triggering a forced cleanup.\n"
+ "Note: When triggered, the loaded chunk threshold will reset and start incrementing.\n"
Expand Down Expand Up @@ -228,6 +238,10 @@ public int getMaxChunkUnloads() {
return this.maxChunkUnloads;
}

public int getMaxChunkLifetime() {
return this.maxChunkLifetime;
}

public double getItemMergeRadius() {
return this.itemMergeRadius;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ public abstract class ChunkMixin implements ChunkBridge, CacheKeyBridge {
@Shadow private boolean loaded;
@Shadow private boolean dirty;
@Shadow public boolean unloadQueued;
@Shadow private long lastSaveTime;

@Shadow @Nullable public abstract TileEntity getTileEntity(BlockPos pos, net.minecraft.world.chunk.Chunk.EnumCreateEntityType p_177424_2_);
@Shadow public abstract void generateSkylightMap();
Expand Down Expand Up @@ -155,11 +156,21 @@ public abstract class ChunkMixin implements ChunkBridge, CacheKeyBridge {
this.dirty = true;
}

@Override
public boolean bridge$isChunkDirty() {
return this.dirty;
}

@Override
public boolean bridge$isQueuedForUnload() {
return this.unloadQueued;
}

@Override
public long bridge$getLastSaveTime() {
return this.lastSaveTime;
}

@Override
public boolean bridge$isPersistedChunk() {
return this.impl$persistedChunk;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ public abstract class ChunkProviderServerMixin implements ChunkProviderServerBri
private boolean impl$forceChunkRequests = false;
private long impl$chunkUnloadDelay = Constants.World.DEFAULT_CHUNK_UNLOAD_DELAY;
private int impl$maxChunkUnloads = Constants.World.MAX_CHUNK_UNLOADS;
private int impl$maxChunkLifetime = Constants.World.MAX_CHUNK_LIFETIME;

@Shadow @Final private WorldServer world;
@Shadow @Final private IChunkLoader chunkLoader;
Expand All @@ -108,6 +109,7 @@ public abstract class ChunkProviderServerMixin implements ChunkProviderServerBri
this.impl$denyChunkRequests = worldCategory.getDenyChunkRequests();
this.impl$chunkUnloadDelay = worldCategory.getChunkUnloadDelay() * 1000;
this.impl$maxChunkUnloads = worldCategory.getMaxChunkUnloads();
this.impl$maxChunkLifetime = worldCategory.getMaxChunkLifetime();
}

@Override
Expand Down Expand Up @@ -268,22 +270,34 @@ public boolean tick()
final Iterator<Chunk> iterator = this.loadedChunks.values().iterator();
int chunksUnloaded = 0;
final long now = System.currentTimeMillis();
final long world_time = this.world.getTotalWorldTime();
while (chunksUnloaded < this.impl$maxChunkUnloads && iterator.hasNext()) {
final Chunk chunk = iterator.next();
final ChunkBridge spongeChunk = (ChunkBridge) chunk;
if (chunk != null && chunk.unloadQueued && !spongeChunk.bridge$isPersistedChunk()) {
if (chunk == null || spongeChunk.bridge$isPersistedChunk()) {
continue;
}
if (chunk.unloadQueued) {
if (this.bridge$getChunkUnloadDelay() > 0) {
if ((now - spongeChunk.bridge$getScheduledForUnload()) < this.impl$chunkUnloadDelay) {
continue;
}
spongeChunk.bridge$setScheduledForUnload(-1);
}
chunk.onUnload();
this.saveChunkData(chunk);
this.saveChunkExtraData(chunk);
}
// max lifetime only applies to chunks that should stay loaded but still need saving once in a while
else if (this.impl$maxChunkLifetime <= 0 // if setting is disabled
PolyacovYury marked this conversation as resolved.
Show resolved Hide resolved
|| !spongeChunk.bridge$isChunkDirty() // no need to save non-dirty chunks
|| world_time - spongeChunk.bridge$getLastSaveTime() < this.impl$maxChunkLifetime) {
continue; // don't save chunk data
}
this.saveChunkData(chunk);
this.saveChunkExtraData(chunk);
if (chunk.unloadQueued) { // chunks not queued to unload stay loaded
iterator.remove();
chunksUnloaded++;
}
chunksUnloaded++;
}
((WorldServerBridge) this.world).bridge$getTimingsHandler().doChunkUnload.stopTiming();
}
Expand Down
1 change: 1 addition & 0 deletions src/main/java/org/spongepowered/common/util/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,7 @@ public static final class World {
public static final UUID INVALID_WORLD_UUID = java.util.UUID.fromString("00000000-0000-0000-0000-000000000000");
public static final int DEFAULT_CHUNK_UNLOAD_DELAY = 15000;
public static final int MAX_CHUNK_UNLOADS = 100;
public static final int MAX_CHUNK_LIFETIME = 0;
public static final String GENERATE_BONUS_CHEST = "GenerateBonusChest";
public static final int CHUNK_UNLOAD_DELAY = 30000;
public static final int END_DIMENSION_ID = 1;
Expand Down