Pack Benchmarking

- Iris pregen is broken what it relies on so it doesnt work.
Issue: Generated and total chunks dont end up as the same value after the pregen is done
This commit is contained in:
RePixelatedMC
2023-10-26 17:28:43 +02:00
parent 06bc180127
commit 8a0b443d28
8 changed files with 247 additions and 25 deletions
@@ -95,6 +95,8 @@ import java.util.Map;
import static com.volmit.iris.engine.safeguard.IrisSafeguard.unstablemode; import static com.volmit.iris.engine.safeguard.IrisSafeguard.unstablemode;
import static com.volmit.iris.engine.safeguard.ServerBootSFG.passedserversoftware; import static com.volmit.iris.engine.safeguard.ServerBootSFG.passedserversoftware;
import static com.volmit.iris.util.misc.getHardware.getCPUModel;
import static com.volmit.iris.util.misc.getHardware.getCPUThreads;
@SuppressWarnings("CanBeFinal") @SuppressWarnings("CanBeFinal")
public class Iris extends VolmitPlugin implements Listener { public class Iris extends VolmitPlugin implements Listener {
@@ -771,6 +773,8 @@ public class Iris extends VolmitPlugin implements Listener {
} else { Iris.info("Server type & version: " + Bukkit.getVersion()); } } else { Iris.info("Server type & version: " + Bukkit.getVersion()); }
Iris.info("Server OS: " + osName + " (" + osArch + ")"); Iris.info("Server OS: " + osName + " (" + osArch + ")");
Iris.info("Server Cpu: " + C.BLUE + getCPUModel());
Iris.info("Process Threads: " + getCPUThreads());
Iris.info("Process Memory: " + maxMemory + " MB"); Iris.info("Process Memory: " + maxMemory + " MB");
if (maxMemory < 5999) { if (maxMemory < 5999) {
Iris.warn("6GB+ Ram is recommended"); Iris.warn("6GB+ Ram is recommended");
@@ -22,6 +22,7 @@ import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings; import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.service.StudioSVC; import com.volmit.iris.core.service.StudioSVC;
import com.volmit.iris.core.tools.IrisBenchmarking; import com.volmit.iris.core.tools.IrisBenchmarking;
import com.volmit.iris.core.tools.IrisPackBenchmarking;
import com.volmit.iris.core.tools.IrisToolbelt; import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.engine.framework.Engine; import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.IrisDimension; import com.volmit.iris.engine.object.IrisDimension;
@@ -41,6 +42,8 @@ import com.volmit.iris.util.parallel.MultiBurst;
import com.volmit.iris.util.plugin.VolmitSender; import com.volmit.iris.util.plugin.VolmitSender;
import com.volmit.iris.util.scheduling.J; import com.volmit.iris.util.scheduling.J;
import com.volmit.iris.util.scheduling.jobs.QueueJob; import com.volmit.iris.util.scheduling.jobs.QueueJob;
import lombok.Getter;
import lombok.Setter;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Chunk; import org.bukkit.Chunk;
import org.bukkit.World; import org.bukkit.World;
@@ -52,6 +55,7 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import static com.volmit.iris.core.tools.IrisBenchmarking.inProgress; import static com.volmit.iris.core.tools.IrisBenchmarking.inProgress;
import static com.volmit.iris.core.tools.IrisPackBenchmarking.runBenchmark;
import static com.volmit.iris.engine.safeguard.ServerBootSFG.multiverse; import static com.volmit.iris.engine.safeguard.ServerBootSFG.multiverse;
@Decree(name = "iris", aliases = {"ir", "irs"}, description = "Basic Command") @Decree(name = "iris", aliases = {"ir", "irs"}, description = "Basic Command")
@@ -66,6 +70,8 @@ public class CommandIris implements DecreeExecutor {
private CommandFind find; private CommandFind find;
private CommandWorldManager manager; private CommandWorldManager manager;
public static @Getter String BenchDimension;
@Decree(description = "Create a new world", aliases = {"+", "c"}) @Decree(description = "Create a new world", aliases = {"+", "c"})
public void create( public void create(
@Param(aliases = "world-name", description = "The name of the world to create") @Param(aliases = "world-name", description = "The name of the world to create")
@@ -88,6 +94,11 @@ public class CommandIris implements DecreeExecutor {
sender().sendMessage(C.RED + "May we suggest the name \"IrisWorld\" instead?"); sender().sendMessage(C.RED + "May we suggest the name \"IrisWorld\" instead?");
return; return;
} }
if (name.equals("Benchmark")) {
sender().sendMessage(C.RED + "You cannot use the world name \"Benchmark\" for creating worlds as Iris uses this directory for Benchmarking Packs.");
sender().sendMessage(C.RED + "May we suggest the name \"IrisWorld\" instead?");
return;
}
if (new File(Bukkit.getWorldContainer(), name).exists()) { if (new File(Bukkit.getWorldContainer(), name).exists()) {
sender().sendMessage(C.RED + "That folder already exists!"); sender().sendMessage(C.RED + "That folder already exists!");
@@ -142,13 +153,23 @@ public class CommandIris implements DecreeExecutor {
sender().sendMessage(C.GREEN + "Iris v" + Iris.instance.getDescription().getVersion() + " by Volmit Software"); sender().sendMessage(C.GREEN + "Iris v" + Iris.instance.getDescription().getVersion() + " by Volmit Software");
} }
@Decree(description = "Benchmark your server", origin = DecreeOrigin.CONSOLE) @Decree(description = "Benchmark your server", origin = DecreeOrigin.CONSOLE)
public void benchmark() throws InterruptedException { public void serverbenchmark() throws InterruptedException {
if(!inProgress) { if(!inProgress) {
IrisBenchmarking.runBenchmark(); IrisBenchmarking.runBenchmark();
} else { } else {
Iris.info(C.RED + "Benchmark already is in progress."); Iris.info(C.RED + "Benchmark already is in progress.");
} }
} }
@Decree(description = "Benchmark a pack", origin = DecreeOrigin.CONSOLE)
public void packbenchmark(
@Param(description = "Dimension to benchmark")
IrisDimension type
) throws InterruptedException {
BenchDimension = type.getLoadKey();
IrisPackBenchmarking.runBenchmark();
}
@Decree(description = "Print world height information", origin = DecreeOrigin.PLAYER) @Decree(description = "Print world height information", origin = DecreeOrigin.PLAYER)
public void height() { public void height() {
@@ -67,7 +67,8 @@ public class CommandPregen implements DecreeExecutor {
@Decree(description = "Stop the active pregeneration task", aliases = "x") @Decree(description = "Stop the active pregeneration task", aliases = "x")
public void stop() { public void stop() {
if (PregeneratorJob.shutdownInstance()) { if (PregeneratorJob.shutdownInstance()) {
sender().sendMessage(C.GREEN + "Stopped pregeneration task"); Iris.info( C.BLUE + "Finishing up mca region...");
sender().sendMessage(C.DARK_BLUE + "Stopped pregeneration task");
} else { } else {
sender().sendMessage(C.YELLOW + "No active pregeneration tasks to stop"); sender().sendMessage(C.YELLOW + "No active pregeneration tasks to stop");
} }
@@ -19,7 +19,9 @@
package com.volmit.iris.core.pregenerator; package com.volmit.iris.core.pregenerator;
import com.volmit.iris.Iris; import com.volmit.iris.Iris;
import com.volmit.iris.core.tools.IrisPackBenchmarking;
import com.volmit.iris.util.collection.KSet; import com.volmit.iris.util.collection.KSet;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.format.Form; import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.mantle.Mantle; import com.volmit.iris.util.mantle.Mantle;
import com.volmit.iris.util.math.M; import com.volmit.iris.util.math.M;
@@ -28,12 +30,16 @@ import com.volmit.iris.util.math.RollingSequence;
import com.volmit.iris.util.scheduling.ChronoLatch; import com.volmit.iris.util.scheduling.ChronoLatch;
import com.volmit.iris.util.scheduling.J; import com.volmit.iris.util.scheduling.J;
import com.volmit.iris.util.scheduling.Looper; import com.volmit.iris.util.scheduling.Looper;
import lombok.Getter;
import lombok.Setter;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import static com.volmit.iris.core.tools.IrisPackBenchmarking.benchmark;
public class IrisPregenerator { public class IrisPregenerator {
private final PregenTask task; private final PregenTask task;
private final PregeneratorMethod generator; private final PregeneratorMethod generator;
@@ -44,10 +50,10 @@ public class IrisPregenerator {
private final RollingSequence chunksPerSecond; private final RollingSequence chunksPerSecond;
private final RollingSequence chunksPerMinute; private final RollingSequence chunksPerMinute;
private final RollingSequence regionsPerMinute; private final RollingSequence regionsPerMinute;
private final AtomicInteger generated; private static AtomicInteger generated;
private final AtomicInteger generatedLast; private final AtomicInteger generatedLast;
private final AtomicInteger generatedLastMinute; private final AtomicInteger generatedLastMinute;
private final AtomicInteger totalChunks; private static AtomicInteger totalChunks;
private final AtomicLong startTime; private final AtomicLong startTime;
private final ChronoLatch minuteLatch; private final ChronoLatch minuteLatch;
private final AtomicReference<String> currentGeneratorMethod; private final AtomicReference<String> currentGeneratorMethod;
@@ -56,6 +62,8 @@ public class IrisPregenerator {
private final KSet<Position2> net; private final KSet<Position2> net;
private final ChronoLatch cl; private final ChronoLatch cl;
private final ChronoLatch saveLatch = new ChronoLatch(30000); private final ChronoLatch saveLatch = new ChronoLatch(30000);
static long long_generatedChunks = 0;
static long long_totalChunks = 0;
public IrisPregenerator(PregenTask task, PregeneratorMethod generator, PregenListener listener) { public IrisPregenerator(PregenTask task, PregeneratorMethod generator, PregenListener listener) {
this.listener = listenify(listener); this.listener = listenify(listener);
@@ -92,6 +100,8 @@ public class IrisPregenerator {
chunksPerMinute.put(minuteGenerated); chunksPerMinute.put(minuteGenerated);
regionsPerMinute.put((double) minuteGenerated / 1024D); regionsPerMinute.put((double) minuteGenerated / 1024D);
} }
long_generatedChunks = generated.get();
long_totalChunks = totalChunks.get();
listener.onTick(chunksPerSecond.getAverage(), chunksPerMinute.getAverage(), listener.onTick(chunksPerSecond.getAverage(), chunksPerMinute.getAverage(),
regionsPerMinute.getAverage(), regionsPerMinute.getAverage(),
@@ -102,9 +112,12 @@ public class IrisPregenerator {
if (cl.flip()) { if (cl.flip()) {
double percentage = ((double) generated.get() / (double) totalChunks.get()) * 100; double percentage = ((double) generated.get() / (double) totalChunks.get()) * 100;
if(benchmark) {
Iris.info(C.GREEN +"Benchmark: " + C.WHITE + Form.f(generated.get()) + " of " + Form.f(totalChunks.get()) + " (%.0f%%) " + Form.f((int) chunksPerSecond.getAverage()) + "/s ETA: " + Form.duration((double) eta, 2), percentage);
} else {
Iris.info("Pregen: " + Form.f(generated.get()) + " of " + Form.f(totalChunks.get()) + " (%.0f%%) " + Form.f((int) chunksPerSecond.getAverage()) + "/s ETA: " + Form.duration((double) eta, 2), percentage); Iris.info("Pregen: " + Form.f(generated.get()) + " of " + Form.f(totalChunks.get()) + " (%.0f%%) " + Form.f((int) chunksPerSecond.getAverage()) + "/s ETA: " + Form.duration((double) eta, 2), percentage);
} }
}
return 1000; return 1000;
} }
}; };
@@ -119,6 +132,19 @@ public class IrisPregenerator {
); );
} }
public static void shareData(){
long_generatedChunks = generated.get();
long_totalChunks = totalChunks.get();
}
public static long getLongGeneratedChunks() {
return long_generatedChunks;
}
public static long getLongTotalChunks() {
return long_totalChunks;
}
public void close() { public void close() {
shutdown.set(true); shutdown.set(true);
} }
@@ -29,11 +29,9 @@ import java.io.InputStreamReader;
import static com.google.common.math.LongMath.isPrime; import static com.google.common.math.LongMath.isPrime;
import static com.volmit.iris.util.misc.getHardware.getCPUModel; import static com.volmit.iris.util.misc.getHardware.getCPUModel;
import static com.volmit.iris.util.misc.getHardware.getDiskModel; import static com.volmit.iris.util.misc.getHardware.getDiskModel;
public class IrisBenchmarking { public class IrisBenchmarking {
static String ServerOS; static String ServerOS;
static String filePath = "benchmark.dat"; static String filePath = "benchmark.dat";
private static long startTime;
static double avgWriteSpeedMBps; static double avgWriteSpeedMBps;
static double avgReadSpeedMBps; static double avgReadSpeedMBps;
static double highestWriteSpeedMBps; static double highestWriteSpeedMBps;
@@ -58,6 +56,7 @@ public class IrisBenchmarking {
static boolean Winsat = false; static boolean Winsat = false;
static boolean WindowsDiskSpeed = false; static boolean WindowsDiskSpeed = false;
public static boolean inProgress = false; public static boolean inProgress = false;
static double startTime;
// Good enough for now. . . // Good enough for now. . .
public static void runBenchmark() throws InterruptedException { public static void runBenchmark() throws InterruptedException {
@@ -45,6 +45,9 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier; import java.util.function.Supplier;
import static com.volmit.iris.core.tools.IrisPackBenchmarking.benchmark;
import static com.volmit.iris.core.tools.IrisPackBenchmarking.loaded;
/** /**
* Makes it a lot easier to setup an engine, world, studio or whatever * Makes it a lot easier to setup an engine, world, studio or whatever
*/ */
@@ -93,6 +96,9 @@ public class IrisCreator {
yml.save(BUKKIT_YML); yml.save(BUKKIT_YML);
return true; return true;
} }
public static boolean worldLoaded(){
return true;
}
/** /**
* Create the IrisAccess (contains the world) * Create the IrisAccess (contains the world)
@@ -100,6 +106,7 @@ public class IrisCreator {
* @return the IrisAccess * @return the IrisAccess
* @throws IrisException shit happens * @throws IrisException shit happens
*/ */
IrisPackBenchmarking PackBench = new IrisPackBenchmarking();
public World create() throws IrisException { public World create() throws IrisException {
if (Bukkit.isPrimaryThread()) { if (Bukkit.isPrimaryThread()) {
throw new IrisException("You cannot invoke create() on the main thread."); throw new IrisException("You cannot invoke create() on the main thread.");
@@ -117,6 +124,9 @@ public class IrisCreator {
if (!studio()) { if (!studio()) {
Iris.service(StudioSVC.class).installIntoWorld(sender, d.getLoadKey(), new File(Bukkit.getWorldContainer(), name())); Iris.service(StudioSVC.class).installIntoWorld(sender, d.getLoadKey(), new File(Bukkit.getWorldContainer(), name()));
} }
if (benchmark) {
Iris.service(StudioSVC.class).installIntoWorld(sender, d.getLoadKey(), new File(Bukkit.getWorldContainer(), name()));
}
PlatformChunkGenerator access = null; PlatformChunkGenerator access = null;
AtomicReference<World> world = new AtomicReference<>(); AtomicReference<World> world = new AtomicReference<>();
@@ -143,9 +153,9 @@ public class IrisCreator {
} }
return finalAccess1.getEngine().getGenerated(); return finalAccess1.getEngine().getGenerated();
}; };
if(!benchmark) {
while (g.get() < req) { while (g.get() < req) {
double v = (double) g.get() / (double) req; double v = (double) g.get() / (double) req;
if (sender.isPlayer()) { if (sender.isPlayer()) {
sender.sendProgress(v, "Generating"); sender.sendProgress(v, "Generating");
J.sleep(16); J.sleep(16);
@@ -154,6 +164,9 @@ public class IrisCreator {
J.sleep(1000); J.sleep(1000);
} }
} }
}
//if (benchmark){loaded = true;}
Iris.info("Debug1");
}); });
@@ -177,7 +190,7 @@ public class IrisCreator {
}); });
} }
if (studio) { if (studio || benchmark) {
J.s(() -> { J.s(() -> {
Iris.linkMultiverseCore.removeFromConfig(world.get()); Iris.linkMultiverseCore.removeFromConfig(world.get());
@@ -1,9 +1,156 @@
package com.volmit.iris.core.tools; package com.volmit.iris.core.tools;
public class IrisPackBenchmarking { import com.volmit.iris.Iris;
public static void runBenchmark(){ import com.volmit.iris.core.pregenerator.IrisPregenerator;
import com.volmit.iris.core.pregenerator.PregenTask;
import com.volmit.iris.util.exceptions.IrisException;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.math.Position2;
import com.volmit.iris.util.scheduling.J;
import org.apache.commons.io.FileUtils;
import org.bukkit.Bukkit;
import java.io.File;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import static com.volmit.iris.core.commands.CommandIris.BenchDimension;
public class IrisPackBenchmarking {
public static boolean loaded = false;
public static boolean benchmark = false;
static boolean cancelled = false;
static boolean pregenInProgress = false;
static long startTime;
static long totalChunks;
static long generatedChunks;
static double elapsedTimeNs;
public static void runBenchmark() {
// IrisPackBenchmarking IrisPackBenchmarking = new IrisPackBenchmarking();
benchmark = true;
Iris.info(C.BLUE + "Benchmarking Dimension: " + C.AQUA + BenchDimension);
//progress();
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
Iris.info(C.GOLD + "Setting everything up..");
try {
String BenchmarkFolder = "\\Benchmark";
File folder = new File(BenchmarkFolder);
if (folder.exists() && folder.isDirectory()) {
FileUtils.deleteDirectory(folder);
Iris.debug("Deleted old Benchmark");
} else {
Iris.info(C.GOLD + "Old Benchmark not found!");
if(folder.exists()){
Iris.info(C.RED + "FAILED To remove old Benchmark!");
//cancelled = true;
}
}
} catch (Exception e) {
throw new RuntimeException();
} }
}).thenRun(() -> {
Iris.info(C.GOLD + "Creating Benchmark Environment");
createBenchmark();
}).thenRun(() -> {
Iris.info( C.BLUE + "Benchmark Started!");
boolean done = false;
startBenchmarkTimer();
startBenchmark();
basicScheduler();
}).thenRun(() -> {
});
// cancelled = future.cancel(true);
try {
future.get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
private static void results(){
double averageCps = calculateAverageCPS();
Iris.info("Benchmark Dimension: " + BenchDimension);
Iris.info("Speeds");
Iris.info("- Average CPS: " + roundToTwoDecimalPlaces(averageCps));
Iris.info("Duration: " + roundToTwoDecimalPlaces(elapsedTimeNs));
}
private static void basicScheduler() {
while (true) {
totalChunks = IrisPregenerator.getLongTotalChunks();
generatedChunks = IrisPregenerator.getLongGeneratedChunks();
Iris.info("TEST: "+ totalChunks);
Iris.info("TEST2: "+ generatedChunks);
if(totalChunks > 0) {
if (generatedChunks >= totalChunks) {
Iris.info("Benchmark Completed!");
elapsedTimeNs = stopBenchmarkTimer();
results();
break;
}
}
//J.sleep(100);
}
}
static void createBenchmark(){
try {
IrisToolbelt.createWorld()
.dimension(BenchDimension)
.name("Benchmark")
.seed(1337)
.studio(false)
.create();
} catch (IrisException e) {
throw new RuntimeException(e);
}
}
static void startBenchmark(){
int x = 0;
int z = 0;
IrisToolbelt.pregenerate(PregenTask
.builder()
.center(new Position2(x, z))
.width(5)
.height(5)
.build(), Bukkit.getWorld("Benchmark")
);
}
public static double calculateAverageCPS() {
double elapsedTimeSec = elapsedTimeNs / 1_000_000_000.0; // Convert to seconds
return generatedChunks / elapsedTimeSec;
}
private static void startBenchmarkTimer() {
startTime = System.nanoTime();
}
private static double stopBenchmarkTimer() {
long endTime = System.nanoTime();
return (endTime - startTime) / 1_000_000_000.0;
}
public static void deleteDirectory(File dir) {
File[] files = dir.listFiles();
if(files != null) {
for(File file: files) {
if(file.isDirectory()) {
deleteDirectory(file);
} else {
file.delete();
}
}
}
dir.delete();
}
private static double roundToTwoDecimalPlaces(double value) {
return Double.parseDouble(String.format("%.2f", value));
}
} }
@@ -19,6 +19,8 @@
package com.volmit.iris.engine; package com.volmit.iris.engine;
import com.volmit.iris.Iris; import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.tools.IrisPackBenchmarking;
import com.volmit.iris.engine.data.cache.AtomicCache; import com.volmit.iris.engine.data.cache.AtomicCache;
import com.volmit.iris.engine.framework.Engine; import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.mantle.EngineMantle; import com.volmit.iris.engine.mantle.EngineMantle;
@@ -31,6 +33,7 @@ import com.volmit.iris.engine.object.*;
import com.volmit.iris.util.collection.KList; import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap; import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.collection.KSet; import com.volmit.iris.util.collection.KSet;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.format.Form; import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.mantle.Mantle; import com.volmit.iris.util.mantle.Mantle;
import com.volmit.iris.util.parallel.BurstExecutor; import com.volmit.iris.util.parallel.BurstExecutor;
@@ -42,6 +45,8 @@ import java.io.IOException;
import java.util.Map; import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import static com.volmit.iris.core.tools.IrisPackBenchmarking.benchmark;
@Data @Data
public class IrisEngineMantle implements EngineMantle { public class IrisEngineMantle implements EngineMantle {
private final Engine engine; private final Engine engine;
@@ -280,11 +285,17 @@ public class IrisEngineMantle implements EngineMantle {
x = Math.max(x, c); x = Math.max(x, c);
x = (Math.max(x, 16) + 16) >> 4; x = (Math.max(x, 16) + 16) >> 4;
x = x % 2 == 0 ? x + 1 : x; x = x % 2 == 0 ? x + 1 : x;
IrisPackBenchmarking PackBench = new IrisPackBenchmarking();
if (benchmark){
x = 4; x = 4;
Iris.info("Mantle Size: " + x + " Chunks " + C.BLUE + "BENCHMARK MODE");
} else {
Iris.info("Mantle Size: " + x + " Chunks"); Iris.info("Mantle Size: " + x + " Chunks");
Iris.info(" Object Mantle Size: " + u + " (" + ((Math.max(u, 16) + 16) >> 4) + ")"); Iris.info(" Object Mantle Size: " + u + " (" + ((Math.max(u, 16) + 16) >> 4) + ")");
Iris.info(" Jigsaw Mantle Size: " + jig + " (" + ((Math.max(jig, 16) + 16) >> 4) + ")"); Iris.info(" Jigsaw Mantle Size: " + jig + " (" + ((Math.max(jig, 16) + 16) >> 4) + ")");
Iris.info(" Carving Mantle Size: " + c + " (" + ((Math.max(c, 16) + 16) >> 4) + ")"); Iris.info(" Carving Mantle Size: " + c + " (" + ((Math.max(c, 16) + 16) >> 4) + ")");
}
return x; return x;
} }