Refactoring

- better naming
- removed extra functions
- updated better statistics
This commit is contained in:
2025-01-22 22:33:38 +01:00
parent 0f4b0885cc
commit 90340a3193
5 changed files with 121 additions and 152 deletions

View File

@@ -37,47 +37,19 @@ public class Result {
var size = (int) Math.ceil(Math.log10(this.simulationTime));
var iFormat = "%" + size + ".0f";
var fFormat = "%" + (size + 4) + ".3f";
var builder = new StringBuilder();
for (var entry : this.nodes.entrySet()) {
var stats = entry.getValue();
var busy = stats.busyTime * 100 / stats.lastEventTime;
var avgResp = stats.responseTime / stats.numDepartures;
builder.append("===== " + entry.getKey() + " =====\n");
builder.append(String.format(" Arrivals: \t" + iFormat + "\n", stats.numArrivals));
builder.append(String.format(" Departures:\t" + iFormat + "\n", stats.numDepartures));
builder.append(String.format(" Max Queue: \t" + iFormat + "\n", stats.maxQueueLength));
builder.append(String.format(" Avg Queue: \t" + fFormat + "\n", stats.averageQueueLength));
builder.append(String.format(" Response: \t" + fFormat + "\n", avgResp));
builder.append(String.format(" Busy %%: \t" + fFormat + "\n", busy));
builder.append(String.format(" Last Event:\t" + fFormat + "\n", stats.lastEventTime));
}
return builder.toString();
}
/**
* TODO
*/
public String getSummaryAsTable() {
var size = (int) Math.ceil(Math.log10(this.simulationTime));
var iFormat = "%" + size + ".0f";
var fFormat = "%" + (size + 4) + ".3f";
String[] h = { "Node", "Arrivals", "Departures", "Max Queue", "Avg Queue", "Response", "Busy %",
"Last Event" };
String[] h = { "Node", "Departures", "Avg Queue", "Avg Response", "Throughput", "Utilization %", "Last Event" };
var table = new ConsoleTable(h);
for (var entry : this.nodes.entrySet()) {
var stats = entry.getValue();
table.addRow(
entry.getKey(),
String.format(iFormat, stats.numArrivals),
String.format(iFormat, stats.numDepartures),
String.format(iFormat, stats.maxQueueLength),
String.format(fFormat, stats.averageQueueLength),
String.format(fFormat, stats.responseTime / stats.numDepartures),
String.format(fFormat, stats.busyTime * 100 / stats.lastEventTime),
String.format(fFormat, stats.avgQueueLength),
String.format(fFormat, stats.avgResponse),
String.format(fFormat, stats.troughput),
String.format(fFormat, stats.utilization * 100),
String.format(fFormat, stats.lastEventTime));
}
return table.toString();

View File

@@ -17,8 +17,8 @@ public class ResultMultiple {
*/
public ResultMultiple(Result... runs) {
this.runs = runs;
this.average = calcAvg(runs);
this.variance = calcVar(this.average, runs);
this.average = ResultMultiple.calcAvg(runs);
this.variance = ResultMultiple.calcVar(this.average, runs);
}
/**
@@ -37,28 +37,15 @@ public class ResultMultiple {
avgElapsed += run.timeElapsedNano;
for (var entry : run.nodes.entrySet()) {
var stat = nodes.computeIfAbsent(entry.getKey(), _ -> new Statistics());
var other = entry.getValue();
stat.numDepartures += other.numDepartures;
stat.numArrivals += other.numArrivals;
stat.busyTime += other.busyTime;
stat.responseTime += other.responseTime;
stat.lastEventTime += other.lastEventTime;
stat.averageQueueLength += other.averageQueueLength;
stat.maxQueueLength = Math.max(stat.maxQueueLength, other.maxQueueLength);
var stats = nodes.computeIfAbsent(entry.getKey(), _ -> new Statistics());
stats.merge(entry.getValue(), (val1, val2) -> val1 + val2);
}
}
avgTime /= runs.length;
avgElapsed /= runs.length;
for (var stat : nodes.values()) {
stat.numDepartures /= runs.length;
stat.numArrivals /= runs.length;
stat.busyTime /= runs.length;
stat.responseTime /= runs.length;
stat.lastEventTime /= runs.length;
stat.averageQueueLength /= runs.length;
}
for (var stat : nodes.values())
stat.apply(val -> val / runs.length);
return new Result(runs[0].seed, avgTime, avgElapsed, nodes);
}
@@ -82,25 +69,16 @@ public class ResultMultiple {
var stat = nodes.computeIfAbsent(entry.getKey(), _ -> new Statistics());
var average = avg.nodes.get(entry.getKey());
var other = entry.getValue();
stat.numDepartures += Math.pow(other.numDepartures - average.numDepartures, 2);
stat.numArrivals += Math.pow(other.numArrivals - average.numArrivals, 2);
stat.busyTime += Math.pow(other.busyTime - average.busyTime, 2);
stat.responseTime += Math.pow(other.responseTime - average.responseTime, 2);
stat.lastEventTime += Math.pow(other.lastEventTime - average.lastEventTime, 2);
stat.averageQueueLength += Math.pow(other.averageQueueLength - average.averageQueueLength, 2);
var temp = new Statistics();
Statistics.apply(temp, other, average, (o, a) -> Math.pow(o - a, 2));
stat.merge(temp, (var1, var2) -> var1 + var2);
}
}
varTime /= runs.length - 1;
varElapsed /= runs.length - 1;
for (var stat : nodes.values()) {
stat.numDepartures /= runs.length - 1;
stat.numArrivals /= runs.length - 1;
stat.busyTime /= runs.length - 1;
stat.responseTime /= runs.length - 1;
stat.lastEventTime /= runs.length - 1;
stat.averageQueueLength /= runs.length - 1;
}
for (var stat : nodes.values())
stat.apply(val -> val / (runs.length - 1));
return new Result(runs[0].seed, varTime, varElapsed, nodes);
}

View File

@@ -7,49 +7,105 @@ import java.util.function.Function;
* TODO
*/
public class Statistics {
public double numArrivals = 0;
public double numDepartures = 0;
public double maxQueueLength = 0;
public double averageQueueLength = 0.0d;
public double numArrivals = 0.0d;
public double numDepartures = 0.0d;
public double maxQueueLength = 0.0d;
public double avgQueueLength = 0.0d;
public double busyTime = 0.0d;
public double responseTime = 0.0d;
public double lastEventTime = 0.0d;
// derived stats, you can calculate them even at the end
public double avgResponse = 0.0d;
public double troughput = 0.0d;
public double utilization = 0.0d;
/**
* Resets the statistics to their initial values.
* TODO
*
* @param time
* @param newQueueSize
* @param updateBusy
*/
public void updateArrival(double time, double newQueueSize, boolean updateBusy) {
var total = this.avgQueueLength * this.numArrivals;
this.numArrivals++;
this.avgQueueLength = (total + newQueueSize) / this.numArrivals;
this.maxQueueLength = Math.max(this.maxQueueLength, newQueueSize);
if (updateBusy)
this.busyTime += time - this.lastEventTime;
this.lastEventTime = time;
}
/**
* TODO
*
* @param time
* @param response
*/
public void updateDeparture(double time, double response) {
this.numDepartures++;
this.responseTime += response;
this.busyTime += time - this.lastEventTime;
this.lastEventTime = time;
this.avgResponse = this.responseTime / this.numDepartures;
this.troughput = this.numDepartures / this.lastEventTime;
this.utilization = this.busyTime / this.lastEventTime;
}
/**
* Resets the statistics to 0.
*/
public void reset() {
this.applyToAll(_ -> 0.0d);
this.apply(_ -> 0.0d);
}
/**
* Apply a function to ALL the stats in this class.
* The only stats that are not updated with this function are the one that
* starts with max, min (since they are special)
* The input of the function is the current value of the stat.
*
* @param func a function to apply
*/
public void applyToAll(Function<Double, Double> func) {
this.numArrivals = func.apply(this.numArrivals);
this.numDepartures = func.apply(this.numDepartures);
this.maxQueueLength = func.apply(this.maxQueueLength);
this.averageQueueLength = func.apply(this.averageQueueLength);
this.busyTime = func.apply(this.busyTime);
this.responseTime = func.apply(this.responseTime);
this.lastEventTime = func.apply(this.lastEventTime);
public void apply(Function<Double, Double> func) {
Statistics.apply(this, this, this, (val1, _) -> func.apply(val1));
}
/**
* A function used to merge two stats.
* A function used to merge tree stats.
* The only stats that are not updated with this function are the one that
* starts with max, min (since they are special)
*
* @param other
* @param func
*/
public void mergeWith(Statistics other, BiFunction<Double, Double, Double> func) {
this.numArrivals = func.apply(other.numArrivals, this.numArrivals);
this.numDepartures = func.apply(other.numDepartures, this.numDepartures);
this.maxQueueLength = func.apply(other.maxQueueLength, this.maxQueueLength);
this.averageQueueLength = func.apply(other.averageQueueLength, this.averageQueueLength);
this.busyTime = func.apply(other.busyTime, this.busyTime);
this.responseTime = func.apply(other.responseTime, this.responseTime);
this.lastEventTime = func.apply(other.lastEventTime, this.lastEventTime);
public void merge(Statistics other, BiFunction<Double, Double, Double> func) {
Statistics.apply(this, this, other, func);
}
/**
* TODO
*
* @param save
* @param val1
* @param val2
* @param func
*/
public static void apply(Statistics save, Statistics val1, Statistics val2,
BiFunction<Double, Double, Double> func) {
save.numArrivals = func.apply(val1.numArrivals, val2.numArrivals);
save.numDepartures = func.apply(val1.numDepartures, val2.numDepartures);
save.avgQueueLength = func.apply(val1.avgQueueLength, val2.avgQueueLength);
save.busyTime = func.apply(val1.busyTime, val2.busyTime);
save.responseTime = func.apply(val1.responseTime, val2.responseTime);
save.lastEventTime = func.apply(val1.lastEventTime, val2.lastEventTime);
// derived stats
save.troughput = func.apply(val1.troughput, val2.troughput);
save.utilization = func.apply(val1.utilization, val2.utilization);
save.avgResponse = func.apply(val1.avgResponse, val2.avgResponse);
}
}