Refactoring
- better connection between name of class and logic - fixed bugs
This commit is contained in:
@@ -7,10 +7,10 @@ public interface EndCriteria {
|
|||||||
/**
|
/**
|
||||||
* Determines if the simulation should end based on the statistics of the nodes.
|
* Determines if the simulation should end based on the statistics of the nodes.
|
||||||
*
|
*
|
||||||
* @param stats The statistics of the nodes in the network.
|
* @param run The current run of the network.
|
||||||
* @return True if the simulation should end, false otherwise.
|
* @return True if the simulation should end, false otherwise.
|
||||||
*/
|
*/
|
||||||
public boolean shouldEnd(NetStatistics.SingleRun stats);
|
public boolean shouldEnd(NetSimulation.SimulationRun run);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ends the simulation when the given node has reached the specified number of
|
* Ends the simulation when the given node has reached the specified number of
|
||||||
@@ -33,8 +33,8 @@ public interface EndCriteria {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean shouldEnd(NetStatistics.SingleRun stats) {
|
public boolean shouldEnd(NetSimulation.SimulationRun run) {
|
||||||
return stats.nodes.get(nodeName).numArrivals >= this.maxArrivals;
|
return run.getNode(nodeName).stats.numArrivals >= this.maxArrivals;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,8 +59,8 @@ public interface EndCriteria {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean shouldEnd(NetStatistics.SingleRun stats) {
|
public boolean shouldEnd(NetSimulation.SimulationRun run) {
|
||||||
return stats.nodes.get(nodeName).numDepartures >= this.maxDepartures;
|
return run.getNode(nodeName).stats.numDepartures >= this.maxDepartures;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,8 +82,8 @@ public interface EndCriteria {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean shouldEnd(NetStatistics.SingleRun stats) {
|
public boolean shouldEnd(NetSimulation.SimulationRun run) {
|
||||||
return stats.simulationTime >= this.maxTime;
|
return run.getTime() >= this.maxTime;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,13 +1,16 @@
|
|||||||
package net.berack.upo.valpre;
|
package net.berack.upo.valpre;
|
||||||
|
|
||||||
|
import java.util.ArrayDeque;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.PriorityQueue;
|
import java.util.PriorityQueue;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
|
import net.berack.upo.valpre.NetStatistics.RunResult;
|
||||||
import net.berack.upo.valpre.NetStatistics.SingleRun;
|
import net.berack.upo.valpre.NetStatistics.Statistics;
|
||||||
import net.berack.upo.valpre.rand.Rng;
|
import net.berack.upo.valpre.rand.Rng;
|
||||||
import net.berack.upo.valpre.rand.Rngs;
|
import net.berack.upo.valpre.rand.Rngs;
|
||||||
|
|
||||||
@@ -27,19 +30,6 @@ public class NetSimulation {
|
|||||||
this.servers.add(node);
|
this.servers.add(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs the simulation with the given seed until a given criteria is met.
|
|
||||||
*
|
|
||||||
* @param seed The seed to use for the random number generator.
|
|
||||||
* @param criterias The criteria to determine when to end the simulation. If
|
|
||||||
* null then the simulation will run until there are no more
|
|
||||||
* events.
|
|
||||||
* @return The statistics the network.
|
|
||||||
*/
|
|
||||||
public NetStatistics.SingleRun run(long seed, EndCriteria... criterias) {
|
|
||||||
return this.run(new Rng(seed), criterias);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Run the simualtion multiple times with the given seed and number of runs.
|
* Run the simualtion multiple times with the given seed and number of runs.
|
||||||
* The runs are calculated one after the other. For a parallel run see
|
* The runs are calculated one after the other. For a parallel run see
|
||||||
@@ -54,7 +44,7 @@ public class NetSimulation {
|
|||||||
*/
|
*/
|
||||||
public NetStatistics run(long seed, int runs, EndCriteria... criterias) {
|
public NetStatistics run(long seed, int runs, EndCriteria... criterias) {
|
||||||
var rng = new Rng(seed);
|
var rng = new Rng(seed);
|
||||||
var stats = new SingleRun[runs];
|
var stats = new RunResult[runs];
|
||||||
|
|
||||||
for (int i = 0; i < runs; i++) {
|
for (int i = 0; i < runs; i++) {
|
||||||
stats[i] = this.run(rng, criterias);
|
stats[i] = this.run(rng, criterias);
|
||||||
@@ -65,10 +55,11 @@ public class NetSimulation {
|
|||||||
/**
|
/**
|
||||||
* Runs the simulation multiple times with the given seed and number of runs.
|
* Runs the simulation multiple times with the given seed and number of runs.
|
||||||
* The runs are calculated in parallel using the given number of threads.
|
* The runs are calculated in parallel using the given number of threads.
|
||||||
|
* The maximum number of threads are determined by the available processors
|
||||||
|
* and the number of runs.
|
||||||
*
|
*
|
||||||
* @param seed The seed to use for the random number generator.
|
* @param seed The seed to use for the random number generator.
|
||||||
* @param runs The number of runs to perform.
|
* @param runs The number of runs to perform.
|
||||||
* @param numThreads The number of threads to use for the simulation.
|
|
||||||
* @param criterias The criteria to determine when to end the simulation. If
|
* @param criterias The criteria to determine when to end the simulation. If
|
||||||
* null then the simulation will run until there are no more
|
* null then the simulation will run until there are no more
|
||||||
* events.
|
* events.
|
||||||
@@ -79,16 +70,15 @@ public class NetSimulation {
|
|||||||
public NetStatistics runParallel(long seed, int runs, EndCriteria... criterias)
|
public NetStatistics runParallel(long seed, int runs, EndCriteria... criterias)
|
||||||
throws InterruptedException, ExecutionException {
|
throws InterruptedException, ExecutionException {
|
||||||
var rngs = new Rngs(seed);
|
var rngs = new Rngs(seed);
|
||||||
var stats = new NetStatistics.SingleRun[runs];
|
var results = new NetStatistics.RunResult[runs];
|
||||||
var futures = new Future[runs];
|
var futures = new Future[runs];
|
||||||
|
|
||||||
var numThreads = Math.min(runs, Runtime.getRuntime().availableProcessors());
|
var numThreads = Math.min(runs, Runtime.getRuntime().availableProcessors());
|
||||||
var threads = Executors.newFixedThreadPool(numThreads);
|
try (var threads = Executors.newFixedThreadPool(numThreads)) {
|
||||||
|
|
||||||
for (int i = 0; i < runs; i++) {
|
for (int i = 0; i < runs; i++) {
|
||||||
final var id = i;
|
final var id = i;
|
||||||
futures[i] = threads.submit(() -> {
|
futures[i] = threads.submit(() -> {
|
||||||
stats[id] = this.run(rngs.getRng(id), criterias);
|
results[id] = this.run(rngs.getRng(id), criterias);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,8 +86,8 @@ public class NetSimulation {
|
|||||||
futures[i].get();
|
futures[i].get();
|
||||||
}
|
}
|
||||||
|
|
||||||
threads.shutdownNow();
|
return new NetStatistics(results);
|
||||||
return new NetStatistics(stats);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -109,22 +99,24 @@ public class NetSimulation {
|
|||||||
* events.
|
* events.
|
||||||
* @return The statistics the network.
|
* @return The statistics the network.
|
||||||
*/
|
*/
|
||||||
public NetStatistics.SingleRun run(Rng rng, EndCriteria... criterias) {
|
public NetStatistics.RunResult run(Rng rng, EndCriteria... criterias) {
|
||||||
var run = new SimpleRun(this.servers, rng, criterias);
|
var run = new SimulationRun(this.servers, rng, criterias);
|
||||||
while (!run.hasEnded()) {
|
while (!run.hasEnded())
|
||||||
run.processNextEvent();
|
run.processNextEvent();
|
||||||
}
|
|
||||||
return run.endSimulation();
|
return run.endSimulation();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process an entire run of the simulation.
|
* Process an entire run of the simulation.
|
||||||
*/
|
*/
|
||||||
public static class SimpleRun {
|
public static class SimulationRun {
|
||||||
|
private final Map<String, NodeBehavior> nodes;
|
||||||
private final NetStatistics.SingleRun stats;
|
|
||||||
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 seed;
|
||||||
|
private final Rng rng;
|
||||||
|
private double time;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
@@ -132,14 +124,20 @@ public class NetSimulation {
|
|||||||
*
|
*
|
||||||
* @param nodes The nodes in the network.
|
* @param nodes 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.
|
||||||
*/
|
*/
|
||||||
private SimpleRun(Collection<ServerNode> nodes, Rng rng, EndCriteria... criterias) {
|
private SimulationRun(Collection<ServerNode> nodes, Rng rng, EndCriteria... criterias) {
|
||||||
|
this.nodes = new HashMap<>();
|
||||||
this.fel = new PriorityQueue<>();
|
this.fel = new PriorityQueue<>();
|
||||||
this.stats = new NetStatistics.SingleRun(nodes, rng);
|
|
||||||
this.criterias = criterias;
|
this.criterias = criterias;
|
||||||
|
this.timeStartedNano = System.nanoTime();
|
||||||
|
this.seed = rng.getSeed();
|
||||||
|
this.rng = rng;
|
||||||
|
this.time = 0.0d;
|
||||||
|
|
||||||
// Initial arrivals (if spawned)
|
// Initial arrivals (if spawned)
|
||||||
for (var node : nodes) {
|
for (var node : nodes) {
|
||||||
|
this.nodes.put(node.name, new NodeBehavior());
|
||||||
if (node.shouldSpawnArrival(0))
|
if (node.shouldSpawnArrival(0))
|
||||||
this.addEvent(node, Event.Type.ARRIVAL);
|
this.addEvent(node, Event.Type.ARRIVAL);
|
||||||
}
|
}
|
||||||
@@ -154,11 +152,27 @@ public class NetSimulation {
|
|||||||
*/
|
*/
|
||||||
public void processNextEvent() {
|
public void processNextEvent() {
|
||||||
var event = fel.poll();
|
var event = fel.poll();
|
||||||
stats.simulationTime = event.time;
|
var node = this.nodes.get(event.node.name);
|
||||||
|
this.time = event.time;
|
||||||
|
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
case ARRIVAL -> this.processArrival(event);
|
case ARRIVAL -> {
|
||||||
case DEPARTURE -> this.processDeparture(event);
|
if (node.updateArrival(event.time, event.node.maxServers))
|
||||||
|
this.addEvent(event.node, Event.Type.DEPARTURE);
|
||||||
|
|
||||||
|
if (event.node.shouldSpawnArrival(node.stats.numArrivals)) {
|
||||||
|
this.addEvent(event.node, Event.Type.ARRIVAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case DEPARTURE -> {
|
||||||
|
if (node.updateDeparture(event.time))
|
||||||
|
this.addEvent(event.node, Event.Type.DEPARTURE);
|
||||||
|
|
||||||
|
if (!event.node.shouldSinkDeparture(node.stats.numDepartures)) {
|
||||||
|
var next = event.node.getChild(this.rng);
|
||||||
|
this.addEvent(next, Event.Type.ARRIVAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,72 +181,32 @@ public class NetSimulation {
|
|||||||
*
|
*
|
||||||
* @return The statistics of the network.
|
* @return The statistics of the network.
|
||||||
*/
|
*/
|
||||||
public NetStatistics.SingleRun endSimulation() {
|
private NetStatistics.RunResult endSimulation() {
|
||||||
this.stats.endSimulation();
|
var elapsed = System.nanoTime() - this.timeStartedNano;
|
||||||
return this.stats;
|
var nodes = new HashMap<String, Statistics>();
|
||||||
|
for (var entry : this.nodes.entrySet())
|
||||||
|
nodes.put(entry.getKey(), entry.getValue().stats);
|
||||||
|
|
||||||
|
return new RunResult(this.seed, this.time, elapsed, nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Processes an arrival event for the given node at the given time.
|
* Get the current time.
|
||||||
* The event is processed by adding the arrival time to the queue, updating the
|
|
||||||
* maximum queue length, and checking if a server is available to process the
|
|
||||||
* arrival. If a server is available, a departure event is created and added to
|
|
||||||
* the future event list.
|
|
||||||
*
|
*
|
||||||
* @param stats The statistics of the network.
|
* @return a double representing the current time of the simulation.
|
||||||
* @param event The arrival event to process.
|
|
||||||
* @param fel The future event list to add new events to.
|
|
||||||
*/
|
*/
|
||||||
private void processArrival(Event event) {
|
public double getTime() {
|
||||||
var nodeStats = stats.nodes.get(event.node.name);
|
return this.time;
|
||||||
|
|
||||||
nodeStats.numArrivals++;
|
|
||||||
nodeStats.enqueue(event.time);
|
|
||||||
if (event.node.maxServers > nodeStats.numServerBusy) {
|
|
||||||
nodeStats.numServerBusy++;
|
|
||||||
this.addEvent(event.node, Event.Type.DEPARTURE);
|
|
||||||
} else {
|
|
||||||
nodeStats.busyTime += stats.simulationTime - nodeStats.lastEventTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
nodeStats.lastEventTime = stats.simulationTime;
|
|
||||||
if (event.node.shouldSpawnArrival(nodeStats.numArrivals)) {
|
|
||||||
this.addEvent(event.node, Event.Type.ARRIVAL);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Processes a departure event for the given node at the given time.
|
* Get the node requested by the name passed as a string.
|
||||||
* The event is processed by removing the departure time from the queue,
|
|
||||||
* updating the busy time, and checking if there are any arrivals in the queue.
|
|
||||||
* If there are, a new departure event is created and added to the fel.
|
|
||||||
* At the end it will add an arrival to the next node if the current node has a
|
|
||||||
* child.
|
|
||||||
*
|
*
|
||||||
* @param stats The statistics of the network.
|
* @param node the name of the node
|
||||||
* @param event The departure event to process.
|
* @return the node
|
||||||
* @param fel The future event list to add new events to.
|
|
||||||
*/
|
*/
|
||||||
private void processDeparture(Event event) {
|
public NodeBehavior getNode(String node) {
|
||||||
var nodeStats = stats.nodes.get(event.node.name);
|
return this.getNode(node);
|
||||||
var startService = nodeStats.dequeue();
|
|
||||||
var response = stats.simulationTime - startService;
|
|
||||||
|
|
||||||
if (nodeStats.getQueueSize() < nodeStats.numServerBusy) {
|
|
||||||
nodeStats.numServerBusy--;
|
|
||||||
} else {
|
|
||||||
this.addEvent(event.node, Event.Type.DEPARTURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
nodeStats.numDepartures++;
|
|
||||||
nodeStats.responseTime += response;
|
|
||||||
nodeStats.busyTime += stats.simulationTime - nodeStats.lastEventTime;
|
|
||||||
nodeStats.lastEventTime = stats.simulationTime;
|
|
||||||
|
|
||||||
if (!event.node.shouldSinkDeparture(nodeStats.numDepartures)) {
|
|
||||||
var next = event.node.getChild(stats.rng);
|
|
||||||
this.addEvent(next, Event.Type.ARRIVAL);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -245,8 +219,8 @@ public class NetSimulation {
|
|||||||
*/
|
*/
|
||||||
public void addEvent(ServerNode node, Event.Type type) {
|
public void addEvent(ServerNode node, Event.Type type) {
|
||||||
if (node != null) {
|
if (node != null) {
|
||||||
var delay = node.getPositiveSample(stats.rng);
|
var delay = node.getPositiveSample(this.rng);
|
||||||
var event = Event.newType(node, stats.simulationTime + delay, type);
|
var event = Event.newType(node, this.time + delay, type);
|
||||||
fel.add(event);
|
fel.add(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -261,11 +235,68 @@ public class NetSimulation {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
for (var c : this.criterias) {
|
for (var c : this.criterias) {
|
||||||
if (c.shouldEnd(stats)) {
|
if (c.shouldEnd(this)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a summary of the behavior of a server node in the network.
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
public static class NodeBehavior {
|
||||||
|
public int numServerBusy = 0;
|
||||||
|
public final Statistics stats = new Statistics();
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,21 @@
|
|||||||
package net.berack.upo.valpre;
|
package net.berack.upo.valpre;
|
||||||
|
|
||||||
import java.util.ArrayDeque;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import net.berack.upo.valpre.rand.Rng;
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
public class NetStatistics {
|
public class NetStatistics {
|
||||||
public final SingleRun[] runs;
|
public final RunResult[] runs;
|
||||||
|
// public final Run average;
|
||||||
|
// public final Run variance;
|
||||||
|
|
||||||
public NetStatistics(SingleRun... runs) {
|
/**
|
||||||
|
* TODO
|
||||||
|
* @param runs
|
||||||
|
*/
|
||||||
|
public NetStatistics(RunResult... runs) {
|
||||||
this.runs = runs;
|
this.runs = runs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -20,12 +25,11 @@ public class NetStatistics {
|
|||||||
* nodes, including the number of arrivals and departures, the maximum queue
|
* nodes, including the number of arrivals and departures, the maximum queue
|
||||||
* length, the busy time, and the response time.
|
* length, the busy time, and the response time.
|
||||||
*/
|
*/
|
||||||
public static class SingleRun {
|
public static class RunResult {
|
||||||
public final Map<String, Node> nodes;
|
public final Map<String, Statistics> nodes;
|
||||||
public final long seed;
|
public final long seed;
|
||||||
public final Rng rng;
|
public final double simulationTime;
|
||||||
public double simulationTime;
|
public final long timeElapsedNano;
|
||||||
public long timeElapsedNano;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new statistics object for the given collection of server nodes and
|
* Creates a new statistics object for the given collection of server nodes and
|
||||||
@@ -34,25 +38,11 @@ public class NetStatistics {
|
|||||||
* @param nodes The collection of server nodes to track.
|
* @param nodes The collection of server nodes to track.
|
||||||
* @param rng The random number generator to use.
|
* @param rng The random number generator to use.
|
||||||
*/
|
*/
|
||||||
public SingleRun(Collection<ServerNode> nodes, Rng rng) {
|
public RunResult(long seed, double time, long elapsed, HashMap<String, Statistics> nodes) {
|
||||||
this.rng = rng;
|
this.seed = seed;
|
||||||
this.seed = rng.getSeed();
|
this.simulationTime = time;
|
||||||
|
this.timeElapsedNano = elapsed;
|
||||||
this.simulationTime = 0.0d;
|
this.nodes = nodes;
|
||||||
this.timeElapsedNano = System.nanoTime();
|
|
||||||
this.nodes = new HashMap<String, Node>();
|
|
||||||
for (var node : nodes) {
|
|
||||||
var s = new Node();
|
|
||||||
this.nodes.put(node.name, s);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ends the simulation and calculates the elapsed time.
|
|
||||||
*/
|
|
||||||
public void endSimulation() {
|
|
||||||
this.timeElapsedNano = System.nanoTime() - this.timeElapsedNano;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -72,7 +62,7 @@ public class NetStatistics {
|
|||||||
for (var entry : this.nodes.entrySet()) {
|
for (var entry : this.nodes.entrySet()) {
|
||||||
var stats = entry.getValue();
|
var stats = entry.getValue();
|
||||||
var entrySize = (int) Math.max(size, (int) Math.ceil((Math.log10(stats.numArrivals))));
|
var entrySize = (int) Math.max(size, (int) Math.ceil((Math.log10(stats.numArrivals))));
|
||||||
var iFormat = "%" + entrySize + "d";
|
var iFormat = "%" + entrySize + ".0f";
|
||||||
var fFormat = "%" + (entrySize + 4) + ".3f";
|
var fFormat = "%" + (entrySize + 4) + ".3f";
|
||||||
|
|
||||||
System.out.println("===== " + entry.getKey() + " =====");
|
System.out.println("===== " + entry.getKey() + " =====");
|
||||||
@@ -87,23 +77,17 @@ public class NetStatistics {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a statistical summary of the behavior of a server node in the
|
* TODO
|
||||||
* network.
|
|
||||||
* 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.
|
|
||||||
*/
|
*/
|
||||||
public static class Node {
|
public static class Statistics {
|
||||||
public int numArrivals = 0;
|
public double numArrivals = 0;
|
||||||
public int numDepartures = 0;
|
public double numDepartures = 0;
|
||||||
public int maxQueueLength = 0;
|
public double maxQueueLength = 0;
|
||||||
public double averageQueueLength = 0.0d;
|
public double averageQueueLength = 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;
|
||||||
|
|
||||||
public int numServerBusy = 0;
|
|
||||||
private ArrayDeque<Double> queue = new ArrayDeque<>();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resets the statistics to their initial values.
|
* Resets the statistics to their initial values.
|
||||||
*/
|
*/
|
||||||
@@ -111,29 +95,10 @@ public class NetStatistics {
|
|||||||
this.numArrivals = 0;
|
this.numArrivals = 0;
|
||||||
this.numDepartures = 0;
|
this.numDepartures = 0;
|
||||||
this.maxQueueLength = 0;
|
this.maxQueueLength = 0;
|
||||||
this.averageQueueLength = 0.0;
|
this.averageQueueLength = 0.0d;
|
||||||
this.busyTime = 0.0;
|
this.busyTime = 0.0d;
|
||||||
this.responseTime = 0.0;
|
this.responseTime = 0.0d;
|
||||||
this.lastEventTime = 0.0;
|
this.lastEventTime = 0.0d;
|
||||||
this.numServerBusy = 0;
|
|
||||||
this.queue.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public double dequeue() {
|
|
||||||
return this.queue.poll();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void enqueue(double time) {
|
|
||||||
var total = this.averageQueueLength * (this.numArrivals - 1);
|
|
||||||
|
|
||||||
this.queue.add(time);
|
|
||||||
this.averageQueueLength = (total + this.queue.size()) / this.numArrivals;
|
|
||||||
this.maxQueueLength = Math.max(this.maxQueueLength, this.queue.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getQueueSize() {
|
|
||||||
return this.queue.size();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -125,7 +125,7 @@ public class ServerNode {
|
|||||||
* @param numArrivals The number of arrivals to check against.
|
* @param numArrivals The number of arrivals to check against.
|
||||||
* @return True if the node should spawn an arrival, false otherwise.
|
* @return True if the node should spawn an arrival, false otherwise.
|
||||||
*/
|
*/
|
||||||
public boolean shouldSpawnArrival(int numArrivals) {
|
public boolean shouldSpawnArrival(double numArrivals) {
|
||||||
return this.spawnArrivals > numArrivals;
|
return this.spawnArrivals > numArrivals;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,7 +136,7 @@ public class ServerNode {
|
|||||||
* @param numDepartures The number of departures to check against.
|
* @param numDepartures The number of departures to check against.
|
||||||
* @return True if the node should sink a departure, false otherwise.
|
* @return True if the node should sink a departure, false otherwise.
|
||||||
*/
|
*/
|
||||||
public boolean shouldSinkDeparture(int numDepartures) {
|
public boolean shouldSinkDeparture(double numDepartures) {
|
||||||
return this.sinkDepartures > numDepartures;
|
return this.sinkDepartures > numDepartures;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user