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:
Brian Neumann-Fopiano committed 2026-10-21 19:20:17 -04:00
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;
}
}
}