Refactoring
- better naming - removed extra functions - updated better statistics
This commit is contained in:
@@ -32,7 +32,7 @@ public class Main {
|
|||||||
nano = System.nanoTime() - nano;
|
nano = System.nanoTime() - nano;
|
||||||
|
|
||||||
System.out.print(results.average.getHeader());
|
System.out.print(results.average.getHeader());
|
||||||
System.out.print(results.average.getSummaryAsTable());
|
System.out.print(results.average.getSummary());
|
||||||
System.out.println("Final time " + nano / 1e6 + "ms");
|
System.out.println("Final time " + nano / 1e6 + "ms");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -14,7 +14,7 @@ import net.berack.upo.valpre.sim.stats.Statistics;
|
|||||||
*/
|
*/
|
||||||
public final class Simulation {
|
public final class Simulation {
|
||||||
private final Net net;
|
private final Net net;
|
||||||
private final Map<String, NodeBehavior> nodes;
|
private final Map<String, NodeState> states;
|
||||||
private final PriorityQueue<Event> fel;
|
private final PriorityQueue<Event> fel;
|
||||||
private final EndCriteria[] criterias;
|
private final EndCriteria[] criterias;
|
||||||
private final long timeStartedNano;
|
private final long timeStartedNano;
|
||||||
@@ -26,13 +26,13 @@ public final class Simulation {
|
|||||||
* Creates a new run of the simulation with the given nodes and random number
|
* Creates a new run of the simulation with the given nodes and random number
|
||||||
* generator.
|
* generator.
|
||||||
*
|
*
|
||||||
* @param nodes The nodes in the network.
|
* @param states The nodes in the network.
|
||||||
* @param rng The random number generator to use.
|
* @param rng The random number generator to use.
|
||||||
* @param criterias when the simulation has to end.
|
* @param criterias when the simulation has to end.
|
||||||
*/
|
*/
|
||||||
public Simulation(Net net, Rng rng, EndCriteria... criterias) {
|
public Simulation(Net net, Rng rng, EndCriteria... criterias) {
|
||||||
this.net = net;
|
this.net = net;
|
||||||
this.nodes = new HashMap<>();
|
this.states = new HashMap<>();
|
||||||
this.fel = new PriorityQueue<>();
|
this.fel = new PriorityQueue<>();
|
||||||
this.criterias = criterias;
|
this.criterias = criterias;
|
||||||
this.timeStartedNano = System.nanoTime();
|
this.timeStartedNano = System.nanoTime();
|
||||||
@@ -42,7 +42,7 @@ public final class Simulation {
|
|||||||
|
|
||||||
// Initial arrivals (if spawned)
|
// Initial arrivals (if spawned)
|
||||||
net.forEachNode(node -> {
|
net.forEachNode(node -> {
|
||||||
this.nodes.put(node.name, new NodeBehavior());
|
this.states.put(node.name, new NodeState());
|
||||||
if (node.shouldSpawnArrival(0))
|
if (node.shouldSpawnArrival(0))
|
||||||
this.addArrival(node);
|
this.addArrival(node);
|
||||||
});
|
});
|
||||||
@@ -69,23 +69,34 @@ public final class Simulation {
|
|||||||
public void processNextEvent() {
|
public void processNextEvent() {
|
||||||
var event = fel.poll();
|
var event = fel.poll();
|
||||||
var node = event.node;
|
var node = event.node;
|
||||||
var behaviour = this.nodes.get(node.name);
|
var state = this.states.get(node.name);
|
||||||
this.time = event.time;
|
this.time = event.time;
|
||||||
|
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
case ARRIVAL -> {
|
case ARRIVAL -> {
|
||||||
if (behaviour.updateArrival(event.time, node.maxServers))
|
state.queue.add(this.time);
|
||||||
|
state.stats.updateArrival(this.time, state.queue.size(), state.numServerBusy != 0);
|
||||||
|
|
||||||
|
if (state.numServerBusy < node.maxServers) {
|
||||||
|
state.numServerBusy++;
|
||||||
this.addDeparture(node);
|
this.addDeparture(node);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case DEPARTURE -> {
|
case DEPARTURE -> {
|
||||||
if (behaviour.updateDeparture(event.time))
|
var startService = state.queue.poll();
|
||||||
|
state.stats.updateDeparture(this.time, this.time - startService);
|
||||||
|
|
||||||
|
if (state.numServerBusy > state.queue.size()) {
|
||||||
|
state.numServerBusy--;
|
||||||
|
} else {
|
||||||
this.addDeparture(node);
|
this.addDeparture(node);
|
||||||
|
}
|
||||||
|
|
||||||
var next = this.net.getChildOf(node, this.rng);
|
var next = this.net.getChildOf(node, this.rng);
|
||||||
if (next != null) {
|
if (next != null) {
|
||||||
this.addArrival(next);
|
this.addArrival(next);
|
||||||
}
|
}
|
||||||
if (node.shouldSpawnArrival(behaviour.stats.numArrivals)) {
|
if (node.shouldSpawnArrival(state.stats.numArrivals)) {
|
||||||
this.addArrival(node);
|
this.addArrival(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -100,7 +111,7 @@ public final class Simulation {
|
|||||||
public Result endSimulation() {
|
public Result endSimulation() {
|
||||||
var elapsed = System.nanoTime() - this.timeStartedNano;
|
var elapsed = System.nanoTime() - this.timeStartedNano;
|
||||||
var nodes = new HashMap<String, Statistics>();
|
var nodes = new HashMap<String, Statistics>();
|
||||||
for (var entry : this.nodes.entrySet())
|
for (var entry : this.states.entrySet())
|
||||||
nodes.put(entry.getKey(), entry.getValue().stats);
|
nodes.put(entry.getKey(), entry.getValue().stats);
|
||||||
|
|
||||||
return new Result(this.seed, this.time, elapsed, nodes);
|
return new Result(this.seed, this.time, elapsed, nodes);
|
||||||
@@ -116,13 +127,13 @@ public final class Simulation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the node requested by the name passed as a string.
|
* Get the node state requested by the name passed as a string.
|
||||||
*
|
*
|
||||||
* @param node the name of the node
|
* @param node the name of the node
|
||||||
* @return the node
|
* @return the node
|
||||||
*/
|
*/
|
||||||
public NodeBehavior getNode(String node) {
|
public NodeState getNode(String node) {
|
||||||
return this.getNode(node);
|
return this.states.get(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -166,61 +177,13 @@ public final class Simulation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a summary of the behavior of a server node in the network.
|
* Represents a summary of the state of a server node in the network.
|
||||||
* It is used by the simulation to track the number of arrivals and departures,
|
* It is used by the simulation to track the number of arrivals and departures,
|
||||||
* the maximum queue length, the busy time, and the response time.
|
* the maximum queue length, the busy time, and the response time.
|
||||||
*/
|
*/
|
||||||
public static class NodeBehavior {
|
public static class NodeState {
|
||||||
public int numServerBusy = 0;
|
public int numServerBusy = 0;
|
||||||
public final Statistics stats = new Statistics();
|
public final Statistics stats = new Statistics();
|
||||||
private final ArrayDeque<Double> queue = new ArrayDeque<>();
|
private final ArrayDeque<Double> queue = new ArrayDeque<>();
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO
|
|
||||||
*
|
|
||||||
* @param time
|
|
||||||
* @param maxServers
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public boolean updateArrival(double time, int maxServers) {
|
|
||||||
var total = this.stats.averageQueueLength * this.stats.numArrivals;
|
|
||||||
|
|
||||||
this.queue.add(time);
|
|
||||||
this.stats.numArrivals++;
|
|
||||||
this.stats.averageQueueLength = (total + this.queue.size()) / this.stats.numArrivals;
|
|
||||||
this.stats.maxQueueLength = Math.max(this.stats.maxQueueLength, this.queue.size());
|
|
||||||
|
|
||||||
var startDeparture = maxServers > this.numServerBusy;
|
|
||||||
if (startDeparture) {
|
|
||||||
this.numServerBusy++;
|
|
||||||
} else {
|
|
||||||
this.stats.busyTime += time - this.stats.lastEventTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.stats.lastEventTime = time;
|
|
||||||
return startDeparture;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO
|
|
||||||
*
|
|
||||||
* @param time
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public boolean updateDeparture(double time) {
|
|
||||||
var startService = this.queue.poll();
|
|
||||||
var response = time - startService;
|
|
||||||
|
|
||||||
var startDeparture = this.queue.size() >= this.numServerBusy;
|
|
||||||
if (!startDeparture) {
|
|
||||||
this.numServerBusy--;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.stats.numDepartures++;
|
|
||||||
this.stats.responseTime += response;
|
|
||||||
this.stats.busyTime += time - this.stats.lastEventTime;
|
|
||||||
this.stats.lastEventTime = time;
|
|
||||||
return startDeparture;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -37,47 +37,19 @@ public class Result {
|
|||||||
var size = (int) Math.ceil(Math.log10(this.simulationTime));
|
var size = (int) Math.ceil(Math.log10(this.simulationTime));
|
||||||
var iFormat = "%" + size + ".0f";
|
var iFormat = "%" + size + ".0f";
|
||||||
var fFormat = "%" + (size + 4) + ".3f";
|
var fFormat = "%" + (size + 4) + ".3f";
|
||||||
var builder = new StringBuilder();
|
|
||||||
|
|
||||||
for (var entry : this.nodes.entrySet()) {
|
String[] h = { "Node", "Departures", "Avg Queue", "Avg Response", "Throughput", "Utilization %", "Last Event" };
|
||||||
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" };
|
|
||||||
var table = new ConsoleTable(h);
|
var table = new ConsoleTable(h);
|
||||||
|
|
||||||
for (var entry : this.nodes.entrySet()) {
|
for (var entry : this.nodes.entrySet()) {
|
||||||
var stats = entry.getValue();
|
var stats = entry.getValue();
|
||||||
table.addRow(
|
table.addRow(
|
||||||
entry.getKey(),
|
entry.getKey(),
|
||||||
String.format(iFormat, stats.numArrivals),
|
|
||||||
String.format(iFormat, stats.numDepartures),
|
String.format(iFormat, stats.numDepartures),
|
||||||
String.format(iFormat, stats.maxQueueLength),
|
String.format(fFormat, stats.avgQueueLength),
|
||||||
String.format(fFormat, stats.averageQueueLength),
|
String.format(fFormat, stats.avgResponse),
|
||||||
String.format(fFormat, stats.responseTime / stats.numDepartures),
|
String.format(fFormat, stats.troughput),
|
||||||
String.format(fFormat, stats.busyTime * 100 / stats.lastEventTime),
|
String.format(fFormat, stats.utilization * 100),
|
||||||
String.format(fFormat, stats.lastEventTime));
|
String.format(fFormat, stats.lastEventTime));
|
||||||
}
|
}
|
||||||
return table.toString();
|
return table.toString();
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ public class ResultMultiple {
|
|||||||
*/
|
*/
|
||||||
public ResultMultiple(Result... runs) {
|
public ResultMultiple(Result... runs) {
|
||||||
this.runs = runs;
|
this.runs = runs;
|
||||||
this.average = calcAvg(runs);
|
this.average = ResultMultiple.calcAvg(runs);
|
||||||
this.variance = calcVar(this.average, runs);
|
this.variance = ResultMultiple.calcVar(this.average, runs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -37,28 +37,15 @@ public class ResultMultiple {
|
|||||||
avgElapsed += run.timeElapsedNano;
|
avgElapsed += run.timeElapsedNano;
|
||||||
|
|
||||||
for (var entry : run.nodes.entrySet()) {
|
for (var entry : run.nodes.entrySet()) {
|
||||||
var stat = nodes.computeIfAbsent(entry.getKey(), _ -> new Statistics());
|
var stats = nodes.computeIfAbsent(entry.getKey(), _ -> new Statistics());
|
||||||
var other = entry.getValue();
|
stats.merge(entry.getValue(), (val1, val2) -> val1 + val2);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
avgTime /= runs.length;
|
avgTime /= runs.length;
|
||||||
avgElapsed /= runs.length;
|
avgElapsed /= runs.length;
|
||||||
for (var stat : nodes.values()) {
|
for (var stat : nodes.values())
|
||||||
stat.numDepartures /= runs.length;
|
stat.apply(val -> val / runs.length);
|
||||||
stat.numArrivals /= runs.length;
|
|
||||||
stat.busyTime /= runs.length;
|
|
||||||
stat.responseTime /= runs.length;
|
|
||||||
stat.lastEventTime /= runs.length;
|
|
||||||
stat.averageQueueLength /= runs.length;
|
|
||||||
}
|
|
||||||
return new Result(runs[0].seed, avgTime, avgElapsed, nodes);
|
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 stat = nodes.computeIfAbsent(entry.getKey(), _ -> new Statistics());
|
||||||
var average = avg.nodes.get(entry.getKey());
|
var average = avg.nodes.get(entry.getKey());
|
||||||
var other = entry.getValue();
|
var other = entry.getValue();
|
||||||
stat.numDepartures += Math.pow(other.numDepartures - average.numDepartures, 2);
|
var temp = new Statistics();
|
||||||
stat.numArrivals += Math.pow(other.numArrivals - average.numArrivals, 2);
|
Statistics.apply(temp, other, average, (o, a) -> Math.pow(o - a, 2));
|
||||||
stat.busyTime += Math.pow(other.busyTime - average.busyTime, 2);
|
stat.merge(temp, (var1, var2) -> var1 + var2);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
varTime /= runs.length - 1;
|
varTime /= runs.length - 1;
|
||||||
varElapsed /= runs.length - 1;
|
varElapsed /= runs.length - 1;
|
||||||
for (var stat : nodes.values()) {
|
for (var stat : nodes.values())
|
||||||
stat.numDepartures /= runs.length - 1;
|
stat.apply(val -> val / (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;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Result(runs[0].seed, varTime, varElapsed, nodes);
|
return new Result(runs[0].seed, varTime, varElapsed, nodes);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,49 +7,105 @@ import java.util.function.Function;
|
|||||||
* TODO
|
* TODO
|
||||||
*/
|
*/
|
||||||
public class Statistics {
|
public class Statistics {
|
||||||
public double numArrivals = 0;
|
public double numArrivals = 0.0d;
|
||||||
public double numDepartures = 0;
|
public double numDepartures = 0.0d;
|
||||||
public double maxQueueLength = 0;
|
public double maxQueueLength = 0.0d;
|
||||||
public double averageQueueLength = 0.0d;
|
public double avgQueueLength = 0.0d;
|
||||||
public double busyTime = 0.0d;
|
public double busyTime = 0.0d;
|
||||||
public double responseTime = 0.0d;
|
public double responseTime = 0.0d;
|
||||||
public double lastEventTime = 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() {
|
public void reset() {
|
||||||
this.applyToAll(_ -> 0.0d);
|
this.apply(_ -> 0.0d);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply a function to ALL the stats in this class.
|
* 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.
|
* The input of the function is the current value of the stat.
|
||||||
*
|
*
|
||||||
* @param func a function to apply
|
* @param func a function to apply
|
||||||
*/
|
*/
|
||||||
public void applyToAll(Function<Double, Double> func) {
|
public void apply(Function<Double, Double> func) {
|
||||||
this.numArrivals = func.apply(this.numArrivals);
|
Statistics.apply(this, this, this, (val1, _) -> func.apply(val1));
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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 other
|
||||||
* @param func
|
* @param func
|
||||||
*/
|
*/
|
||||||
public void mergeWith(Statistics other, BiFunction<Double, Double, Double> func) {
|
public void merge(Statistics other, BiFunction<Double, Double, Double> func) {
|
||||||
this.numArrivals = func.apply(other.numArrivals, this.numArrivals);
|
Statistics.apply(this, this, other, func);
|
||||||
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);
|
* TODO
|
||||||
this.responseTime = func.apply(other.responseTime, this.responseTime);
|
*
|
||||||
this.lastEventTime = func.apply(other.lastEventTime, this.lastEventTime);
|
* @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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user