mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-08-27 04:37:47 +00:00
Way too much
This commit is contained in:
+5
-1
@@ -55,6 +55,8 @@ Provider<String> probeWarmupChunks = providers.gradleProperty('probeWarmupChunks
|
||||
Provider<String> probeMeasuredChunks = providers.gradleProperty('probeMeasuredChunks').orElse('1024')
|
||||
Provider<String> probeCenterChunkX = providers.gradleProperty('probeCenterChunkX').orElse('2048')
|
||||
Provider<String> probeCenterChunkZ = providers.gradleProperty('probeCenterChunkZ').orElse('2048')
|
||||
Provider<String> probeMulticore = providers.gradleProperty('probeMulticore').orElse('false')
|
||||
Provider<String> probeStudio = providers.gradleProperty('probeStudio').orElse('false')
|
||||
|
||||
tasks.register('genProbe', JavaExec) {
|
||||
group = 'verification'
|
||||
@@ -76,7 +78,9 @@ tasks.register('genProbe', JavaExec) {
|
||||
probeWarmupChunks.get(),
|
||||
probeMeasuredChunks.get(),
|
||||
probeCenterChunkX.get(),
|
||||
probeCenterChunkZ.get())
|
||||
probeCenterChunkZ.get(),
|
||||
probeMulticore.get(),
|
||||
probeStudio.get())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -59,7 +59,6 @@ import java.util.stream.Stream;
|
||||
|
||||
public final class GenerationProbe {
|
||||
private static final long SEED = 1337L;
|
||||
private static final int SIGNATURE_SAMPLE_STEP = 8;
|
||||
private static final List<Throwable> REPORTED = Collections.synchronizedList(new ArrayList<>());
|
||||
|
||||
private static final class InertPreservation implements PreservationRegistry {
|
||||
@@ -127,7 +126,7 @@ public final class GenerationProbe {
|
||||
}
|
||||
|
||||
record ProbeConfiguration(File packSource, String dimensionKey, int warmupChunks, int measuredChunks,
|
||||
int centerChunkX, int centerChunkZ) {
|
||||
int centerChunkX, int centerChunkZ, boolean multicore, boolean studio) {
|
||||
ProbeConfiguration {
|
||||
if (packSource == null) {
|
||||
throw new IllegalArgumentException("Pack folder is required.");
|
||||
@@ -144,8 +143,8 @@ public final class GenerationProbe {
|
||||
}
|
||||
|
||||
static ProbeConfiguration parse(String[] args) {
|
||||
if (args.length != 6) {
|
||||
throw new IllegalArgumentException("Expected: <pack> <dimension> <warmupChunks> <measuredChunks> <centerChunkX> <centerChunkZ>");
|
||||
if (args.length != 8) {
|
||||
throw new IllegalArgumentException("Expected: <pack> <dimension> <warmupChunks> <measuredChunks> <centerChunkX> <centerChunkZ> <multicore> <studio>");
|
||||
}
|
||||
return new ProbeConfiguration(
|
||||
new File(args[0]),
|
||||
@@ -153,7 +152,9 @@ public final class GenerationProbe {
|
||||
Integer.parseInt(args[2]),
|
||||
Integer.parseInt(args[3]),
|
||||
Integer.parseInt(args[4]),
|
||||
Integer.parseInt(args[5]));
|
||||
Integer.parseInt(args[5]),
|
||||
Boolean.parseBoolean(args[6]),
|
||||
Boolean.parseBoolean(args[7]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,18 +190,21 @@ public final class GenerationProbe {
|
||||
TimingSummary measuredTimings, String signature) {
|
||||
}
|
||||
|
||||
record ProbeResult(String status, String dimensionKey, int warmupChunks, int measuredChunks,
|
||||
record ProbeResult(String status, String dimensionKey, int warmupChunks, int measuredChunks, boolean multicore,
|
||||
boolean studio,
|
||||
int successfulChunks, int failedChunks, long engineReadyNanos, long firstChunkNanos,
|
||||
TimingSummary measuredTimings, String signature) {
|
||||
String machineLine() {
|
||||
double measuredSeconds = measuredTimings.totalNanos() / 1_000_000_000D;
|
||||
double chunksPerSecond = measuredSeconds == 0D ? 0D : measuredChunks / measuredSeconds;
|
||||
return String.format(Locale.ROOT,
|
||||
"IRIS_GENPROBE_RESULT version=1 status=%s dimension=%s warmup_chunks=%d measured_chunks=%d successful_chunks=%d failed_chunks=%d engine_ready_ms=%.3f first_chunk_ms=%.3f measured_median_ms=%.3f measured_p95_ms=%.3f measured_max_ms=%.3f measured_total_ms=%.3f measured_cps=%.3f signature=%s",
|
||||
"IRIS_GENPROBE_RESULT version=1 status=%s dimension=%s warmup_chunks=%d measured_chunks=%d multicore=%s studio=%s successful_chunks=%d failed_chunks=%d engine_ready_ms=%.3f first_chunk_ms=%.3f measured_median_ms=%.3f measured_p95_ms=%.3f measured_max_ms=%.3f measured_total_ms=%.3f measured_cps=%.3f signature=%s",
|
||||
status,
|
||||
dimensionKey,
|
||||
warmupChunks,
|
||||
measuredChunks,
|
||||
multicore,
|
||||
studio,
|
||||
successfulChunks,
|
||||
failedChunks,
|
||||
nanosToMillis(engineReadyNanos),
|
||||
@@ -239,6 +243,8 @@ public final class GenerationProbe {
|
||||
configuration.dimensionKey(),
|
||||
configuration.warmupChunks(),
|
||||
configuration.measuredChunks(),
|
||||
configuration.multicore(),
|
||||
configuration.studio(),
|
||||
0,
|
||||
configuration.warmupChunks() + configuration.measuredChunks(),
|
||||
0L,
|
||||
@@ -285,6 +291,8 @@ public final class GenerationProbe {
|
||||
System.out.println("[genprobe] warmup chunks: " + configuration.warmupChunks());
|
||||
System.out.println("[genprobe] measured chunks: " + configuration.measuredChunks());
|
||||
System.out.println("[genprobe] center chunk: " + configuration.centerChunkX() + "," + configuration.centerChunkZ());
|
||||
System.out.println("[genprobe] multicore: " + configuration.multicore());
|
||||
System.out.println("[genprobe] studio: " + configuration.studio());
|
||||
|
||||
long engineStart = System.nanoTime();
|
||||
data = IrisData.get(pack);
|
||||
@@ -302,7 +310,11 @@ public final class GenerationProbe {
|
||||
.maxHeight(dimension.getMaxHeight())
|
||||
.build();
|
||||
EngineTarget target = new EngineTarget(world, dimension, data);
|
||||
engine = new IrisEngine(target, IrisEngine.InitializationMode.RUNTIME);
|
||||
engine = new IrisEngine(
|
||||
target,
|
||||
configuration.studio()
|
||||
? IrisEngine.InitializationMode.STUDIO
|
||||
: IrisEngine.InitializationMode.RUNTIME);
|
||||
long engineReadyNanos = System.nanoTime() - engineStart;
|
||||
|
||||
List<Throwable> initNoise = settleAndDrain();
|
||||
@@ -311,7 +323,6 @@ public final class GenerationProbe {
|
||||
+ " seed=" + engine.getSeedManager().getSeed()
|
||||
+ " minY=" + engine.getMinHeight() + " maxY=" + engine.getMaxHeight()
|
||||
+ " timeMs=" + String.format(Locale.ROOT, "%.3f", nanosToMillis(engineReadyNanos)));
|
||||
|
||||
GenerationResult generation = generate(engine, configuration);
|
||||
String status = generation.failedChunks() == 0 ? "PASS" : "FAIL";
|
||||
printGenerationFailures(generation);
|
||||
@@ -320,6 +331,8 @@ public final class GenerationProbe {
|
||||
configuration.dimensionKey(),
|
||||
configuration.warmupChunks(),
|
||||
configuration.measuredChunks(),
|
||||
configuration.multicore(),
|
||||
configuration.studio(),
|
||||
generation.successfulChunks(),
|
||||
generation.failedChunks(),
|
||||
engineReadyNanos,
|
||||
@@ -390,7 +403,12 @@ public final class GenerationProbe {
|
||||
Hunk<PlatformBiome> biomes = Hunk.newArrayHunk(16, height, 16);
|
||||
long started = System.nanoTime();
|
||||
try {
|
||||
engine.generate(coordinate.x() << 4, coordinate.z() << 4, blocks, biomes, false);
|
||||
engine.generate(
|
||||
coordinate.x() << 4,
|
||||
coordinate.z() << 4,
|
||||
blocks,
|
||||
biomes,
|
||||
configuration.multicore());
|
||||
} catch (Throwable e) {
|
||||
failures.add(e);
|
||||
}
|
||||
@@ -465,10 +483,9 @@ public final class GenerationProbe {
|
||||
private static void updateSignature(MessageDigest digest, ChunkCoordinate coordinate,
|
||||
Hunk<PlatformBlockState> blocks, Hunk<PlatformBiome> biomes, int height) {
|
||||
updateDigest(digest, coordinate.x() + "," + coordinate.z());
|
||||
int verticalStep = Math.max(1, height / 16);
|
||||
for (int x = 0; x < 16; x += SIGNATURE_SAMPLE_STEP) {
|
||||
for (int z = 0; z < 16; z += SIGNATURE_SAMPLE_STEP) {
|
||||
for (int y = 0; y < height; y += verticalStep) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
PlatformBlockState state = blocks.get(x, y, z);
|
||||
PlatformBiome biome = biomes.get(x, y, z);
|
||||
updateDigest(digest, state == null ? "minecraft:air" : state.key());
|
||||
|
||||
@@ -0,0 +1,157 @@
|
||||
package art.arcane.iris.probe;
|
||||
|
||||
import art.arcane.iris.engine.river.RiverBodyProfile;
|
||||
import art.arcane.iris.engine.river.RiverEdgeId;
|
||||
import art.arcane.iris.engine.river.RiverNode;
|
||||
import art.arcane.iris.engine.river.RiverNodeId;
|
||||
import art.arcane.iris.engine.river.RiverPolyline;
|
||||
import art.arcane.iris.engine.river.RiverReach;
|
||||
import art.arcane.iris.engine.river.RiverRouteState;
|
||||
import art.arcane.iris.engine.river.RiverSample;
|
||||
import art.arcane.iris.engine.river.RiverTile;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
public final class RiverTileProbe {
|
||||
private static final int WARMUP_ROUNDS = 5;
|
||||
private static final int MEASURED_ROUNDS = 25;
|
||||
private static final int SAMPLES_PER_ROUND = 8_192;
|
||||
|
||||
private RiverTileProbe() {
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
RiverTile tile = createTile();
|
||||
long expectedSignature = sampleRound(tile);
|
||||
for (int round = 0; round < WARMUP_ROUNDS; round++) {
|
||||
requireSignature(expectedSignature, sampleRound(tile));
|
||||
}
|
||||
|
||||
long[] timings = new long[MEASURED_ROUNDS];
|
||||
for (int round = 0; round < MEASURED_ROUNDS; round++) {
|
||||
long start = System.nanoTime();
|
||||
long signature = sampleRound(tile);
|
||||
timings[round] = System.nanoTime() - start;
|
||||
requireSignature(expectedSignature, signature);
|
||||
System.out.printf(Locale.ROOT,
|
||||
"IRIS_RIVER_TILE_SAMPLE round=%d nanos=%d signature=%016x%n",
|
||||
round,
|
||||
timings[round],
|
||||
signature);
|
||||
}
|
||||
long[] sorted = timings.clone();
|
||||
Arrays.sort(sorted);
|
||||
System.out.printf(Locale.ROOT,
|
||||
"IRIS_RIVER_TILE_RESULT version=1 rounds=%d samples_per_round=%d median_nanos=%d p95_nanos=%d signature=%016x%n",
|
||||
MEASURED_ROUNDS,
|
||||
SAMPLES_PER_ROUND,
|
||||
sorted[MEASURED_ROUNDS / 2],
|
||||
sorted[(int) StrictMath.ceil(MEASURED_ROUNDS * 0.95D) - 1],
|
||||
expectedSignature);
|
||||
}
|
||||
|
||||
private static RiverTile createTile() {
|
||||
List<RiverReach> reaches = new ArrayList<>(64);
|
||||
for (int reachIndex = 0; reachIndex < 64; reachIndex++) {
|
||||
RiverNode from = node(0L, reachIndex, 0D, reachIndex * 32D);
|
||||
RiverNode to = node(1L, reachIndex, 2_048D, reachIndex * 32D);
|
||||
RiverBodyProfile profile = profile(reachIndex);
|
||||
double[] x = new double[33];
|
||||
double[] z = new double[33];
|
||||
for (int point = 0; point < x.length; point++) {
|
||||
x[point] = point * 64D;
|
||||
z[point] = reachIndex * 32D
|
||||
+ StrictMath.sin(point * 0.625D + reachIndex * 0.25D) * 12D;
|
||||
}
|
||||
reaches.add(new RiverReach(
|
||||
RiverEdgeId.of(from.id(), to.id()),
|
||||
from,
|
||||
to,
|
||||
RiverRouteState.WET,
|
||||
1 + reachIndex % 4,
|
||||
1 + reachIndex % 3,
|
||||
profile.maximumWidth(),
|
||||
profile.maximumBankWidth(),
|
||||
profile.maximumDepth(),
|
||||
profile,
|
||||
false,
|
||||
false,
|
||||
new RiverPolyline(x, z)
|
||||
));
|
||||
}
|
||||
return new RiverTile(0, 0, 0, 0, 2_048, 2_048, reaches);
|
||||
}
|
||||
|
||||
private static RiverBodyProfile profile(int reachIndex) {
|
||||
double[] positions = new double[17];
|
||||
double[] widths = new double[17];
|
||||
double[] bankWidths = new double[17];
|
||||
double[] depths = new double[17];
|
||||
double[] roofScales = new double[17];
|
||||
for (int index = 0; index < positions.length; index++) {
|
||||
double position = index / 16D;
|
||||
double body = StrictMath.sin(StrictMath.PI * position);
|
||||
positions[index] = position;
|
||||
widths[index] = 8D + reachIndex % 5 + body * 6D;
|
||||
bankWidths[index] = 4D + reachIndex % 3 + body * 4D;
|
||||
depths[index] = 3D + reachIndex % 2 + body * 2D;
|
||||
roofScales[index] = 1D - body * 0.4D;
|
||||
}
|
||||
return new RiverBodyProfile(positions, widths, bankWidths, depths, roofScales);
|
||||
}
|
||||
|
||||
private static RiverNode node(long cellX, long cellZ, double x, double z) {
|
||||
return new RiverNode(
|
||||
new RiverNodeId(cellX, cellZ),
|
||||
x,
|
||||
z,
|
||||
64D,
|
||||
64D,
|
||||
64D,
|
||||
64D,
|
||||
false,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
private static long sampleRound(RiverTile tile) {
|
||||
long signature = 0xCBF29CE484222325L;
|
||||
for (int sampleIndex = 0; sampleIndex < SAMPLES_PER_ROUND; sampleIndex++) {
|
||||
double x = Math.floorMod(sampleIndex * 1_229, 2_048) + 0.375D;
|
||||
double z = Math.floorMod(sampleIndex * 811, 2_048) + 0.625D;
|
||||
double additionalRadius = 16D + sampleIndex % 17;
|
||||
RiverSample sample = tile.sampleExpanded(x, z, additionalRadius);
|
||||
signature = mix(signature, sample.present() ? 1L : 0L);
|
||||
if (!sample.present()) {
|
||||
continue;
|
||||
}
|
||||
signature = mix(signature, sample.reachId().stableId());
|
||||
signature = mix(signature, Double.doubleToLongBits(sample.distance()));
|
||||
signature = mix(signature, Double.doubleToLongBits(sample.alongReach()));
|
||||
signature = mix(signature, Double.doubleToLongBits(sample.carveWeight()));
|
||||
signature = mix(signature, Double.doubleToLongBits(sample.width()));
|
||||
signature = mix(signature, Double.doubleToLongBits(sample.bankWidth()));
|
||||
signature = mix(signature, Double.doubleToLongBits(sample.depth()));
|
||||
signature = mix(signature, sample.section().ordinal());
|
||||
}
|
||||
return signature;
|
||||
}
|
||||
|
||||
private static long mix(long hash, long value) {
|
||||
return (hash ^ value) * 0x100000001B3L;
|
||||
}
|
||||
|
||||
private static void requireSignature(long expected, long actual) {
|
||||
if (actual != expected) {
|
||||
throw new IllegalStateException(String.format(
|
||||
Locale.ROOT,
|
||||
"River tile output changed: expected %016x but got %016x",
|
||||
expected,
|
||||
actual
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,9 @@ public final class GenerationProbeTest {
|
||||
"256",
|
||||
"1024",
|
||||
"2048",
|
||||
"-2048"
|
||||
"-2048",
|
||||
"true",
|
||||
"true"
|
||||
});
|
||||
|
||||
assertEquals(new File("/tmp/pack"), configuration.packSource());
|
||||
@@ -31,6 +33,8 @@ public final class GenerationProbeTest {
|
||||
assertEquals(1024, configuration.measuredChunks());
|
||||
assertEquals(2048, configuration.centerChunkX());
|
||||
assertEquals(-2048, configuration.centerChunkZ());
|
||||
assertTrue(configuration.multicore());
|
||||
assertTrue(configuration.studio());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -38,11 +42,11 @@ public final class GenerationProbeTest {
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> GenerationProbe.ProbeConfiguration.parse(new String[]{"/tmp/pack"}));
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> new GenerationProbe.ProbeConfiguration(new File("/tmp/pack"), " ", 1, 1, 0, 0));
|
||||
() -> new GenerationProbe.ProbeConfiguration(new File("/tmp/pack"), " ", 1, 1, 0, 0, false, false));
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> new GenerationProbe.ProbeConfiguration(new File("/tmp/pack"), "overworld", 0, 1, 0, 0));
|
||||
() -> new GenerationProbe.ProbeConfiguration(new File("/tmp/pack"), "overworld", 0, 1, 0, 0, false, false));
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> new GenerationProbe.ProbeConfiguration(new File("/tmp/pack"), "overworld", 1, 0, 0, 0));
|
||||
() -> new GenerationProbe.ProbeConfiguration(new File("/tmp/pack"), "overworld", 1, 0, 0, 0, false, false));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -73,11 +77,11 @@ public final class GenerationProbeTest {
|
||||
GenerationProbe.TimingSummary timings = new GenerationProbe.TimingSummary(
|
||||
10_000_000L, 20_000_000L, 30_000_000L, 40_000_000L);
|
||||
GenerationProbe.ProbeResult result = new GenerationProbe.ProbeResult(
|
||||
"PASS", "underworld", 2, 4, 6, 0,
|
||||
"PASS", "underworld", 2, 4, true, true, 6, 0,
|
||||
5_000_000L, 6_000_000L, timings, "0123456789abcdef");
|
||||
|
||||
assertEquals(
|
||||
"IRIS_GENPROBE_RESULT version=1 status=PASS dimension=underworld warmup_chunks=2 measured_chunks=4 successful_chunks=6 failed_chunks=0 engine_ready_ms=5.000 first_chunk_ms=6.000 measured_median_ms=10.000 measured_p95_ms=20.000 measured_max_ms=30.000 measured_total_ms=40.000 measured_cps=100.000 signature=0123456789abcdef",
|
||||
"IRIS_GENPROBE_RESULT version=1 status=PASS dimension=underworld warmup_chunks=2 measured_chunks=4 multicore=true studio=true successful_chunks=6 failed_chunks=0 engine_ready_ms=5.000 first_chunk_ms=6.000 measured_median_ms=10.000 measured_p95_ms=20.000 measured_max_ms=30.000 measured_total_ms=40.000 measured_cps=100.000 signature=0123456789abcdef",
|
||||
result.machineLine());
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user