Don't sleep between chunk saves

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.

If there is work to do, then the thread should be doing its work, and only sleep when it is done.
This commit is contained in:
Aikar 2015-09-09 21:16:42 -04:00 committed by Zach Brown
parent c95273f973
commit 88826e053a
2 changed files with 124 additions and 2 deletions

View file

@ -1,4 +1,4 @@
From e3594bfb2e702b31dfb5ed0e2b1c00d58036449c Mon Sep 17 00:00:00 2001
From 53f6a9f493204f2c521e776e3faff4252b1ba69b Mon Sep 17 00:00:00 2001
From: md_5 <md_5@live.com.au>
Date: Sun, 1 Dec 2013 15:10:48 +1100
Subject: [PATCH] mc-dev imports
@ -1945,6 +1945,87 @@ index 0000000..9865681
+ void a(Enchantment enchantment, int i);
+ }
+}
diff --git a/src/main/java/net/minecraft/server/FileIOThread.java b/src/main/java/net/minecraft/server/FileIOThread.java
new file mode 100644
index 0000000..198b00f
--- /dev/null
+++ b/src/main/java/net/minecraft/server/FileIOThread.java
@@ -0,0 +1,75 @@
+package net.minecraft.server;
+
+import com.google.common.collect.Lists;
+import java.util.Collections;
+import java.util.List;
+
+public class FileIOThread implements Runnable {
+
+ private static final FileIOThread a = new FileIOThread();
+ private List<IAsyncChunkSaver> b = Collections.synchronizedList(Lists.<IAsyncChunkSaver>newArrayList());
+ private volatile long c;
+ private volatile long d;
+ private volatile boolean e;
+
+ private FileIOThread() {
+ Thread thread = new Thread(this, "File IO Thread");
+
+ thread.setPriority(1);
+ thread.start();
+ }
+
+ public static FileIOThread a() {
+ return FileIOThread.a;
+ }
+
+ public void run() {
+ while (true) {
+ this.c();
+ }
+ }
+
+ private void c() {
+ for (int i = 0; i < this.b.size(); ++i) {
+ IAsyncChunkSaver iasyncchunksaver = (IAsyncChunkSaver) this.b.get(i);
+ boolean flag = iasyncchunksaver.c();
+
+ if (!flag) {
+ this.b.remove(i--);
+ ++this.d;
+ }
+
+ try {
+ Thread.sleep(this.e ? 0L : 10L);
+ } catch (InterruptedException interruptedexception) {
+ interruptedexception.printStackTrace();
+ }
+ }
+
+ if (this.b.isEmpty()) {
+ try {
+ Thread.sleep(25L);
+ } catch (InterruptedException interruptedexception1) {
+ interruptedexception1.printStackTrace();
+ }
+ }
+
+ }
+
+ public void a(IAsyncChunkSaver iasyncchunksaver) {
+ if (!this.b.contains(iasyncchunksaver)) {
+ ++this.c;
+ this.b.add(iasyncchunksaver);
+ }
+ }
+
+ public void b() throws InterruptedException {
+ this.e = true;
+
+ while (this.c != this.d) {
+ Thread.sleep(10L);
+ }
+
+ this.e = false;
+ }
+}
diff --git a/src/main/java/net/minecraft/server/GameProfileBanEntry.java b/src/main/java/net/minecraft/server/GameProfileBanEntry.java
new file mode 100644
index 0000000..27ce9d9
@ -4930,5 +5011,5 @@ index 0000000..31fc0a9
+ }
+}
--
2.1.4
1.9.1

View file

@ -0,0 +1,41 @@
From e2baf643e39f01e43476500f56f49ee1e284a1fb Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Wed, 9 Sep 2015 21:09:58 -0400
Subject: [PATCH] Don't sleep between chunk saves
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.
If there is work to do, then the thread should be doing its work, and only sleep when it is done.
diff --git a/src/main/java/net/minecraft/server/FileIOThread.java b/src/main/java/net/minecraft/server/FileIOThread.java
index 198b00f..c9b3bf4 100644
--- a/src/main/java/net/minecraft/server/FileIOThread.java
+++ b/src/main/java/net/minecraft/server/FileIOThread.java
@@ -39,11 +39,12 @@ public class FileIOThread implements Runnable {
++this.d;
}
+ /* // Spigot start - don't sleep in between chunks so we unload faster.
try {
Thread.sleep(this.e ? 0L : 10L);
} catch (InterruptedException interruptedexception) {
interruptedexception.printStackTrace();
- }
+ } */ // Spigot end
}
if (this.b.isEmpty()) {
--
2.1.4