package org.spigotmc;
/**
* Keeps track of the time spent doing main thread activities that can be spread across ticks,
* so that such work doesn't exceed the current tick's estimated available slack time. Each
* activity is allotted a proportion of the expected slack time according to its weight, versus the
* estimated total weight of all activities.
*/
public class SlackActivityAccountant {
private double prevTickSlackWeightReciprocal = 1 / MIN_SLACK_WEIGHT;
private static final double MIN_SLACK_WEIGHT = 1 / 65536.0;
private double averageTickNonSlackNanos = 0;
private static final double AVERAGING_FACTOR = 0.375;
private long currentActivityStartNanos;
private static final long OFF = -1;
private long currentActivityEndNanos;
private double tickSlackWeight;
private long tickSlackNanos;
private double getSlackFraction(double slackWeight) {
return Math.min(slackWeight * this.prevTickSlackWeightReciprocal, 1);
}
private int getEstimatedSlackNanos() {
return (int) Math.max(net.minecraft.server.MinecraftServer.TICK_TIME - (long) this.averageTickNonSlackNanos, 0);
}
public void tickStarted() {
this.currentActivityStartNanos = OFF;
this.tickSlackWeight = 0;
this.tickSlackNanos = 0;
}
public void startActivity(double slackWeight) {
double slackFraction0 = getSlackFraction(this.tickSlackWeight);
this.tickSlackWeight += slackWeight;
double slackFraction1 = getSlackFraction(this.tickSlackWeight);
long t = System.nanoTime();
this.currentActivityStartNanos = t;
this.currentActivityEndNanos = t + ((int) ((slackFraction1 - slackFraction0) * this.getEstimatedSlackNanos()));
}
private void endActivity(long endNanos) {
this.tickSlackNanos += endNanos - this.currentActivityStartNanos;
this.currentActivityStartNanos = OFF;
}
public boolean activityTimeIsExhausted() {
if (this.currentActivityStartNanos == OFF) {
return true;
}
long t = System.nanoTime();
if (t <= this.currentActivityEndNanos) {
return false;
} else {
this.endActivity(this.currentActivityEndNanos);
return true;
}
}
public void endActivity() {
if (this.currentActivityStartNanos == OFF) {
return;
}
this.endActivity(Math.min(System.nanoTime(), this.currentActivityEndNanos));
}
public void tickEnded(long tickNanos) {
this.prevTickSlackWeightReciprocal = 1 / Math.max(this.tickSlackWeight, MIN_SLACK_WEIGHT);
long tickNonSlackNanos = tickNanos - this.tickSlackNanos;
this.averageTickNonSlackNanos = this.averageTickNonSlackNanos * (1 - AVERAGING_FACTOR) + tickNonSlackNanos * AVERAGING_FACTOR;
}
}