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

optimize data palette for mantle slices

This commit is contained in:
Julian Krings
2025-10-26 22:18:57 +01:00
parent 38a579453d
commit aadd03990a
5 changed files with 103 additions and 44 deletions

View File

@@ -27,6 +27,7 @@ import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
public class IrisEngineSVC implements IrisService { public class IrisEngineSVC implements IrisService {
private static final int TRIM_PERIOD = 2_000;
private final AtomicInteger tectonicLimit = new AtomicInteger(30); private final AtomicInteger tectonicLimit = new AtomicInteger(30);
private final AtomicInteger tectonicPlates = new AtomicInteger(); private final AtomicInteger tectonicPlates = new AtomicInteger();
private final AtomicInteger queuedTectonicPlates = new AtomicInteger(); private final AtomicInteger queuedTectonicPlates = new AtomicInteger();
@@ -68,6 +69,7 @@ public class IrisEngineSVC implements IrisService {
sender.sendMessage(C.DARK_PURPLE + "Status:"); sender.sendMessage(C.DARK_PURPLE + "Status:");
sender.sendMessage(C.DARK_PURPLE + "- Service: " + C.LIGHT_PURPLE + (service.isShutdown() ? "Shutdown" : "Running")); sender.sendMessage(C.DARK_PURPLE + "- Service: " + C.LIGHT_PURPLE + (service.isShutdown() ? "Shutdown" : "Running"));
sender.sendMessage(C.DARK_PURPLE + "- Updater: " + C.LIGHT_PURPLE + (updateTicker.isAlive() ? "Running" : "Stopped")); sender.sendMessage(C.DARK_PURPLE + "- Updater: " + C.LIGHT_PURPLE + (updateTicker.isAlive() ? "Running" : "Stopped"));
sender.sendMessage(C.DARK_PURPLE + "- Period: " + C.LIGHT_PURPLE + Form.duration(TRIM_PERIOD));
sender.sendMessage(C.DARK_PURPLE + "- Trimmers: " + C.LIGHT_PURPLE + trimmerAlive.get()); sender.sendMessage(C.DARK_PURPLE + "- Trimmers: " + C.LIGHT_PURPLE + trimmerAlive.get());
sender.sendMessage(C.DARK_PURPLE + "- Unloaders: " + C.LIGHT_PURPLE + unloaderAlive.get()); sender.sendMessage(C.DARK_PURPLE + "- Unloaders: " + C.LIGHT_PURPLE + unloaderAlive.get());
sender.sendMessage(C.DARK_PURPLE + "Tectonic Plates:"); sender.sendMessage(C.DARK_PURPLE + "Tectonic Plates:");
@@ -157,7 +159,7 @@ public class IrisEngineSVC implements IrisService {
private final class Registered { private final class Registered {
private final String name; private final String name;
private final PlatformChunkGenerator access; private final PlatformChunkGenerator access;
private final int offset = RNG.r.nextInt(1000); private final int offset = RNG.r.nextInt(TRIM_PERIOD);
private transient ScheduledFuture<?> trimmer; private transient ScheduledFuture<?> trimmer;
private transient ScheduledFuture<?> unloader; private transient ScheduledFuture<?> unloader;
private transient boolean closed; private transient boolean closed;
@@ -194,7 +196,7 @@ public class IrisEngineSVC implements IrisService {
Iris.error("EngineSVC: Failed to trim for " + name); Iris.error("EngineSVC: Failed to trim for " + name);
e.printStackTrace(); e.printStackTrace();
} }
}, offset, 2000, TimeUnit.MILLISECONDS); }, offset, TRIM_PERIOD, TimeUnit.MILLISECONDS);
} }
if (unloader == null || unloader.isDone() || unloader.isCancelled()) { if (unloader == null || unloader.isDone() || unloader.isCancelled()) {
@@ -214,7 +216,7 @@ public class IrisEngineSVC implements IrisService {
Iris.error("EngineSVC: Failed to unload for " + name); Iris.error("EngineSVC: Failed to unload for " + name);
e.printStackTrace(); e.printStackTrace();
} }
}, offset + 1000, 2000, TimeUnit.MILLISECONDS); }, offset + 1000, TRIM_PERIOD, TimeUnit.MILLISECONDS);
} }
} }

View File

