aboutsummaryrefslogtreecommitdiffhomepage
path: root/Spigot-Server-Patches/0503-Stop-copy-on-write-operations-for-updating-light-dat.patch
blob: ede6c2717b6c172234123f3f56f873d85cbb7028 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <spottedleaf@spottedleaf.dev>
Date: Mon, 27 Apr 2020 04:05:38 -0700
Subject: [PATCH] Stop copy-on-write operations for updating light data

Causes huge memory allocations + gc issues

diff --git a/src/main/java/net/minecraft/server/LightEngineStorage.java b/src/main/java/net/minecraft/server/LightEngineStorage.java
index a3f919816eb2a742ed09b553995e6508684e5ea5..88277d23c36696fdd5363e41a130c9a443fac2c0 100644
--- a/src/main/java/net/minecraft/server/LightEngineStorage.java
+++ b/src/main/java/net/minecraft/server/LightEngineStorage.java
@@ -19,8 +19,8 @@ public abstract class LightEngineStorage<M extends LightEngineStorageArray<M>> e
     protected final LongSet b = new LongOpenHashSet();
     protected final LongSet c = new LongOpenHashSet();
     protected final LongSet d = new LongOpenHashSet();
-    protected volatile M e;
-    protected final M f;
+    protected volatile M e_visible; protected final Object visibleUpdateLock = new Object(); // Paper - diff on change, should be "visible" - force compile fail on usage change
+    protected final M f; // Paper - diff on change, should be "updating"
     protected final LongSet g = new LongOpenHashSet();
     protected final LongSet h = new LongOpenHashSet();
     protected final Long2ObjectMap<NibbleArray> i = Long2ObjectMaps.synchronize(new Long2ObjectOpenHashMap());
@@ -33,8 +33,8 @@ public abstract class LightEngineStorage<M extends LightEngineStorageArray<M>> e
         this.l = enumskyblock;
         this.m = ilightaccess;
         this.f = m0;
