5GB of Ram, 50 Chunks/sec seems to be the new "safe spot"

This commit is contained in:
PryPurity 2020-07-01 07:08:17 -05:00
parent 8ac70874fa
commit b53629e7cf
2 changed files with 11 additions and 47 deletions

View File

@ -6,9 +6,9 @@ import org.bukkit.entity.Player;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.List;
import java.util.*;
@ -38,6 +38,7 @@ public class WorldFileData {
if (!newData.regionFolder.exists() || !newData.regionFolder.isDirectory()) {
// check for region folder inside a DIM* folder (DIM-1 for nether, DIM1 for end, DIMwhatever for custom world types)
File[] possibleDimFolders = newData.world.getWorldFolder().listFiles(new DimFolderFileFilter());
assert possibleDimFolders != null;
for (File possibleDimFolder : possibleDimFolders) {
File possible = new File(newData.world.getWorldFolder(), possibleDimFolder.getName() + File.separator + "region");
if (possible.exists() && possible.isDirectory()) {
@ -155,44 +156,6 @@ public class WorldFileData {
data.add(Boolean.FALSE);
}
for (int i = 0; i < regionFiles.length; i++) {
CoordXZ coord = regionFileCoordinates(i);
// is this region file the one we're looking for?
if (!coord.equals(region))
continue;
//
try {
RandomAccessFile regionData = new RandomAccessFile(this.regionFile(i), "r");
//
// Use of ByteBuffer+IntBuffer for reading file headers to improve performance, as suggested by aikar, reference:
// https://github.com/PaperMC/Paper/blob/b62dfa0bf95ac27ba0fbb3fae18c064e4bb61d50/Spigot-Server-Patches/0086-Reduce-IO-ops-opening-a-new-region-file.patch
ByteBuffer header = ByteBuffer.allocate(8192);
while (header.hasRemaining()) {
if (regionData.getChannel().read(header) == -1)
throw new EOFException();
}
header.clear();
IntBuffer headerAsInts = header.asIntBuffer();
//
// first 4096 bytes of region file consists of 4-byte int pointers to chunk data in the file (32*32 chunks = 1024; 1024 chunks * 4 bytes each = 4096)
for (int j = 0; j < 1024; j++) {
// if chunk pointer data is 0, chunk doesn't exist yet; otherwise, it does
if (headerAsInts.get() != 0)
data.set(j, true);
}
// Read timestamps
for (int j = 0; j < 1024; j++) {
// if timestamp is zero, it is protochunk (ignore it)
if ((headerAsInts.get() == 0) && data.get(j))
data.set(j, false);
}
regionData.close();
} catch (FileNotFoundException ex) {
sendMessage("Error! Could not open region file to find generated chunks: " + this.regionFile(i).getName());
} catch (IOException ex) {
sendMessage("Error! Could not read region file to find generated chunks: " + this.regionFile(i).getName());
}
}
regionChunkExistence.put(region, data);
testImage(region, data);
return data;
@ -214,9 +177,9 @@ public class WorldFileData {
int current = 0;
g2.setColor(Color.BLACK);
for (int x = 0; x < 32; x++) {
for (int z = 0; z < 32; z++) {
if (data.get(current).booleanValue())
for (int x = 0; x < 32; ++x) {
for (int z = 0; z < 32; ++z) {
if (data.get(current))
g2.fillRect(x, z, x + 1, z + 1);
current++;
}

View File

@ -106,7 +106,7 @@ public class WorldFillTask implements Runnable {
int chunkWidthX = (int) Math.ceil((double) ((border.getRadiusX() + 16) * 2) / 16);
int chunkWidthZ = (int) Math.ceil((double) ((border.getRadiusZ() + 16) * 2) / 16);
int biggerWidth = (chunkWidthX > chunkWidthZ) ? chunkWidthX : chunkWidthZ; //We need to calculate the reportTarget with the bigger width, since the spiral will only stop if it has a size of biggerWidth x biggerWidth
int biggerWidth = Math.max(chunkWidthX, chunkWidthZ); //We need to calculate the reportTarget with the bigger width, since the spiral will only stop if it has a size of biggerWidth x biggerWidth
this.reportTarget = (biggerWidth * biggerWidth) + biggerWidth + 1;
//This would be another way to calculate reportTarget, it assumes that we don't need time to check if the chunk is outside and then skip it (it calculates the area of the rectangle/ellipse)
@ -208,7 +208,8 @@ public class WorldFillTask implements Runnable {
int chunksToProcess = chunksPerRun;
if (chunksProcessedLastTick > 0 || pendingChunks.size() > 0) {
// Note we generally queue 3 chunks, so real numbers are 1/3 of chunksProcessedLastTick and pendingchunks.size
int chunksExpectedToGetProcessed = (chunksProcessedLastTick - pendingChunks.size()) / 3 + 3;
// Trying 4 chunks
int chunksExpectedToGetProcessed = (chunksProcessedLastTick - pendingChunks.size()) / 4 + 4;
if (chunksExpectedToGetProcessed < chunksToProcess)
chunksToProcess = chunksExpectedToGetProcessed;
}
@ -560,7 +561,7 @@ public class WorldFillTask implements Runnable {
@Override
public boolean equals(Object other) {
if (other == null || !(other instanceof UnloadDependency))
if (!(other instanceof UnloadDependency))
return false;
return this.neededX == ((UnloadDependency) other).neededX