@@ -19,21 +19,30 @@
package com.volmit.iris.util.hunk.bits; package com.volmit.iris.util.hunk.bits;
import com.volmit.iris.util.data.Varint; import com.volmit.iris.util.data.Varint;
import lombok.Synchronized; import it.unimi.dsi.fastutil.ints.*;
import java.io.*; import java.io.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class DataContainer<T> { public class DataContainer<T> {
private static final boolean TRIM = Boolean.getBoolean("iris.trim-palette");
protected static final int INITIAL_BITS = 3; protected static final int INITIAL_BITS = 3;
protected static final int LINEAR_BITS_LIMIT = 4; protected static final int LINEAR_BITS_LIMIT = 4;
protected static final int LINEAR_INITIAL_LENGTH = (int) Math.pow(2, LINEAR_BITS_LIMIT) + 1; protected static final int LINEAR_INITIAL_LENGTH = (int) Math.pow(2, LINEAR_BITS_LIMIT) + 1;
protected static final int[] BIT = computeBitLimits(); protected static final int[] BIT = computeBitLimits();
private final Lock read, write;
private volatile Palette<T> palette; private volatile Palette<T> palette;
private volatile DataBits data; private volatile DataBits data;
private final int length; private final int length;
private final Writable<T> writer; private final Writable<T> writer;
public DataContainer(Writable<T> writer, int length) { public DataContainer(Writable<T> writer, int length) {
var lock = new ReentrantReadWriteLock();
this.read = lock.readLock();
this.write = lock.writeLock();
this.writer = writer; this.writer = writer;
this.length = length; this.length = length;
this.data = new DataBits(INITIAL_BITS, length); this.data = new DataBits(INITIAL_BITS, length);
@@ -41,10 +50,15 @@ public class DataContainer<T> {
} }
public DataContainer(DataInputStream din, Writable<T> writer) throws IOException { public DataContainer(DataInputStream din, Writable<T> writer) throws IOException {
var lock = new ReentrantReadWriteLock();
this.read = lock.readLock();
this.write = lock.writeLock();
this.writer = writer; this.writer = writer;
this.length = Varint.readUnsignedVarInt(din); this.length = Varint.readUnsignedVarInt(din);
this.palette = newPalette(din); this.palette = newPalette(din);
this.data = new DataBits(palette.bits(), length, din); this.data = new DataBits(palette.bits(), length, din);
trim();
} }
private static int[] computeBitLimits() { private static int[] computeBitLimits() {
@@ -86,13 +100,18 @@ public class DataContainer<T> {
writeDos(new DataOutputStream(out)); writeDos(new DataOutputStream(out));
} }
@Synchronized
public void writeDos(DataOutputStream dos) throws IOException { public void writeDos(DataOutputStream dos) throws IOException {
Varint.writeUnsignedVarInt(length, dos); write.lock();
Varint.writeUnsignedVarInt(palette.size(), dos); try {
palette.iterateIO((data, __) -> writer.writeNodeData(dos, data)); trim();
data.write(dos); Varint.writeUnsignedVarInt(length, dos);
dos.flush(); Varint.writeUnsignedVarInt(palette.size(), dos);
palette.iterateIO((data, __) -> writer.writeNodeData(dos, data));
data.write(dos);
dos.flush();
} finally {
write.unlock();
}
} }
private Palette<T> newPalette(DataInputStream din) throws IOException { private Palette<T> newPalette(DataInputStream din) throws IOException {
@@ -110,25 +129,38 @@ public class DataContainer<T> {
return new HashPalette<>(); return new HashPalette<>();
} }
@Synchronized
public void set(int position, T t) { public void set(int position, T t) {
int id = palette.id(t); int id;
if (id == -1) { read.lock();
id = palette.add(t); try {
updateBits(); id = palette.id(t);
if (id == -1) {
id = palette.add(t);
if (palette.bits() == data.getBits()) {
data.set(position, id);
return;
}
}
} finally {
read.unlock();
} }
data.set(position, id); write.lock();
try {
updateBits();
data.set(position, id);
} finally {
write.unlock();
}
} }
@Synchronized
@SuppressWarnings("NonAtomicOperationOnVolatileField") @SuppressWarnings("NonAtomicOperationOnVolatileField")
private void updateBits() { private void updateBits() {
if (palette.bits() == data.getBits()) int bits = palette.bits();
if (bits == data.getBits())
return; return;
int bits = palette.bits();
if (data.getBits() <= LINEAR_BITS_LIMIT != bits <= LINEAR_BITS_LIMIT) { if (data.getBits() <= LINEAR_BITS_LIMIT != bits <= LINEAR_BITS_LIMIT) {
palette = newPalette(bits).from(palette); palette = newPalette(bits).from(palette);
} }
@@ -136,18 +168,44 @@ public class DataContainer<T> {
data = data.setBits(bits); data = data.setBits(bits);
} }
@Synchronized
public T get(int position) { public T get(int position) {
int id = data.get(position); read.lock();
try {
int id = data.get(position);
if (id <= 0) { if (id <= 0) {
return null; return null;
}
return palette.get(id);
} finally {
read.unlock();
} }
return palette.get(id);
} }
public int size() { public int size() {
return data.getSize(); return data.getSize();
} }
private void trim() {
var ints = new Int2IntRBTreeMap();
for (int i = 0; i < length; i++) {
int x = data.get(i);
if (x <= 0) continue;
ints.put(x, x);
}
if (ints.size() == palette.size())
return;
int bits = bits(ints.size() + 1);
var trimmed = newPalette(bits);
ints.replaceAll((k, v) -> trimmed.add(palette.get(k)));
var tBits = new DataBits(bits, length);
for (int i = 0; i < length; i++) {
tBits.set(i, ints.get(data.get(i)));
}
data = tBits;
palette = trimmed;
}
} }

View File

@@ -27,13 +27,14 @@ import java.util.LinkedHashMap;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
public class HashPalette<T> implements Palette<T> { public class HashPalette<T> implements Palette<T> {
private final LinkedHashMap<T, Integer> palette; private final Object lock = new Object();
private final KMap<T, Integer> palette;
private final KMap<Integer, T> lookup; private final KMap<Integer, T> lookup;
private final AtomicInteger size; private final AtomicInteger size;
public HashPalette() { public HashPalette() {
this.size = new AtomicInteger(1); this.size = new AtomicInteger(1);
this.palette = new LinkedHashMap<>(); this.palette = new KMap<>();
this.lookup = new KMap<>(); this.lookup = new KMap<>();
} }
@@ -52,13 +53,13 @@ public class HashPalette<T> implements Palette<T> {
return 0; return 0;
} }
synchronized (palette) { return palette.computeIfAbsent(t, $ -> {
return palette.computeIfAbsent(t, $ -> { synchronized (lock) {
int index = size.getAndIncrement(); int index = size.getAndIncrement();
lookup.put(index, t); lookup.put(index, t);
return index; return index;
}); }
} });
} }
@Override @Override
@@ -78,7 +79,7 @@ public class HashPalette<T> implements Palette<T> {
@Override @Override
public void iterate(Consumer2<T, Integer> c) { public void iterate(Consumer2<T, Integer> c) {
synchronized (palette) { synchronized (lock) {
for (int i = 1; i < size.get(); i++) { for (int i = 1; i < size.get(); i++) {
c.accept(lookup.get(i), i); c.accept(lookup.get(i), i);
} }

View File

@@ -45,25 +45,23 @@ public class LinearPalette<T> implements Palette<T> {
@Override @Override
public int add(T t) { public int add(T t) {
if (t == null) {
return 0;
}
int index = size.getAndIncrement(); int index = size.getAndIncrement();
grow(index + 1); if (palette.length() <= index)
grow(index);
palette.set(index, t); palette.set(index, t);
return index; return index;
} }
private synchronized void grow(int newLength) { private synchronized void grow(int newLength) {
if (newLength > palette.length()) { if (palette.length() <= newLength)
AtomicReferenceArray<T> a = new AtomicReferenceArray<>(newLength); return;
for (int i = 0; i < palette.length(); i++) { AtomicReferenceArray<T> a = new AtomicReferenceArray<>(newLength + 1);
a.set(i, palette.get(i)); for (int i = 0; i < palette.length(); i++) {
} a.set(i, palette.get(i));
palette = a;
} }
palette = a;
} }
@Override @Override

View File

@@ -999,7 +999,7 @@ public class IrisInterpolation {
public static double getNoise(InterpolationMethod method, int x, int z, double h, NoiseProvider noise) { public static double getNoise(InterpolationMethod method, int x, int z, double h, NoiseProvider noise) {
HashMap<NoiseKey, Double> cache = new HashMap<>(64); HashMap<NoiseKey, Double> cache = new HashMap<>(64);
NoiseProvider n = (x1, z1) -> cache.computeIfAbsent(new NoiseKey(x1, z1), k -> noise.noise(k.x, k.z)); NoiseProvider n = (x1, z1) -> cache.computeIfAbsent(new NoiseKey(x1 - x, z1 - z), k -> noise.noise(x1, z1));
if (method.equals(InterpolationMethod.BILINEAR)) { if (method.equals(InterpolationMethod.BILINEAR)) {
return getBilinearNoise(x, z, h, n); return getBilinearNoise(x, z, h, n);