mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-11-01 08:50:06 +00:00
Probe fidelity options
- Print measured-window stage totals from EngineMetrics as IRIS_GENPROBE_STAGES - Time each context prefill task into its prefill timer - Add gated generation counters for generator evaluations, corner starcasts and hydrology lookups - Add -PprobeHydrologyPreplan to plan the probe area's hydrology tiles before warmup - Add -PprobeHistoryRouter to generate through a generation-history router and registry contract - Add -PprobeProductionBuffers to generate into production-equivalent block and biome hunks - Print the mantle radius as IRIS_GENPROBE_MANTLE
This commit is contained in:
1 parent
e2430500cf
commit
b6b01c88f5
15 files changed
+1020
-113
No files matched your search
@@ -1,15 +1,20 @@
|
||||
package art.arcane.iris.probe;
|
||||
|
||||
import art.arcane.iris.generation.hydrology.HydrologyTileCache;
|
||||
import art.arcane.iris.generation.hydrology.HydrologyTileKey;
|
||||
import art.arcane.iris.generation.runtime.EngineMetrics;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
@@ -128,7 +133,96 @@ public final class GenerationProbeTest {
|
||||
GenerationProbe.ProbeOptions defaults = GenerationProbe.ProbeOptions.fromSystemProperties();
|
||||
assertEquals(1, defaults.threads());
|
||||
assertNull(defaults.dumpFile());
|
||||
assertThrows(IllegalArgumentException.class, () -> new GenerationProbe.ProbeOptions(0, null, false));
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> new GenerationProbe.ProbeOptions(0, null, false, false, false, false, false));
|
||||
assertFalse(defaults.hydrologyPreplan());
|
||||
assertFalse(defaults.historyRouter());
|
||||
assertFalse(defaults.productionBuffers());
|
||||
assertFalse(defaults.counters());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void readsHarnessFidelityOptionsFromSystemProperties() {
|
||||
System.setProperty("iris.probe.hydrologyPreplan", "true");
|
||||
System.setProperty("iris.probe.historyRouter", "true");
|
||||
System.setProperty("iris.probe.productionBuffers", "true");
|
||||
System.setProperty("iris.generation.counters", "true");
|
||||
try {
|
||||
GenerationProbe.ProbeOptions options = GenerationProbe.ProbeOptions.fromSystemProperties();
|
||||
assertTrue(options.hydrologyPreplan());
|
||||
assertTrue(options.historyRouter());
|
||||
assertTrue(options.productionBuffers());
|
||||
assertTrue(options.counters());
|
||||
assertFalse(options.parallel());
|
||||
} finally {
|
||||
System.clearProperty("iris.probe.hydrologyPreplan");
|
||||
System.clearProperty("iris.probe.historyRouter");
|
||||
System.clearProperty("iris.probe.productionBuffers");
|
||||
System.clearProperty("iris.generation.counters");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stageLineReportsOnlyTheMeasuredWindow() {
|
||||
Map<String, EngineMetrics.StageTotal> before = new LinkedHashMap<>();
|
||||
before.put("total", new EngineMetrics.StageTotal(100D, 10L));
|
||||
before.put("context.prefill.height", new EngineMetrics.StageTotal(0D, 0L));
|
||||
Map<String, EngineMetrics.StageTotal> after = new LinkedHashMap<>();
|
||||
after.put("total", new EngineMetrics.StageTotal(350.25D, 20L));
|
||||
after.put("context.prefill.height", new EngineMetrics.StageTotal(12.5D, 10L));
|
||||
|
||||
String line = GenerationProbe.stagesLine(new GenerationProbe.WindowMetrics(before, Map.of()),
|
||||
new GenerationProbe.WindowMetrics(after, Map.of()), 10, 1);
|
||||
|
||||
assertEquals("IRIS_GENPROBE_STAGES version=1 chunks=10 threads=1 total=250.250 context.prefill.height=12.500", line);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void counterLineReportsWindowTotalsAndPerChunkRates() {
|
||||
Map<String, Long> before = new LinkedHashMap<>();
|
||||
before.put("generator_evaluations", 1_000L);
|
||||
before.put("corner_starcasts", 0L);
|
||||
Map<String, Long> after = new LinkedHashMap<>();
|
||||
after.put("generator_evaluations", 5_000L);
|
||||
after.put("corner_starcasts", 330L);
|
||||
|
||||
String line = GenerationProbe.countersLine(new GenerationProbe.WindowMetrics(Map.of(), before),
|
||||
new GenerationProbe.WindowMetrics(Map.of(), after), 2);
|
||||
|
||||
assertEquals("IRIS_GENPROBE_COUNTERS version=1 chunks=2 generator_evaluations=4000"
|
||||
+ " generator_evaluations_per_chunk=2000.0 corner_starcasts=330 corner_starcasts_per_chunk=165.0", line);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hydrologyPreplanCoversEveryTileAScheduledChunkComposesFromPlusTheNeighbourRing() {
|
||||
GenerationProbe.ProbeConfiguration configuration = new GenerationProbe.ProbeConfiguration(
|
||||
new File("/tmp/pack"), "overworld", 256, 1024, 2048, 2048, false, false, 1337L);
|
||||
int tileSize = 512;
|
||||
int publicationRadius = 96;
|
||||
int reachChunks = 13;
|
||||
List<HydrologyTileKey> keys = GenerationProbe.preplanTiles(configuration, tileSize, publicationRadius, reachChunks);
|
||||
Set<HydrologyTileKey> planned = new HashSet<>(keys);
|
||||
|
||||
assertEquals(keys.size(), planned.size());
|
||||
for (GenerationProbe.ChunkCoordinate chunk : GenerationProbe.scheduleCoordinates(1280, 2048, 2048)) {
|
||||
for (int offsetX = -reachChunks; offsetX <= reachChunks; offsetX++) {
|
||||
for (int offsetZ = -reachChunks; offsetZ <= reachChunks; offsetZ++) {
|
||||
long minimumX = (long) (chunk.x() + offsetX) * 16L;
|
||||
long minimumZ = (long) (chunk.z() + offsetZ) * 16L;
|
||||
int firstX = Math.floorDiv(Math.toIntExact(minimumX - publicationRadius), tileSize) - 1;
|
||||
int lastX = Math.floorDiv(Math.toIntExact(minimumX + 15L + publicationRadius), tileSize) + 1;
|
||||
int firstZ = Math.floorDiv(Math.toIntExact(minimumZ - publicationRadius), tileSize) - 1;
|
||||
int lastZ = Math.floorDiv(Math.toIntExact(minimumZ + 15L + publicationRadius), tileSize) + 1;
|
||||
for (int tileX = firstX; tileX <= lastX; tileX++) {
|
||||
for (int tileZ = firstZ; tileZ <= lastZ; tileZ++) {
|
||||
assertTrue(planned.contains(new HydrologyTileKey(tileX, tileZ)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
HydrologyTileKey first = keys.getFirst();
|
||||
assertEquals(new HydrologyTileKey(Math.floorDiv(2048 * 16 + 8, tileSize), Math.floorDiv(2048 * 16 + 8, tileSize)), first);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
package art.arcane.iris.probe;
|
||||
|
||||
import art.arcane.volmlib.nativelib.terrain.NativeBiome;
|
||||
import art.arcane.volmlib.nativelib.terrain.NativeBlockState;
|
||||
import art.arcane.volmlib.util.hunk.Hunk;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public final class ProductionHunkTest {
|
||||
private static final int HEIGHT = 24;
|
||||
|
||||
@Test
|
||||
public void blockHunkIgnoresNullWritesAndTracksTheHighestStoredCellPerColumn() {
|
||||
ProductionBlockHunk blocks = new ProductionBlockHunk(HEIGHT);
|
||||
NativeBlockState stone = StubPlatform.blockStateForTest("minecraft:stone");
|
||||
NativeBlockState dirt = StubPlatform.blockStateForTest("minecraft:dirt");
|
||||
|
||||
blocks.setRaw(3, 5, 7, stone);
|
||||
blocks.setRaw(3, 9, 7, dirt);
|
||||
blocks.setRaw(3, 2, 7, stone);
|
||||
blocks.setRaw(3, 9, 7, null);
|
||||
|
||||
assertSame(dirt, blocks.getStoredRaw(3, 9, 7));
|
||||
assertSame(stone, blocks.getStoredRaw(3, 5, 7));
|
||||
assertNull(blocks.getStoredRaw(3, 6, 7));
|
||||
assertEquals(9, blocks.highestStoredY(3, 7));
|
||||
assertEquals(-1, blocks.highestStoredY(7, 3));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dumpCaptureOfTheBlockHunkMatchesAnArrayHunkHoldingTheSameWrites() {
|
||||
ProductionBlockHunk production = new ProductionBlockHunk(HEIGHT);
|
||||
Hunk<NativeBlockState> array = Hunk.newArrayHunk(16, HEIGHT, 16);
|
||||
Hunk<NativeBiome> biomes = Hunk.newArrayHunk(16, HEIGHT, 16);
|
||||
NativeBlockState stone = StubPlatform.blockStateForTest("minecraft:stone");
|
||||
NativeBlockState water = StubPlatform.blockStateForTest("minecraft:water");
|
||||
for (int x = 0; x < 16; x++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
int top = (x * 7 + z * 3) % HEIGHT;
|
||||
for (int y = 0; y <= top; y++) {
|
||||
NativeBlockState state = y == top ? water : stone;
|
||||
production.setRaw(x, y, z, state);
|
||||
array.setRaw(x, y, z, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ChunkDump.ChunkSnapshot fromProduction = ChunkDump.capture(4, -9, production, biomes, HEIGHT);
|
||||
ChunkDump.ChunkSnapshot fromArray = ChunkDump.capture(4, -9, array, biomes, HEIGHT);
|
||||
|
||||
assertArrayEquals(fromArray.blockPalette(), fromProduction.blockPalette());
|
||||
assertArrayEquals(fromArray.blocks(), fromProduction.blocks());
|
||||
assertTrue(List.of(fromProduction.blockPalette()).contains(ChunkDump.NULL_BLOCK_KEY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void biomeHunkKeepsWholeColumnWritesPerColumnAndReadsLikeAnArrayHunk() {
|
||||
ProductionBiomeHunk production = new ProductionBiomeHunk(HEIGHT, () -> biome("minecraft:plains"));
|
||||
Hunk<NativeBiome> array = Hunk.newArrayHunk(16, HEIGHT, 16);
|
||||
NativeBiome forest = biome("minecraft:forest");
|
||||
NativeBiome desert = biome("minecraft:desert");
|
||||
for (int x = 0; x < 16; x++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
NativeBiome column = ((x + z) & 1) == 0 ? forest : desert;
|
||||
production.set(x, 0, z, x, HEIGHT - 1, z, column);
|
||||
array.set(x, 0, z, x, HEIGHT - 1, z, column);
|
||||
}
|
||||
}
|
||||
|
||||
assertFalse(production.expanded());
|
||||
assertSameCells(array, production);
|
||||
|
||||
production.setRaw(2, 4, 9, desert);
|
||||
array.setRaw(2, 4, 9, desert);
|
||||
production.set(5, 0, 5, 5, HEIGHT - 1, 5, desert);
|
||||
array.set(5, 0, 5, 5, HEIGHT - 1, 5, desert);
|
||||
|
||||
assertTrue(production.expanded());
|
||||
assertSameCells(array, production);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void biomeHunkReadsTheFallbackOnlyForUnwrittenCells() {
|
||||
NativeBiome plains = biome("minecraft:plains");
|
||||
ProductionBiomeHunk production = new ProductionBiomeHunk(HEIGHT, () -> plains);
|
||||
NativeBiome forest = biome("minecraft:forest");
|
||||
production.set(1, 0, 1, 1, HEIGHT - 1, 1, forest);
|
||||
|
||||
assertSame(forest, production.getRaw(1, HEIGHT - 1, 1));
|
||||
assertSame(plains, production.getRaw(0, 0, 0));
|
||||
}
|
||||
|
||||
private static void assertSameCells(Hunk<NativeBiome> expected, Hunk<NativeBiome> actual) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
for (int y = 0; y < HEIGHT; y++) {
|
||||
assertSame(expected.get(x, y, z), actual.get(x, y, z));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static NativeBiome biome(String key) {
|
||||
return new TestBiome(key);
|
||||
}
|
||||
|
||||
private record TestBiome(String key) implements NativeBiome {
|
||||
@Override
|
||||
public String namespace() {
|
||||
return key.substring(0, key.indexOf(':'));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object nativeHandle() {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user