Nuke IOWorker, make stuff compile (#2733)

* remove removed patch cause its not removed anymore

* Nuke IOWorker, oh, and also make it compile

* synchronize writes properly

* Remove note about IOWorker
This commit is contained in:
MiniDigger 2019-12-13 14:46:45 +01:00 committed by Shane Freeder
parent 4565495711
commit bd93836d4c
2 changed files with 151 additions and 420 deletions

View File

@ -1,11 +1,8 @@
From 867219c4f28a3b9b5ea9dfe010569d45b620f1e1 Mon Sep 17 00:00:00 2001 From 783755ca4f609df8e98ca724b6efa576e29bd117 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com> From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Sat, 13 Jul 2019 09:23:10 -0700 Date: Sat, 13 Jul 2019 09:23:10 -0700
Subject: [PATCH] Asynchronous chunk IO and loading Subject: [PATCH] Asynchronous chunk IO and loading
THIS PATCH NEEDS RE-EVALUTING AND WILL LIKELY NOT WORK AS-IS RIGHT THIS SECOND
- Pending investigation of IOWorker changes (Will do this when not too tired)
This patch re-adds a file IO thread as well as shoving de-serializing This patch re-adds a file IO thread as well as shoving de-serializing
chunk NBT data onto worker threads. This patch also will shove chunk NBT data onto worker threads. This patch also will shove
chunk data serialization onto the same worker threads when the chunk chunk data serialization onto the same worker threads when the chunk
@ -2826,10 +2823,10 @@ index 721021791..f7156acb8 100644
; ;
} }
diff --git a/src/main/java/net/minecraft/server/IChunkLoader.java b/src/main/java/net/minecraft/server/IChunkLoader.java diff --git a/src/main/java/net/minecraft/server/IChunkLoader.java b/src/main/java/net/minecraft/server/IChunkLoader.java
index 2f95174fc..1025e01d5 100644 index 2f95174fc..134c76065 100644
--- a/src/main/java/net/minecraft/server/IChunkLoader.java --- a/src/main/java/net/minecraft/server/IChunkLoader.java
+++ b/src/main/java/net/minecraft/server/IChunkLoader.java +++ b/src/main/java/net/minecraft/server/IChunkLoader.java
@@ -3,6 +3,10 @@ package net.minecraft.server; @@ -3,37 +3,49 @@ package net.minecraft.server;
import com.mojang.datafixers.DataFixer; import com.mojang.datafixers.DataFixer;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@ -2840,8 +2837,11 @@ index 2f95174fc..1025e01d5 100644
import java.util.function.Supplier; import java.util.function.Supplier;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@@ -11,7 +15,9 @@ public class IChunkLoader implements AutoCloseable { -public class IChunkLoader implements AutoCloseable {
private final IOWorker a; public IOWorker getIOWorker() { return a; } // Paper - OBFHELPER +public class IChunkLoader extends RegionFileCache implements AutoCloseable {
- private final IOWorker a; public IOWorker getIOWorker() { return a; } // Paper - OBFHELPER
+// private final IOWorker a; public IOWorker getIOWorker() { return a; } // Paper - OBFHELPER - nuke IOWorker
protected final DataFixer b; protected final DataFixer b;
@Nullable @Nullable
- private PersistentStructureLegacy c; - private PersistentStructureLegacy c;
@ -2850,8 +2850,13 @@ index 2f95174fc..1025e01d5 100644
+ private final Object persistentDataLock = new Object(); // Paper + private final Object persistentDataLock = new Object(); // Paper
public IChunkLoader(File file, DataFixer datafixer) { public IChunkLoader(File file, DataFixer datafixer) {
+ super(file);
this.b = datafixer; this.b = datafixer;
@@ -22,18 +28,23 @@ public class IChunkLoader implements AutoCloseable { - this.a = new IOWorker(new RegionFileCache(file), "chunk");
+// this.a = new IOWorker(new RegionFileCache(file), "chunk"); // Paper - nuke IOWorker
}
// CraftBukkit start
private boolean check(ChunkProviderServer cps, int x, int z) throws IOException { private boolean check(ChunkProviderServer cps, int x, int z) throws IOException {
ChunkCoordIntPair pos = new ChunkCoordIntPair(x, z); ChunkCoordIntPair pos = new ChunkCoordIntPair(x, z);
if (cps != null) { if (cps != null) {
@ -2883,7 +2888,7 @@ index 2f95174fc..1025e01d5 100644
ChunkStatus status = ChunkStatus.a(level.getString("Status")); ChunkStatus status = ChunkStatus.a(level.getString("Status"));
if (status != null && status.b(ChunkStatus.FEATURES)) { if (status != null && status.b(ChunkStatus.FEATURES)) {
@@ -64,11 +75,13 @@ public class IChunkLoader implements AutoCloseable { @@ -64,11 +76,13 @@ public class IChunkLoader implements AutoCloseable {
if (i < 1493) { if (i < 1493) {
nbttagcompound = GameProfileSerializer.a(this.b, DataFixTypes.CHUNK, nbttagcompound, i, 1493); nbttagcompound = GameProfileSerializer.a(this.b, DataFixTypes.CHUNK, nbttagcompound, i, 1493);
if (nbttagcompound.getCompound("Level").getBoolean("hasLegacyStructureData")) { if (nbttagcompound.getCompound("Level").getBoolean("hasLegacyStructureData")) {
@ -2897,14 +2902,26 @@ index 2f95174fc..1025e01d5 100644
} }
} }
@@ -89,10 +102,12 @@ public class IChunkLoader implements AutoCloseable { @@ -84,24 +98,28 @@ public class IChunkLoader implements AutoCloseable {
return this.a.a(chunkcoordintpair); return nbttagcompound.hasKeyOfType("DataVersion", 99) ? nbttagcompound.getInt("DataVersion") : -1;
} }
- @Nullable
- public NBTTagCompound read(ChunkCoordIntPair chunkcoordintpair) throws IOException {
- return this.a.a(chunkcoordintpair);
- }
-
- public void a(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) { - public void a(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) {
- this.a.a(chunkcoordintpair, nbttagcompound);
+// Paper start - nuke IOWorker
+// @Nullable
+// public NBTTagCompound read(ChunkCoordIntPair chunkcoordintpair) throws IOException {
+// return this.a.a(chunkcoordintpair);
+// }
+//
+ public void a(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException { write(chunkcoordintpair, nbttagcompound); } // Paper OBFHELPER + public void a(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException { write(chunkcoordintpair, nbttagcompound); } // Paper OBFHELPER
+ public void write(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException { // Paper - OBFHELPER - (Switched around for safety) + public void write(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException { // Paper - OBFHELPER - (Switched around for safety)
this.a.a(chunkcoordintpair, nbttagcompound); + super.write(chunkcoordintpair, nbttagcompound);
if (this.c != null) { if (this.c != null) {
- this.c.a(chunkcoordintpair.pair()); - this.c.a(chunkcoordintpair.pair());
+ synchronized (this.persistentDataLock) { // Paper - Async chunk loading + synchronized (this.persistentDataLock) { // Paper - Async chunk loading
@ -2912,6 +2929,24 @@ index 2f95174fc..1025e01d5 100644
} }
} }
-
- public void i() {
- this.a.a().join();
- }
-
- public void close() throws IOException {
- this.a.close();
- }
+//
+// public void i() {
+// this.a.a().join();
+// }
+//
+// public void close() throws IOException {
+// this.a.close();
+// }
+// Paper end
}
diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java
index 25a87c2d3..c02c53b50 100644 index 25a87c2d3..c02c53b50 100644
--- a/src/main/java/net/minecraft/server/MCUtil.java --- a/src/main/java/net/minecraft/server/MCUtil.java
@ -2939,7 +2974,7 @@ index 8e15aba7f..edb3a6035 100644
public String getServerIp() { public String getServerIp() {
diff --git a/src/main/java/net/minecraft/server/NextTickListEntry.java b/src/main/java/net/minecraft/server/NextTickListEntry.java diff --git a/src/main/java/net/minecraft/server/NextTickListEntry.java b/src/main/java/net/minecraft/server/NextTickListEntry.java
index 8471920b8..04429a274 100644 index e9c405fb5..33cfeabde 100644
--- a/src/main/java/net/minecraft/server/NextTickListEntry.java --- a/src/main/java/net/minecraft/server/NextTickListEntry.java
+++ b/src/main/java/net/minecraft/server/NextTickListEntry.java +++ b/src/main/java/net/minecraft/server/NextTickListEntry.java
@@ -4,7 +4,7 @@ import java.util.Comparator; @@ -4,7 +4,7 @@ import java.util.Comparator;
@ -2999,7 +3034,7 @@ index 7a1578afa..0fb9c1e44 100644
completablefuture = (CompletableFuture) this.statusFutures.get(i); completablefuture = (CompletableFuture) this.statusFutures.get(i);
if (completablefuture != null) { if (completablefuture != null) {
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
index 6a54ccb86..66bd402e9 100644 index 6a54ccb86..fce37d0d6 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java --- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java +++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -63,7 +63,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { @@ -63,7 +63,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@ -3064,15 +3099,16 @@ index 6a54ccb86..66bd402e9 100644
mutableboolean.setTrue(); mutableboolean.setTrue();
}); });
} while (mutableboolean.isTrue()); } while (mutableboolean.isTrue());
@@ -354,6 +355,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { @@ -354,18 +355,20 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
this.b(() -> { this.b(() -> {
return true; return true;
}); });
- this.i();
+ this.world.asyncChunkTaskManager.flush(); // Paper - flush to preserve behavior compat with pre-async behaviour + this.world.asyncChunkTaskManager.flush(); // Paper - flush to preserve behavior compat with pre-async behaviour
this.i(); +// this.i(); // Paper - nuke IOWorker
PlayerChunkMap.LOGGER.info("ThreadedAnvilChunkStorage ({}): All chunks are saved", this.w.getName()); PlayerChunkMap.LOGGER.info("ThreadedAnvilChunkStorage ({}): All chunks are saved", this.w.getName());
} else { } else {
@@ -361,11 +363,12 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { this.visibleChunks.values().stream().filter(PlayerChunk::hasBeenLoaded).forEach((playerchunk) -> {
IChunkAccess ichunkaccess = (IChunkAccess) playerchunk.getChunkSave().getNow(null); // CraftBukkit - decompile error IChunkAccess ichunkaccess = (IChunkAccess) playerchunk.getChunkSave().getNow(null); // CraftBukkit - decompile error
if (ichunkaccess instanceof ProtoChunkExtension || ichunkaccess instanceof Chunk) { if (ichunkaccess instanceof ProtoChunkExtension || ichunkaccess instanceof Chunk) {
@ -3392,7 +3428,14 @@ index 6a54ccb86..66bd402e9 100644
@Nullable @Nullable
public NBTTagCompound readChunkData(ChunkCoordIntPair chunkcoordintpair) throws IOException { // Paper - private -> public public NBTTagCompound readChunkData(ChunkCoordIntPair chunkcoordintpair) throws IOException { // Paper - private -> public
NBTTagCompound nbttagcompound = this.read(chunkcoordintpair); NBTTagCompound nbttagcompound = this.read(chunkcoordintpair);
@@ -927,27 +1087,47 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { @@ -921,33 +1081,53 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
// Paper start - chunk status cache "api"
public ChunkStatus getChunkStatusOnDiskIfCached(ChunkCoordIntPair chunkPos) {
- RegionFile regionFile = this.getIOWorker().getRegionFileCache().getRegionFileIfLoaded(chunkPos);
+ RegionFile regionFile = this.getRegionFileIfLoaded(chunkPos);
return regionFile == null ? null : regionFile.getStatusIfCached(chunkPos.x, chunkPos.z);
} }
public ChunkStatus getChunkStatusOnDisk(ChunkCoordIntPair chunkPos) throws IOException { public ChunkStatus getChunkStatusOnDisk(ChunkCoordIntPair chunkPos) throws IOException {
@ -3414,7 +3457,7 @@ index 6a54ccb86..66bd402e9 100644
} }
+ // Paper end + // Paper end
+ synchronized (this) { // Paper - async io + synchronized (this) { // Paper - async io
+ RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, false); + RegionFile regionFile = this.getFile(chunkPos, false);
+ +
+ if (!regionFile.chunkExists(chunkPos)) { + if (!regionFile.chunkExists(chunkPos)) {
+ return null; + return null;
@ -3442,7 +3485,7 @@ index 6a54ccb86..66bd402e9 100644
public void updateChunkStatusOnDisk(ChunkCoordIntPair chunkPos, @Nullable NBTTagCompound compound) throws IOException { public void updateChunkStatusOnDisk(ChunkCoordIntPair chunkPos, @Nullable NBTTagCompound compound) throws IOException {
- RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, false); - RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, false);
+ synchronized (this) { + synchronized (this) {
+ RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, false); + RegionFile regionFile = this.getFile(chunkPos, false);
- regionFile.setStatus(chunkPos.x, chunkPos.z, ChunkRegionLoader.getStatus(compound)); - regionFile.setStatus(chunkPos.x, chunkPos.z, ChunkRegionLoader.getStatus(compound));
+ regionFile.setStatus(chunkPos.x, chunkPos.z, ChunkRegionLoader.getStatus(compound)); + regionFile.setStatus(chunkPos.x, chunkPos.z, ChunkRegionLoader.getStatus(compound));
@ -3478,7 +3521,7 @@ index 6a54ccb86..66bd402e9 100644
+ synchronized (world.getChunkProvider().playerChunkMap) { + synchronized (world.getChunkProvider().playerChunkMap) {
+ net.minecraft.server.RegionFile file; + net.minecraft.server.RegionFile file;
+ try { + try {
+ file = world.getChunkProvider().playerChunkMap.getIOWorker().getRegionFileCache().getFile(chunkPos, false); + file = world.getChunkProvider().playerChunkMap.getFile(chunkPos, false);
+ } catch (IOException ex) { + } catch (IOException ex) {
+ throw new RuntimeException(ex); + throw new RuntimeException(ex);
+ } + }
@ -3499,9 +3542,18 @@ index 6a54ccb86..66bd402e9 100644
return this.m; return this.m;
} }
diff --git a/src/main/java/net/minecraft/server/RegionFile.java b/src/main/java/net/minecraft/server/RegionFile.java diff --git a/src/main/java/net/minecraft/server/RegionFile.java b/src/main/java/net/minecraft/server/RegionFile.java
index 7eb87c517..551e91869 100644 index 7eb87c517..b252684c2 100644
--- a/src/main/java/net/minecraft/server/RegionFile.java --- a/src/main/java/net/minecraft/server/RegionFile.java
+++ b/src/main/java/net/minecraft/server/RegionFile.java +++ b/src/main/java/net/minecraft/server/RegionFile.java
@@ -218,7 +218,7 @@ public class RegionFile implements AutoCloseable {
return (i + 4096 - 1) / 4096;
}
- public boolean b(ChunkCoordIntPair chunkcoordintpair) {
+ public synchronized boolean b(ChunkCoordIntPair chunkcoordintpair) { // Paper - synchronized
int i = this.getOffset(chunkcoordintpair);
if (i == 0) {
@@ -373,7 +373,7 @@ public class RegionFile implements AutoCloseable { @@ -373,7 +373,7 @@ public class RegionFile implements AutoCloseable {
return chunkcoordintpair.j() + chunkcoordintpair.k() * 32; return chunkcoordintpair.j() + chunkcoordintpair.k() * 32;
} }
@ -3512,10 +3564,19 @@ index 7eb87c517..551e91869 100644
try { try {
this.c(); this.c();
diff --git a/src/main/java/net/minecraft/server/RegionFileCache.java b/src/main/java/net/minecraft/server/RegionFileCache.java diff --git a/src/main/java/net/minecraft/server/RegionFileCache.java b/src/main/java/net/minecraft/server/RegionFileCache.java
index 1a6be7c6d..9a0fdec47 100644 index 1a6be7c6d..386f47dc8 100644
--- a/src/main/java/net/minecraft/server/RegionFileCache.java --- a/src/main/java/net/minecraft/server/RegionFileCache.java
+++ b/src/main/java/net/minecraft/server/RegionFileCache.java +++ b/src/main/java/net/minecraft/server/RegionFileCache.java
@@ -20,7 +20,7 @@ public final class RegionFileCache implements AutoCloseable { @@ -9,7 +9,7 @@ import java.io.File;
import java.io.IOException;
import javax.annotation.Nullable;
-public final class RegionFileCache implements AutoCloseable {
+public class RegionFileCache implements AutoCloseable { // Paper - no final
public final Long2ObjectLinkedOpenHashMap<RegionFile> cache = new Long2ObjectLinkedOpenHashMap();
private final File b;
@@ -20,12 +20,12 @@ public final class RegionFileCache implements AutoCloseable {
// Paper start // Paper start
@ -3524,6 +3585,21 @@ index 1a6be7c6d..9a0fdec47 100644
return this.cache.getAndMoveToFirst(ChunkCoordIntPair.pair(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ())); return this.cache.getAndMoveToFirst(ChunkCoordIntPair.pair(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ()));
} }
// Paper end
- public RegionFile getFile(ChunkCoordIntPair chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit // Paper - private > public
+ public synchronized RegionFile getFile(ChunkCoordIntPair chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit // Paper - private > public, synchronize
long i = ChunkCoordIntPair.pair(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ());
RegionFile regionfile = (RegionFile) this.cache.getAndMoveToFirst(i);
@@ -126,7 +126,7 @@ public final class RegionFileCache implements AutoCloseable {
// Paper end
}
- public void close() throws IOException {
+ public synchronized void close() throws IOException { // Paper -> synchronized
ObjectIterator objectiterator = this.cache.values().iterator();
while (objectiterator.hasNext()) {
@@ -138,7 +138,7 @@ public final class RegionFileCache implements AutoCloseable { @@ -138,7 +138,7 @@ public final class RegionFileCache implements AutoCloseable {
} }
@ -3534,19 +3610,35 @@ index 1a6be7c6d..9a0fdec47 100644
return regionfile != null ? regionfile.chunkExists(pos) : false; return regionfile != null ? regionfile.chunkExists(pos) : false;
diff --git a/src/main/java/net/minecraft/server/RegionFileSection.java b/src/main/java/net/minecraft/server/RegionFileSection.java diff --git a/src/main/java/net/minecraft/server/RegionFileSection.java b/src/main/java/net/minecraft/server/RegionFileSection.java
index db9f0196b..e7ea04861 100644 index db9f0196b..a6d8ef5eb 100644
--- a/src/main/java/net/minecraft/server/RegionFileSection.java --- a/src/main/java/net/minecraft/server/RegionFileSection.java
+++ b/src/main/java/net/minecraft/server/RegionFileSection.java +++ b/src/main/java/net/minecraft/server/RegionFileSection.java
@@ -25,7 +25,7 @@ public class RegionFileSection<R extends MinecraftSerializable> implements AutoC @@ -20,28 +20,29 @@ import javax.annotation.Nullable;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
-public class RegionFileSection<R extends MinecraftSerializable> implements AutoCloseable {
+public class RegionFileSection<R extends MinecraftSerializable> extends RegionFileCache implements AutoCloseable { // Paper - nuke IOWorker
private static final Logger LOGGER = LogManager.getLogger(); private static final Logger LOGGER = LogManager.getLogger();
private final IOWorker b; - private final IOWorker b;
+// private final IOWorker b;
private final Long2ObjectMap<Optional<R>> c = new Long2ObjectOpenHashMap(); private final Long2ObjectMap<Optional<R>> c = new Long2ObjectOpenHashMap();
- private final LongLinkedOpenHashSet d = new LongLinkedOpenHashSet(); - private final LongLinkedOpenHashSet d = new LongLinkedOpenHashSet();
+ protected final LongLinkedOpenHashSet d = new LongLinkedOpenHashSet(); // Paper - private -> protected + protected final LongLinkedOpenHashSet d = new LongLinkedOpenHashSet(); // Paper - private -> protected
private final BiFunction<Runnable, Dynamic<?>, R> e; private final BiFunction<Runnable, Dynamic<?>, R> e;
private final Function<Runnable, R> f; private final Function<Runnable, R> f;
private final DataFixer g; private final DataFixer g;
@@ -40,8 +40,8 @@ public class RegionFileSection<R extends MinecraftSerializable> implements AutoC private final DataFixTypes h;
public RegionFileSection(File file, BiFunction<Runnable, Dynamic<?>, R> bifunction, Function<Runnable, R> function, DataFixer datafixer, DataFixTypes datafixtypes) {
+ super(file); // Paper - nuke IOWorker
this.e = bifunction;
this.f = function;
this.g = datafixer;
this.h = datafixtypes;
- this.b = new IOWorker(new RegionFileCache(file), file.getName());
+// this.b = new IOWorker(new RegionFileCache(file), file.getName()); // Paper - nuke IOWorker
} }
protected void a(BooleanSupplier booleansupplier) { protected void a(BooleanSupplier booleansupplier) {
@ -3557,7 +3649,7 @@ index db9f0196b..e7ea04861 100644
this.d(chunkcoordintpair); this.d(chunkcoordintpair);
} }
@@ -95,7 +95,12 @@ public class RegionFileSection<R extends MinecraftSerializable> implements AutoC @@ -95,13 +96,18 @@ public class RegionFileSection<R extends MinecraftSerializable> implements AutoC
} }
private void b(ChunkCoordIntPair chunkcoordintpair) { private void b(ChunkCoordIntPair chunkcoordintpair) {
@ -3571,7 +3663,14 @@ index db9f0196b..e7ea04861 100644
} }
@Nullable @Nullable
@@ -143,7 +148,7 @@ public class RegionFileSection<R extends MinecraftSerializable> implements AutoC private NBTTagCompound c(ChunkCoordIntPair chunkcoordintpair) {
try {
- return this.b.a(chunkcoordintpair);
+ return this.read(chunkcoordintpair); // Paper - nuke IOWorker
} catch (IOException ioexception) {
RegionFileSection.LOGGER.error("Error reading chunk {} data from disk", chunkcoordintpair, ioexception);
return null;
@@ -143,17 +149,31 @@ public class RegionFileSection<R extends MinecraftSerializable> implements AutoC
} }
private void d(ChunkCoordIntPair chunkcoordintpair) { private void d(ChunkCoordIntPair chunkcoordintpair) {
@ -3580,7 +3679,11 @@ index db9f0196b..e7ea04861 100644
NBTBase nbtbase = (NBTBase) dynamic.getValue(); NBTBase nbtbase = (NBTBase) dynamic.getValue();
if (nbtbase instanceof NBTTagCompound) { if (nbtbase instanceof NBTTagCompound) {
@@ -154,6 +159,20 @@ public class RegionFileSection<R extends MinecraftSerializable> implements AutoC - this.b.a(chunkcoordintpair, (NBTTagCompound) nbtbase);
+ try { this.write(chunkcoordintpair, (NBTTagCompound) nbtbase); } catch (IOException ioexception) { RegionFileSection.LOGGER.error("Error writing data to disk", ioexception); } // Paper - nuke IOWorker // TODO make this write async
} else {
RegionFileSection.LOGGER.error("Expected compound tag, got {}", nbtbase);
}
} }
@ -3601,7 +3704,7 @@ index db9f0196b..e7ea04861 100644
private <T> Dynamic<T> a(ChunkCoordIntPair chunkcoordintpair, DynamicOps<T> dynamicops) { private <T> Dynamic<T> a(ChunkCoordIntPair chunkcoordintpair, DynamicOps<T> dynamicops) {
Map<T, T> map = Maps.newHashMap(); Map<T, T> map = Maps.newHashMap();
@@ -190,9 +209,9 @@ public class RegionFileSection<R extends MinecraftSerializable> implements AutoC @@ -190,9 +210,9 @@ public class RegionFileSection<R extends MinecraftSerializable> implements AutoC
public void a(ChunkCoordIntPair chunkcoordintpair) { public void a(ChunkCoordIntPair chunkcoordintpair) {
if (!this.d.isEmpty()) { if (!this.d.isEmpty()) {
for (int i = 0; i < 16; ++i) { for (int i = 0; i < 16; ++i) {
@ -3613,10 +3716,17 @@ index db9f0196b..e7ea04861 100644
this.d(chunkcoordintpair); this.d(chunkcoordintpair);
return; return;
} }
@@ -204,4 +223,21 @@ public class RegionFileSection<R extends MinecraftSerializable> implements AutoC @@ -201,7 +221,26 @@ public class RegionFileSection<R extends MinecraftSerializable> implements AutoC
public void close() throws IOException {
this.b.close();
} }
- public void close() throws IOException {
- this.b.close();
+// Paper start - nuke IOWorker
+// public void close() throws IOException {
+// this.b.close();
+// }
+// Paper end
+ +
+ // Paper start - get data function + // Paper start - get data function
+ public NBTTagCompound getData(ChunkCoordIntPair chunkcoordintpair) { + public NBTTagCompound getData(ChunkCoordIntPair chunkcoordintpair) {
@ -3632,7 +3742,7 @@ index db9f0196b..e7ea04861 100644
+ } + }
+ } + }
+ return null; + return null;
+ } }
+ // Paper end + // Paper end
} }
diff --git a/src/main/java/net/minecraft/server/TicketType.java b/src/main/java/net/minecraft/server/TicketType.java diff --git a/src/main/java/net/minecraft/server/TicketType.java b/src/main/java/net/minecraft/server/TicketType.java
@ -3737,7 +3847,7 @@ index c999f8c9b..b59ef1a63 100644
HAS_SPACE(VillagePlaceRecord::d), IS_OCCUPIED(VillagePlaceRecord::e), ANY((villageplacerecord) -> { HAS_SPACE(VillagePlaceRecord::d), IS_OCCUPIED(VillagePlaceRecord::e), ANY((villageplacerecord) -> {
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index 8ea9b34a1..fecbe7914 100644 index 049d4ef4e..59b2fc629 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java --- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java +++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -81,6 +81,79 @@ public class WorldServer extends World { @@ -81,6 +81,79 @@ public class WorldServer extends World {
@ -3762,7 +3872,7 @@ index 8ea9b34a1..fecbe7914 100644
+ RegionFile file; + RegionFile file;
+ +
+ try { + try {
+ file = WorldServer.this.getChunkProvider().playerChunkMap.getVillagePlace().getRegionFile(new ChunkCoordIntPair(chunkX, chunkZ), false); + file = WorldServer.this.getChunkProvider().playerChunkMap.getVillagePlace().getFile(new ChunkCoordIntPair(chunkX, chunkZ), false);
+ } catch (java.io.IOException ex) { + } catch (java.io.IOException ex) {
+ throw new RuntimeException(ex); + throw new RuntimeException(ex);
+ } + }
@ -3797,7 +3907,7 @@ index 8ea9b34a1..fecbe7914 100644
+ RegionFile file; + RegionFile file;
+ +
+ try { + try {
+ file = WorldServer.this.getChunkProvider().playerChunkMap.getRegionFile(new ChunkCoordIntPair(chunkX, chunkZ), false); + file = WorldServer.this.getChunkProvider().playerChunkMap.getFile(new ChunkCoordIntPair(chunkX, chunkZ), false);
+ } catch (java.io.IOException ex) { + } catch (java.io.IOException ex) {
+ throw new RuntimeException(ex); + throw new RuntimeException(ex);
+ } + }
@ -3920,5 +4030,5 @@ index a1d93200e..6ca0ebfde 100644
log.log( Level.SEVERE, "------------------------------" ); log.log( Level.SEVERE, "------------------------------" );
// //
-- --
2.24.1 2.17.1

View File

@ -1,379 +0,0 @@
From 14f4011c2f16754e3f39826237f4822c3b6446b1 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Sat, 15 Jun 2019 08:54:33 -0700
Subject: [PATCH] Fix World#isChunkGenerated calls
Optimize World#loadChunk() too
This patch also adds a chunk status cache on region files (note that
its only purpose is to cache the status on DISK)
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
index 8689e0f9f..56761afdf 100644
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
@@ -28,7 +28,7 @@ public class ChunkProviderServer extends IChunkProvider {
private final WorldServer world;
private final Thread serverThread;
private final LightEngineThreaded lightEngine;
- private final ChunkProviderServer.a serverThreadQueue;
+ public final ChunkProviderServer.a serverThreadQueue; // Paper private -> public
public final PlayerChunkMap playerChunkMap;
private final WorldPersistentData worldPersistentData;
private long lastTickTime;
@@ -109,6 +109,21 @@ public class ChunkProviderServer extends IChunkProvider {
return playerChunk.getFullChunk();
}
+
+ @Nullable
+ public IChunkAccess getChunkAtImmediately(int x, int z) {
+ long k = ChunkCoordIntPair.pair(x, z);
+
+ // Note: Bypass cache to make this MT-Safe
+
+ PlayerChunk playerChunk = this.getChunk(k);
+ if (playerChunk == null) {
+ return null;
+ }
+
+ return playerChunk.getAvailableChunkNow();
+
+ }
// Paper end
@Nullable
diff --git a/src/main/java/net/minecraft/server/ChunkRegionLoader.java b/src/main/java/net/minecraft/server/ChunkRegionLoader.java
index e778c2e85..73f93e494 100644
--- a/src/main/java/net/minecraft/server/ChunkRegionLoader.java
+++ b/src/main/java/net/minecraft/server/ChunkRegionLoader.java
@@ -410,6 +410,17 @@ public class ChunkRegionLoader {
return nbttagcompound;
}
+ // Paper start
+ public static ChunkStatus getStatus(NBTTagCompound compound) {
+ if (compound == null) {
+ return null;
+ }
+
+ // Note: Copied from below
+ return ChunkStatus.getStatus(compound.getCompound("Level").getString("Status"));
+ }
+ // Paper end
+
public static ChunkStatus.Type a(@Nullable NBTTagCompound nbttagcompound) {
if (nbttagcompound != null) {
ChunkStatus chunkstatus = ChunkStatus.a(nbttagcompound.getCompound("Level").getString("Status"));
diff --git a/src/main/java/net/minecraft/server/ChunkStatus.java b/src/main/java/net/minecraft/server/ChunkStatus.java
index dd1822d6f..e324989b4 100644
--- a/src/main/java/net/minecraft/server/ChunkStatus.java
+++ b/src/main/java/net/minecraft/server/ChunkStatus.java
@@ -176,6 +176,7 @@ public class ChunkStatus {
return this.s;
}
+ public ChunkStatus getPreviousStatus() { return this.e(); } // Paper - OBFHELPER
public ChunkStatus e() {
return this.u;
}
@@ -196,6 +197,17 @@ public class ChunkStatus {
return this.y;
}
+ // Paper start
+ public static ChunkStatus getStatus(String name) {
+ try {
+ // We need this otherwise we return EMPTY for invalid names
+ MinecraftKey key = new MinecraftKey(name);
+ return IRegistry.CHUNK_STATUS.getOptional(key).orElse(null);
+ } catch (Exception ex) {
+ return null; // invalid name
+ }
+ }
+ // Paper end
public static ChunkStatus a(String s) {
return (ChunkStatus) IRegistry.CHUNK_STATUS.get(MinecraftKey.a(s));
}
diff --git a/src/main/java/net/minecraft/server/PlayerChunk.java b/src/main/java/net/minecraft/server/PlayerChunk.java
index 14a176d61..98590e233 100644
--- a/src/main/java/net/minecraft/server/PlayerChunk.java
+++ b/src/main/java/net/minecraft/server/PlayerChunk.java
@@ -70,6 +70,19 @@ public class PlayerChunk {
Either<IChunkAccess, PlayerChunk.Failure> either = (Either<IChunkAccess, PlayerChunk.Failure>) statusFuture.getNow(null);
return either == null ? null : (Chunk) either.left().orElse(null);
}
+
+ public IChunkAccess getAvailableChunkNow() {
+ // TODO can we just getStatusFuture(EMPTY)?
+ for (ChunkStatus curr = ChunkStatus.FULL, next = curr.getPreviousStatus(); curr != next; curr = next, next = next.getPreviousStatus()) {
+ CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> future = this.getStatusFutureUnchecked(curr);
+ Either<IChunkAccess, PlayerChunk.Failure> either = future.getNow(null);
+ if (either == null || !either.left().isPresent()) {
+ continue;
+ }
+ return either.left().get();
+ }
+ return null;
+ }
// Paper end
public CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> getStatusFutureUnchecked(ChunkStatus chunkstatus) {
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
index 6f1e48ba4..eb49e9021 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -897,11 +897,61 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
}
@Nullable
- private NBTTagCompound readChunkData(ChunkCoordIntPair chunkcoordintpair) throws IOException {
+ public NBTTagCompound readChunkData(ChunkCoordIntPair chunkcoordintpair) throws IOException { // Paper - private -> public
NBTTagCompound nbttagcompound = this.read(chunkcoordintpair);
- return nbttagcompound == null ? null : this.getChunkData(this.world.getWorldProvider().getDimensionManager(), this.m, nbttagcompound, chunkcoordintpair, world); // CraftBukkit
+ // Paper start - Cache chunk status on disk
+ if (nbttagcompound == null) {
+ return null;
+ }
+
+ nbttagcompound = this.getChunkData(this.world.getWorldProvider().getDimensionManager(), this.m, nbttagcompound, chunkcoordintpair, world); // CraftBukkit
+ if (nbttagcompound == null) {
+ return null;
+ }
+
+ this.updateChunkStatusOnDisk(chunkcoordintpair, nbttagcompound);
+
+ return nbttagcompound;
+ // Paper end
+ }
+
+ // Paper start - chunk status cache "api"
+ public ChunkStatus getChunkStatusOnDiskIfCached(ChunkCoordIntPair chunkPos) {
+ RegionFile regionFile = this.getRegionFileIfLoaded(chunkPos);
+
+ return regionFile == null ? null : regionFile.getStatusIfCached(chunkPos.x, chunkPos.z);
+ }
+
+ public ChunkStatus getChunkStatusOnDisk(ChunkCoordIntPair chunkPos) throws IOException {
+ RegionFile regionFile = this.getRegionFile(chunkPos, false);
+
+ if (!regionFile.chunkExists(chunkPos)) {
+ return null;
+ }
+
+ ChunkStatus status = regionFile.getStatusIfCached(chunkPos.x, chunkPos.z);
+
+ if (status != null) {
+ return status;
+ }
+
+ this.readChunkData(chunkPos);
+
+ return regionFile.getStatusIfCached(chunkPos.x, chunkPos.z);
+ }
+
+ public void updateChunkStatusOnDisk(ChunkCoordIntPair chunkPos, @Nullable NBTTagCompound compound) throws IOException {
+ RegionFile regionFile = this.getRegionFile(chunkPos, false);
+
+ regionFile.setStatus(chunkPos.x, chunkPos.z, ChunkRegionLoader.getStatus(compound));
+ }
+
+ public IChunkAccess getUnloadingChunk(int chunkX, int chunkZ) {
+ PlayerChunk chunkHolder = this.pendingUnload.get(ChunkCoordIntPair.pair(chunkX, chunkZ));
+ return chunkHolder == null ? null : chunkHolder.getAvailableChunkNow();
}
+ // Paper end
boolean isOutsideOfRange(ChunkCoordIntPair chunkcoordintpair) {
// Spigot start
diff --git a/src/main/java/net/minecraft/server/RegionFile.java b/src/main/java/net/minecraft/server/RegionFile.java
index ccc3d6c7a..b487e8060 100644
--- a/src/main/java/net/minecraft/server/RegionFile.java
+++ b/src/main/java/net/minecraft/server/RegionFile.java
@@ -31,6 +31,30 @@ public class RegionFile implements AutoCloseable {
private final int[] d = new int[1024]; private final int[] timestamps = d; // Paper - OBFHELPER
private final List<Boolean> e; // PAIL freeSectors
+ // Paper start - Cache chunk status
+ private final ChunkStatus[] statuses = new ChunkStatus[32 * 32];
+
+ private boolean closed;
+
+ // invoked on write/read
+ public void setStatus(int x, int z, ChunkStatus status) {
+ if (this.closed) {
+ // We've used an invalid region file.
+ throw new IllegalStateException("RegionFile is closed");
+ }
+ this.statuses[this.getChunkLocation(new ChunkCoordIntPair(x, z))] = status;
+ }
+
+ public ChunkStatus getStatusIfCached(int x, int z) {
+ if (this.closed) {
+ // We've used an invalid region file.
+ throw new IllegalStateException("RegionFile is closed");
+ }
+ final int location = this.getChunkLocation(new ChunkCoordIntPair(x, z));
+ return this.statuses[location];
+ }
+ // Paper end
+
public RegionFile(File file) throws IOException {
this.b = new RandomAccessFile(file, "rw");
this.file = file; // Spigot // Paper - We need this earlier
@@ -291,6 +315,7 @@ public class RegionFile implements AutoCloseable {
return this.c[this.f(chunkcoordintpair)];
}
+ public final boolean chunkExists(ChunkCoordIntPair chunkPos) { return this.d(chunkPos); } // Paper - OBFHELPER
public boolean d(ChunkCoordIntPair chunkcoordintpair) {
return this.getOffset(chunkcoordintpair) != 0;
}
@@ -304,6 +329,7 @@ public class RegionFile implements AutoCloseable {
this.c[j] = i; // Spigot - move this to after the write
}
+ private final int getChunkLocation(ChunkCoordIntPair chunkcoordintpair) { return this.f(chunkcoordintpair); } // Paper - OBFHELPER
private int f(ChunkCoordIntPair chunkcoordintpair) {
return chunkcoordintpair.j() + chunkcoordintpair.k() * 32;
}
@@ -318,6 +344,7 @@ public class RegionFile implements AutoCloseable {
}
public void close() throws IOException {
+ this.closed = true; // Paper
this.b.close();
}
diff --git a/src/main/java/net/minecraft/server/RegionFileCache.java b/src/main/java/net/minecraft/server/RegionFileCache.java
index 6f34d8aea..d2b328945 100644
--- a/src/main/java/net/minecraft/server/RegionFileCache.java
+++ b/src/main/java/net/minecraft/server/RegionFileCache.java
@@ -47,6 +47,12 @@ public abstract class RegionFileCache implements AutoCloseable {
// Paper start
}
+ // Paper start
+ public RegionFile getRegionFileIfLoaded(ChunkCoordIntPair chunkcoordintpair) {
+ return this.cache.getAndMoveToFirst(ChunkCoordIntPair.pair(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ()));
+ }
+ // Paper end
+
public RegionFile getRegionFile(ChunkCoordIntPair chunkcoordintpair, boolean existingOnly) throws IOException { return this.a(chunkcoordintpair, existingOnly); } // Paper - OBFHELPER
private RegionFile a(ChunkCoordIntPair chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit
long i = ChunkCoordIntPair.pair(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ());
@@ -110,6 +116,7 @@ public abstract class RegionFileCache implements AutoCloseable {
try {
NBTCompressedStreamTools.writeNBT(nbttagcompound, out);
out.close();
+ regionfile.setStatus(chunk.x, chunk.z, ChunkRegionLoader.getStatus(nbttagcompound)); // Paper - cache status on disk
regionfile.setOversized(chunkX, chunkZ, false);
} catch (RegionFile.ChunkTooLargeException ignored) {
printOversizedLog("ChunkTooLarge! Someone is trying to duplicate.", regionfile.file, chunkX, chunkZ);
@@ -127,6 +134,7 @@ public abstract class RegionFileCache implements AutoCloseable {
if (SIZE_THRESHOLD == OVERZEALOUS_THRESHOLD) {
resetFilterThresholds();
}
+ regionfile.setStatus(chunk.x, chunk.z, ChunkRegionLoader.getStatus(nbttagcompound)); // Paper - cache status on disk
} catch (RegionFile.ChunkTooLargeException e) {
printOversizedLog("ChunkTooLarge even after reduction. Trying in overzealous mode.", regionfile.file, chunkX, chunkZ);
// Eek, major fail. We have retry logic, so reduce threshholds and fall back
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index e42bd2638..2227de3bf 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -18,6 +18,7 @@ import java.util.Objects;
import java.util.Random;
import java.util.Set;
import java.util.UUID;
+import java.util.concurrent.CompletableFuture;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
@@ -408,8 +409,22 @@ public class CraftWorld implements World {
@Override
public boolean isChunkGenerated(int x, int z) {
+ // Paper start - Fix this method
+ if (!Bukkit.isPrimaryThread()) {
+ return CompletableFuture.supplyAsync(() -> {
+ return CraftWorld.this.isChunkGenerated(x, z);
+ }, world.getChunkProvider().serverThreadQueue).join();
+ }
+ IChunkAccess chunk = world.getChunkProvider().getChunkAtImmediately(x, z);
+ if (chunk == null) {
+ chunk = world.getChunkProvider().playerChunkMap.getUnloadingChunk(x, z);
+ }
+ if (chunk != null) {
+ return chunk instanceof ProtoChunkExtension || chunk instanceof net.minecraft.server.Chunk;
+ }
try {
- return world.getChunkProvider().getChunkAtIfCachedImmediately(x, z) != null || world.getChunkProvider().playerChunkMap.chunkExists(new ChunkCoordIntPair(x, z)); // Paper
+ return world.getChunkProvider().playerChunkMap.getChunkStatusOnDisk(new ChunkCoordIntPair(x, z)) == ChunkStatus.FULL;
+ // Paper end
} catch (IOException ex) {
throw new RuntimeException(ex);
}
@@ -521,20 +536,49 @@ public class CraftWorld implements World {
@Override
public boolean loadChunk(int x, int z, boolean generate) {
org.spigotmc.AsyncCatcher.catchOp("chunk load"); // Spigot
- IChunkAccess chunk = world.getChunkProvider().getChunkAt(x, z, generate || isChunkGenerated(x, z) ? ChunkStatus.FULL : ChunkStatus.EMPTY, true); // Paper
+ // Paper start - Optimize this method
+ ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(x, z);
- // If generate = false, but the chunk already exists, we will get this back.
- if (chunk instanceof ProtoChunkExtension) {
- // We then cycle through again to get the full chunk immediately, rather than after the ticket addition
- chunk = world.getChunkProvider().getChunkAt(x, z, ChunkStatus.FULL, true);
- }
+ if (!generate) {
- if (chunk instanceof net.minecraft.server.Chunk) {
- world.getChunkProvider().addTicket(TicketType.PLUGIN, new ChunkCoordIntPair(x, z), 1, Unit.INSTANCE);
- return true;
+ IChunkAccess immediate = world.getChunkProvider().getChunkAtImmediately(x, z);
+ if (immediate == null) {
+ immediate = world.getChunkProvider().playerChunkMap.getUnloadingChunk(x, z);
+ }
+ if (immediate != null) {
+ if (!(immediate instanceof ProtoChunkExtension) && !(immediate instanceof net.minecraft.server.Chunk)) {
+ return false; // not full status
+ }
+ world.getChunkProvider().addTicket(TicketType.PLUGIN, chunkPos, 1, Unit.INSTANCE);
+ world.getChunkAt(x, z); // make sure we're at ticket level 32 or lower
+ return true;
+ }
+
+ net.minecraft.server.RegionFile file;
+ try {
+ file = world.getChunkProvider().playerChunkMap.getRegionFile(chunkPos, false);
+ } catch (IOException ex) {
+ throw new RuntimeException(ex);
+ }
+
+ ChunkStatus status = file.getStatusIfCached(x, z);
+ if (!file.chunkExists(chunkPos) || (status != null && status != ChunkStatus.FULL)) {
+ return false;
+ }
+
+ IChunkAccess chunk = world.getChunkProvider().getChunkAt(x, z, ChunkStatus.EMPTY, true);
+ if (!(chunk instanceof ProtoChunkExtension) && !(chunk instanceof net.minecraft.server.Chunk)) {
+ return false;
+ }
+
+ // fall through to load
+ // we do this so we do not re-read the chunk data on disk
}
- return false;
+ world.getChunkProvider().addTicket(TicketType.PLUGIN, chunkPos, 1, Unit.INSTANCE);
+ world.getChunkProvider().getChunkAt(x, z, ChunkStatus.FULL, true);
+ return true;
+ // Paper end
}
@Override
--
2.24.0