mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-10-28 15:00:11 +00:00
Parallelized mod builds
- Mod targets run through bounded Gradle workers with separate caches and daemon slots - Target logs retain verification failures and bounded output summaries - Nested tests use bounded forks and JVM thread counts - Lifecycle tests control deadlines through injected clocks
This commit is contained in:
1 parent
d7059d84a4
commit
fc810221bb
17 files changed
+447
-61
No files matched your search
+12
-4
@@ -30,6 +30,7 @@ import art.arcane.iris.generation.runtime.Engine;
|
||||
import art.arcane.iris.modded.ModdedGenPool;
|
||||
import art.arcane.volmlib.util.mantle.runtime.Mantle;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Semaphore;
|
||||
@@ -39,6 +40,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.LongSupplier;
|
||||
|
||||
public final class ModdedPregenMethod implements PregeneratorMethod {
|
||||
private static final int ADAPTIVE_TIMEOUT_STEP = 3;
|
||||
@@ -68,8 +70,14 @@ public final class ModdedPregenMethod implements PregeneratorMethod {
|
||||
private final int timeoutSeconds;
|
||||
private final PregenMantleBackpressure backpressure;
|
||||
private final PauseWhenEmptyGuard pauseGuard;
|
||||
private final LongSupplier clock;
|
||||
|
||||
public ModdedPregenMethod(Configuration configuration) {
|
||||
this(configuration, System::nanoTime);
|
||||
}
|
||||
|
||||
ModdedPregenMethod(Configuration configuration, LongSupplier clock) {
|
||||
this.clock = Objects.requireNonNull(clock);
|
||||
runtime = configuration.runtime();
|
||||
engine = configuration.engine();
|
||||
sync = configuration.sync();
|
||||
@@ -178,7 +186,7 @@ public final class ModdedPregenMethod implements PregeneratorMethod {
|
||||
if (sync || runtime.isServerThread()) {
|
||||
return;
|
||||
}
|
||||
long deadline = System.nanoTime() + TimeUnit.SECONDS.toNanos(timeoutSeconds)
|
||||
long deadline = clock.getAsLong() + TimeUnit.SECONDS.toNanos(timeoutSeconds)
|
||||
+ TimeUnit.MILLISECONDS.toNanos(FINAL_SAVE_TIMEOUT_MILLIS);
|
||||
boolean interrupted = false;
|
||||
try {
|
||||
@@ -186,7 +194,7 @@ public final class ModdedPregenMethod implements PregeneratorMethod {
|
||||
if (finalSaveOnServerThread.get() || !runtime.isRunning()) {
|
||||
return;
|
||||
}
|
||||
if (System.nanoTime() >= deadline) {
|
||||
if (clock.getAsLong() >= deadline) {
|
||||
throw new IllegalStateException("Iris pregen chunk callbacks did not finish for "
|
||||
+ runtime.worldIdentity() + ": " + inFlight.get() + " pending");
|
||||
}
|
||||
@@ -263,14 +271,14 @@ public final class ModdedPregenMethod implements PregeneratorMethod {
|
||||
}
|
||||
|
||||
private void awaitFinalSave(FinalSaveRequest request) {
|
||||
long deadline = System.nanoTime() + TimeUnit.MILLISECONDS.toNanos(FINAL_SAVE_TIMEOUT_MILLIS);
|
||||
long deadline = clock.getAsLong() + TimeUnit.MILLISECONDS.toNanos(FINAL_SAVE_TIMEOUT_MILLIS);
|
||||
boolean interrupted = false;
|
||||
try {
|
||||
while (true) {
|
||||
if (deferFinalSaveIfRequested()) {
|
||||
return;
|
||||
}
|
||||
long remainingNanos = deadline - System.nanoTime();
|
||||
long remainingNanos = deadline - clock.getAsLong();
|
||||
if (remainingNanos <= 0L) {
|
||||
ModdedIrisLog.warn("Iris pregen level save did not complete in time for {}", runtime.worldIdentity());
|
||||
return;
|
||||
|
||||
+17
-7
@@ -21,6 +21,7 @@ import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
@@ -97,6 +98,9 @@ public class ModdedPregenMethodLifecycleTest {
|
||||
|
||||
@Test
|
||||
public void finalSaveWaitsForEveryCallbackBeyondFiveSeconds() throws Exception {
|
||||
AtomicLong clock = new AtomicLong();
|
||||
CountDownLatch started = new CountDownLatch(1);
|
||||
CountDownLatch advanced = new CountDownLatch(2);
|
||||
CompletableFuture<ChunkLoad> load = new CompletableFuture<>();
|
||||
CompletableFuture<ChunkLoad> failedLoad = new CompletableFuture<>();
|
||||
PregenListener listener = mock(PregenListener.class);
|
||||
@@ -110,16 +114,22 @@ public class ModdedPregenMethodLifecycleTest {
|
||||
}).when(runtime).execute(any());
|
||||
try (MockedStatic<MantleHeapPressure> pressure = mockStatic(MantleHeapPressure.class)) {
|
||||
pressure.when(MantleHeapPressure::memoryBudgetBytes).thenReturn(512L << 20);
|
||||
method = new ModdedPregenMethod(new ModdedPregenMethod.Configuration(runtime, engine, false));
|
||||
method = new ModdedPregenMethod(new ModdedPregenMethod.Configuration(runtime, engine, false), () -> {
|
||||
long now = clock.get();
|
||||
if (now >= TimeUnit.SECONDS.toNanos(6)) {
|
||||
advanced.countDown();
|
||||
} else {
|
||||
started.countDown();
|
||||
}
|
||||
return now;
|
||||
});
|
||||
method.generateChunk(2, 3, listener);
|
||||
method.generateChunk(4, 5, listener);
|
||||
CountDownLatch started = new CountDownLatch(1);
|
||||
Future<?> closing = executor.submit(() -> {
|
||||
started.countDown();
|
||||
method.close();
|
||||
});
|
||||
Future<?> closing = executor.submit(method::close);
|
||||
assertTrue(started.await(5, TimeUnit.SECONDS));
|
||||
assertThrows(TimeoutException.class, () -> closing.get(6, TimeUnit.SECONDS));
|
||||
clock.set(TimeUnit.SECONDS.toNanos(6));
|
||||
assertTrue(advanced.await(5, TimeUnit.SECONDS));
|
||||
assertFalse(closing.isDone());
|
||||
verify(runtime, never()).save();
|
||||
verify(engine, never()).syncGenerationHistory();
|
||||
load.complete(new ChunkLoad(true, null));
|
||||
|
||||
Reference in new issue
Block a user