geforkt von Mirrors/Paper
b68b282439
Upstream has released updates that appears to apply and compile correctly. This update has not been tested by PaperMC and as with ANY update, please do your own testing Warning: this commit contains more mapping changes from upstream, As always, ensure that you have working backups and test this build before deployment; Developers working on paper will, yet again, need to delete their work/Minecraft/1.13.2 folder Bukkit Changes: 7fca5fd4 SPIGOT-4558: Preserve user order in the face of copied defaults in configurations 15c9b1eb Ignore spurious slot IDs sent by client, e.g. in enchanting tables 5d2a10c5 SPIGOT-3747: Add API for force loaded chunks d6dd2bb3 SPIGOT-3538: Add getHitBlockFace for ProjectileHitEvent 771db4aa SPIGOT-794: Call EntityPlaceEvent for Minecart placement 55462509 Add InventoryView#getSlotType 2f3ce5b6 Remove EntityTransformEvent and CustomItemTagContainer from draft API f04ad7b6 Make ProjectileLaunchEvent extend EntitySpawnEvent ccb85808 Define EntitySpawnEvent b8cc3ebe Add PlayerItemDamageEvent 184a495d Ease ClassLoader Deadlocks Where Possible 11ac4728 Expand Boolean Prompt Values in Conversation API aae62d51 Added getAllSessionData() to the Conversation API. 9290ff91 Add InventoryView#getInventory API 995e530f Add API to get / set base arrow damage CraftBukkit Changes:c4a67eed
SPIGOT-4556: Fix plugins closing inventory during drop events5be2ddcb
Replace version constants with methods to prevent compiler inlininga5b9c7b3
Use API method to create offset command completions2bc7d1df
SPIGOT-3747: Add API for force loaded chunksa408f375
SPIGOT-3538: Add getHitBlockFace for ProjectileHitEventb54b9409
SPIGOT-2864: Make Arrow / Item setTicksLived behave like FallingBlock79ded7a8
SPIGOT-1811: Death message not shown on respawn screenb4a4f15d
SPIGOT-943: InventoryCloseEvent called on death regardless of open inventory0afed592
SPIGOT-794: Call EntityPlaceEvent for Minecart placement2b2d084a
Add InventoryView#getSlotType01a9959a
Do not use deprecated ItemSpawnEvent constructor9642498d
SPIGOT-4547: Call EntitySpawnEvent as general spawn fallback event963f4a5f
Add PlayerItemDamageEvent63db0445
Add API to get / set base arrow damage531c25d7
Add CraftMagicNumbers.MAPPINGS_VERSION for use by NMS pluginsd05c8b14
Mappings Updatebd36e200
SPIGOT-4551: Ignore invalid attribute modifier slots Spigot Changes: 518206a1 Remove redundant trove depend 1959ad21 MC-11211,SPIGOT-4552: Fix placing double slabs at y = 255 29ab5e43 SPIGOT-3661: Allow arguments in restart-script 7cc46316 SPIGOT-852: Growth modifiers for beetroots, potatoes, carrots 82e117e1 Squelch "fatal: Resolve operation not in progress" message 0a1a68e7 Mappings Update & Patch Rebuild
207 Zeilen
10 KiB
Diff
207 Zeilen
10 KiB
Diff
From 509516752bce9e1f9a8e0eb8f0d94d11b4ff841c Mon Sep 17 00:00:00 2001
|
|
From: Aikar <aikar@aikar.co>
|
|
Date: Fri, 4 Mar 2016 18:18:37 -0600
|
|
Subject: [PATCH] Chunk save queue improvements
|
|
|
|
For some unknown reason, Minecraft is sleeping 10ms between every single chunk being saved to disk.
|
|
Under high chunk load/unload activity (lots of movement / teleporting), this causes the chunk unload queue
|
|
to build up in size.
|
|
|
|
This has multiple impacts:
|
|
1) Performance of the unload queue itself - The save thread is pretty ineffecient for how it accesses it
|
|
By letting the queue get larger, checking and popping work off the queue can get less performant.
|
|
2) Performance of chunk loading - As with #1, chunk loads also have to check this queue when loading
|
|
chunk data so that it doesn't load stale data if new data is pending write to disk.
|
|
3) Memory Usage - The entire chunk has been serialized to NBT, and now sits in this queue. This leads to
|
|
elevated memory usage, and then the objects used in the serialization sit around longer than needed,
|
|
resulting in promotion to Old Generation instead of dying young.
|
|
|
|
To optimize this, we change the entire unload queue to be a proper queue. This improves the behavior of popping
|
|
the first queued chunk off, instead of abusing iterators like Mojang was doing.
|
|
|
|
This also improves reliability of chunk saving, as the previous hack job had a race condition that could
|
|
fail to save some chunks.
|
|
|
|
Then finally, Sleeping will by default be removed, but due to known issues with 1.9, a config option was added.
|
|
But if sleeps are to remain enabled, we at least lower the sleep interval so it doesn't have as much negative impact.
|
|
|
|
diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java
|
|
index cc69ff3a4..f80b385ff 100644
|
|
--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java
|
|
+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java
|
|
@@ -217,4 +217,10 @@ public class PaperConfig {
|
|
" - Interval: " + timeSummary(Timings.getHistoryInterval() / 20) +
|
|
" - Length: " + timeSummary(Timings.getHistoryLength() / 20));
|
|
}
|
|
+
|
|
+ public static boolean enableFileIOThreadSleep;
|
|
+ private static void enableFileIOThreadSleep() {
|
|
+ enableFileIOThreadSleep = getBoolean("settings.sleep-between-chunk-saves", false);
|
|
+ if (enableFileIOThreadSleep) Bukkit.getLogger().info("Enabled sleeping between chunk saves, beware of memory issues");
|
|
+ }
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/server/ChunkCoordIntPair.java b/src/main/java/net/minecraft/server/ChunkCoordIntPair.java
|
|
index b0c004b1f..d2cece265 100644
|
|
--- a/src/main/java/net/minecraft/server/ChunkCoordIntPair.java
|
|
+++ b/src/main/java/net/minecraft/server/ChunkCoordIntPair.java
|
|
@@ -20,6 +20,7 @@ public class ChunkCoordIntPair {
|
|
this.z = (int) (i >> 32);
|
|
}
|
|
|
|
+ public long asLong() { return a(); } // Paper
|
|
public long a() {
|
|
return a(this.x, this.z);
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/server/ChunkRegionLoader.java b/src/main/java/net/minecraft/server/ChunkRegionLoader.java
|
|
index 63533d237..c0785eea0 100644
|
|
--- a/src/main/java/net/minecraft/server/ChunkRegionLoader.java
|
|
+++ b/src/main/java/net/minecraft/server/ChunkRegionLoader.java
|
|
@@ -20,6 +20,7 @@ import java.util.Map.Entry;
|
|
import java.util.function.Consumer;
|
|
import java.util.function.Function;
|
|
import javax.annotation.Nullable;
|
|
+import java.util.concurrent.ConcurrentLinkedQueue; // Paper
|
|
import org.apache.logging.log4j.LogManager;
|
|
import org.apache.logging.log4j.Logger;
|
|
// Spigot start
|
|
@@ -29,8 +30,28 @@ import org.spigotmc.SupplierUtils;
|
|
|
|
public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver {
|
|
|
|
+ // Paper start - Chunk queue improvements
|
|
+ private static class QueuedChunk {
|
|
+ public ChunkCoordIntPair coords;
|
|
+ public Supplier<NBTTagCompound> compoundSupplier;
|
|
+ public Runnable onSave;
|
|
+
|
|
+ public QueuedChunk(Runnable run) {
|
|
+ this.coords = null;
|
|
+ this.compoundSupplier = null;
|
|
+ this.onSave = run;
|
|
+ }
|
|
+
|
|
+ public QueuedChunk(ChunkCoordIntPair coords, Supplier<NBTTagCompound> compoundSupplier) {
|
|
+ this.coords = coords;
|
|
+ this.compoundSupplier = compoundSupplier;
|
|
+ }
|
|
+ }
|
|
+ final private ConcurrentLinkedQueue<QueuedChunk> queue = new ConcurrentLinkedQueue<>();
|
|
+ // Paper end
|
|
+
|
|
private static final Logger a = LogManager.getLogger();
|
|
- private final Map<ChunkCoordIntPair, Supplier<NBTTagCompound>> b = Maps.newHashMap();
|
|
+ private final it.unimi.dsi.fastutil.longs.Long2ObjectMap<Supplier<NBTTagCompound>> saveMap = it.unimi.dsi.fastutil.longs.Long2ObjectMaps.synchronize(new it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap<>()); // Paper
|
|
private final File c;
|
|
private final DataFixer d;
|
|
private PersistentStructureLegacy e;
|
|
@@ -80,7 +101,7 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver {
|
|
|
|
@Nullable
|
|
private NBTTagCompound a(DimensionManager dimensionmanager, @Nullable PersistentCollection persistentcollection, int i, int j, @Nullable GeneratorAccess generatoraccess) throws IOException {
|
|
- NBTTagCompound nbttagcompound = SupplierUtils.getIfExists(this.b.get(new ChunkCoordIntPair(i, j))); // Spigot
|
|
+ NBTTagCompound nbttagcompound = SupplierUtils.getIfExists(this.saveMap.get(ChunkCoordIntPair.asLong(i, j))); // Spigot // Paper
|
|
|
|
if (nbttagcompound != null) {
|
|
return nbttagcompound;
|
|
@@ -308,7 +329,7 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver {
|
|
};
|
|
}
|
|
|
|
- this.a(chunkcoordintpair, SupplierUtils.createUnivaluedSupplier(completion, unloaded && this.b.size() < SAVE_QUEUE_TARGET_SIZE));
|
|
+ this.a(chunkcoordintpair, SupplierUtils.createUnivaluedSupplier(completion, unloaded)); // Paper - Remove save queue target size
|
|
// Spigot end
|
|
} catch (Exception exception) {
|
|
ChunkRegionLoader.a.error("Failed to save chunk", exception);
|
|
@@ -317,7 +338,8 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver {
|
|
}
|
|
|
|
protected void a(ChunkCoordIntPair chunkcoordintpair, Supplier<NBTTagCompound> nbttagcompound) { // Spigot
|
|
- this.b.put(chunkcoordintpair, nbttagcompound);
|
|
+ this.saveMap.put(chunkcoordintpair.asLong(), nbttagcompound); // Paper
|
|
+ queue.add(new QueuedChunk(chunkcoordintpair, nbttagcompound)); // Paper - Chunk queue improvements
|
|
FileIOThread.a().a(this);
|
|
}
|
|
|
|
@@ -327,20 +349,24 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver {
|
|
}
|
|
|
|
private boolean processSaveQueueEntry(boolean logCompletion) {
|
|
- Iterator<Entry<ChunkCoordIntPair, Supplier<NBTTagCompound>>> iterator = this.b.entrySet().iterator(); // Spigot
|
|
-
|
|
- if (!iterator.hasNext()) {
|
|
+ // Paper start - Chunk queue improvements
|
|
+ QueuedChunk chunk = queue.poll();
|
|
+ if (chunk == null) {
|
|
+ // Paper - end
|
|
if (logCompletion) { // CraftBukkit
|
|
ChunkRegionLoader.a.info("ThreadedAnvilChunkStorage ({}): All chunks are saved", this.c.getName());
|
|
}
|
|
|
|
return false;
|
|
} else {
|
|
- Entry<ChunkCoordIntPair, NBTTagCompound> entry = (Entry) iterator.next();
|
|
-
|
|
- iterator.remove();
|
|
- ChunkCoordIntPair chunkcoordintpair = (ChunkCoordIntPair) entry.getKey();
|
|
- Supplier<NBTTagCompound> nbttagcompound = (Supplier<NBTTagCompound>) entry.getValue(); // Spigot
|
|
+ // Paper start
|
|
+ if (chunk.onSave != null) {
|
|
+ chunk.onSave.run();
|
|
+ return true;
|
|
+ }
|
|
+ // Paper end
|
|
+ ChunkCoordIntPair chunkcoordintpair = chunk.coords; // Paper - Chunk queue improvements
|
|
+ Supplier<NBTTagCompound> nbttagcompound = chunk.compoundSupplier; // Spigot // Paper
|
|
|
|
if (nbttagcompound == null) {
|
|
return true;
|
|
@@ -349,6 +375,15 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver {
|
|
// CraftBukkit start
|
|
RegionFileCache.write(this.c, chunkcoordintpair.x, chunkcoordintpair.z, SupplierUtils.getIfExists(nbttagcompound)); // Spigot
|
|
|
|
+ // Paper start remove from map only if this was the latest version of the chunk
|
|
+ synchronized (this.saveMap) {
|
|
+ long k = chunkcoordintpair.asLong();
|
|
+ // This will not equal if a newer version is still pending - wait until newest is saved to remove
|
|
+ if (this.saveMap.get(k) == chunk.compoundSupplier) {
|
|
+ this.saveMap.remove(k);
|
|
+ }
|
|
+ }
|
|
+ // Paper end
|
|
/*
|
|
NBTCompressedStreamTools.a(nbttagcompound, (DataOutput) dataoutputstream);
|
|
dataoutputstream.close();
|
|
diff --git a/src/main/java/net/minecraft/server/FileIOThread.java b/src/main/java/net/minecraft/server/FileIOThread.java
|
|
index 8c3537ab8..3c688f546 100644
|
|
--- a/src/main/java/net/minecraft/server/FileIOThread.java
|
|
+++ b/src/main/java/net/minecraft/server/FileIOThread.java
|
|
@@ -38,20 +38,21 @@ public class FileIOThread implements Runnable {
|
|
IAsyncChunkSaver iasyncchunksaver = (IAsyncChunkSaver) this.c.get(i);
|
|
boolean flag;
|
|
|
|
- synchronized (iasyncchunksaver) {
|
|
+ //synchronized (iasyncchunksaver) { // Paper - remove synchronized
|
|
flag = iasyncchunksaver.a();
|
|
- }
|
|
+ //} // Paper
|
|
|
|
if (!flag) {
|
|
this.c.remove(i--);
|
|
++this.e;
|
|
}
|
|
|
|
+ if (com.destroystokyo.paper.PaperConfig.enableFileIOThreadSleep) { // Paper
|
|
try {
|
|
- Thread.sleep(this.f ? 0L : 10L);
|
|
+ Thread.sleep(this.f ? 0L : 1L); // Paper
|
|
} catch (InterruptedException interruptedexception) {
|
|
interruptedexception.printStackTrace();
|
|
- }
|
|
+ }} // Paper
|
|
}
|
|
|
|
if (this.c.isEmpty()) {
|
|
--
|
|
2.20.1
|
|
|