Yatopia/patches/server/0058-New-nbt-cache.patch
Simon Gardling cc91a8080f
Upstream (#461)
* Updated Upstream and Sidestream(s) (Paper)

Upstream/An Sidestream has released updates that appears to apply and compile correctly
This update has NOT been tested by YatopiaMC and as with ANY update, please do your own testing.

Paper Changes:
8a29f5894 [Auto] Updated Upstream (Bukkit/CraftBukkit)
8756d232c Expose server protocol version (#5416)

* Updated Upstream and Sidestream(s) (Tuinity/Purpur)

Upstream/An Sidestream has released updates that appears to apply and compile correctly
This update has NOT been tested by YatopiaMC and as with ANY update, please do your own testing.

Tuinity Changes:
32b4d52 Updated Upstream (Paper)
ac5adca Make sure lit is set for pre 1.14 chunks

Purpur Changes:
24d9e61 Piglin portal spawn modifier
5866f36 Fix #263 - NPE on TPSBar when player disconnects
7f7f024 Updated Upstream (Paper, Tuinity, & Airplane)

* bump kotlin-stdlib

* Updated Upstream and Sidestream(s) (Paper/Airplane/Purpur)

Upstream/An Sidestream has released updates that appears to apply and compile correctly
This update has NOT been tested by YatopiaMC and as with ANY update, please do your own testing.

Paper Changes:
606cdac60 Update the view distance before scheduling chunk loads (#5269)

Airplane Changes:
0789789 Updated Upstream (Tuinity)
c1e4d71 Fluid cache patch

Purpur Changes:
04f73c5 Fix error when using non living entity on monster egg
76c35fc Fix #287 - TPSBarTask NPE (again)

* Updated Upstream and Sidestream(s) (Purpur)

Upstream/An Sidestream has released updates that appears to apply and compile correctly
This update has NOT been tested by YatopiaMC and as with ANY update, please do your own testing.

Purpur Changes:
2e62618 Fix #280 - Ridables do not reset idle timer
2021-04-15 14:46:34 -04:00

138 lines
7.1 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Hugo Planque <hookwood01@gmail.com>
Date: Thu, 21 Jan 2021 17:56:03 +0100
Subject: [PATCH] New nbt cache
The goal of this patch is to reduce I/O operations from the main thread while saving player data and also to avoid too many I/O operations while reading NBT Player file by using a cache (Which start to delete the oldest data when there is too much player compared to the map size)
Co-authored-by: ishland <ishlandmc@yeah.net>
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index ada7639c31fe6952f689bc2e437db57abe1b1037..0f7fec04ac5c46dec5947be337499f4f93df39f0 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -941,7 +941,9 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
}
// Spigot start
MCUtil.asyncExecutor.shutdown(); // Paper
+ this.worldNBTStorage.executorService.shutdown(); // Yatopia
try { MCUtil.asyncExecutor.awaitTermination(30, java.util.concurrent.TimeUnit.SECONDS); // Paper
+ this.worldNBTStorage.executorService.awaitTermination(30, java.util.concurrent.TimeUnit.SECONDS); // Yatopia - New async nbt cache
} catch (java.lang.InterruptedException ignored) {} // Paper
if (org.spigotmc.SpigotConfig.saveUserCacheOnStopOnly) {
LOGGER.info("Saving usercache.json");
diff --git a/src/main/java/net/minecraft/world/level/storage/WorldNBTStorage.java b/src/main/java/net/minecraft/world/level/storage/WorldNBTStorage.java
index d9c2c7a20953fc3bcdd07d70233ccf6e3748b14b..933b09169b2177f70412722264c0d5f129f3d93f 100644
--- a/src/main/java/net/minecraft/world/level/storage/WorldNBTStorage.java
+++ b/src/main/java/net/minecraft/world/level/storage/WorldNBTStorage.java
@@ -24,6 +24,11 @@ public class WorldNBTStorage {
private static final Logger LOGGER = LogManager.getLogger();
private final File playerDir;
protected final DataFixer a;
+ // Yatopia start - NBT Cache system
+ private final org.yatopiamc.yatopia.server.cache.NBTCache dataCache = new org.yatopiamc.yatopia.server.cache.NBTCache();
+ public final java.util.concurrent.ExecutorService executorService = java.util.concurrent.Executors.newSingleThreadExecutor(
+ new com.google.common.util.concurrent.ThreadFactoryBuilder().setDaemon(true).setPriority(Thread.NORM_PRIORITY - 1).build());
+ // Yatopia end
public WorldNBTStorage(Convertable.ConversionSession convertable_conversionsession, DataFixer datafixer) {
this.a = datafixer;
@@ -37,11 +42,22 @@ public class WorldNBTStorage {
NBTTagCompound nbttagcompound = entityhuman.save(new NBTTagCompound());
File file = File.createTempFile(entityhuman.getUniqueIDString() + "-", ".dat", this.playerDir);
- NBTCompressedStreamTools.a(nbttagcompound, file);
+ // NBTCompressedStreamTools.a(nbttagcompound, file); // Yatopia
+ // Yatopia start - NBT Cache system
+ Runnable task = () -> { try { NBTCompressedStreamTools.a(nbttagcompound, file);
File file1 = new File(this.playerDir, entityhuman.getUniqueIDString() + ".dat");
File file2 = new File(this.playerDir, entityhuman.getUniqueIDString() + ".dat_old");
SystemUtils.a(file1, file, file2);
+ } catch (Exception exception) {
+ WorldNBTStorage.LOGGER.error("Failed to save player data for {}", entityhuman.getName(), exception); // Paper
+ }
+ };
+ synchronized (this.dataCache){
+ this.dataCache.put(file, nbttagcompound);
+ }
+ this.executorService.execute(task);
+ // Yatopia end
} catch (Exception exception) {
WorldNBTStorage.LOGGER.error("Failed to save player data for {}", entityhuman.getName(), exception); // Paper
}
@@ -57,9 +73,18 @@ public class WorldNBTStorage {
// Spigot Start
boolean usingWrongFile = false;
boolean normalFile = file.exists() && file.isFile(); // Akarin - ensures normal file
- if ( org.bukkit.Bukkit.getOnlineMode() && !normalFile ) // Paper - Check online mode first // Akarin - ensures normal file
+ // if ( org.bukkit.Bukkit.getOnlineMode() && !normalFile ) // Paper - Check online mode first // Akarin - ensures normal file // Yatopia
+ // Yatopia start - NBT Cache system
+ NBTTagCompound playerData;
+ synchronized (this.dataCache){
+ playerData = this.dataCache.get(file);
+ }
+ if (playerData == null && org.bukkit.Bukkit.getOnlineMode() && !normalFile ) // Paper - Check online mode first // Akarin - ensures normal file
{
file = new File( this.playerDir, java.util.UUID.nameUUIDFromBytes( ( "OfflinePlayer:" + entityhuman.getName() ).getBytes( "UTF-8" ) ).toString() + ".dat");
+ synchronized (this.dataCache){
+ playerData = this.dataCache.get(file);
+ }
if ( file.exists() )
{
usingWrongFile = true;
@@ -67,10 +92,13 @@ public class WorldNBTStorage {
}
}
// Spigot End
-
- if (normalFile) { // Akarin - avoid double I/O operation
+ // if (normalFile) { // Akarin - avoid double I/O operation // Yatopia
+ if (playerData != null) {
+ nbttagcompound = playerData;
+ } else if (normalFile) { // Akarin - avoid double I/O operation
nbttagcompound = NBTCompressedStreamTools.a(file);
}
+ // Yatopia end
// Spigot Start
if ( usingWrongFile )
{
diff --git a/src/main/java/org/yatopiamc/yatopia/server/cache/NBTCache.java b/src/main/java/org/yatopiamc/yatopia/server/cache/NBTCache.java
new file mode 100644
index 0000000000000000000000000000000000000000..d739a71c91b54d156f6e1d8487add372a06d5939
--- /dev/null
+++ b/src/main/java/org/yatopiamc/yatopia/server/cache/NBTCache.java
@@ -0,0 +1,32 @@
+package org.yatopiamc.yatopia.server.cache;
+
+import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenCustomHashMap;
+import net.minecraft.server.MinecraftServer;
+import net.minecraft.nbt.NBTTagCompound;
+
+import java.io.File;
+
+public class NBTCache extends Object2ObjectLinkedOpenCustomHashMap<File, NBTTagCompound> {
+
+ public NBTCache() {
+ super(100, 0.75F, new Strategy<File>() {
+ @Override
+ public int hashCode(File k) {
+ return k.hashCode();
+ }
+
+ @Override
+ public boolean equals(File k, File k1) {
+ return k.equals(k1);
+ }
+ });
+ }
+
+ @Override
+ public NBTTagCompound put(File k, NBTTagCompound v) {
+ if (this.size() > MinecraftServer.getServer().getPlayerCount()) {
+ this.removeLast();
+ }
+ return super.putAndMoveToFirst(k, v);
+ }
+}