928bcc8d3a
Upstream has released updates that appear to apply and compile correctly. This update has not been tested by PaperMC and as with ANY update, please do your own testing Bukkit Changes: 09943450 Update SnakeYAML version 5515734f SPIGOT-7162: Incorrect description for Entity#getVehicle javadoc 6f82b381 PR-788: Add getHand() to all relevant events CraftBukkit Changes: aaf484f6f SPIGOT-7163: CraftMerchantRecipe doesn't copy demand and specialPrice from BukkitMerchantRecipe 5329dd6fd PR-1107: Add getHand() to all relevant events 93061706e SPIGOT-7045: Ocelots never spawn with babies with spawn reason OCELOT_BABY
298 Zeilen
17 KiB
Diff
298 Zeilen
17 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
|
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/world/level/lighting/BlockLightSectionStorage.java b/src/main/java/net/minecraft/world/level/lighting/BlockLightSectionStorage.java
|
|
index 573cdb0897978eef8f5fc906ed4928293f4b2ab9..314b46f0becd088d26956b45981217b128d539cb 100644
|
|
--- a/src/main/java/net/minecraft/world/level/lighting/BlockLightSectionStorage.java
|
|
+++ b/src/main/java/net/minecraft/world/level/lighting/BlockLightSectionStorage.java
|
|
@@ -9,7 +9,7 @@ import net.minecraft.world.level.chunk.LightChunkGetter;
|
|
|
|
public class BlockLightSectionStorage extends LayerLightSectionStorage<BlockLightSectionStorage.BlockDataLayerStorageMap> {
|
|
protected BlockLightSectionStorage(LightChunkGetter chunkProvider) {
|
|
- super(LightLayer.BLOCK, chunkProvider, new BlockLightSectionStorage.BlockDataLayerStorageMap(new Long2ObjectOpenHashMap<>()));
|
|
+ super(LightLayer.BLOCK, chunkProvider, new BlockLightSectionStorage.BlockDataLayerStorageMap(new com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object<>(), false)); // Paper - avoid copying light data
|
|
}
|
|
|
|
@Override
|
|
@@ -20,13 +20,13 @@ public class BlockLightSectionStorage extends LayerLightSectionStorage<BlockLigh
|
|
}
|
|
|
|
protected static final class BlockDataLayerStorageMap extends DataLayerStorageMap<BlockLightSectionStorage.BlockDataLayerStorageMap> {
|
|
- public BlockDataLayerStorageMap(Long2ObjectOpenHashMap<DataLayer> arrays) {
|
|
- super(arrays);
|
|
+ public BlockDataLayerStorageMap(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object<DataLayer> long2objectopenhashmap, boolean isVisible) { // Paper - avoid copying light data
|
|
+ super(long2objectopenhashmap, isVisible); // Paper - avoid copying light data
|
|
}
|
|
|
|
@Override
|
|
public BlockLightSectionStorage.BlockDataLayerStorageMap copy() {
|
|
- return new BlockLightSectionStorage.BlockDataLayerStorageMap(this.map.clone());
|
|
+ return new BlockDataLayerStorageMap(this.data, true); // Paper - avoid copying light data
|
|
}
|
|
}
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java b/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java
|
|
index 67ff66e232592203cf8dad605ad01eabc4dded89..f357a3473682c2d37a20fb862522c67b9979402a 100644
|
|
--- a/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java
|
|
+++ b/src/main/java/net/minecraft/world/level/lighting/DataLayerStorageMap.java
|
|
@@ -9,10 +9,23 @@ public abstract class DataLayerStorageMap<M extends DataLayerStorageMap<M>> {
|
|
private final long[] lastSectionKeys = new long[2];
|
|
private final DataLayer[] lastSections = new DataLayer[2];
|
|
private boolean cacheEnabled;
|
|
- protected final Long2ObjectOpenHashMap<DataLayer> map;
|
|
+ protected final com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object<DataLayer> data; // Paper - avoid copying light data
|
|
+ protected final boolean isVisible; // Paper - avoid copying light data
|
|
+ java.util.function.Function<Long, DataLayer> lookup; // Paper - faster branchless lookup
|
|
|
|
- protected DataLayerStorageMap(Long2ObjectOpenHashMap<DataLayer> arrays) {
|
|
- this.map = arrays;
|
|
+ // Paper start - avoid copying light data
|
|
+ protected DataLayerStorageMap(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object<DataLayer> 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.clearCache();
|
|
this.cacheEnabled = true;
|
|
}
|
|
@@ -20,16 +33,17 @@ public abstract class DataLayerStorageMap<M extends DataLayerStorageMap<M>> {
|
|
public abstract M copy();
|
|
|
|
public void copyDataLayer(long pos) {
|
|
- this.map.put(pos, this.map.get(pos).copy());
|
|
+ if (this.isVisible) { throw new IllegalStateException("writing to visible data"); } // Paper - avoid copying light data
|
|
+ this.data.queueUpdate(pos, ((DataLayer) this.data.getUpdating(pos)).copy()); // Paper - avoid copying light data
|
|
this.clearCache();
|
|
}
|
|
|
|
public boolean hasLayer(long chunkPos) {
|
|
- return this.map.containsKey(chunkPos);
|
|
+ return lookup.apply(chunkPos) != null; // Paper - avoid copying light data
|
|
}
|
|
|
|
@Nullable
|
|
- public DataLayer getLayer(long chunkPos) {
|
|
+ public final DataLayer getLayer(long chunkPos) { // Paper - final
|
|
if (this.cacheEnabled) {
|
|
for(int i = 0; i < 2; ++i) {
|
|
if (chunkPos == this.lastSectionKeys[i]) {
|
|
@@ -38,7 +52,7 @@ public abstract class DataLayerStorageMap<M extends DataLayerStorageMap<M>> {
|
|
}
|
|
}
|
|
|
|
- DataLayer dataLayer = this.map.get(chunkPos);
|
|
+ DataLayer dataLayer = lookup.apply(chunkPos); // Paper - avoid copying light data
|
|
if (dataLayer == null) {
|
|
return null;
|
|
} else {
|
|
@@ -58,11 +72,13 @@ public abstract class DataLayerStorageMap<M extends DataLayerStorageMap<M>> {
|
|
|
|
@Nullable
|
|
public DataLayer removeLayer(long chunkPos) {
|
|
- return this.map.remove(chunkPos);
|
|
+ if (this.isVisible) { throw new IllegalStateException("writing to visible data"); } // Paper - avoid copying light data
|
|
+ return (DataLayer) this.data.queueRemove(chunkPos); // Paper - avoid copying light data
|
|
}
|
|
|
|
public void setLayer(long pos, DataLayer data) {
|
|
- this.map.put(pos, data);
|
|
+ if (this.isVisible) { throw new IllegalStateException("writing to visible data"); } // Paper - avoid copying light data
|
|
+ this.data.queueUpdate(pos, data); // Paper - avoid copying light data
|
|
}
|
|
|
|
public void clearCache() {
|
|
diff --git a/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java b/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java
|
|
index c899674ee24167ee3abdf1588d7396df0ab4f0aa..85175b01b1623b3bc66c65805cec26eaead48265 100644
|
|
--- a/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java
|
|
+++ b/src/main/java/net/minecraft/world/level/lighting/LayerLightSectionStorage.java
|
|
@@ -27,7 +27,7 @@ public abstract class LayerLightSectionStorage<M extends DataLayerStorageMap<M>>
|
|
protected final LongSet dataSectionSet = new LongOpenHashSet();
|
|
protected final LongSet toMarkNoData = new LongOpenHashSet();
|
|
protected final LongSet toMarkData = new LongOpenHashSet();
|
|
- protected volatile M visibleSectionData;
|
|
+ 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 updatingSectionData;
|
|
protected final LongSet changedSections = new LongOpenHashSet();
|
|
protected final LongSet sectionsAffectedByLightUpdates = new LongOpenHashSet();
|
|
@@ -42,8 +42,8 @@ public abstract class LayerLightSectionStorage<M extends DataLayerStorageMap<M>>
|
|
this.layer = lightType;
|
|
this.chunkSource = chunkProvider;
|
|
this.updatingSectionData = lightData;
|
|
- this.visibleSectionData = lightData.copy();
|
|
- this.visibleSectionData.disableCache();
|
|
+ this.e_visible = lightData.copy(); // Paper - avoid copying light dat
|
|
+ this.e_visible.disableCache(); // Paper - avoid copying light dat
|
|
}
|
|
|
|
protected boolean storingLightForSection(long sectionPos) {
|
|
@@ -52,7 +52,15 @@ public abstract class LayerLightSectionStorage<M extends DataLayerStorageMap<M>>
|
|
|
|
@Nullable
|
|
protected DataLayer getDataLayer(long sectionPos, boolean cached) {
|
|
- return this.getDataLayer((M)(cached ? this.updatingSectionData : this.visibleSectionData), sectionPos);
|
|
+ // Paper start - avoid copying light data
|
|
+ if (cached) {
|
|
+ return this.getDataLayer(this.updatingSectionData, sectionPos);
|
|
+ } else {
|
|
+ synchronized (this.visibleUpdateLock) {
|
|
+ return this.getDataLayer(this.e_visible, sectionPos);
|
|
+ }
|
|
+ }
|
|
+ // Paper end - avoid copying light data
|
|
}
|
|
|
|
@Nullable
|
|
@@ -342,9 +350,11 @@ public abstract class LayerLightSectionStorage<M extends DataLayerStorageMap<M>>
|
|
|
|
protected void swapSectionMap() {
|
|
if (!this.changedSections.isEmpty()) {
|
|
+ synchronized (this.visibleUpdateLock) { // Paper - avoid copying light data
|
|
M dataLayerStorageMap = this.updatingSectionData.copy();
|
|
dataLayerStorageMap.disableCache();
|
|
- this.visibleSectionData = dataLayerStorageMap;
|
|
+ this.e_visible = dataLayerStorageMap; // Paper - avoid copying light data
|
|
+ } // Paper - avoid copying light data
|
|
this.changedSections.clear();
|
|
}
|
|
|
|
diff --git a/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java b/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java
|
|
index 59d2af9f883541518c203302257f03dbe957aa0b..e6c857c8b4e4e65e3cf6a75ce6d844ff61acb566 100644
|
|
--- a/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java
|
|
+++ b/src/main/java/net/minecraft/world/level/lighting/SkyLightSectionStorage.java
|
|
@@ -21,7 +21,7 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage<SkyLightSec
|
|
private volatile boolean hasSourceInconsistencies;
|
|
|
|
protected SkyLightSectionStorage(LightChunkGetter chunkProvider) {
|
|
- super(LightLayer.SKY, chunkProvider, new SkyLightSectionStorage.SkyDataLayerStorageMap(new Long2ObjectOpenHashMap<>(), new Long2IntOpenHashMap(), Integer.MAX_VALUE));
|
|
+ super(LightLayer.SKY, chunkProvider, new SkyLightSectionStorage.SkyDataLayerStorageMap(new com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object<>(), new com.destroystokyo.paper.util.map.QueuedChangesMapLong2Int(), Integer.MAX_VALUE, false)); // Paper - avoid copying light data
|
|
}
|
|
|
|
@Override
|
|
@@ -32,8 +32,9 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage<SkyLightSec
|
|
protected int getLightValue(long blockPos, boolean cached) {
|
|
long l = SectionPos.blockToSection(blockPos);
|
|
int i = SectionPos.y(l);
|
|
- SkyLightSectionStorage.SkyDataLayerStorageMap skyDataLayerStorageMap = cached ? this.updatingSectionData : this.visibleSectionData;
|
|
- int j = skyDataLayerStorageMap.topSections.get(SectionPos.getZeroNode(l));
|
|
+ synchronized (this.visibleUpdateLock) { // Paper - avoid copying light data
|
|
+ SkyLightSectionStorage.SkyDataLayerStorageMap skyDataLayerStorageMap = (SkyLightSectionStorage.SkyDataLayerStorageMap) this.e_visible; // Paper - avoid copying light data - must be after lock acquire
|
|
+ int j = skyDataLayerStorageMap.otherData.getVisibleAsync(SectionPos.getZeroNode(l)); // Paper - avoid copying light data
|
|
if (j != skyDataLayerStorageMap.currentLowestY && i < j) {
|
|
DataLayer dataLayer = this.getDataLayer(skyDataLayerStorageMap, l);
|
|
if (dataLayer == null) {
|
|
@@ -52,6 +53,7 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage<SkyLightSec
|
|
} else {
|
|
return cached && !this.lightOnInSection(l) ? 0 : 15;
|
|
}
|
|
+ } // Paper - avoid copying light data
|
|
}
|
|
|
|
@Override
|
|
@@ -59,13 +61,13 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage<SkyLightSec
|
|
int i = SectionPos.y(sectionPos);
|
|
if ((this.updatingSectionData).currentLowestY > i) {
|
|
(this.updatingSectionData).currentLowestY = i;
|
|
- (this.updatingSectionData).topSections.defaultReturnValue((this.updatingSectionData).currentLowestY);
|
|
+ (this.updatingSectionData).otherData.queueDefaultReturnValue((this.updatingSectionData).currentLowestY); // Paper - avoid copying light data
|
|
}
|
|
|
|
long l = SectionPos.getZeroNode(sectionPos);
|
|
- int j = (this.updatingSectionData).topSections.get(l);
|
|
+ int j = (this.updatingSectionData).otherData.getUpdating(l); // Paper - avoid copying light data
|
|
if (j < i + 1) {
|
|
- (this.updatingSectionData).topSections.put(l, i + 1);
|
|
+ (this.updatingSectionData).otherData.queueUpdate(l, i + 1); // Paper - avoid copying light data
|
|
if (this.columnsWithSkySources.contains(l)) {
|
|
this.queueAddSource(sectionPos);
|
|
if (j > (this.updatingSectionData).currentLowestY) {
|
|
@@ -102,19 +104,19 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage<SkyLightSec
|
|
}
|
|
|
|
int i = SectionPos.y(sectionPos);
|
|
- if ((this.updatingSectionData).topSections.get(l) == i + 1) {
|
|
+ if ((this.updatingSectionData).otherData.getUpdating(l) == i + 1) { // Paper - avoid copying light data
|
|
long m;
|
|
for(m = sectionPos; !this.storingLightForSection(m) && this.hasSectionsBelow(i); m = SectionPos.offset(m, Direction.DOWN)) {
|
|
--i;
|
|
}
|
|
|
|
if (this.storingLightForSection(m)) {
|
|
- (this.updatingSectionData).topSections.put(l, i + 1);
|
|
+ (this.updatingSectionData).otherData.queueUpdate(l, i + 1); // Paper - avoid copying light data
|
|
if (bl) {
|
|
this.queueAddSource(m);
|
|
}
|
|
} else {
|
|
- (this.updatingSectionData).topSections.remove(l);
|
|
+ (this.updatingSectionData).otherData.queueRemove(l); // Paper - avoid copying light data
|
|
}
|
|
}
|
|
|
|
@@ -128,7 +130,7 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage<SkyLightSec
|
|
protected void enableLightSources(long columnPos, boolean enabled) {
|
|
this.runAllUpdates();
|
|
if (enabled && this.columnsWithSkySources.add(columnPos)) {
|
|
- int i = (this.updatingSectionData).topSections.get(columnPos);
|
|
+ int i = (this.updatingSectionData).otherData.getUpdating(columnPos); // Paper - avoid copying light data
|
|
if (i != (this.updatingSectionData).currentLowestY) {
|
|
long l = SectionPos.asLong(SectionPos.x(columnPos), i - 1, SectionPos.z(columnPos));
|
|
this.queueAddSource(l);
|
|
@@ -152,7 +154,7 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage<SkyLightSec
|
|
return dataLayer;
|
|
} else {
|
|
long l = SectionPos.offset(sectionPos, Direction.UP);
|
|
- int i = (this.updatingSectionData).topSections.get(SectionPos.getZeroNode(sectionPos));
|
|
+ int i = (this.updatingSectionData).otherData.getUpdating(SectionPos.getZeroNode(sectionPos)); // Paper - avoid copying light data
|
|
if (i != (this.updatingSectionData).currentLowestY && SectionPos.y(l) < i) {
|
|
DataLayer dataLayer2;
|
|
while((dataLayer2 = this.getDataLayer(l, true)) == null) {
|
|
@@ -275,7 +277,7 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage<SkyLightSec
|
|
|
|
protected boolean isAboveData(long sectionPos) {
|
|
long l = SectionPos.getZeroNode(sectionPos);
|
|
- int i = (this.updatingSectionData).topSections.get(l);
|
|
+ int i = (this.updatingSectionData).otherData.getUpdating(l); // Paper - avoid copying light data
|
|
return i == (this.updatingSectionData).currentLowestY || SectionPos.y(sectionPos) >= i;
|
|
}
|
|
|
|
@@ -286,18 +288,21 @@ public class SkyLightSectionStorage extends LayerLightSectionStorage<SkyLightSec
|
|
|
|
protected static final class SkyDataLayerStorageMap extends DataLayerStorageMap<SkyLightSectionStorage.SkyDataLayerStorageMap> {
|
|
int currentLowestY;
|
|
- final Long2IntOpenHashMap topSections;
|
|
-
|
|
- public SkyDataLayerStorageMap(Long2ObjectOpenHashMap<DataLayer> arrays, Long2IntOpenHashMap columnToTopSection, int minSectionY) {
|
|
- super(arrays);
|
|
- this.topSections = columnToTopSection;
|
|
- columnToTopSection.defaultReturnValue(minSectionY);
|
|
+ private final com.destroystokyo.paper.util.map.QueuedChangesMapLong2Int otherData; // Paper - avoid copying light data
|
|
+
|
|
+ // Paper start - avoid copying light data
|
|
+ public SkyDataLayerStorageMap(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object<DataLayer> arrays, com.destroystokyo.paper.util.map.QueuedChangesMapLong2Int columnToTopSection, int minSectionY, boolean isVisible) {
|
|
+ super(arrays, isVisible);
|
|
+ this.otherData = columnToTopSection;
|
|
+ otherData.queueDefaultReturnValue(minSectionY);
|
|
+ // Paper end
|
|
this.currentLowestY = minSectionY;
|
|
}
|
|
|
|
@Override
|
|
public SkyLightSectionStorage.SkyDataLayerStorageMap copy() {
|
|
- return new SkyLightSectionStorage.SkyDataLayerStorageMap(this.map.clone(), this.topSections.clone(), this.currentLowestY);
|
|
+ this.otherData.performUpdatesLockMap(); // Paper - avoid copying light data
|
|
+ return new SkyLightSectionStorage.SkyDataLayerStorageMap(this.data, this.otherData, this.currentLowestY, true); // Paper - avoid copying light data
|
|
}
|
|
}
|
|
}
|