-        this.e = m0.b();
-        this.e.d();
+        this.e_visible = m0.b(); // Paper - avoid copying light data
+        this.e_visible.d(); // Paper - avoid copying light data
     }
 
     protected boolean g(long i) {
@@ -43,7 +43,15 @@ public abstract class LightEngineStorage<M extends LightEngineStorageArray<M>> e
 
     @Nullable
     protected NibbleArray a(long i, boolean flag) {
-        return this.a(flag ? this.f : this.e, i);
+        // Paper start - avoid copying light data
+        if (flag) {
+            return this.a(this.f, i);
+        } else {
+            synchronized (this.visibleUpdateLock) {
+                return this.a(this.e_visible, i);
+            }
+        }
+        // Paper end - avoid copying light data
     }
 
     @Nullable
@@ -340,10 +348,12 @@ public abstract class LightEngineStorage<M extends LightEngineStorageArray<M>> e
 
     protected void e() {
         if (!this.g.isEmpty()) {
+            synchronized (this.visibleUpdateLock) { // Paper - avoid copying light data
             M m0 = this.f.b();
 
             m0.d();
-            this.e = m0;
+            this.e_visible = m0; // Paper - avoid copying light data
+            } // Paper - avoid copying light data
             this.g.clear();
         }
 
diff --git a/src/main/java/net/minecraft/server/LightEngineStorageArray.java b/src/main/java/net/minecraft/server/LightEngineStorageArray.java
index b978723a66d001f70325df0c7521025e079d7cfa..53199595da71a25710bd1ff8ee2868ee63edc0e1 100644
--- a/src/main/java/net/minecraft/server/LightEngineStorageArray.java
+++ b/src/main/java/net/minecraft/server/LightEngineStorageArray.java
@@ -8,10 +8,23 @@ public abstract class LightEngineStorageArray<M extends LightEngineStorageArray<
     private final long[] b = new long[2];
     private final NibbleArray[] c = new NibbleArray[2];
     private boolean d;
-    protected final Long2ObjectOpenHashMap<NibbleArray> a;
-
-    protected LightEngineStorageArray(Long2ObjectOpenHashMap<NibbleArray> long2objectopenhashmap) {
-        this.a = long2objectopenhashmap;
+    protected final com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object<NibbleArray> data; // Paper - avoid copying light data
+    protected final boolean isVisible; // Paper - avoid copying light data
+    java.util.function.Function<Long, NibbleArray> lookup; // Paper - faster branchless lookup
+
+    // Paper start - avoid copying light data
+    protected LightEngineStorageArray(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object<NibbleArray> data, boolean isVisible) {
+        if (isVisible) {
+            data.performUpdatesLockMap();
+        }
+        this.data = data;
+        this.isVisible = isVisible;
+        if (isVisible) {
+            lookup = data::getVisibleAsync;
+        } else {
+            lookup = data::getUpdating;
+        }
+        // Paper end - avoid copying light data
         this.c();
         this.d = true;
     }
@@ -19,16 +32,17 @@ public abstract class LightEngineStorageArray<M extends LightEngineStorageArray<
     public abstract M b();
 
     public void a(long i) {
-        this.a.put(i, ((NibbleArray) this.a.get(i)).b());
+        if (this.isVisible) { throw new IllegalStateException("writing to visible data"); } // Paper - avoid copying light data
+        this.data.queueUpdate(i, ((NibbleArray) this.data.getUpdating(i)).b()); // Paper - avoid copying light data
         this.c();
     }
 
     public boolean b(long i) {
-        return this.a.containsKey(i);
+        return lookup.apply(i) != null; // Paper - avoid copying light data
     }
 
     @Nullable
-    public NibbleArray c(long i) {
+    public final NibbleArray c(long i) { // Paper - final
         if (this.d) {
             for (int j = 0; j < 2; ++j) {
                 if (i == this.b[j]) {
@@ -37,7 +51,7 @@ public abstract class LightEngineStorageArray<M extends LightEngineStorageArray<
             }
         }
 
-        NibbleArray nibblearray = (NibbleArray) this.a.get(i);
+        NibbleArray nibblearray = lookup.apply(i); // Paper - avoid copying light data
 
         if (nibblearray == null) {
             return null;
@@ -58,11 +72,13 @@ public abstract class LightEngineStorageArray<M extends LightEngineStorageArray<
 
     @Nullable
     public NibbleArray d(long i) {
-        return (NibbleArray) this.a.remove(i);
+        if (this.isVisible) { throw new IllegalStateException("writing to visible data"); } // Paper - avoid copying light data
+        return (NibbleArray) this.data.queueRemove(i); // Paper - avoid copying light data
     }
 
     public void a(long i, NibbleArray nibblearray) {
-        this.a.put(i, nibblearray);
+        if (this.isVisible) { throw new IllegalStateException("writing to visible data"); } // Paper - avoid copying light data
+        this.data.queueUpdate(i, nibblearray); // Paper - avoid copying light data
     }
 
     public void c() {
@@ -70,7 +86,6 @@ public abstract class LightEngineStorageArray<M extends LightEngineStorageArray<
             this.b[i] = Long.MAX_VALUE;
             this.c[i] = null;
         }
-
     }
 
     public void d() {
diff --git a/src/main/java/net/minecraft/server/LightEngineStorageBlock.java b/src/main/java/net/minecraft/server/LightEngineStorageBlock.java
index 0f7f4744d9f9e5174fb38ccc72248397a4b064ea..292d8c742d3be41ba8ad7fb7f1251dc7f790b62b 100644
--- a/src/main/java/net/minecraft/server/LightEngineStorageBlock.java
+++ b/src/main/java/net/minecraft/server/LightEngineStorageBlock.java
@@ -5,7 +5,7 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
 public class LightEngineStorageBlock extends LightEngineStorage<LightEngineStorageBlock.a> {
 
     protected LightEngineStorageBlock(ILightAccess ilightaccess) {
-        super(EnumSkyBlock.BLOCK, ilightaccess, new LightEngineStorageBlock.a(new Long2ObjectOpenHashMap()));
+        super(EnumSkyBlock.BLOCK, ilightaccess, new LightEngineStorageBlock.a(new com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object<>(), false)); // Paper - avoid copying light data
     }
 
     @Override
@@ -18,13 +18,13 @@ public class LightEngineStorageBlock extends LightEngineStorage<LightEngineStora
 
     public static final class a extends LightEngineStorageArray<LightEngineStorageBlock.a> {
 
-        public a(Long2ObjectOpenHashMap<NibbleArray> long2objectopenhashmap) {
-            super(long2objectopenhashmap);
+        public a(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object<NibbleArray> long2objectopenhashmap, boolean isVisible) { // Paper - avoid copying light data
+            super(long2objectopenhashmap, isVisible); // Paper - avoid copying light data
         }
 
         @Override
         public LightEngineStorageBlock.a b() {
-            return new LightEngineStorageBlock.a(this.a.clone());
+            return new a(this.data, true); // Paper - avoid copying light data
         }
     }
 }
diff --git a/src/main/java/net/minecraft/server/LightEngineStorageSky.java b/src/main/java/net/minecraft/server/LightEngineStorageSky.java
index 75d9065b32731dc635d9d09c48fb9643172381a9..06bc8371fe9de4d23fdd47e5a3919541bb399fd8 100644
--- a/src/main/java/net/minecraft/server/LightEngineStorageSky.java
+++ b/src/main/java/net/minecraft/server/LightEngineStorageSky.java
@@ -17,15 +17,16 @@ public class LightEngineStorageSky extends LightEngineStorage<LightEngineStorage
     private volatile boolean p;
 
     protected LightEngineStorageSky(ILightAccess ilightaccess) {
-        super(EnumSkyBlock.SKY, ilightaccess, new LightEngineStorageSky.a(new Long2ObjectOpenHashMap(), new Long2IntOpenHashMap(), Integer.MAX_VALUE));
+        super(EnumSkyBlock.SKY, ilightaccess, new LightEngineStorageSky.a(new com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object<>(), new com.destroystokyo.paper.util.map.QueuedChangesMapLong2Int(), Integer.MAX_VALUE, false)); // Paper - avoid copying light data
     }
 
     @Override
     protected int d(long i) {
         long j = SectionPosition.e(i);
         int k = SectionPosition.c(j);
-        LightEngineStorageSky.a lightenginestoragesky_a = (LightEngineStorageSky.a) this.e;
-        int l = lightenginestoragesky_a.c.get(SectionPosition.f(j));
+        synchronized (this.visibleUpdateLock) { // Paper - avoid copying light data
+        LightEngineStorageSky.a lightenginestoragesky_a = (LightEngineStorageSky.a) this.e_visible; // Paper - avoid copying light data - must be after lock acquire
+        int l = lightenginestoragesky_a.otherData.getVisibleAsync(SectionPosition.f(j)); // Paper - avoid copying light data
 
         if (l != lightenginestoragesky_a.b && k < l) {
             NibbleArray nibblearray = this.a(lightenginestoragesky_a, j); // Paper - decompile fix
@@ -46,6 +47,7 @@ public class LightEngineStorageSky extends LightEngineStorage<LightEngineStorage
         } else {
             return 15;
         }
+        } // Paper - avoid copying light data
     }
 
     @Override
@@ -54,14 +56,14 @@ public class LightEngineStorageSky extends LightEngineStorage<LightEngineStorage
 
         if (((LightEngineStorageSky.a) this.f).b > j) {
             ((LightEngineStorageSky.a) this.f).b = j;
-            ((LightEngineStorageSky.a) this.f).c.defaultReturnValue(((LightEngineStorageSky.a) this.f).b);
+            ((LightEngineStorageSky.a) this.f).otherData.queueDefaultReturnValue(((LightEngineStorageSky.a) this.f).b); // Paper - avoid copying light data
         }
 
         long k = SectionPosition.f(i);
-        int l = ((LightEngineStorageSky.a) this.f).c.get(k);
+        int l = ((LightEngineStorageSky.a) this.f).otherData.getUpdating(k); // Paper - avoid copying light data
 
         if (l < j + 1) {
-            ((LightEngineStorageSky.a) this.f).c.put(k, j + 1);
+            ((LightEngineStorageSky.a) this.f).otherData.queueUpdate(k, j + 1); // Paper - avoid copying light data
             if (this.o.contains(k)) {
                 this.q(i);
                 if (l > ((LightEngineStorageSky.a) this.f).b) {
@@ -101,7 +103,7 @@ public class LightEngineStorageSky extends LightEngineStorage<LightEngineStorage
 
         int k = SectionPosition.c(i);
 
-        if (((LightEngineStorageSky.a) this.f).c.get(j) == k + 1) {
+        if (((LightEngineStorageSky.a) this.f).otherData.getUpdating(j) == k + 1) { // Paper - avoid copying light data
             long l;
 
             for (l = i; !this.g(l) && this.a(k); l = SectionPosition.a(l, EnumDirection.DOWN)) {
@@ -109,12 +111,12 @@ public class LightEngineStorageSky extends LightEngineStorage<LightEngineStorage
             }
 
             if (this.g(l)) {
-                ((LightEngineStorageSky.a) this.f).c.put(j, k + 1);
+                ((LightEngineStorageSky.a) this.f).otherData.queueUpdate(j, k + 1); // Paper - avoid copying light data
                 if (flag) {
                     this.q(l);
                 }
             } else {
-                ((LightEngineStorageSky.a) this.f).c.remove(j);
+                ((LightEngineStorageSky.a) this.f).otherData.queueRemove(j); // Paper - avoid copying light data
             }
         }
 
@@ -128,7 +130,7 @@ public class LightEngineStorageSky extends LightEngineStorage<LightEngineStorage
     protected void b(long i, boolean flag) {
         this.d();
         if (flag && this.o.add(i)) {
-            int j = ((LightEngineStorageSky.a) this.f).c.get(i);
+            int j = ((LightEngineStorageSky.a) this.f).otherData.getUpdating(i); // Paper - avoid copying light data
 
             if (j != ((LightEngineStorageSky.a) this.f).b) {
                 long k = SectionPosition.b(SectionPosition.b(i), j - 1, SectionPosition.d(i));
@@ -155,7 +157,7 @@ public class LightEngineStorageSky extends LightEngineStorage<LightEngineStorage
             return nibblearray;
         } else {
             long j = SectionPosition.a(i, EnumDirection.UP);
-            int k = ((LightEngineStorageSky.a) this.f).c.get(SectionPosition.f(i));
+            int k = ((LightEngineStorageSky.a) this.f).otherData.getUpdating(SectionPosition.f(i)); // Paper - avoid copying light data
 
             if (k != ((LightEngineStorageSky.a) this.f).b && SectionPosition.c(j) < k) {
                 NibbleArray nibblearray1;
@@ -298,7 +300,7 @@ public class LightEngineStorageSky extends LightEngineStorage<LightEngineStorage
             if (!this.o.contains(l)) {
                 return false;
             } else {
-                int i1 = ((LightEngineStorageSky.a) this.f).c.get(l);
+                int i1 = ((LightEngineStorageSky.a) this.f).otherData.getUpdating(l); // Paper - avoid copying light data
 
                 return SectionPosition.c(i1) == j + 16;
             }
@@ -307,7 +309,7 @@ public class LightEngineStorageSky extends LightEngineStorage<LightEngineStorage
 
     protected boolean n(long i) {
         long j = SectionPosition.f(i);
-        int k = ((LightEngineStorageSky.a) this.f).c.get(j);
+        int k = ((LightEngineStorageSky.a) this.f).otherData.getUpdating(j); // Paper - avoid copying light data
 
         return k == ((LightEngineStorageSky.a) this.f).b || SectionPosition.c(i) >= k;
     }
@@ -321,18 +323,20 @@ public class LightEngineStorageSky extends LightEngineStorage<LightEngineStorage
     public static final class a extends LightEngineStorageArray<LightEngineStorageSky.a> {
 
         private int b;
-        private final Long2IntOpenHashMap c;
+        private final com.destroystokyo.paper.util.map.QueuedChangesMapLong2Int otherData; // Paper - avoid copying light data
 
-        public a(Long2ObjectOpenHashMap<NibbleArray> long2objectopenhashmap, Long2IntOpenHashMap long2intopenhashmap, int i) {
-            super(long2objectopenhashmap);
-            this.c = long2intopenhashmap;
-            long2intopenhashmap.defaultReturnValue(i);
+        // Paper start - avoid copying light data
+        public a(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object<NibbleArray> data, com.destroystokyo.paper.util.map.QueuedChangesMapLong2Int otherData, int i, boolean isVisible) {
+            super(data, isVisible);
+            this.otherData = otherData;
+            // Paper end - avoid copying light data
             this.b = i;
         }
 
         @Override
         public LightEngineStorageSky.a b() {
-            return new LightEngineStorageSky.a(this.a.clone(), this.c.clone(), this.b);
+            this.otherData.performUpdatesLockMap(); // Paper - avoid copying light data
+            return new LightEngineStorageSky.a(this.data, this.otherData, this.b, true); // Paper - avoid copying light data
         }
     }
 }