9
0
mirror of https://github.com/VolmitSoftware/Iris.git synced 2025-12-19 15:09:18 +00:00

even more performance improvements

This commit is contained in:
Julian Krings
2025-11-06 15:29:03 +01:00
parent 1d7cba184c
commit 8cea165a29
7 changed files with 128 additions and 91 deletions

View File

@@ -63,7 +63,7 @@ public class MantleWriter implements IObjectPlacer, AutoCloseable {
this.engineMantle = engineMantle; this.engineMantle = engineMantle;
this.mantle = mantle; this.mantle = mantle;
int d = radius * 2 + 1; int d = radius * 2 + 1;
this.cachedChunks = new KMap<>(d * d); this.cachedChunks = new KMap<>(d * d, 0.75f, Math.max(32, Runtime.getRuntime().availableProcessors() * 4));
this.radius = radius; this.radius = radius;
this.x = x; this.x = x;
this.z = z; this.z = z;

View File

@@ -39,7 +39,6 @@ import com.volmit.iris.util.matter.MatterMarker;
import com.volmit.iris.util.parallel.BurstExecutor; import com.volmit.iris.util.parallel.BurstExecutor;
import com.volmit.iris.util.parallel.MultiBurst; import com.volmit.iris.util.parallel.MultiBurst;
import com.volmit.iris.util.plugin.VolmitSender; import com.volmit.iris.util.plugin.VolmitSender;
import com.volmit.iris.util.scheduling.IrisLock;
import com.volmit.iris.util.scheduling.PrecisionStopwatch; import com.volmit.iris.util.scheduling.PrecisionStopwatch;
import com.volmit.iris.util.scheduling.jobs.Job; import com.volmit.iris.util.scheduling.jobs.Job;
import com.volmit.iris.util.stream.ProceduralStream; import com.volmit.iris.util.stream.ProceduralStream;
@@ -63,6 +62,8 @@ import java.util.*;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import java.util.stream.StreamSupport; import java.util.stream.StreamSupport;
@@ -74,16 +75,16 @@ public class IrisObject extends IrisRegistrant {
protected static final BlockData VAIR = B.get("VOID_AIR"); protected static final BlockData VAIR = B.get("VOID_AIR");
protected static final BlockData VAIR_DEBUG = B.get("COBWEB"); protected static final BlockData VAIR_DEBUG = B.get("COBWEB");
protected static final BlockData[] SNOW_LAYERS = new BlockData[]{B.get("minecraft:snow[layers=1]"), B.get("minecraft:snow[layers=2]"), B.get("minecraft:snow[layers=3]"), B.get("minecraft:snow[layers=4]"), B.get("minecraft:snow[layers=5]"), B.get("minecraft:snow[layers=6]"), B.get("minecraft:snow[layers=7]"), B.get("minecraft:snow[layers=8]")}; protected static final BlockData[] SNOW_LAYERS = new BlockData[]{B.get("minecraft:snow[layers=1]"), B.get("minecraft:snow[layers=2]"), B.get("minecraft:snow[layers=3]"), B.get("minecraft:snow[layers=4]"), B.get("minecraft:snow[layers=5]"), B.get("minecraft:snow[layers=6]"), B.get("minecraft:snow[layers=7]"), B.get("minecraft:snow[layers=8]")};
protected transient final IrisLock readLock = new IrisLock("read-conclock"); protected transient final Lock readLock;
protected transient final Lock writeLock;
@Getter @Getter
@Setter @Setter
protected transient volatile boolean smartBored = false; protected transient volatile boolean smartBored = false;
@Getter
@Setter
protected transient IrisLock lock = new IrisLock("Preloadcache");
@Setter @Setter
protected transient AtomicCache<AxisAlignedBB> aabb = new AtomicCache<>(); protected transient AtomicCache<AxisAlignedBB> aabb = new AtomicCache<>();
@Getter
private VectorMap<BlockData> blocks; private VectorMap<BlockData> blocks;
@Getter
private VectorMap<TileData> states; private VectorMap<TileData> states;
@Getter @Getter
@Setter @Setter
@@ -105,6 +106,9 @@ public class IrisObject extends IrisRegistrant {
this.h = h; this.h = h;
this.d = d; this.d = d;
center = new Vector3i(w / 2, h / 2, d / 2); center = new Vector3i(w / 2, h / 2, d / 2);
var lock = new ReentrantReadWriteLock();
readLock = lock.readLock();
writeLock = lock.writeLock();
} }
public IrisObject() { public IrisObject() {
@@ -160,10 +164,10 @@ public class IrisObject extends IrisRegistrant {
PrecisionStopwatch p = PrecisionStopwatch.start(); PrecisionStopwatch p = PrecisionStopwatch.start();
BlockData vair = debug ? VAIR_DEBUG : VAIR; BlockData vair = debug ? VAIR_DEBUG : VAIR;
lock.lock(); writeLock.lock();
AtomicInteger applied = new AtomicInteger(); AtomicInteger applied = new AtomicInteger();
if (getBlocks().isEmpty()) { if (blocks.isEmpty()) {
lock.unlock(); writeLock.unlock();
Iris.warn("Cannot Smart Bore " + getLoadKey() + " because it has 0 blocks in it."); Iris.warn("Cannot Smart Bore " + getLoadKey() + " because it has 0 blocks in it.");
smartBored = true; smartBored = true;
return; return;
@@ -172,7 +176,7 @@ public class IrisObject extends IrisRegistrant {
BlockVector max = new BlockVector(Double.MIN_VALUE, Double.MIN_VALUE, Double.MIN_VALUE); BlockVector max = new BlockVector(Double.MIN_VALUE, Double.MIN_VALUE, Double.MIN_VALUE);
BlockVector min = new BlockVector(Double.MAX_VALUE, Double.MAX_VALUE, Double.MAX_VALUE); BlockVector min = new BlockVector(Double.MAX_VALUE, Double.MAX_VALUE, Double.MAX_VALUE);
for (BlockVector i : getBlocks().keys()) { for (BlockVector i : blocks.keys()) {
max.setX(Math.max(i.getX(), max.getX())); max.setX(Math.max(i.getX(), max.getX()));
min.setX(Math.min(i.getX(), min.getX())); min.setX(Math.min(i.getX(), min.getX()));
max.setY(Math.max(i.getY(), max.getY())); max.setY(Math.max(i.getY(), max.getY()));
@@ -192,7 +196,7 @@ public class IrisObject extends IrisRegistrant {
int end = Integer.MIN_VALUE; int end = Integer.MIN_VALUE;
for (int ray = min.getBlockX(); ray <= max.getBlockX(); ray++) { for (int ray = min.getBlockX(); ray <= max.getBlockX(); ray++) {
if (getBlocks().containsKey(new Vector3i(ray, finalRayY, rayZ))) { if (blocks.containsKey(new Vector3i(ray, finalRayY, rayZ))) {
start = Math.min(ray, start); start = Math.min(ray, start);
end = Math.max(ray, end); end = Math.max(ray, end);
} }
@@ -202,8 +206,8 @@ public class IrisObject extends IrisRegistrant {
for (int i = start; i <= end; i++) { for (int i = start; i <= end; i++) {
Vector3i v = new Vector3i(i, finalRayY, rayZ); Vector3i v = new Vector3i(i, finalRayY, rayZ);
if (!vair.equals(getBlocks().get(v))) { if (!vair.equals(blocks.get(v))) {
getBlocks().computeIfAbsent(v, (vv) -> vair); blocks.computeIfAbsent(v, (vv) -> vair);
applied.getAndIncrement(); applied.getAndIncrement();
} }
} }
@@ -221,7 +225,7 @@ public class IrisObject extends IrisRegistrant {
int end = Integer.MIN_VALUE; int end = Integer.MIN_VALUE;
for (int ray = min.getBlockY(); ray <= max.getBlockY(); ray++) { for (int ray = min.getBlockY(); ray <= max.getBlockY(); ray++) {
if (getBlocks().containsKey(new Vector3i(finalRayX, ray, rayZ))) { if (blocks.containsKey(new Vector3i(finalRayX, ray, rayZ))) {
start = Math.min(ray, start); start = Math.min(ray, start);
end = Math.max(ray, end); end = Math.max(ray, end);
} }
@@ -231,8 +235,8 @@ public class IrisObject extends IrisRegistrant {
for (int i = start; i <= end; i++) { for (int i = start; i <= end; i++) {
Vector3i v = new Vector3i(finalRayX, i, rayZ); Vector3i v = new Vector3i(finalRayX, i, rayZ);
if (!vair.equals(getBlocks().get(v))) { if (!vair.equals(blocks.get(v))) {
getBlocks().computeIfAbsent(v, (vv) -> vair); blocks.computeIfAbsent(v, (vv) -> vair);
applied.getAndIncrement(); applied.getAndIncrement();
} }
} }
@@ -250,7 +254,7 @@ public class IrisObject extends IrisRegistrant {
int end = Integer.MIN_VALUE; int end = Integer.MIN_VALUE;
for (int ray = min.getBlockZ(); ray <= max.getBlockZ(); ray++) { for (int ray = min.getBlockZ(); ray <= max.getBlockZ(); ray++) {
if (getBlocks().containsKey(new Vector3i(finalRayX, rayY, ray))) { if (blocks.containsKey(new Vector3i(finalRayX, rayY, ray))) {
start = Math.min(ray, start); start = Math.min(ray, start);
end = Math.max(ray, end); end = Math.max(ray, end);
} }
@@ -260,8 +264,8 @@ public class IrisObject extends IrisRegistrant {
for (int i = start; i <= end; i++) { for (int i = start; i <= end; i++) {
Vector3i v = new Vector3i(finalRayX, rayY, i); Vector3i v = new Vector3i(finalRayX, rayY, i);
if (!vair.equals(getBlocks().get(v))) { if (!vair.equals(blocks.get(v))) {
getBlocks().computeIfAbsent(v, (vv) -> vair); blocks.computeIfAbsent(v, (vv) -> vair);
applied.getAndIncrement(); applied.getAndIncrement();
} }
} }
@@ -272,7 +276,7 @@ public class IrisObject extends IrisRegistrant {
burst.complete(); burst.complete();
smartBored = true; smartBored = true;
lock.unlock(); writeLock.unlock();
Iris.debug("Smart Bore: " + getLoadKey() + " in " + Form.duration(p.getMilliseconds(), 2) + " (" + Form.f(applied.get()) + ")"); Iris.debug("Smart Bore: " + getLoadKey() + " in " + Form.duration(p.getMilliseconds(), 2) + " (" + Form.f(applied.get()) + ")");
} }
@@ -283,8 +287,8 @@ public class IrisObject extends IrisRegistrant {
o.setLoadFile(getLoadFile()); o.setLoadFile(getLoadFile());
o.setCenter(getCenter().clone()); o.setCenter(getCenter().clone());
getBlocks().forEach((i, v) -> o.getBlocks().put(i.clone(), v.clone())); blocks.forEach((i, v) -> o.blocks.put(i.clone(), v.clone()));
getStates().forEach((i, v) -> o.getStates().put(i.clone(), v.clone())); states.forEach((i, v) -> o.states.put(i.clone(), v.clone()));
return o; return o;
} }
@@ -298,14 +302,14 @@ public class IrisObject extends IrisRegistrant {
int s = din.readInt(); int s = din.readInt();
for (int i = 0; i < s; i++) { for (int i = 0; i < s; i++) {
getBlocks().put(new Vector3i(din.readShort(), din.readShort(), din.readShort()), B.get(din.readUTF())); blocks.put(new Vector3i(din.readShort(), din.readShort(), din.readShort()), B.get(din.readUTF()));
} }
try { try {
int size = din.readInt(); int size = din.readInt();
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
getStates().put(new Vector3i(din.readShort(), din.readShort(), din.readShort()), TileData.read(din)); states.put(new Vector3i(din.readShort(), din.readShort(), din.readShort()), TileData.read(din));
} }
} catch (Throwable e) { } catch (Throwable e) {
Iris.reportError(e); Iris.reportError(e);
@@ -333,13 +337,13 @@ public class IrisObject extends IrisRegistrant {
s = din.readInt(); s = din.readInt();
for (i = 0; i < s; i++) { for (i = 0; i < s; i++) {
getBlocks().put(new Vector3i(din.readShort(), din.readShort(), din.readShort()), B.get(palette.get(din.readShort()))); blocks.put(new Vector3i(din.readShort(), din.readShort(), din.readShort()), B.get(palette.get(din.readShort())));
} }
s = din.readInt(); s = din.readInt();
for (i = 0; i < s; i++) { for (i = 0; i < s; i++) {
getStates().put(new Vector3i(din.readShort(), din.readShort(), din.readShort()), TileData.read(din)); states.put(new Vector3i(din.readShort(), din.readShort(), din.readShort()), TileData.read(din));
} }
} }
@@ -351,7 +355,7 @@ public class IrisObject extends IrisRegistrant {
dos.writeUTF("Iris V2 IOB;"); dos.writeUTF("Iris V2 IOB;");
KList<String> palette = new KList<>(); KList<String> palette = new KList<>();
for (BlockData i : getBlocks().values()) { for (BlockData i : blocks.values()) {
palette.addIfMissing(i.getAsString()); palette.addIfMissing(i.getAsString());
} }
@@ -361,9 +365,9 @@ public class IrisObject extends IrisRegistrant {
dos.writeUTF(i); dos.writeUTF(i);
} }
dos.writeInt(getBlocks().size()); dos.writeInt(blocks.size());
for (var entry : getBlocks()) { for (var entry : blocks) {
var i = entry.getKey(); var i = entry.getKey();
dos.writeShort(i.getBlockX()); dos.writeShort(i.getBlockX());
dos.writeShort(i.getBlockY()); dos.writeShort(i.getBlockY());
@@ -371,8 +375,8 @@ public class IrisObject extends IrisRegistrant {
dos.writeShort(palette.indexOf(entry.getValue().getAsString())); dos.writeShort(palette.indexOf(entry.getValue().getAsString()));
} }
dos.writeInt(getStates().size()); dos.writeInt(states.size());
for (var entry : getStates()) { for (var entry : states) {
var i = entry.getKey(); var i = entry.getKey();
dos.writeShort(i.getBlockX()); dos.writeShort(i.getBlockX());
dos.writeShort(i.getBlockY()); dos.writeShort(i.getBlockY());
@@ -385,7 +389,7 @@ public class IrisObject extends IrisRegistrant {
AtomicReference<IOException> ref = new AtomicReference<>(); AtomicReference<IOException> ref = new AtomicReference<>();
CountDownLatch latch = new CountDownLatch(1); CountDownLatch latch = new CountDownLatch(1);
new Job() { new Job() {
private int total = getBlocks().size() * 3 + getStates().size(); private int total = blocks.size() * 3 + states.size();
private int c = 0; private int c = 0;
@Override @Override
@@ -404,11 +408,11 @@ public class IrisObject extends IrisRegistrant {
KList<String> palette = new KList<>(); KList<String> palette = new KList<>();
for (BlockData i : getBlocks().values()) { for (BlockData i : blocks.values()) {
palette.addIfMissing(i.getAsString()); palette.addIfMissing(i.getAsString());
++c; ++c;
} }
total -= getBlocks().size() - palette.size(); total -= blocks.size() - palette.size();
dos.writeShort(palette.size()); dos.writeShort(palette.size());
@@ -417,9 +421,9 @@ public class IrisObject extends IrisRegistrant {
++c; ++c;
} }
dos.writeInt(getBlocks().size()); dos.writeInt(blocks.size());
for (var entry : getBlocks()) { for (var entry : blocks) {
var i = entry.getKey(); var i = entry.getKey();
dos.writeShort(i.getBlockX()); dos.writeShort(i.getBlockX());
dos.writeShort(i.getBlockY()); dos.writeShort(i.getBlockY());
@@ -428,8 +432,8 @@ public class IrisObject extends IrisRegistrant {
++c; ++c;
} }
dos.writeInt(getStates().size()); dos.writeInt(states.size());
for (var entry : getStates()) { for (var entry : states) {
var i = entry.getKey(); var i = entry.getKey();
dos.writeShort(i.getBlockX()); dos.writeShort(i.getBlockX());
dos.writeShort(i.getBlockY()); dos.writeShort(i.getBlockY());
@@ -503,7 +507,7 @@ public class IrisObject extends IrisRegistrant {
BlockVector min = new BlockVector(); BlockVector min = new BlockVector();
BlockVector max = new BlockVector(); BlockVector max = new BlockVector();
for (BlockVector i : getBlocks().keys()) { for (BlockVector i : blocks.keys()) {
min.setX(Math.min(min.getX(), i.getX())); min.setX(Math.min(min.getX(), i.getX()));
min.setY(Math.min(min.getY(), i.getY())); min.setY(Math.min(min.getY(), i.getY()));
min.setZ(Math.min(min.getZ(), i.getZ())); min.setZ(Math.min(min.getZ(), i.getZ()));
@@ -520,10 +524,10 @@ public class IrisObject extends IrisRegistrant {
public void clean() { public void clean() {
VectorMap<BlockData> d = new VectorMap<>(); VectorMap<BlockData> d = new VectorMap<>();
d.putAll(getBlocks()); d.putAll(blocks);
VectorMap<TileData> dx = new VectorMap<>(); VectorMap<TileData> dx = new VectorMap<>();
dx.putAll(getStates()); dx.putAll(states);
blocks = d; blocks = d;
states = dx; states = dx;
@@ -541,10 +545,10 @@ public class IrisObject extends IrisRegistrant {
Vector3i v = getSigned(x, y, z); Vector3i v = getSigned(x, y, z);
if (block == null) { if (block == null) {
getBlocks().remove(v); blocks.remove(v);
getStates().remove(v); states.remove(v);
} else { } else {
getBlocks().put(v, block); blocks.put(v, block);
} }
} }
@@ -552,15 +556,15 @@ public class IrisObject extends IrisRegistrant {
Vector3i v = getSigned(x, y, z); Vector3i v = getSigned(x, y, z);
if (block == null) { if (block == null) {
getBlocks().remove(v); blocks.remove(v);
getStates().remove(v); states.remove(v);
} else { } else {
BlockData data = block.getBlockData(); BlockData data = block.getBlockData();
getBlocks().put(v, data); blocks.put(v, data);
TileData state = TileData.getTileState(block, legacy); TileData state = TileData.getTileState(block, legacy);
if (state != null) { if (state != null) {
Iris.debug("Saved State " + v); Iris.debug("Saved State " + v);
getStates().put(v, state); states.put(v, state);
} }
} }
} }
@@ -857,7 +861,7 @@ public class IrisObject extends IrisRegistrant {
try { try {
if (config.getMarkers().isNotEmpty() && placer.getEngine() != null) { if (config.getMarkers().isNotEmpty() && placer.getEngine() != null) {
markers = new KMap<>(); markers = new KMap<>();
var list = StreamSupport.stream(getBlocks().keys().spliterator(), false) var list = StreamSupport.stream(blocks.keys().spliterator(), false)
.collect(KList.collector()); .collect(KList.collector());
for (IrisObjectMarker j : config.getMarkers()) { for (IrisObjectMarker j : config.getMarkers()) {
@@ -873,7 +877,7 @@ public class IrisObject extends IrisRegistrant {
break; break;
} }
BlockData data = getBlocks().get(i); BlockData data = blocks.get(i);
for (BlockData k : j.getMark(rdata)) { for (BlockData k : j.getMark(rdata)) {
if (max <= 0) { if (max <= 0) {
@@ -894,14 +898,14 @@ public class IrisObject extends IrisRegistrant {
} }
} }
for (var entry : getBlocks()) { for (var entry : blocks) {
var g = entry.getKey(); var g = entry.getKey();
BlockData d; BlockData d;
TileData tile = null; TileData tile = null;
try { try {
d = entry.getValue(); d = entry.getValue();
tile = getStates().get(g); tile = states.get(g);
} catch (Throwable e) { } catch (Throwable e) {
Iris.reportError(e); Iris.reportError(e);
Iris.warn("Failed to read block node " + g.getBlockX() + "," + g.getBlockY() + "," + g.getBlockZ() + " in object " + getLoadKey() + " (cme)"); Iris.warn("Failed to read block node " + g.getBlockX() + "," + g.getBlockY() + "," + g.getBlockZ() + " in object " + getLoadKey() + " (cme)");
@@ -1019,12 +1023,12 @@ public class IrisObject extends IrisRegistrant {
if (stilting) { if (stilting) {
readLock.lock(); readLock.lock();
IrisStiltSettings settings = config.getStiltSettings(); IrisStiltSettings settings = config.getStiltSettings();
for (BlockVector g : getBlocks().keys()) { for (BlockVector g : blocks.keys()) {
BlockData d; BlockData d;
if (settings == null || settings.getPalette() == null) { if (settings == null || settings.getPalette() == null) {
try { try {
d = getBlocks().get(g); d = blocks.get(g);
} catch (Throwable e) { } catch (Throwable e) {
Iris.reportError(e); Iris.reportError(e);
Iris.warn("Failed to read block node " + g.getBlockX() + "," + g.getBlockY() + "," + g.getBlockZ() + " in object " + getLoadKey() + " (stilt cme)"); Iris.warn("Failed to read block node " + g.getBlockX() + "," + g.getBlockY() + "," + g.getBlockZ() + " in object " + getLoadKey() + " (stilt cme)");
@@ -1131,60 +1135,60 @@ public class IrisObject extends IrisRegistrant {
} }
public void rotate(IrisObjectRotation r, int spinx, int spiny, int spinz) { public void rotate(IrisObjectRotation r, int spinx, int spiny, int spinz) {
writeLock.lock();
VectorMap<BlockData> d = new VectorMap<>(); VectorMap<BlockData> d = new VectorMap<>();
for (var entry : getBlocks()) { for (var entry : blocks) {
d.put(r.rotate(entry.getKey(), spinx, spiny, spinz), r.rotate(entry.getValue(), spinx, spiny, spinz)); d.put(r.rotate(entry.getKey(), spinx, spiny, spinz), r.rotate(entry.getValue(), spinx, spiny, spinz));
} }
VectorMap<TileData> dx = new VectorMap<>(); VectorMap<TileData> dx = new VectorMap<>();
for (var entry : getStates()) { for (var entry : states) {
dx.put(r.rotate(entry.getKey(), spinx, spiny, spinz), entry.getValue()); dx.put(r.rotate(entry.getKey(), spinx, spiny, spinz), entry.getValue());
} }
blocks = d; blocks = d;
states = dx; states = dx;
writeLock.unlock();
shrinkwrap(); shrinkwrap();
} }
public void place(Location at) { public void place(Location at) {
for (var entry : getBlocks()) { readLock.lock();
for (var entry : blocks) {
var i = entry.getKey(); var i = entry.getKey();
Block b = at.clone().add(0, getCenter().getY(), 0).add(i).getBlock(); Block b = at.clone().add(0, getCenter().getY(), 0).add(i).getBlock();
b.setBlockData(Objects.requireNonNull(entry.getValue()), false); b.setBlockData(Objects.requireNonNull(entry.getValue()), false);
if (getStates().containsKey(i)) { if (states.containsKey(i)) {
Iris.info(Objects.requireNonNull(states.get(i)).toString()); Iris.info(Objects.requireNonNull(states.get(i)).toString());
Objects.requireNonNull(getStates().get(i)).toBukkitTry(b); Objects.requireNonNull(states.get(i)).toBukkitTry(b);
} }
} }
readLock.unlock();
} }
public void placeCenterY(Location at) { public void placeCenterY(Location at) {
for (var entry : getBlocks()) { readLock.lock();
for (var entry : blocks) {
var i = entry.getKey(); var i = entry.getKey();
Block b = at.clone().add(getCenter().getX(), getCenter().getY(), getCenter().getZ()).add(i).getBlock(); Block b = at.clone().add(getCenter().getX(), getCenter().getY(), getCenter().getZ()).add(i).getBlock();
b.setBlockData(Objects.requireNonNull(entry.getValue()), false); b.setBlockData(Objects.requireNonNull(entry.getValue()), false);
if (getStates().containsKey(i)) { if (states.containsKey(i)) {
Objects.requireNonNull(getStates().get(i)).toBukkitTry(b); Objects.requireNonNull(states.get(i)).toBukkitTry(b);
} }
} }
} readLock.unlock();
public synchronized VectorMap<BlockData> getBlocks() {
return blocks;
}
public synchronized VectorMap<TileData> getStates() {
return states;
} }
public void unplaceCenterY(Location at) { public void unplaceCenterY(Location at) {
for (BlockVector i : getBlocks().keys()) { readLock.lock();
for (BlockVector i : blocks.keys()) {
at.clone().add(getCenter().getX(), getCenter().getY(), getCenter().getZ()).add(i).getBlock().setBlockData(AIR, false); at.clone().add(getCenter().getX(), getCenter().getY(), getCenter().getZ()).add(i).getBlock().setBlockData(AIR, false);
} }
readLock.unlock();
} }
public IrisObject scaled(double scale, IrisObjectPlacementScaleInterpolator interpolation) { public IrisObject scaled(double scale, IrisObjectPlacementScaleInterpolator interpolation) {
@@ -1211,17 +1215,19 @@ public class IrisObject extends IrisRegistrant {
IrisObject oo = new IrisObject((int) Math.ceil((w * scale) + (scale * 2)), (int) Math.ceil((h * scale) + (scale * 2)), (int) Math.ceil((d * scale) + (scale * 2))); IrisObject oo = new IrisObject((int) Math.ceil((w * scale) + (scale * 2)), (int) Math.ceil((h * scale) + (scale * 2)), (int) Math.ceil((d * scale) + (scale * 2)));
readLock.lock();
for (var entry : blocks) { for (var entry : blocks) {
BlockData bd = entry.getValue(); BlockData bd = entry.getValue();
placeBlock.put(entry.getKey().clone().add(HALF).subtract(center) placeBlock.put(entry.getKey().clone().add(HALF).subtract(center)
.multiply(scale).add(sm1).toBlockVector(), bd); .multiply(scale).add(sm1).toBlockVector(), bd);
} }
readLock.unlock();
for (var entry : placeBlock) { for (var entry : placeBlock) {
BlockVector v = entry.getKey(); BlockVector v = entry.getKey();
if (scale > 1) { if (scale > 1) {
for (BlockVector vec : blocksBetweenTwoPoints(v.clone().add(center), v.clone().add(center).add(sm1))) { for (BlockVector vec : blocksBetweenTwoPoints(v.clone().add(center), v.clone().add(center).add(sm1))) {
oo.getBlocks().put(vec, entry.getValue()); oo.blocks.put(vec, entry.getValue());
} }
} else { } else {
oo.setUnsigned(v.getBlockX(), v.getBlockY(), v.getBlockZ(), entry.getValue()); oo.setUnsigned(v.getBlockX(), v.getBlockY(), v.getBlockZ(), entry.getValue());
@@ -1240,7 +1246,8 @@ public class IrisObject extends IrisRegistrant {
} }
public void trilinear(int rad) { public void trilinear(int rad) {
VectorMap<BlockData> v = getBlocks(); writeLock.lock();
VectorMap<BlockData> v = blocks;
VectorMap<BlockData> b = new VectorMap<>(); VectorMap<BlockData> b = new VectorMap<>();
BlockVector min = getAABB().minbv(); BlockVector min = getAABB().minbv();
BlockVector max = getAABB().maxbv(); BlockVector max = getAABB().maxbv();
@@ -1266,10 +1273,12 @@ public class IrisObject extends IrisRegistrant {
} }
blocks = b; blocks = b;
writeLock.unlock();
} }
public void tricubic(int rad) { public void tricubic(int rad) {
VectorMap<BlockData> v = getBlocks(); writeLock.lock();
VectorMap<BlockData> v = blocks;
VectorMap<BlockData> b = new VectorMap<>(); VectorMap<BlockData> b = new VectorMap<>();
BlockVector min = getAABB().minbv(); BlockVector min = getAABB().minbv();
BlockVector max = getAABB().maxbv(); BlockVector max = getAABB().maxbv();
@@ -1295,6 +1304,7 @@ public class IrisObject extends IrisRegistrant {
} }
blocks = b; blocks = b;
writeLock.unlock();
} }
public void trihermite(int rad) { public void trihermite(int rad) {
@@ -1302,7 +1312,8 @@ public class IrisObject extends IrisRegistrant {
} }
public void trihermite(int rad, double tension, double bias) { public void trihermite(int rad, double tension, double bias) {
VectorMap<BlockData> v = getBlocks(); writeLock.lock();
VectorMap<BlockData> v = blocks;
VectorMap<BlockData> b = new VectorMap<>(); VectorMap<BlockData> b = new VectorMap<>();
BlockVector min = getAABB().minbv(); BlockVector min = getAABB().minbv();
BlockVector max = getAABB().maxbv(); BlockVector max = getAABB().maxbv();
@@ -1328,11 +1339,13 @@ public class IrisObject extends IrisRegistrant {
} }
blocks = b; blocks = b;
writeLock.unlock();
} }
private BlockData nearestBlockData(int x, int y, int z) { private BlockData nearestBlockData(int x, int y, int z) {
BlockVector vv = new BlockVector(x, y, z); BlockVector vv = new BlockVector(x, y, z);
BlockData r = getBlocks().get(vv); readLock.lock();
BlockData r = blocks.get(vv);
if (r != null && !r.getMaterial().isAir()) { if (r != null && !r.getMaterial().isAir()) {
return r; return r;
@@ -1354,6 +1367,7 @@ public class IrisObject extends IrisRegistrant {
r = dat; r = dat;
} }
} }
readLock.unlock();
return r; return r;
} }

View File

@@ -3,13 +3,15 @@ package com.volmit.iris.util.cache;
import com.volmit.iris.util.function.Function2; import com.volmit.iris.util.function.Function2;
public class ChunkCache2D<T> { public class ChunkCache2D<T> {
private static final boolean FAST = Boolean.getBoolean("iris.cache.fast");
private final Entry<T>[] cache; private final Entry<T>[] cache;
@SuppressWarnings({"unchecked"}) @SuppressWarnings({"unchecked"})
public ChunkCache2D() { public ChunkCache2D() {
this.cache = new Entry[256]; this.cache = new Entry[256];
for (int i = 0; i < cache.length; i++) { for (int i = 0; i < cache.length; i++) {
cache[i] = new Entry<>(); cache[i] = FAST ? new FastEntry<>() : new Entry<>();
} }
} }
@@ -19,9 +21,9 @@ public class ChunkCache2D<T> {
} }
private static class Entry<T> { private static class Entry<T> {
private volatile T t; protected volatile T t;
private T compute(int x, int z, Function2<Integer, Integer, T> resolver) { protected T compute(int x, int z, Function2<Integer, Integer, T> resolver) {
if (t != null) return t; if (t != null) return t;
synchronized (this) { synchronized (this) {
if (t == null) t = resolver.apply(x, z); if (t == null) t = resolver.apply(x, z);
@@ -29,4 +31,12 @@ public class ChunkCache2D<T> {
} }
} }
} }
private static class FastEntry<T> extends Entry<T> {
@Override
protected T compute(int x, int z, Function2<Integer, Integer, T> resolver) {
if (t != null) return t;
return t = resolver.apply(x, z);
}
}
} }

View File

@@ -8,12 +8,12 @@ public class WorldCache2D<T> {
private final ConcurrentLinkedHashMap<Long, ChunkCache2D<T>> chunks; private final ConcurrentLinkedHashMap<Long, ChunkCache2D<T>> chunks;
private final Function2<Integer, Integer, T> resolver; private final Function2<Integer, Integer, T> resolver;
public WorldCache2D(Function2<Integer, Integer, T> resolver) { public WorldCache2D(Function2<Integer, Integer, T> resolver, int size) {
this.resolver = resolver; this.resolver = resolver;
chunks = new ConcurrentLinkedHashMap.Builder<Long, ChunkCache2D<T>>() chunks = new ConcurrentLinkedHashMap.Builder<Long, ChunkCache2D<T>>()
.initialCapacity(1024) .initialCapacity(size)
.maximumWeightedCapacity(1024) .maximumWeightedCapacity(size)
.concurrencyLevel(32) .concurrencyLevel(Math.max(32, Runtime.getRuntime().availableProcessors() * 4))
.build(); .build();
} }

View File

@@ -37,7 +37,11 @@ public class KMap<K, V> extends ConcurrentHashMap<K, V> {
} }
public KMap(int initialCapacity) { public KMap(int initialCapacity) {
super(initialCapacity, 0.75f, Runtime.getRuntime().availableProcessors()); this(initialCapacity, 0.75f, 1);
}
public KMap(int initialCapacity, float loadFactor, int concurrencyLevel) {
super(initialCapacity, loadFactor, concurrencyLevel);
} }
public KMap(Map<K, V> gMap) { public KMap(Map<K, V> gMap) {

View File

@@ -37,7 +37,7 @@ public class CachedStream2D<T> extends BasicStream<T> implements ProceduralStrea
super(); super();
this.stream = stream; this.stream = stream;
this.engine = engine; this.engine = engine;
cache = new WorldCache2D<>(stream::get); cache = new WorldCache2D<>(stream::get, size);
Iris.service(PreservationSVC.class).registerCache(this); Iris.service(PreservationSVC.class).registerCache(this);
} }

View File

@@ -6,9 +6,12 @@ import com.volmit.iris.engine.framework.Engine
import com.volmit.iris.util.context.ChunkContext import com.volmit.iris.util.context.ChunkContext
import com.volmit.iris.util.documentation.ChunkCoordinates import com.volmit.iris.util.documentation.ChunkCoordinates
import com.volmit.iris.util.mantle.Mantle import com.volmit.iris.util.mantle.Mantle
import com.volmit.iris.util.mantle.MantleChunk
import com.volmit.iris.util.mantle.flag.MantleFlag import com.volmit.iris.util.mantle.flag.MantleFlag
import com.volmit.iris.util.parallel.MultiBurst import com.volmit.iris.util.parallel.MultiBurst
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.flow.FlowCollector import kotlinx.coroutines.flow.FlowCollector
import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@@ -25,6 +28,7 @@ interface MatterGenerator {
fun generateMatter(x: Int, z: Int, multicore: Boolean, context: ChunkContext) { fun generateMatter(x: Int, z: Int, multicore: Boolean, context: ChunkContext) {
if (!engine.dimension.isUseMantle || mantle.hasFlag(x, z, MantleFlag.PLANNED)) if (!engine.dimension.isUseMantle || mantle.hasFlag(x, z, MantleFlag.PLANNED))
return return
val multicore = multicore || IrisSettings.get().generator.isUseMulticoreMantle
mantle.write(engine.mantle, x, z, radius * 2).use { writer -> mantle.write(engine.mantle, x, z, radius * 2).use { writer ->
for (pair in components) { for (pair in components) {
@@ -32,8 +36,8 @@ interface MatterGenerator {
for (c in pair.a) { for (c in pair.a) {
emit(Triple(x, z, c)) emit(Triple(x, z, c))
} }
}, { (x, z, c) -> launch { }, { (x, z, c) -> launch(multicore) {
writer.acquireChunk(x, z) acquireChunk(multicore, writer, x, z)
.raiseFlagSuspend(MantleFlag.PLANNED, c.flag) { .raiseFlagSuspend(MantleFlag.PLANNED, c.flag) {
if (c.isEnabled) c.generateLayer(writer, x, z, context) if (c.isEnabled) c.generateLayer(writer, x, z, context)
} }
@@ -61,7 +65,12 @@ interface MatterGenerator {
companion object { companion object {
private val dispatcher = MultiBurst.burst.dispatcher private val dispatcher = MultiBurst.burst.dispatcher
private fun CoroutineScope.launch(block: suspend CoroutineScope.() -> Unit) = private fun CoroutineScope.launch(multicore: Boolean, block: suspend CoroutineScope.() -> Unit) =
launch(if (IrisSettings.get().generator.isUseMulticoreMantle) dispatcher else EmptyCoroutineContext, block = block) launch(if (multicore) dispatcher else EmptyCoroutineContext, block = block)
private suspend fun CoroutineScope.acquireChunk(multicore: Boolean, writer: MantleWriter, x: Int, z: Int): MantleChunk {
return if (multicore) async(Dispatchers.IO) { writer.acquireChunk(x, z) }.await()
else writer.acquireChunk(x, z)
}
} }
} }