mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-06-18 14:50:57 +00:00
shakey shakey
This commit is contained in:
@@ -72,6 +72,8 @@ public class PregeneratorJob implements PregenListener {
|
|||||||
private PregenRenderer renderer;
|
private PregenRenderer renderer;
|
||||||
private int rgc = 0;
|
private int rgc = 0;
|
||||||
private String[] info;
|
private String[] info;
|
||||||
|
private volatile double lastChunksPerSecond = 0D;
|
||||||
|
private volatile long lastChunksRemaining = 0L;
|
||||||
|
|
||||||
public PregeneratorJob(PregenTask task, PregeneratorMethod method, Engine engine) {
|
public PregeneratorJob(PregenTask task, PregeneratorMethod method, Engine engine) {
|
||||||
instance.updateAndGet(old -> {
|
instance.updateAndGet(old -> {
|
||||||
@@ -146,6 +148,16 @@ public class PregeneratorJob implements PregenListener {
|
|||||||
return inst.paused();
|
return inst.paused();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static double chunksPerSecond() {
|
||||||
|
PregeneratorJob inst = instance.get();
|
||||||
|
return inst == null ? 0D : Math.max(0D, inst.lastChunksPerSecond);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long chunksRemaining() {
|
||||||
|
PregeneratorJob inst = instance.get();
|
||||||
|
return inst == null ? -1L : Math.max(0L, inst.lastChunksRemaining);
|
||||||
|
}
|
||||||
|
|
||||||
private static Color parseColor(String c) {
|
private static Color parseColor(String c) {
|
||||||
String v = (c.startsWith("#") ? c : "#" + c).trim();
|
String v = (c.startsWith("#") ? c : "#" + c).trim();
|
||||||
try {
|
try {
|
||||||
@@ -234,6 +246,9 @@ public class PregeneratorJob implements PregenListener {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTick(double chunksPerSecond, double chunksPerMinute, double regionsPerMinute, double percent, long generated, long totalChunks, long chunksRemaining, long eta, long elapsed, String method, boolean cached) {
|
public void onTick(double chunksPerSecond, double chunksPerMinute, double regionsPerMinute, double percent, long generated, long totalChunks, long chunksRemaining, long eta, long elapsed, String method, boolean cached) {
|
||||||
|
lastChunksPerSecond = chunksPerSecond;
|
||||||
|
lastChunksRemaining = chunksRemaining;
|
||||||
|
|
||||||
info = new String[]{
|
info = new String[]{
|
||||||
(paused() ? "PAUSED" : (saving ? "Saving... " : "Generating")) + " " + Form.f(generated) + " of " + Form.f(totalChunks) + " (" + Form.pc(percent, 0) + " Complete)",
|
(paused() ? "PAUSED" : (saving ? "Saving... " : "Generating")) + " " + Form.f(generated) + " of " + Form.f(totalChunks) + " (" + Form.pc(percent, 0) + " Complete)",
|
||||||
"Speed: " + (cached ? "Cached " : "") + Form.f(chunksPerSecond, 0) + " Chunks/s, " + Form.f(regionsPerMinute, 1) + " Regions/m, " + Form.f(chunksPerMinute, 0) + " Chunks/m",
|
"Speed: " + (cached ? "Cached " : "") + Form.f(chunksPerSecond, 0) + " Chunks/s, " + Form.f(regionsPerMinute, 1) + " Regions/m, " + Form.f(chunksPerMinute, 0) + " Chunks/m",
|
||||||
|
|||||||
@@ -221,6 +221,25 @@ public class LazyPregenerator extends Thread implements Listener {
|
|||||||
return job != null && job.isPaused();
|
return job != null && job.isPaused();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static long remainingChunks() {
|
||||||
|
LazyPregenerator local = instance;
|
||||||
|
AtomicInteger generated = lazyGeneratedChunks;
|
||||||
|
if (local == null || generated == null) {
|
||||||
|
return -1L;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Math.max(0L, local.lazyTotalChunks.get() - generated.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double chunksPerSecond() {
|
||||||
|
LazyPregenerator local = instance;
|
||||||
|
if (local == null) {
|
||||||
|
return 0D;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Math.max(0D, local.chunksPerMinute.getAverage() / 60D);
|
||||||
|
}
|
||||||
|
|
||||||
public void shutdownInstance(World world) throws IOException {
|
public void shutdownInstance(World world) throws IOException {
|
||||||
Iris.info("LazyGen: " + C.IRIS + world.getName() + C.BLUE + " Shutting down..");
|
Iris.info("LazyGen: " + C.IRIS + world.getName() + C.BLUE + " Shutting down..");
|
||||||
LazyPregenJob job = jobs.get(world.getName());
|
LazyPregenJob job = jobs.get(world.getName());
|
||||||
@@ -282,4 +301,3 @@ public class LazyPregenerator extends Thread implements Listener {
|
|||||||
boolean paused = false;
|
boolean paused = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -285,6 +285,25 @@ public class TurboPregenerator extends Thread implements Listener {
|
|||||||
return job != null && job.isPaused();
|
return job != null && job.isPaused();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static long remainingChunks() {
|
||||||
|
TurboPregenerator local = instance;
|
||||||
|
AtomicInteger generated = turboGeneratedChunks;
|
||||||
|
if (local == null || generated == null) {
|
||||||
|
return -1L;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Math.max(0L, local.turboTotalChunks.get() - generated.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double chunksPerSecond() {
|
||||||
|
TurboPregenerator local = instance;
|
||||||
|
if (local == null) {
|
||||||
|
return 0D;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Math.max(0D, local.chunksPerSecond.getAverage());
|
||||||
|
}
|
||||||
|
|
||||||
public void shutdownInstance(World world) throws IOException {
|
public void shutdownInstance(World world) throws IOException {
|
||||||
Iris.info("turboGen: " + C.IRIS + world.getName() + C.BLUE + " Shutting down..");
|
Iris.info("turboGen: " + C.IRIS + world.getName() + C.BLUE + " Shutting down..");
|
||||||
TurboPregenJob job = jobs.get(world.getName());
|
TurboPregenJob job = jobs.get(world.getName());
|
||||||
@@ -338,4 +357,3 @@ public class TurboPregenerator extends Thread implements Listener {
|
|||||||
boolean paused = false;
|
boolean paused = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -66,6 +66,24 @@ public class IrisEngineSVC implements IrisService {
|
|||||||
worlds.clear();
|
worlds.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getQueuedTectonicPlateCount() {
|
||||||
|
return queuedTectonicPlates.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getAverageIdleDuration() {
|
||||||
|
double min = minIdleDuration.get();
|
||||||
|
double max = maxIdleDuration.get();
|
||||||
|
if (!Double.isFinite(min) || !Double.isFinite(max) || min < 0D || max < 0D) {
|
||||||
|
return 0D;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (max < min) {
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (min + max) / 2D;
|
||||||
|
}
|
||||||
|
|
||||||
public void engineStatus(VolmitSender sender) {
|
public void engineStatus(VolmitSender sender) {
|
||||||
long[] sizes = new long[4];
|
long[] sizes = new long[4];
|
||||||
long[] count = new long[4];
|
long[] count = new long[4];
|
||||||
|
|||||||
@@ -0,0 +1,219 @@
|
|||||||
|
package art.arcane.iris.core.service;
|
||||||
|
|
||||||
|
import art.arcane.iris.Iris;
|
||||||
|
import art.arcane.iris.core.gui.PregeneratorJob;
|
||||||
|
import art.arcane.iris.core.pregenerator.LazyPregenerator;
|
||||||
|
import art.arcane.iris.core.pregenerator.TurboPregenerator;
|
||||||
|
import art.arcane.iris.util.plugin.IrisService;
|
||||||
|
import art.arcane.volmlib.integration.IntegrationHandshakeRequest;
|
||||||
|
import art.arcane.volmlib.integration.IntegrationHandshakeResponse;
|
||||||
|
import art.arcane.volmlib.integration.IntegrationHeartbeat;
|
||||||
|
import art.arcane.volmlib.integration.IntegrationMetricDescriptor;
|
||||||
|
import art.arcane.volmlib.integration.IntegrationMetricSample;
|
||||||
|
import art.arcane.volmlib.integration.IntegrationMetricSchema;
|
||||||
|
import art.arcane.volmlib.integration.IntegrationProtocolNegotiator;
|
||||||
|
import art.arcane.volmlib.integration.IntegrationProtocolVersion;
|
||||||
|
import art.arcane.volmlib.integration.IntegrationServiceContract;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.plugin.ServicePriority;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class IrisIntegrationService implements IrisService, IntegrationServiceContract {
|
||||||
|
private static final Set<IntegrationProtocolVersion> SUPPORTED_PROTOCOLS = Set.of(
|
||||||
|
new IntegrationProtocolVersion(1, 0),
|
||||||
|
new IntegrationProtocolVersion(1, 1)
|
||||||
|
);
|
||||||
|
|
||||||
|
private static final Set<String> CAPABILITIES = Set.of(
|
||||||
|
"handshake",
|
||||||
|
"heartbeat",
|
||||||
|
"metrics",
|
||||||
|
"iris-engine-metrics"
|
||||||
|
);
|
||||||
|
|
||||||
|
private volatile IntegrationProtocolVersion negotiatedProtocol = new IntegrationProtocolVersion(1, 1);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEnable() {
|
||||||
|
Bukkit.getServicesManager().register(IntegrationServiceContract.class, this, Iris.instance, ServicePriority.Normal);
|
||||||
|
Iris.verbose("Integration provider registered for Iris");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDisable() {
|
||||||
|
Bukkit.getServicesManager().unregister(IntegrationServiceContract.class, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String pluginId() {
|
||||||
|
return "iris";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String pluginVersion() {
|
||||||
|
return Iris.instance.getDescription().getVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<IntegrationProtocolVersion> supportedProtocols() {
|
||||||
|
return SUPPORTED_PROTOCOLS;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> capabilities() {
|
||||||
|
return CAPABILITIES;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<IntegrationMetricDescriptor> metricDescriptors() {
|
||||||
|
return IntegrationMetricSchema.descriptors().stream()
|
||||||
|
.filter(descriptor -> descriptor.key().startsWith("iris."))
|
||||||
|
.collect(java.util.stream.Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IntegrationHandshakeResponse handshake(IntegrationHandshakeRequest request) {
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
if (request == null) {
|
||||||
|
return new IntegrationHandshakeResponse(
|
||||||
|
pluginId(),
|
||||||
|
pluginVersion(),
|
||||||
|
false,
|
||||||
|
null,
|
||||||
|
SUPPORTED_PROTOCOLS,
|
||||||
|
CAPABILITIES,
|
||||||
|
"missing request",
|
||||||
|
now
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<IntegrationProtocolVersion> negotiated = IntegrationProtocolNegotiator.negotiate(
|
||||||
|
SUPPORTED_PROTOCOLS,
|
||||||
|
request.supportedProtocols()
|
||||||
|
);
|
||||||
|
if (negotiated.isEmpty()) {
|
||||||
|
return new IntegrationHandshakeResponse(
|
||||||
|
pluginId(),
|
||||||
|
pluginVersion(),
|
||||||
|
false,
|
||||||
|
null,
|
||||||
|
SUPPORTED_PROTOCOLS,
|
||||||
|
CAPABILITIES,
|
||||||
|
"no-common-protocol",
|
||||||
|
now
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
negotiatedProtocol = negotiated.get();
|
||||||
|
return new IntegrationHandshakeResponse(
|
||||||
|
pluginId(),
|
||||||
|
pluginVersion(),
|
||||||
|
true,
|
||||||
|
negotiatedProtocol,
|
||||||
|
SUPPORTED_PROTOCOLS,
|
||||||
|
CAPABILITIES,
|
||||||
|
"ok",
|
||||||
|
now
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IntegrationHeartbeat heartbeat() {
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
return new IntegrationHeartbeat(negotiatedProtocol, true, now, "ok");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, IntegrationMetricSample> sampleMetrics(Set<String> metricKeys) {
|
||||||
|
Set<String> requested = metricKeys == null || metricKeys.isEmpty()
|
||||||
|
? IntegrationMetricSchema.irisKeys()
|
||||||
|
: metricKeys;
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
Map<String, IntegrationMetricSample> out = new HashMap<>();
|
||||||
|
|
||||||
|
for (String key : requested) {
|
||||||
|
switch (key) {
|
||||||
|
case IntegrationMetricSchema.IRIS_CHUNK_STREAM_MS -> out.put(key, sampleChunkStreamMetric(now));
|
||||||
|
case IntegrationMetricSchema.IRIS_PREGEN_QUEUE -> out.put(key, samplePregenQueueMetric(now));
|
||||||
|
case IntegrationMetricSchema.IRIS_BIOME_CACHE_HIT_RATE -> out.put(key, IntegrationMetricSample.unavailable(
|
||||||
|
IntegrationMetricSchema.descriptor(key),
|
||||||
|
"biome-cache-hit-rate-not-instrumented",
|
||||||
|
now
|
||||||
|
));
|
||||||
|
default -> out.put(key, IntegrationMetricSample.unavailable(
|
||||||
|
IntegrationMetricSchema.descriptor(key),
|
||||||
|
"unsupported-key",
|
||||||
|
now
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IntegrationMetricSample sampleChunkStreamMetric(long now) {
|
||||||
|
IntegrationMetricDescriptor descriptor = IntegrationMetricSchema.descriptor(IntegrationMetricSchema.IRIS_CHUNK_STREAM_MS);
|
||||||
|
|
||||||
|
double chunksPerSecond = PregeneratorJob.chunksPerSecond();
|
||||||
|
if (chunksPerSecond <= 0D) {
|
||||||
|
chunksPerSecond = TurboPregenerator.chunksPerSecond();
|
||||||
|
}
|
||||||
|
if (chunksPerSecond <= 0D) {
|
||||||
|
chunksPerSecond = LazyPregenerator.chunksPerSecond();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chunksPerSecond > 0D) {
|
||||||
|
return IntegrationMetricSample.available(descriptor, 1000D / chunksPerSecond, now);
|
||||||
|
}
|
||||||
|
|
||||||
|
IrisEngineSVC engineService = Iris.service(IrisEngineSVC.class);
|
||||||
|
if (engineService != null) {
|
||||||
|
double idle = engineService.getAverageIdleDuration();
|
||||||
|
if (idle > 0D && Double.isFinite(idle)) {
|
||||||
|
return IntegrationMetricSample.available(descriptor, idle, now);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return IntegrationMetricSample.unavailable(descriptor, "chunk-stream-not-active", now);
|
||||||
|
}
|
||||||
|
|
||||||
|
private IntegrationMetricSample samplePregenQueueMetric(long now) {
|
||||||
|
IntegrationMetricDescriptor descriptor = IntegrationMetricSchema.descriptor(IntegrationMetricSchema.IRIS_PREGEN_QUEUE);
|
||||||
|
long totalQueue = 0L;
|
||||||
|
boolean hasAnySource = false;
|
||||||
|
|
||||||
|
long pregenRemaining = PregeneratorJob.chunksRemaining();
|
||||||
|
if (pregenRemaining >= 0L) {
|
||||||
|
totalQueue += pregenRemaining;
|
||||||
|
hasAnySource = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
long turboRemaining = TurboPregenerator.remainingChunks();
|
||||||
|
if (turboRemaining >= 0L) {
|
||||||
|
totalQueue += turboRemaining;
|
||||||
|
hasAnySource = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
long lazyRemaining = LazyPregenerator.remainingChunks();
|
||||||
|
if (lazyRemaining >= 0L) {
|
||||||
|
totalQueue += lazyRemaining;
|
||||||
|
hasAnySource = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
IrisEngineSVC engineService = Iris.service(IrisEngineSVC.class);
|
||||||
|
if (engineService != null) {
|
||||||
|
totalQueue += Math.max(0, engineService.getQueuedTectonicPlateCount());
|
||||||
|
hasAnySource = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasAnySource) {
|
||||||
|
return IntegrationMetricSample.unavailable(descriptor, "queue-not-available", now);
|
||||||
|
}
|
||||||
|
|
||||||
|
return IntegrationMetricSample.available(descriptor, totalQueue, now);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user