9
0
mirror of https://github.com/VolmitSoftware/Iris.git synced 2025-12-26 18:49:06 +00:00

Performance improvements

This commit is contained in:
cyberpwn
2021-08-19 03:26:45 -04:00
parent 5924495035
commit f5f4c5c672
12 changed files with 238 additions and 97 deletions

View File

@@ -412,14 +412,14 @@ public class IrisEngine extends BlockPopulator implements Engine {
switch (getDimension().getTerrainMode()) {
case NORMAL -> {
getMantle().generateMatter(x >> 4, z >> 4);
getMantle().generateMatter(x >> 4, z >> 4, multicore);
getTerrainActuator().actuate(x, z, vblocks, multicore);
getBiomeActuator().actuate(x, z, vbiomes, multicore);
getCaveModifier().modify(x, z, vblocks, multicore);
getRavineModifier().modify(x, z, vblocks, multicore);
getPostModifier().modify(x, z, vblocks, multicore);
getDecorantActuator().actuate(x, z, blocks, multicore);
getMantle().insertMatter(x >> 4, z >> 4, BlockData.class, blocks);
getMantle().insertMatter(x >> 4, z >> 4, BlockData.class, blocks, multicore);
getDepositModifier().modify(x, z, blocks, multicore);
}
case ISLANDS -> {

View File

@@ -26,9 +26,12 @@ import com.volmit.iris.engine.framework.EngineAssignedActuator;
import com.volmit.iris.engine.object.biome.IrisBiome;
import com.volmit.iris.engine.object.biome.IrisBiomeCustom;
import com.volmit.iris.util.documentation.BlockCoordinates;
import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.hunk.Hunk;
import com.volmit.iris.util.hunk.view.BiomeGridHunkView;
import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.parallel.BurstExecutor;
import com.volmit.iris.util.parallel.MultiBurst;
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
import org.bukkit.block.Biome;
import org.bukkit.generator.ChunkGenerator;
@@ -65,41 +68,46 @@ public class IrisBiomeActuator extends EngineAssignedActuator<Biome> {
@Override
public void onActuate(int x, int z, Hunk<Biome> h, boolean multicore) {
PrecisionStopwatch p = PrecisionStopwatch.start();
int zf, maxHeight;
IrisBiome ib;
BurstExecutor burst = burst().burst();
burst.setMulticore(multicore);
for (int xf = 0; xf < h.getWidth(); xf++) {
for (zf = 0; zf < h.getDepth(); zf++) {
ib = getComplex().getTrueBiomeStream().get(modX(xf + x), modZ(zf + z));
maxHeight = (int) (getComplex().getFluidHeight() + ib.getMaxWithObjectHeight(getData()));
if (ib.isCustom()) {
try {
IrisBiomeCustom custom = ib.getCustomBiome(rng, x, 0, z);
Object biomeBase = INMS.get().getCustomBiomeBaseFor(getDimension().getLoadKey() + ":" + custom.getId());
int finalXf = xf;
burst.queue(() -> {
IrisBiome ib;
for (int zf = 0; zf < h.getDepth(); zf++) {
ib = getComplex().getTrueBiomeStream().get(modX(finalXf + x), modZ(zf + z));
int maxHeight = (int) (getComplex().getFluidHeight() + ib.getMaxWithObjectHeight(getData()));
if (ib.isCustom()) {
try {
IrisBiomeCustom custom = ib.getCustomBiome(rng, x, 0, z);
Object biomeBase = INMS.get().getCustomBiomeBaseFor(getDimension().getLoadKey() + ":" + custom.getId());
if (biomeBase == null || !injectBiome(h, x, 0, z, biomeBase)) {
throw new RuntimeException("Cant inject biome!");
}
if (biomeBase == null || !injectBiome(h, x, 0, z, biomeBase)) {
throw new RuntimeException("Cant inject biome!");
}
for (int i = 0; i < maxHeight; i++) {
injectBiome(h, xf, i, zf, biomeBase);
for (int i = 0; i < maxHeight; i++) {
injectBiome(h, finalXf, i, zf, biomeBase);
}
} catch (Throwable e) {
Iris.reportError(e);
Biome v = ib.getSkyBiome(rng, x, 0, z);
for (int i = 0; i < maxHeight; i++) {
h.set(finalXf, i, zf, v);
}
}
} catch (Throwable e) {
Iris.reportError(e);
} else {
Biome v = ib.getSkyBiome(rng, x, 0, z);
for (int i = 0; i < maxHeight; i++) {
h.set(xf, i, zf, v);
h.set(finalXf, i, zf, v);
}
}
} else {
Biome v = ib.getSkyBiome(rng, x, 0, z);
for (int i = 0; i < maxHeight; i++) {
h.set(xf, i, zf, v);
}
}
}
});
}
burst.complete();
getEngine().getMetrics().getBiome().put(p.getMilliseconds());
}
}

View File

@@ -23,19 +23,19 @@ import com.volmit.iris.engine.decorator.*;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.framework.EngineAssignedActuator;
import com.volmit.iris.engine.framework.EngineDecorator;
import com.volmit.iris.engine.object.biome.InferredType;
import com.volmit.iris.engine.object.biome.IrisBiome;
import com.volmit.iris.engine.object.carve.IrisCaveLayer;
import com.volmit.iris.engine.object.decoration.IrisDecorationPart;
import com.volmit.iris.engine.object.decoration.IrisDecorator;
import com.volmit.iris.util.documentation.BlockCoordinates;
import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.hunk.Hunk;
import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.parallel.BurstExecutor;
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
import lombok.Getter;
import org.bukkit.Material;
import org.bukkit.block.data.BlockData;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiPredicate;
import java.util.function.Predicate;
@@ -90,76 +90,82 @@ public class IrisDecorantActuator extends EngineAssignedActuator<BlockData> {
}
PrecisionStopwatch p = PrecisionStopwatch.start();
int j, realX, realZ, height;
IrisBiome biome, cave;
BurstExecutor burst = burst().burst();
burst.setMulticore(multicore);
for (int i = 0; i < output.getWidth(); i++) {
for (j = 0; j < output.getDepth(); j++) {
boolean solid, liquid;
int emptyFor = 0;
int liquidFor = 0;
int lastSolid = 0;
realX = (int) Math.round(modX(x + i));
realZ = (int) Math.round(modZ(z + j));
height = (int) Math.round(getComplex().getHeightStream().get(realX, realZ));
biome = getComplex().getTrueBiomeStream().get(realX, realZ);
cave = shouldRay ? getComplex().getCaveBiomeStream().get(realX, realZ) : null;
int finalI = i;
burst.queue(() -> {
int height;
int realX = (int) Math.round(modX(x + finalI));
int realZ;
IrisBiome biome, cave;
for (int j=0; j < output.getDepth(); j++) {
boolean solid, liquid;
int emptyFor = 0;
int liquidFor = 0;
int lastSolid = 0;
realZ = (int) Math.round(modZ(z + j));
height = (int) Math.round(getComplex().getHeightStream().get(realX, realZ));
biome = getComplex().getTrueBiomeStream().get(realX, realZ);
cave = shouldRay ? getComplex().getCaveBiomeStream().get(realX, realZ) : null;
if (biome.getDecorators().isEmpty() && (cave == null || cave.getDecorators().isEmpty())) {
continue;
}
if (biome.getDecorators().isEmpty() && (cave == null || cave.getDecorators().isEmpty())) {
continue;
}
if(height < getDimension().getFluidHeight())
{
getSeaSurfaceDecorator().decorate(i, j,
realX, (int) Math.round(modX(x + i + 1)), (int) Math.round(modX(x + i - 1)),
realZ, (int) Math.round(modZ(z + j + 1)), (int) Math.round(modZ(z + j - 1)),
output, biome, getDimension().getFluidHeight(), getEngine().getHeight());
getSeaFloorDecorator().decorate(i, j,
realX, realZ, output, biome, height + 1,
getDimension().getFluidHeight() + 1);
}
if(height < getDimension().getFluidHeight())
{
getSeaSurfaceDecorator().decorate(finalI, j,
realX, (int) Math.round(modX(x + finalI + 1)), (int) Math.round(modX(x + finalI - 1)),
realZ, (int) Math.round(modZ(z + j + 1)), (int) Math.round(modZ(z + j - 1)),
output, biome, getDimension().getFluidHeight(), getEngine().getHeight());
getSeaFloorDecorator().decorate(finalI, j,
realX, realZ, output, biome, height + 1,
getDimension().getFluidHeight() + 1);
}
if (height == getDimension().getFluidHeight()) {
getShoreLineDecorator().decorate(i, j,
realX, (int) Math.round(modX(x + i + 1)), (int) Math.round(modX(x + i - 1)),
realZ, (int) Math.round(modZ(z + j + 1)), (int) Math.round(modZ(z + j - 1)),
output, biome, height, getEngine().getHeight());
}
if (height == getDimension().getFluidHeight()) {
getShoreLineDecorator().decorate(finalI, j,
realX, (int) Math.round(modX(x + finalI + 1)), (int) Math.round(modX(x + finalI - 1)),
realZ, (int) Math.round(modZ(z + j + 1)), (int) Math.round(modZ(z + j - 1)),
output, biome, height, getEngine().getHeight());
}
getSurfaceDecorator().decorate(i, j, realX, realZ, output, biome, height, getEngine().getHeight() - height);
getSurfaceDecorator().decorate(finalI, j, realX, realZ, output, biome, height, getEngine().getHeight() - height);
if (cave != null && cave.getDecorators().isNotEmpty()) {
for (int k = height; k > 0; k--) {
solid = PREDICATE_SOLID.test(output.get(i, k, j));
liquid = PREDICATE_CAVELIQUID.test(output.get(i, k + 1, j), k + 1);
if (cave != null && cave.getDecorators().isNotEmpty()) {
for (int k = height; k > 0; k--) {
solid = PREDICATE_SOLID.test(output.get(finalI, k, j));
liquid = PREDICATE_CAVELIQUID.test(output.get(finalI, k + 1, j), k + 1);
if (solid) {
if (emptyFor > 0) {
if (liquid) {
getSeaFloorDecorator().decorate(i, j, realX, realZ, output, cave, k + 1, liquidFor + lastSolid - emptyFor + 1);
getSeaSurfaceDecorator().decorate(i, j, realX, realZ, output, cave, k + liquidFor + 1, emptyFor - liquidFor + lastSolid);
} else {
getSurfaceDecorator().decorate(i, j, realX, realZ, output, cave, k, lastSolid);
getCeilingDecorator().decorate(i, j, realX, realZ, output, cave, lastSolid - 1, emptyFor);
if (solid) {
if (emptyFor > 0) {
if (liquid) {
getSeaFloorDecorator().decorate(finalI, j, realX, realZ, output, cave, k + 1, liquidFor + lastSolid - emptyFor + 1);
getSeaSurfaceDecorator().decorate(finalI, j, realX, realZ, output, cave, k + liquidFor + 1, emptyFor - liquidFor + lastSolid);
} else {
getSurfaceDecorator().decorate(finalI, j, realX, realZ, output, cave, k, lastSolid);
getCeilingDecorator().decorate(finalI, j, realX, realZ, output, cave, lastSolid - 1, emptyFor);
}
emptyFor = 0;
liquidFor = 0;
}
emptyFor = 0;
liquidFor = 0;
lastSolid = k;
} else {
emptyFor++;
if (liquid) liquidFor++;
}
lastSolid = k;
} else {
emptyFor++;
if (liquid) liquidFor++;
}
}
}
}
});
}
burst.complete();
getEngine().getMetrics().getDecoration().put(p.getMilliseconds());
}
private boolean shouldRayDecorate() {

View File

@@ -23,6 +23,7 @@ import com.volmit.iris.core.project.loader.IrisData;
import com.volmit.iris.engine.IrisComplex;
import com.volmit.iris.engine.object.dimensional.IrisDimension;
import com.volmit.iris.util.math.RollingSequence;
import com.volmit.iris.util.parallel.MultiBurst;
import org.bukkit.event.Listener;
public interface EngineComponent {
@@ -32,6 +33,11 @@ public interface EngineComponent {
String getName();
default MultiBurst burst()
{
return getEngine().burst();
}
default void close() {
try {
if (this instanceof Listener) {

View File

@@ -184,7 +184,7 @@ public interface EngineMantle extends IObjectPlacer {
@ChunkCoordinates
default void generateMatter(int x, int z) {
default void generateMatter(int x, int z, boolean multicore) {
if (!getEngine().getDimension().isUseMantle()) {
return;
}
@@ -199,6 +199,7 @@ public interface EngineMantle extends IObjectPlacer {
};
int s = getRealRadius();
BurstExecutor burst = burst().burst();
burst.setMulticore(multicore);
for (int i = -s; i <= s; i++) {
int xx = i + x;
@@ -216,7 +217,16 @@ public interface EngineMantle extends IObjectPlacer {
{
KList<Runnable> px = post.copy();
post.clear();
burst().burst(px);
if(multicore)
{
burst().burst(px);
}
else
{
burst().sync(px);
}
}
}
@@ -225,7 +235,7 @@ public interface EngineMantle extends IObjectPlacer {
}
@ChunkCoordinates
default <T> void insertMatter(int x, int z, Class<T> t, Hunk<T> blocks) {
default <T> void insertMatter(int x, int z, Class<T> t, Hunk<T> blocks, boolean multicore) {
if (!getEngine().getDimension().isUseMantle()) {
return;
}

View File

@@ -18,6 +18,7 @@
package com.volmit.iris.engine.modifier;
import com.volmit.iris.Iris;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.framework.EngineAssignedModifier;
import com.volmit.iris.engine.object.biome.IrisBiome;
@@ -25,8 +26,11 @@ import com.volmit.iris.engine.object.deposits.IrisDepositGenerator;
import com.volmit.iris.engine.object.objects.IrisObject;
import com.volmit.iris.engine.object.regional.IrisRegion;
import com.volmit.iris.util.data.HeightMap;
import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.hunk.Hunk;
import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.parallel.BurstExecutor;
import com.volmit.iris.util.parallel.MultiBurst;
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
import org.bukkit.block.data.BlockData;
import org.bukkit.util.BlockVector;
@@ -42,30 +46,32 @@ public class IrisDepositModifier extends EngineAssignedModifier<BlockData> {
@Override
public void onModify(int x, int z, Hunk<BlockData> output, boolean multicore) {
PrecisionStopwatch p = PrecisionStopwatch.start();
generateDeposits(rng, output, Math.floorDiv(x, 16), Math.floorDiv(z, 16));
generateDeposits(rng, output, Math.floorDiv(x, 16), Math.floorDiv(z, 16), multicore);
getEngine().getMetrics().getDeposit().put(p.getMilliseconds());
}
public void generateDeposits(RNG rx, Hunk<BlockData> terrain, int x, int z) {
public void generateDeposits(RNG rx, Hunk<BlockData> terrain, int x, int z, boolean multicore) {
RNG ro = rx.nextParallelRNG(x * x).nextParallelRNG(z * z);
IrisRegion region = getComplex().getRegionStream().get((x * 16) + 7, (z * 16) + 7);
IrisBiome biome = getComplex().getTrueBiomeStream().get((x * 16) + 7, (z * 16) + 7);
BurstExecutor burst = burst().burst();
burst.setMulticore(multicore);
for (IrisDepositGenerator k : getDimension().getDeposits()) {
generate(k, terrain, ro, x, z, false);
burst.queue(() -> generate(k, terrain, ro, x, z, false));
}
for (IrisDepositGenerator k : region.getDeposits()) {
for (int l = 0; l < ro.i(k.getMinPerChunk(), k.getMaxPerChunk()); l++) {
generate(k, terrain, ro, x, z, false);
burst.queue(() -> generate(k, terrain, ro, x, z, false));
}
}
for (IrisDepositGenerator k : biome.getDeposits()) {
for (int l = 0; l < ro.i(k.getMinPerChunk(), k.getMaxPerChunk()); l++) {
generate(k, terrain, ro, x, z, false);
burst.queue(() -> generate(k, terrain, ro, x, z, false));
}
}
burst.complete();
}
public void generate(IrisDepositGenerator k, Hunk<BlockData> data, RNG rng, int cx, int cz, boolean safe) {

View File

@@ -19,14 +19,26 @@
package com.volmit.iris.engine.modifier;
import com.volmit.iris.Iris;
import com.volmit.iris.engine.data.cache.AtomicCache;
import com.volmit.iris.engine.data.cache.Cache;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.framework.EngineAssignedModifier;
import com.volmit.iris.engine.object.biome.IrisBiome;
import com.volmit.iris.engine.object.common.CaveResult;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.data.B;
import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.function.*;
import com.volmit.iris.util.hunk.Hunk;
import com.volmit.iris.util.hunk.storage.ArrayHunk;
import com.volmit.iris.util.math.Average;
import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.math.RollingSequence;
import com.volmit.iris.util.parallel.BurstExecutor;
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
import com.volmit.iris.util.stream.ProceduralStream;
import com.volmit.iris.util.stream.interpolation.Interpolated;
import org.bukkit.Material;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.Levelled;
@@ -34,9 +46,11 @@ import org.bukkit.block.data.Waterlogged;
import org.bukkit.block.data.type.Slab;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.function.Supplier;
public class IrisPostModifier extends EngineAssignedModifier<BlockData> {
private static final BlockData AIR = B.get("CAVE_AIR");
private static final BlockData AIR = B.get("AIR");
private static final BlockData WATER = B.get("WATER");
private final RNG rng;
@@ -48,15 +62,22 @@ public class IrisPostModifier extends EngineAssignedModifier<BlockData> {
@Override
public void onModify(int x, int z, Hunk<BlockData> output, boolean multicore) {
PrecisionStopwatch p = PrecisionStopwatch.start();
int i;
AtomicInteger i = new AtomicInteger();
AtomicInteger j = new AtomicInteger();
for (i = 0; i < output.getWidth(); i++) {
for (j.set(0); j.get() < output.getDepth(); j.getAndIncrement()) {
post(i, j.get(), output, i + x, j.get() + z);
}
BurstExecutor burst = burst().burst();
burst.setMulticore(multicore);
Hunk<BlockData> sync = output.synchronize();
for (i.set(0); i.get() < output.getWidth(); i.getAndIncrement()) {
burst.queue(() -> {
for (j.set(0); j.get() < output.getDepth(); j.getAndIncrement()) {
int ii = i.get();
int jj = j.get();
post(ii, jj, sync, ii + x, jj + z);
}
});
}
burst.complete();
getEngine().getMetrics().getPost().put(p.getMilliseconds());
}

View File

@@ -1449,4 +1449,9 @@ public interface Hunk<T> {
default boolean isEmpty() {
return false;
}
default boolean contains(int x, int y, int z)
{
return x < getWidth() && x >= 0 && y < getHeight() && y >= 0 && z < getDepth() && z >= 0;
}
}

View File

@@ -111,6 +111,17 @@ public class Mantle {
get(x >> 5, z >> 5).getOrCreate(x & 31, z & 31).iterate(type, iterator);
}
@ChunkCoordinates
public <T> void iterateChunk(int x, int z, Class<T> type, Consumer4<Integer, Integer, Integer, T> iterator, BurstExecutor e, MantleFlag... requiredFlags) {
for (MantleFlag i : requiredFlags) {
if (!hasFlag(x, z, i)) {
return;
}
}
get(x >> 5, z >> 5).getOrCreate(x & 31, z & 31).iterate(type, iterator, e);
}
@ChunkCoordinates
public boolean hasFlag(int x, int z, MantleFlag flag) {
return get(x >> 5, z >> 5).getOrCreate(x & 31, z & 31).isFlagged(flag);

View File

@@ -23,6 +23,8 @@ import com.volmit.iris.util.function.Consumer4;
import com.volmit.iris.util.matter.IrisMatter;
import com.volmit.iris.util.matter.Matter;
import com.volmit.iris.util.matter.MatterSlice;
import com.volmit.iris.util.parallel.BurstExecutor;
import com.volmit.iris.util.parallel.MultiBurst;
import java.io.DataInputStream;
import java.io.DataOutputStream;
@@ -184,6 +186,26 @@ public class MantleChunk {
}
}
public <T> void iterate(Class<T> type, Consumer4<Integer, Integer, Integer, T> iterator, BurstExecutor burst) {
for (int i = 0; i < sections.length(); i++) {
int finalI = i;
burst.queue(() -> {
int bs = (finalI << 4);
Matter matter = get(finalI);
if (matter != null) {
MatterSlice<T> t = matter.getSlice(type);
if (t != null) {
t.iterateSync((a, b, c, f) -> iterator.accept(a, b + bs, c, f));
}
}
});
}
burst.complete();
}
public <T> void iterate(Class<T> type, Consumer4<Integer, Integer, Integer, T> iterator) {
for (int i = 0; i < sections.length(); i++) {
int bs = (i << 4);

View File

@@ -20,6 +20,7 @@ package com.volmit.iris.util.parallel;
import com.volmit.iris.Iris;
import com.volmit.iris.util.collection.KList;
import lombok.Setter;
import java.util.List;
import java.util.concurrent.*;
@@ -28,6 +29,8 @@ import java.util.concurrent.*;
public class BurstExecutor {
private final ExecutorService executor;
private final KList<CompletableFuture<Void>> futures;
@Setter
private boolean multicore = true;
public BurstExecutor(ExecutorService executor, int burstSizeEstimate) {
this.executor = executor;
@@ -36,6 +39,12 @@ public class BurstExecutor {
@SuppressWarnings("UnusedReturnValue")
public CompletableFuture<Void> queue(Runnable r) {
if(!multicore)
{
r.run();
return null;
}
synchronized (futures) {
CompletableFuture<Void> c = CompletableFuture.runAsync(r, executor);
futures.add(c);
@@ -44,6 +53,16 @@ public class BurstExecutor {
}
public BurstExecutor queue(List<Runnable> r) {
if(!multicore)
{
for(Runnable i : r)
{
i.run();
}
return this;
}
synchronized (futures) {
for (Runnable i : new KList<>(r)) {
CompletableFuture<Void> c = CompletableFuture.runAsync(i, executor);
@@ -55,6 +74,16 @@ public class BurstExecutor {
}
public BurstExecutor queue(Runnable[] r) {
if(!multicore)
{
for(Runnable i : r)
{
i.run();
}
return this;
}
synchronized (futures) {
for (Runnable i : r) {
CompletableFuture<Void> c = CompletableFuture.runAsync(i, executor);
@@ -66,6 +95,11 @@ public class BurstExecutor {
}
public void complete() {
if(!multicore)
{
return;
}
synchronized (futures) {
if (futures.isEmpty()) {
return;
@@ -81,6 +115,11 @@ public class BurstExecutor {
}
public boolean complete(long maxDur) {
if(!multicore)
{
return true;
}
synchronized (futures) {
if (futures.isEmpty()) {
return true;

View File

@@ -21,6 +21,7 @@ package com.volmit.iris.util.parallel;
import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.service.PreservationSVC;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.io.InstanceState;
import com.volmit.iris.util.math.M;
import com.volmit.iris.util.scheduling.J;
@@ -111,6 +112,12 @@ public class MultiBurst {
}
}
public void sync(KList<Runnable> r) {
for (Runnable i : r) {
i.run();
}
}
public BurstExecutor burst(int estimate) {
return new BurstExecutor(getService(), estimate);
}