From bf7742bf96ca426af7ee07906eba425ff1ebfa18 Mon Sep 17 00:00:00 2001 From: Aikar Date: Mon, 17 Sep 2018 22:32:37 -0400 Subject: [PATCH] Use BigDecimal to improve accracy of TPS results - long live 20 TPS! It's always been commonly said to 'ignore' that TPS was '19.X', that it was fine. I suspect that the inaccuracy of floating point math resulted in us losing precision over time, making it difficult to actually get back to 20, as you know the fun 0.1 + 0.1 ... 9 more times != 1 problem. BigDecimal supports working with doubles with higher precision. This change makes it so our RollingAverage class maintains all of the data using BigDecimal and using BigDecimal arithematic operations. This ensures we have extremely high precision, enabling us to actually be able print '20 TPS' when TPS is perfect. --- ...dd-Early-Warning-Feature-to-WatchDog.patch | 2 +- .../Auto-Save-Improvements.patch | 8 +++--- .../Basic-PlayerProfile-API.patch | 2 +- ...ix-major-memory-leaks-in-ExpiringMap.patch | 2 +- .../Further-improve-server-tick-loop.patch | 26 +++++++++++-------- ...nt-extended-PaperServerListPingEvent.patch | 2 +- Spigot-Server-Patches/Lighting-Queue.patch | 6 ++--- Spigot-Server-Patches/Optimize-Hoppers.patch | 2 +- .../Optimize-explosions.patch | 4 +-- ...oleAppender-for-console-improvements.patch | 2 +- ...-possibility-for-getServer-singleton.patch | 2 +- 11 files changed, 31 insertions(+), 27 deletions(-) diff --git a/Spigot-Server-Patches/Add-Early-Warning-Feature-to-WatchDog.patch b/Spigot-Server-Patches/Add-Early-Warning-Feature-to-WatchDog.patch index 979f4d234..e94227a7a 100644 --- a/Spigot-Server-Patches/Add-Early-Warning-Feature-to-WatchDog.patch +++ b/Spigot-Server-Patches/Add-Early-Warning-Feature-to-WatchDog.patch @@ -37,7 +37,7 @@ index cc2e4ad3bd..54f088c242 100644 public static int tabSpamLimit = 500; private static void tabSpamLimiters() { diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 2e9836d8f9..8b8cbde2b9 100644 +index 18eeee5106..6fa54386e8 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -0,0 +0,0 @@ public abstract class MinecraftServer implements IAsyncTaskHandler, IMojangStati diff --git a/Spigot-Server-Patches/Auto-Save-Improvements.patch b/Spigot-Server-Patches/Auto-Save-Improvements.patch index 59e9ab1e7..12d353793 100644 --- a/Spigot-Server-Patches/Auto-Save-Improvements.patch +++ b/Spigot-Server-Patches/Auto-Save-Improvements.patch @@ -96,7 +96,7 @@ index 3c9c3cd41d..8d1264879b 100644 public boolean isEmpty() { diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java -index 7417660e4d..7a972f4187 100644 +index 9739288b53..a35eac043c 100644 --- a/src/main/java/net/minecraft/server/ChunkProviderServer.java +++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java @@ -0,0 +0,0 @@ public class ChunkProviderServer implements IChunkProvider { @@ -109,7 +109,7 @@ index 7417660e4d..7a972f4187 100644 } } diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java -index faf733f824..c6903559ef 100644 +index 3d83900298..690cff8828 100644 --- a/src/main/java/net/minecraft/server/EntityPlayer.java +++ b/src/main/java/net/minecraft/server/EntityPlayer.java @@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { @@ -121,7 +121,7 @@ index faf733f824..c6903559ef 100644 public final MinecraftServer server; public final PlayerInteractManager playerInteractManager; diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 13d3315b9c..a367cbf52b 100644 +index 04d8c108b4..a547ee5ca1 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -0,0 +0,0 @@ public abstract class MinecraftServer implements IAsyncTaskHandler, IMojangStati @@ -207,7 +207,7 @@ index 02dbb8c6c3..73d72ef7e3 100644 public WhiteList getWhitelist() { return this.whitelist; diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java -index 4be3a6ae94..59b5a04581 100644 +index c5201697d5..ca2e027cda 100644 --- a/src/main/java/net/minecraft/server/WorldServer.java +++ b/src/main/java/net/minecraft/server/WorldServer.java @@ -0,0 +0,0 @@ public class WorldServer extends World implements IAsyncTaskHandler { diff --git a/Spigot-Server-Patches/Basic-PlayerProfile-API.patch b/Spigot-Server-Patches/Basic-PlayerProfile-API.patch index b8e54692e..b3b819155 100644 --- a/Spigot-Server-Patches/Basic-PlayerProfile-API.patch +++ b/Spigot-Server-Patches/Basic-PlayerProfile-API.patch @@ -429,7 +429,7 @@ index dce1417aff..f7856897f6 100644 * Calculates distance between 2 entities * @param e1 diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 464db5ebb8..3e99221619 100644 +index 6a3d5fdff4..65204c259e 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -0,0 +0,0 @@ public abstract class MinecraftServer implements IAsyncTaskHandler, IMojangStati diff --git a/Spigot-Server-Patches/Fix-major-memory-leaks-in-ExpiringMap.patch b/Spigot-Server-Patches/Fix-major-memory-leaks-in-ExpiringMap.patch index bd67ba1d1..19e163121 100644 --- a/Spigot-Server-Patches/Fix-major-memory-leaks-in-ExpiringMap.patch +++ b/Spigot-Server-Patches/Fix-major-memory-leaks-in-ExpiringMap.patch @@ -180,7 +180,7 @@ index 4006f5a69c..d64c143017 100644 } diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 80e8b023cf..70a609efcc 100644 +index eb3fc836fb..81cda5df56 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -0,0 +0,0 @@ public abstract class MinecraftServer implements IAsyncTaskHandler, IMojangStati diff --git a/Spigot-Server-Patches/Further-improve-server-tick-loop.patch b/Spigot-Server-Patches/Further-improve-server-tick-loop.patch index cd9c007ab..796bd7b77 100644 --- a/Spigot-Server-Patches/Further-improve-server-tick-loop.patch +++ b/Spigot-Server-Patches/Further-improve-server-tick-loop.patch @@ -12,7 +12,7 @@ Previous implementation did not calculate TPS correctly. Switch to a realistic rolling average and factor in std deviation as an extra reporting variable diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 788f0519a8..13c6021ffa 100644 +index 788f0519a8..d6ea4ae532 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -0,0 +0,0 @@ public abstract class MinecraftServer implements IAsyncTaskHandler, IMojangStati @@ -59,39 +59,43 @@ index 788f0519a8..13c6021ffa 100644 + public static class RollingAverage { + private final int size; + private long time; -+ private double total; ++ private java.math.BigDecimal total; + private int index = 0; -+ private final double[] samples; ++ private final java.math.BigDecimal[] samples; + private final long[] times; + + RollingAverage(int size) { + this.size = size; + this.time = size * SEC_IN_NANO; -+ this.total = TPS * SEC_IN_NANO * size; -+ this.samples = new double[size]; ++ this.total = dec(TPS).multiply(dec(SEC_IN_NANO)).multiply(dec(size)); ++ this.samples = new java.math.BigDecimal[size]; + this.times = new long[size]; + for (int i = 0; i < size; i++) { -+ this.samples[i] = TPS; ++ this.samples[i] = dec(TPS); + this.times[i] = SEC_IN_NANO; + } + } + -+ public void add(double x, long t) { ++ private static java.math.BigDecimal dec(long t) { ++ return new java.math.BigDecimal(t); ++ } ++ public void add(java.math.BigDecimal x, long t) { + time -= times[index]; -+ total -= samples[index] * times[index]; ++ total = total.subtract(samples[index].multiply(dec(times[index]))); + samples[index] = x; + times[index] = t; + time += t; -+ total += x * t; ++ total = total.add(x.multiply(dec(t))); + if (++index == size) { + index = 0; + } + } + + public double getAverage() { -+ return total / time; ++ return total.divide(dec(time), 30, java.math.RoundingMode.HALF_UP).doubleValue(); + } + } ++ private static final java.math.BigDecimal TPS_BASE = new java.math.BigDecimal(1E9).multiply(new java.math.BigDecimal(SAMPLE_INTERVAL)); + // Paper End // Spigot End @@ -138,7 +142,7 @@ index 788f0519a8..13c6021ffa 100644 - recentTps[1] = calcTps( recentTps[1], 0.9835, currentTps ); // 1/exp(5sec/5min) - recentTps[2] = calcTps( recentTps[2], 0.9945, currentTps ); // 1/exp(5sec/15min) + final long diff = curTime - tickSection; -+ double currentTps = 1E9 / diff * SAMPLE_INTERVAL; ++ java.math.BigDecimal currentTps = TPS_BASE.divide(new java.math.BigDecimal(diff), 30, java.math.RoundingMode.HALF_UP); + tps1.add(currentTps, diff); + tps5.add(currentTps, diff); + tps15.add(currentTps, diff); diff --git a/Spigot-Server-Patches/Implement-extended-PaperServerListPingEvent.patch b/Spigot-Server-Patches/Implement-extended-PaperServerListPingEvent.patch index 2b5dd6061..77f22ef2e 100644 --- a/Spigot-Server-Patches/Implement-extended-PaperServerListPingEvent.patch +++ b/Spigot-Server-Patches/Implement-extended-PaperServerListPingEvent.patch @@ -177,7 +177,7 @@ index 0000000000..350410527b + +} diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 3e99221619..2e9836d8f9 100644 +index 65204c259e..18eeee5106 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -0,0 +0,0 @@ diff --git a/Spigot-Server-Patches/Lighting-Queue.patch b/Spigot-Server-Patches/Lighting-Queue.patch index b5a7b1a7b..b0f1cf2de 100644 --- a/Spigot-Server-Patches/Lighting-Queue.patch +++ b/Spigot-Server-Patches/Lighting-Queue.patch @@ -102,7 +102,7 @@ index 4622e92b05..d4bebddab0 100644 IMMEDIATE, QUEUED, CHECK; diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java -index 0034956af9..1379b574ef 100644 +index 68212aa26e..046973a4ed 100644 --- a/src/main/java/net/minecraft/server/ChunkProviderServer.java +++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java @@ -0,0 +0,0 @@ public class ChunkProviderServer implements IChunkProvider { @@ -114,7 +114,7 @@ index 0034956af9..1379b574ef 100644 // Update neighbor counts for (int x = -2; x < 3; x++) { diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 13c6021ffa..30541dfa5a 100644 +index d6ea4ae532..5086fe4027 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -0,0 +0,0 @@ public abstract class MinecraftServer implements IAsyncTaskHandler, IMojangStati @@ -233,7 +233,7 @@ index 0000000000..60562f1fd2 + } +} diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java -index 929875340f..0fe8a97f24 100644 +index 499d64ea2c..e06da6bef9 100644 --- a/src/main/java/net/minecraft/server/World.java +++ b/src/main/java/net/minecraft/server/World.java @@ -0,0 +0,0 @@ public abstract class World implements IEntityAccess, GeneratorAccess, IIBlockAc diff --git a/Spigot-Server-Patches/Optimize-Hoppers.patch b/Spigot-Server-Patches/Optimize-Hoppers.patch index 7cd01f6c2..e5bbac98e 100644 --- a/Spigot-Server-Patches/Optimize-Hoppers.patch +++ b/Spigot-Server-Patches/Optimize-Hoppers.patch @@ -47,7 +47,7 @@ index 9326eaa2a9..4641113f9d 100644 itemstack.d(this.B()); if (this.tag != null) { diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 8b8cbde2b9..80e8b023cf 100644 +index 6fa54386e8..eb3fc836fb 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -0,0 +0,0 @@ public abstract class MinecraftServer implements IAsyncTaskHandler, IMojangStati diff --git a/Spigot-Server-Patches/Optimize-explosions.patch b/Spigot-Server-Patches/Optimize-explosions.patch index 68c3f9819..87fc6642e 100644 --- a/Spigot-Server-Patches/Optimize-explosions.patch +++ b/Spigot-Server-Patches/Optimize-explosions.patch @@ -124,7 +124,7 @@ index 2620c4c2bd..a31e07b903 100644 + // Paper end } diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 30541dfa5a..bbd476bb0e 100644 +index 5086fe4027..abed6bb977 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -0,0 +0,0 @@ public abstract class MinecraftServer implements IAsyncTaskHandler, IMojangStati @@ -136,7 +136,7 @@ index 30541dfa5a..bbd476bb0e 100644 } diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java -index 0fe8a97f24..c8b9c10f12 100644 +index e06da6bef9..c823cef341 100644 --- a/src/main/java/net/minecraft/server/World.java +++ b/src/main/java/net/minecraft/server/World.java @@ -0,0 +0,0 @@ import org.apache.logging.log4j.Logger; diff --git a/Spigot-Server-Patches/Use-TerminalConsoleAppender-for-console-improvements.patch b/Spigot-Server-Patches/Use-TerminalConsoleAppender-for-console-improvements.patch index 36a4b21e6..1d60a24c6 100644 --- a/Spigot-Server-Patches/Use-TerminalConsoleAppender-for-console-improvements.patch +++ b/Spigot-Server-Patches/Use-TerminalConsoleAppender-for-console-improvements.patch @@ -185,7 +185,7 @@ index dabad6b055..fc7e244f8b 100644 System.setOut(new PrintStream(new LoggerOutputStream(logger, Level.INFO), true)); System.setErr(new PrintStream(new LoggerOutputStream(logger, Level.WARN), true)); diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 08ce98d071..464db5ebb8 100644 +index 8d345a0502..6a3d5fdff4 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -0,0 +0,0 @@ import org.apache.commons.lang3.Validate; diff --git a/Spigot-Server-Patches/remove-null-possibility-for-getServer-singleton.patch b/Spigot-Server-Patches/remove-null-possibility-for-getServer-singleton.patch index 2ddcd2a9f..13e1a1934 100644 --- a/Spigot-Server-Patches/remove-null-possibility-for-getServer-singleton.patch +++ b/Spigot-Server-Patches/remove-null-possibility-for-getServer-singleton.patch @@ -6,7 +6,7 @@ Subject: [PATCH] remove null possibility for getServer singleton to stop IDE complaining about potential NPE diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 9675d5a100..ca5e4cd65a 100644 +index 74c84dda69..eb6ada935f 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -0,0 +0,0 @@ import co.aikar.timings.MinecraftTimings; // Paper