diff options
4 files changed, 36 insertions, 21 deletions
diff --git a/spark-bukkit/src/main/java/me/lucko/spark/bukkit/placeholder/SparkPlaceholderProvider.java b/spark-bukkit/src/main/java/me/lucko/spark/bukkit/placeholder/SparkPlaceholderProvider.java index 0f57149..ee96630 100644 --- a/spark-bukkit/src/main/java/me/lucko/spark/bukkit/placeholder/SparkPlaceholderProvider.java +++ b/spark-bukkit/src/main/java/me/lucko/spark/bukkit/placeholder/SparkPlaceholderProvider.java @@ -68,12 +68,9 @@ enum SparkPlaceholderProvider { switch (placeholder) { case "tickduration": return TextComponent.builder("") - .append(HealthModule.formatTickDurations(tickStatistics.duration5Sec())).append(TextComponent.of(", ")) - .append(HealthModule.formatTickDurations(tickStatistics.duration10Sec())).append(TextComponent.of(", ")) + .append(HealthModule.formatTickDurations(tickStatistics.duration10Sec())).append(TextComponent.of("; ")) .append(HealthModule.formatTickDurations(tickStatistics.duration1Min())) .build(); - case "tickduration_5s": - return HealthModule.formatTickDurations(tickStatistics.duration5Sec()); case "tickduration_10s": return HealthModule.formatTickDurations(tickStatistics.duration10Sec()); case "tickduration_1m": diff --git a/spark-common/src/main/java/me/lucko/spark/common/command/modules/HealthModule.java b/spark-common/src/main/java/me/lucko/spark/common/command/modules/HealthModule.java index 08233db..64c2fba 100644 --- a/spark-common/src/main/java/me/lucko/spark/common/command/modules/HealthModule.java +++ b/spark-common/src/main/java/me/lucko/spark/common/command/modules/HealthModule.java @@ -48,6 +48,8 @@ import java.util.function.Consumer; public class HealthModule implements CommandModule { + private static final int MSPT_95_PERCENTILE = 95; + @Override public void registerCommands(Consumer<Command> consumer) { consumer.accept(Command.builder() @@ -67,10 +69,9 @@ public class HealthModule implements CommandModule { resp.replyPrefixed(TextComponent.empty()); if (tickStatistics.isDurationSupported()) { - resp.replyPrefixed(TextComponent.of("Tick durations (avg/min/max ms) from last 5s, 10s, 1m:")); + resp.replyPrefixed(TextComponent.of("Tick durations (min/med/95%ile/max ms) from last 10s, 1m:")); resp.replyPrefixed(TextComponent.builder(" ") - .append(formatTickDurations(tickStatistics.duration5Sec())).append(TextComponent.of(", ")) - .append(formatTickDurations(tickStatistics.duration10Sec())).append(TextComponent.of(", ")) + .append(formatTickDurations(tickStatistics.duration10Sec())).append(TextComponent.of("; ")) .append(formatTickDurations(tickStatistics.duration1Min())) .build() ); @@ -129,12 +130,11 @@ public class HealthModule implements CommandModule { report.add(TextComponent.builder("") .append(TextComponent.builder(">").color(TextColor.DARK_GRAY).decoration(TextDecoration.BOLD, true).build()) .append(TextComponent.space()) - .append(TextComponent.of("Tick durations (avg/min/max ms) from last 5s, 10s, 1m:", TextColor.GOLD)) + .append(TextComponent.of("Tick durations (min/med/95%ile/max ms) from last 10s, 1m:", TextColor.GOLD)) .build() ); report.add(TextComponent.builder(" ") - .append(formatTickDurations(tickStatistics.duration5Sec())).append(TextComponent.of(", ")) - .append(formatTickDurations(tickStatistics.duration10Sec())).append(TextComponent.of(", ")) + .append(formatTickDurations(tickStatistics.duration10Sec())).append(TextComponent.of("; ")) .append(formatTickDurations(tickStatistics.duration1Min())) .build() ); @@ -299,10 +299,12 @@ public class HealthModule implements CommandModule { public static TextComponent formatTickDurations(RollingAverage average){ return TextComponent.builder("") - .append(formatTickDuration(average.getAverage())) - .append(TextComponent.of('/', TextColor.GRAY)) .append(formatTickDuration(average.getMin())) .append(TextComponent.of('/', TextColor.GRAY)) + .append(formatTickDuration(average.getMedian())) + .append(TextComponent.of('/', TextColor.GRAY)) + .append(formatTickDuration(average.getPercentile(MSPT_95_PERCENTILE))) + .append(TextComponent.of('/', TextColor.GRAY)) .append(formatTickDuration(average.getMax())) .build(); } diff --git a/spark-common/src/main/java/me/lucko/spark/common/monitor/tick/TickStatistics.java b/spark-common/src/main/java/me/lucko/spark/common/monitor/tick/TickStatistics.java index 1ab0ea2..9e6f7c5 100644 --- a/spark-common/src/main/java/me/lucko/spark/common/monitor/tick/TickStatistics.java +++ b/spark-common/src/main/java/me/lucko/spark/common/monitor/tick/TickStatistics.java @@ -54,10 +54,9 @@ public class TickStatistics implements TickHook.Callback, TickReporter.Callback private final TpsRollingAverage[] tpsAverages = {this.tps5Sec, this.tps10Sec, this.tps1Min, this.tps5Min, this.tps15Min}; private boolean durationSupported = false; - private final RollingAverage tickDuration5Sec = new RollingAverage(TPS * 5); private final RollingAverage tickDuration10Sec = new RollingAverage(TPS * 10); private final RollingAverage tickDuration1Min = new RollingAverage(TPS * 60); - private final RollingAverage[] tickDurationAverages = {this.tickDuration5Sec, this.tickDuration10Sec, this.tickDuration1Min}; + private final RollingAverage[] tickDurationAverages = {this.tickDuration10Sec, this.tickDuration1Min}; private long last = 0; @@ -118,13 +117,6 @@ public class TickStatistics implements TickHook.Callback, TickReporter.Callback return this.tps15Min.getAverage(); } - public RollingAverage duration5Sec() { - if (!this.durationSupported) { - return null; - } - return this.tickDuration5Sec; - } - public RollingAverage duration10Sec() { if (!this.durationSupported) { return null; diff --git a/spark-common/src/main/java/me/lucko/spark/common/util/RollingAverage.java b/spark-common/src/main/java/me/lucko/spark/common/util/RollingAverage.java index 5cf5bb5..1e5e8b2 100644 --- a/spark-common/src/main/java/me/lucko/spark/common/util/RollingAverage.java +++ b/spark-common/src/main/java/me/lucko/spark/common/util/RollingAverage.java @@ -23,6 +23,8 @@ package me.lucko.spark.common.util; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.List; import java.util.Queue; public class RollingAverage { @@ -79,4 +81,26 @@ public class RollingAverage { } } + public double getMedian() { + return getPercentile(50); + } + + public double getPercentile(int percentile) { + if (percentile < 0 || percentile > 100) { + throw new IllegalArgumentException("Invalid percentage " + percentile); + } + + List<BigDecimal> sortedSamples; + synchronized (this) { + if (this.samples.isEmpty()) { + return 0; + } + sortedSamples = new ArrayList<>(this.samples); + } + sortedSamples.sort(null); + + int rank = (int) Math.ceil((percentile / 100d) * sortedSamples.size()); + return sortedSamples.get(rank).doubleValue(); + } + } |