Trim generation hot path allocations

- Replace the six per-voxel IrisPosition probes in MantleWriter neighborhood hollowing with an origin-relative primitive key set
- Look mask membership up through the same primitive key set instead of allocating an IrisPosition per candidate voxel
- Give the squared-distance helper a fixed arity so ballooning no longer depends on escape analysis to drop its varargs array
- Resolve each Matter slice once per write instead of paying a hasSlice probe and a getSlice lookup for the same class
- Read the river water surface through the primitive stream accessor instead of boxing a Double per column
- Add nullable primary surface layer accessors so the terrain actuator stops building two Optionals per column
- Add MantleWriterNeighborhoodTest, MantleWriterNeighborhoodBenchmarkTest and HydrologyColumnSampleAccessorTest
This commit is contained in:
Brian Neumann-Fopiano committed 2026-09-08 04:33:32 -04:00
1 parent 1be563bd28
commit 79af11c435
6 files changed
+580 -63

No files matched your search

@@ -22,6 +22,7 @@ import art.arcane.iris.engine.framework.Engine;
import art.arcane.iris.engine.framework.EngineAssignedActuator;
import art.arcane.iris.core.loader.IrisData;
import art.arcane.iris.engine.IrisComplex;
import art.arcane.iris.util.project.stream.ProceduralStream;
import art.arcane.iris.engine.UpperDimensionContext;
import art.arcane.iris.engine.hydrology.HydrologyColumnLayer;
import art.arcane.iris.engine.hydrology.HydrologyColumnSample;
@@ -84,6 +85,7 @@ public class IrisTerrainNormalActuator extends EngineAssignedActuator<PlatformBl
IrisDimension dimension = getDimension();
IrisData data = getData();
IrisComplex complex = getComplex();
ProceduralStream<Double> riverWaterSurfaceStream = complex.getRiverWaterSurfaceStream();
RNG localRng = rng;
boolean bedrockEnabled = dimension.isBedrock();
boolean hideOres = dimension.isHideOresForHiddenOre();
@@ -117,7 +119,7 @@ public class IrisTerrainNormalActuator extends EngineAssignedActuator<PlatformBl
int he = Math.min(chunkHeight, context.getRoundedHeight(xf, zf));
int surfaceFluidHeight = Math.min(
chunkHeight,
(int) Math.round(complex.getRiverWaterSurfaceStream().get(realX, realZ))
(int) Math.round(riverWaterSurfaceStream.getDouble(realX, realZ))
);
int hf = Math.max(surfaceFluidHeight, he);
if (hf < 0) {
@@ -128,10 +130,10 @@ public class IrisTerrainNormalActuator extends EngineAssignedActuator<PlatformBl
HydrologyColumnSample hydrology = complex.sampleHydrologyColumn(realX, realZ);
HydrologyColumnLayer hydrologyFluid = hydrology == null
? null
: hydrology.primarySurfaceFluidLayer().orElse(null);
: hydrology.primarySurfaceFluidLayerOrNull();
HydrologyColumnLayer hydrologyTerrain = hydrology == null
? null
: hydrology.primarySurfaceLayer().orElse(null);
: hydrology.primarySurfaceLayerOrNull();
int cut = exposeCutStrata
&& hydrologyTerrain != null
&& hydrologyTerrain.terrainOwned()
@@ -92,10 +92,18 @@ public record HydrologyColumnSample(
}
public Optional<HydrologyColumnLayer> primarySurfaceLayer() {
return selectSurfaceLayer(false);
return Optional.ofNullable(selectSurfaceLayer(false));
}
public Optional<HydrologyColumnLayer> primarySurfaceFluidLayer() {
return Optional.ofNullable(selectSurfaceLayer(true));
}
public HydrologyColumnLayer primarySurfaceLayerOrNull() {
return selectSurfaceLayer(false);
}
public HydrologyColumnLayer primarySurfaceFluidLayerOrNull() {
return selectSurfaceLayer(true);
}
@@ -120,11 +128,10 @@ public record HydrologyColumnSample(
}
public int terrainHeight() {
Optional<HydrologyColumnLayer> layer = primarySurfaceLayer();
if (layer.isEmpty()) {
HydrologyColumnLayer primary = selectSurfaceLayer(false);
if (primary == null) {
return naturalHeight;
}
HydrologyColumnLayer primary = layer.get();
if (primary.channel()) {
return primary.bedY();
}
@@ -147,7 +154,7 @@ public record HydrologyColumnSample(
return new HydrologyRenderSample(x, z, features);
}
private Optional<HydrologyColumnLayer> selectSurfaceLayer(boolean fluidOnly) {
private HydrologyColumnLayer selectSurfaceLayer(boolean fluidOnly) {
HydrologyColumnLayer selected = null;
for (HydrologyColumnLayer layer : layers) {
if (layer.oceanApron() || !layer.feature().type().isSurface()) {
@@ -164,7 +171,7 @@ public record HydrologyColumnSample(
selected = layer;
}
}
return Optional.ofNullable(selected);
return selected;
}
private static int surfaceRolePriority(HydrologyColumnLayer layer) {
@@ -23,6 +23,7 @@ import art.arcane.iris.spi.IrisLogging;
import art.arcane.iris.util.project.matter.TileWrapper;
import art.arcane.iris.util.project.matter.PreObjectMatterCell;
import com.google.common.collect.ImmutableList;
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
import art.arcane.iris.core.IrisSettings;
import art.arcane.iris.core.link.Identifier;
import art.arcane.iris.core.tools.WorldMaintenance;
@@ -175,7 +176,7 @@ public class MantleWriter implements ObjectPassPlacer, AutoCloseable {
}
}
private static Set<IrisPosition> getBallooned(Set<IrisPosition> vset, double radius) {
static Set<IrisPosition> getBallooned(Set<IrisPosition> vset, double radius) {
Set<IrisPosition> returnset = new HashSet<>();
int ceilrad = (int) Math.ceil(radius);
double r2 = Math.pow(radius, 2);
@@ -198,30 +199,83 @@ public class MantleWriter implements ObjectPassPlacer, AutoCloseable {
return returnset;
}
private static Set<IrisPosition> getHollowed(Set<IrisPosition> vset) {
static Set<IrisPosition> getHollowed(Set<IrisPosition> vset) {
PositionLookup lookup = PositionLookup.of(vset);
Set<IrisPosition> returnset = new KSet<>();
for (IrisPosition v : vset) {
double x = v.getX();
double y = v.getY();
double z = v.getZ();
if (!(vset.contains(new IrisPosition(x + 1, y, z))
&& vset.contains(new IrisPosition(x - 1, y, z))
&& vset.contains(new IrisPosition(x, y + 1, z))
&& vset.contains(new IrisPosition(x, y - 1, z))
&& vset.contains(new IrisPosition(x, y, z + 1))
&& vset.contains(new IrisPosition(x, y, z - 1)))) {
int x = v.getX();
int y = v.getY();
int z = v.getZ();
if (!(lookup.contains(x + 1, y, z)
&& lookup.contains(x - 1, y, z)
&& lookup.contains(x, y + 1, z)
&& lookup.contains(x, y - 1, z)
&& lookup.contains(x, y, z + 1)
&& lookup.contains(x, y, z - 1))) {
returnset.add(v);
}
}
return returnset;
}
private static double hypot(double... pars) {
double sum = 0;
for (double d : pars) {
sum += Math.pow(d, 2);
private static double hypot(double x, double y, double z) {
return Math.pow(x, 2) + Math.pow(y, 2) + Math.pow(z, 2);
}
record PositionLookup(LongOpenHashSet keys, Set<IrisPosition> positions, int originX, int originY, int originZ) {
private static final int AXIS_BITS = 21;
private static final long AXIS_LIMIT = 1L << AXIS_BITS;
static PositionLookup of(Set<IrisPosition> positions) {
if (positions.isEmpty()) {
return new PositionLookup(new LongOpenHashSet(), positions, 0, 0, 0);
}
int minX = Integer.MAX_VALUE;
int minY = Integer.MAX_VALUE;
int minZ = Integer.MAX_VALUE;
int maxX = Integer.MIN_VALUE;
int maxY = Integer.MIN_VALUE;
int maxZ = Integer.MIN_VALUE;
for (IrisPosition position : positions) {
minX = Math.min(minX, position.getX());
minY = Math.min(minY, position.getY());
minZ = Math.min(minZ, position.getZ());
maxX = Math.max(maxX, position.getX());
maxY = Math.max(maxY, position.getY());
maxZ = Math.max(maxZ, position.getZ());
}
if ((long) maxX - minX >= AXIS_LIMIT - 2L
|| (long) maxY - minY >= AXIS_LIMIT - 2L
|| (long) maxZ - minZ >= AXIS_LIMIT - 2L) {
return new PositionLookup(null, positions, 0, 0, 0);
}
LongOpenHashSet keys = new LongOpenHashSet(positions.size());
for (IrisPosition position : positions) {
keys.add(key(position.getX() - minX, position.getY() - minY, position.getZ() - minZ));
}
return new PositionLookup(keys, positions, minX, minY, minZ);
}
boolean contains(int x, int y, int z) {
if (keys == null) {
return positions.contains(new IrisPosition(x, y, z));
}
long dx = (long) x - originX;
long dy = (long) y - originY;
long dz = (long) z - originZ;
if ((dx | dy | dz) < 0L || dx >= AXIS_LIMIT || dy >= AXIS_LIMIT || dz >= AXIS_LIMIT) {
return false;
}
return keys.contains(key(dx, dy, dz));
}
private static long key(long x, long y, long z) {
return (x << (AXIS_BITS * 2)) | (y << AXIS_BITS) | z;
}
return sum;
}
private static double lengthSq(double x, double y, double z) {
@@ -294,9 +348,7 @@ public class MantleWriter implements ObjectPassPlacer, AutoCloseable {
if (hasProtectedHydrology(matter, x, y, z)) {
return false;
}
MatterSlice<MatterCavern> cavernSlice = matter.hasSlice(MatterCavern.class)
? matter.getSlice(MatterCavern.class)
: null;
MatterSlice<MatterCavern> cavernSlice = matter.getSlice(MatterCavern.class);
MatterCavern existing = cavernSlice == null
? null
: cavernSlice.get(x & 15, y & 15, z & 15);
@@ -328,15 +380,13 @@ public class MantleWriter implements ObjectPassPlacer, AutoCloseable {
if (hasProtectedHydrology(matter, x, y, z)) {
return false;
}
if (matter.hasSlice(PlatformBlockState.class)) {
MatterSlice<PlatformBlockState> blockSlice = matter.getSlice(PlatformBlockState.class);
if (blockSlice != null) {
capturePreObjectOriginal(matter, x, y, z, PlatformBlockState.class);
matter.<PlatformBlockState>getSlice(PlatformBlockState.class)
.set(x & 15, y & 15, z & 15, null);
blockSlice.set(x & 15, y & 15, z & 15, null);
}
clearDeferredPlacement(matter, x, y, z);
MatterSlice<MatterCavern> cavernSlice = matter.hasSlice(MatterCavern.class)
? matter.getSlice(MatterCavern.class)
: null;
MatterSlice<MatterCavern> cavernSlice = matter.getSlice(MatterCavern.class);
if (cavernSlice != null && cavernSlice.get(x & 15, y & 15, z & 15) != null) {
return false;
}
@@ -363,10 +413,10 @@ public class MantleWriter implements ObjectPassPlacer, AutoCloseable {
if (hasProtectedHydrology(matter, x, y, z)) {
return;
}
if (matter.hasSlice(PlatformBlockState.class)) {
MatterSlice<PlatformBlockState> blockSlice = matter.getSlice(PlatformBlockState.class);
if (blockSlice != null) {
capturePreObjectOriginal(matter, x, y, z, PlatformBlockState.class);
matter.<PlatformBlockState>getSlice(PlatformBlockState.class)
.set(x & 15, y & 15, z & 15, null);
blockSlice.set(x & 15, y & 15, z & 15, null);
}
clearDeferredPlacement(matter, x, y, z);
capturePreObjectOriginal(matter, x, y, z, MatterCavern.class);
@@ -394,10 +444,10 @@ public class MantleWriter implements ObjectPassPlacer, AutoCloseable {
if (hasProtectedHydrology(matter, x, y, z)) {
return;
}
if (matter.hasSlice(PlatformBlockState.class)) {
MatterSlice<PlatformBlockState> blockSlice = matter.getSlice(PlatformBlockState.class);
if (blockSlice != null) {
capturePreObjectOriginal(matter, x, y, z, PlatformBlockState.class);
matter.<PlatformBlockState>getSlice(PlatformBlockState.class)
.set(x & 15, y & 15, z & 15, null);
blockSlice.set(x & 15, y & 15, z & 15, null);
}
clearDeferredPlacement(matter, x, y, z);
}
@@ -651,17 +701,18 @@ public class MantleWriter implements ObjectPassPlacer, AutoCloseable {
}
private static boolean hasProtectedHydrology(Matter matter, int x, int y, int z) {
if (!matter.hasSlice(HydrologyCaveCell.class)) {
MatterSlice<HydrologyCaveCell> slice = matter.getSlice(HydrologyCaveCell.class);
if (slice == null) {
return false;
}
HydrologyCaveCell hydrology = matter.<HydrologyCaveCell>getSlice(HydrologyCaveCell.class)
.get(x & 15, y & 15, z & 15);
HydrologyCaveCell hydrology = slice.get(x & 15, y & 15, z & 15);
return hydrology != null && hydrology.protectsPlacement();
}
private static void clearDeferredPlacement(Matter matter, int x, int y, int z) {
if (matter.hasSlice(Identifier.class)) {
matter.<Identifier>getSlice(Identifier.class).set(x & 15, y & 15, z & 15, null);
MatterSlice<Identifier> slice = matter.getSlice(Identifier.class);
if (slice != null) {
slice.set(x & 15, y & 15, z & 15, null);
}
}
@@ -728,11 +779,11 @@ public class MantleWriter implements ObjectPassPlacer, AutoCloseable {
}
private static PreObjectMatterCell preObjectCell(Matter matter, int x, int y, int z) {
if (matter == null || !matter.hasSlice(PreObjectMatterCell.class)) {
if (matter == null) {
return null;
}
return matter.<PreObjectMatterCell>getSlice(PreObjectMatterCell.class)
.get(x & 15, y & 15, z & 15);
MatterSlice<PreObjectMatterCell> slice = matter.getSlice(PreObjectMatterCell.class);
return slice == null ? null : slice.get(x & 15, y & 15, z & 15);
}
private static <T> T prerequisiteValue(Matter matter, int x, int y, int z, Class<T> type) {
@@ -740,17 +791,13 @@ public class MantleWriter implements ObjectPassPlacer, AutoCloseable {
if (cell != null && cell.captures(type)) {
return cell.original(type);
}
if (!matter.hasSlice(type)) {
return null;
}
return matter.<T>getSlice(type).get(x & 15, y & 15, z & 15);
MatterSlice<T> slice = matter.getSlice(type);
return slice == null ? null : slice.get(x & 15, y & 15, z & 15);
}
private static Object rawValue(Matter matter, int x, int y, int z, Class<?> type) {
if (!matter.hasSlice(type)) {
return null;
}
return matter.getSlice(type).get(x, y, z);
MatterSlice<?> slice = matter.getSlice(type);
return slice == null ? null : slice.get(x, y, z);
}
private boolean allowsWrite(int blockX, int blockZ) {
@@ -762,10 +809,10 @@ public class MantleWriter implements ObjectPassPlacer, AutoCloseable {
private static void restoreRaw(Matter matter, int x, int y, int z, Class<?> type, Object value) {
MatterSlice<Object> slice;
if (value == null) {
if (!matter.hasSlice(type)) {
slice = (MatterSlice<Object>) matter.getSlice(type);
if (slice == null) {
return;
}
slice = (MatterSlice<Object>) matter.getSlice(type);
} else {
slice = (MatterSlice<Object>) matter.slice(type);
}
@@ -951,9 +998,7 @@ public class MantleWriter implements ObjectPassPlacer, AutoCloseable {
continue;
}
MatterSlice<MatterCavern> cavernSlice = matter.hasSlice(MatterCavern.class)
? matter.getSlice(MatterCavern.class)
: null;
MatterSlice<MatterCavern> cavernSlice = matter.getSlice(MatterCavern.class);
MatterSlice<HydrologyCaveCell> hydrologySlice = matter.hasSlice(HydrologyCaveCell.class)
? matter.getSlice(HydrologyCaveCell.class)
: null;
@@ -1277,10 +1322,11 @@ public class MantleWriter implements ObjectPassPlacer, AutoCloseable {
setConsumer(vset, data);
}
private static Set<IrisPosition> getMasked(Set<IrisPosition> vectors, Set<IrisPosition> masks, double radius) {
static Set<IrisPosition> getMasked(Set<IrisPosition> vectors, Set<IrisPosition> masks, double radius) {
Set<IrisPosition> vset = new KSet<>();
int ceil = (int) Math.ceil(radius);
double r2 = Math.pow(radius, 2);
PositionLookup maskLookup = PositionLookup.of(masks);
for (IrisPosition v : vectors) {
int tipX = v.getX();
@@ -1290,7 +1336,7 @@ public class MantleWriter implements ObjectPassPlacer, AutoCloseable {
for (int x = -ceil; x <= ceil; x++) {
for (int y = -ceil; y <= ceil; y++) {
for (int z = -ceil; z <= ceil; z++) {
if (hypot(x, y, z) > r2 || !masks.contains(new IrisPosition(x, y, z)))
if (hypot(x, y, z) > r2 || !maskLookup.contains(x, y, z))
continue;
vset.add(new IrisPosition(tipX + x, tipY + y, tipZ + z));
}