From d5768cdbad4e6295192e58441d6f656f22592683 Mon Sep 17 00:00:00 2001
From: Manoel Campos
Date: Wed, 9 Nov 2016 16:52:18 +0000
Subject: [PATCH] - Finished the first version of the
CloudletSchedulerCompletelyFair, the most used scheduler in recent versions
of Linux Kernel. - Included new testbeds in the cloudsim-plus-testbeds module
to compare the new scheduler with the CloudletSchedulerTimeShared - Included
the LinuxCompletelyFairSchedulerExample example for the new scheduler in the
cloudsim-plus-examples module
---
.../LinuxCompletelyFairSchedulerExample.java | 79 ++----
.../testbeds/ExperimentRunner.java | 78 ++++--
.../testbeds/SimulationExperiment.java | 253 ++++++++----------
.../DynamicCloudletsArrivalExperiment.java | 28 +-
.../DynamicCloudletsArrivalRunner.java | 9 +-
.../DatacenterBrokerHeuristicExperiment.java | 161 ++++++++++-
.../DatacenterBrokerHeuristicRunner.java | 64 +++--
.../CloudletSchedulerExperiment.java | 174 ++++++++++++
.../CloudletSchedulerRunner.java | 112 ++++++++
...CloudletSchedulerTimeSharedExperiment.java | 44 +++
.../CloudletSchedulerTimeSharedRunner.java | 33 +++
.../CompletelyFairSchedulerExperiment.java | 48 ++++
.../CompletelyFairSchedulerRunner.java | 38 +++
.../testbeds/linuxscheduler/package-info.java | 15 ++
.../java/org/cloudbus/cloudsim/Cloudlet.java | 9 +-
.../cloudsim/CloudletExecutionInfo.java | 4 +-
.../brokers/DatacenterBrokerHeuristic.java | 4 +-
.../cloudsim/distributions/UniformDistr.java | 2 +-
.../schedulers/CloudletScheduler.java | 21 +-
.../schedulers/CloudletSchedulerAbstract.java | 51 ++--
.../CloudletSchedulerCompletelyFair.java | 250 ++++++++---------
.../CloudletSchedulerSpaceShared.java | 14 +-
.../CloudletSchedulerTimeShared.java | 62 ++---
.../CloudletsTableBuilderHelper.java | 16 +-
.../PriorityCloudletsTableBuilderHelper.java | 28 ++
.../CloudletSchedulerSpaceSharedTest.java | 5 +-
.../CloudletSchedulerTimeSharedTest.java | 8 +-
27 files changed, 1113 insertions(+), 497 deletions(-)
rename cloudsim-plus-testbeds/src/main/java/org/cloudsimplus/testbeds/{ => dynamiccloudlets}/DynamicCloudletsArrivalExperiment.java (71%)
rename cloudsim-plus-testbeds/src/main/java/org/cloudsimplus/testbeds/{ => dynamiccloudlets}/DynamicCloudletsArrivalRunner.java (61%)
create mode 100644 cloudsim-plus-testbeds/src/main/java/org/cloudsimplus/testbeds/linuxscheduler/CloudletSchedulerExperiment.java
create mode 100644 cloudsim-plus-testbeds/src/main/java/org/cloudsimplus/testbeds/linuxscheduler/CloudletSchedulerRunner.java
create mode 100644 cloudsim-plus-testbeds/src/main/java/org/cloudsimplus/testbeds/linuxscheduler/CloudletSchedulerTimeSharedExperiment.java
create mode 100644 cloudsim-plus-testbeds/src/main/java/org/cloudsimplus/testbeds/linuxscheduler/CloudletSchedulerTimeSharedRunner.java
create mode 100644 cloudsim-plus-testbeds/src/main/java/org/cloudsimplus/testbeds/linuxscheduler/CompletelyFairSchedulerExperiment.java
create mode 100644 cloudsim-plus-testbeds/src/main/java/org/cloudsimplus/testbeds/linuxscheduler/CompletelyFairSchedulerRunner.java
create mode 100644 cloudsim-plus-testbeds/src/main/java/org/cloudsimplus/testbeds/linuxscheduler/package-info.java
create mode 100644 cloudsim-plus/src/main/java/org/cloudsimplus/util/tablebuilder/PriorityCloudletsTableBuilderHelper.java
diff --git a/cloudsim-plus-examples/src/main/java/org/cloudsimplus/examples/LinuxCompletelyFairSchedulerExample.java b/cloudsim-plus-examples/src/main/java/org/cloudsimplus/examples/LinuxCompletelyFairSchedulerExample.java
index c72e7f71e..77660a5d2 100644
--- a/cloudsim-plus-examples/src/main/java/org/cloudsimplus/examples/LinuxCompletelyFairSchedulerExample.java
+++ b/cloudsim-plus-examples/src/main/java/org/cloudsimplus/examples/LinuxCompletelyFairSchedulerExample.java
@@ -1,6 +1,5 @@
package org.cloudsimplus.examples;
-import org.cloudsimplus.util.tablebuilder.CloudletsTableBuilderHelper;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.LinkedList;
@@ -32,14 +31,15 @@
import org.cloudbus.cloudsim.provisioners.ResourceProvisionerSimple;
import org.cloudbus.cloudsim.resources.Ram;
import org.cloudbus.cloudsim.schedulers.CloudletSchedulerCompletelyFair;
+import org.cloudsimplus.util.tablebuilder.PriorityCloudletsTableBuilderHelper;
/**
* An example that uses an implementation of the {@link CloudletSchedulerCompletelyFair Completely Fair Scheduler}
* used in the Linux Kernel for scheduling of Cloudlets execution inside a Vm.
- *
+ *
* @author Manoel Campos da Silva Filho
* @see Completely Fair Scheduler (CFS)
- *
+ *
*/
public class LinuxCompletelyFairSchedulerExample {
private static final int HOSTS_NUMBER = 1;
@@ -51,21 +51,21 @@ public class LinuxCompletelyFairSchedulerExample {
private static final int CLOUDLETS_NUMBER = HOST_PES*2;
private static final int CLOUDLET_PES = 1;
private static final int CLOUDLET_LEN = 10000; //in MI
-
+
/**
* Virtual Machine Monitor name.
*/
- private static final String VMM = "Xen";
+ private static final String VMM = "Xen";
private List cloudletList;
private List vmList;
-
+
private int numberOfCreatedCloudlets = 0;
private int numberOfCreatedVms = 0;
private int numberOfCreatedHosts = 0;
/**
* Starts the simulation.
- * @param args
+ * @param args
*/
public static void main(String[] args) {
new LinuxCompletelyFairSchedulerExample();
@@ -78,9 +78,9 @@ public LinuxCompletelyFairSchedulerExample() {
Log.printFormattedLine("Starting %s...", getClass().getSimpleName());
try {
//Number of cloud customers
- int numberOfCloudUsers = 1;
+ int numberOfCloudUsers = 1;
boolean traceEvents = false;
-
+
CloudSim.init(numberOfCloudUsers, Calendar.getInstance(), traceEvents);
Datacenter datacenter0 = createDatacenter("Datacenter0");
@@ -90,12 +90,12 @@ public LinuxCompletelyFairSchedulerExample() {
createAndSubmitVms(broker0);
createAndSubmitCloudlets(broker0);
for(int i = 0; i < CLOUDLETS_NUMBER/2; i++){
- cloudletList.get(i).setPriority(10);
+ cloudletList.get(i).setPriority(4);
}
CloudSim.startSimulation();
CloudSim.stopSimulation();
-
+
List finishedCloudlets = broker0.getCloudletsFinishedList();
new PriorityCloudletsTableBuilderHelper(finishedCloudlets).build();
Log.printFormattedLine("%s finished!", getClass().getSimpleName());
@@ -117,13 +117,13 @@ private void createAndSubmitVms(DatacenterBroker broker0) {
for(int i = 0; i < VMS_NUMBER; i++){
this.vmList.add(createVm(broker0));
}
- broker0.submitVmList(vmList);
+ broker0.submitVmList(vmList);
}
private DatacenterSimple createDatacenter(String name) {
List hostList = new ArrayList<>(HOSTS_NUMBER);
for(int i = 0; i < HOSTS_NUMBER; i++){
- hostList.add(createHost());
+ hostList.add(createHost());
}
//Defines the characteristics of the data center
@@ -140,17 +140,17 @@ private DatacenterSimple createDatacenter(String name) {
arch, os, VMM, hostList, time_zone, cost, costPerMem,
costPerStorage, costPerBw);
- return new DatacenterSimple(name, characteristics,
+ return new DatacenterSimple(name, characteristics,
new VmAllocationPolicySimple(hostList), storageList, 0);
- }
+ }
private Host createHost() {
final int ram = 2048; // host memory (MB)
final long storage = 1000000; // host storage
final long bw = 10000;
-
+
List cpuCoresList = createHostPesList(HOST_MIPS);
-
+
return new HostSimple(numberOfCreatedHosts++,
new ResourceProvisionerSimple<>(new Ram(ram)),
new ResourceProvisionerSimple<>(new Bandwidth(bw)),
@@ -163,59 +163,36 @@ private List createHostPesList(double mips) {
for(int i = 0; i < HOST_PES; i++){
cpuCoresList.add(new PeSimple(i, new PeProvisionerSimple(mips)));
}
-
+
return cpuCoresList;
}
private Vm createVm(DatacenterBroker broker) {
final long storage = 10000; // vm image size (MB)
final int ram = 512; // vm memory (MB)
- final long bw = 1000; // vm bandwidth
-
- return new VmSimple(numberOfCreatedVms++,
- broker.getId(), VM_MIPS, VM_PES, ram, bw, storage,
- VMM, new CloudletSchedulerCompletelyFair());
+ final long bw = 1000; // vm bandwidth
+
+ return new VmSimple(numberOfCreatedVms++,
+ broker.getId(), VM_MIPS, VM_PES, ram, bw, storage, VMM,
+ new CloudletSchedulerCompletelyFair());
}
private Cloudlet createCloudlet(DatacenterBroker broker) {
final long fileSize = 300; //Size (in bytes) before execution
final long outputSize = 300; //Size (in bytes) after execution
-
+
//Defines how CPU, RAM and Bandwidth resources are used
//Sets the same utilization model for all these resources.
UtilizationModel utilization = new UtilizationModelFull();
-
+
Cloudlet cloudlet
= new CloudletSimple(
- numberOfCreatedCloudlets++, CLOUDLET_LEN, CLOUDLET_PES,
- fileSize, outputSize,
+ numberOfCreatedCloudlets++, CLOUDLET_LEN, CLOUDLET_PES,
+ fileSize, outputSize,
utilization, utilization, utilization);
cloudlet.setUserId(broker.getId());
-
+
return cloudlet;
}
}
-/**
- * A helper class to print cloudlets results as a table that includes
- * the Cloudlet priority as a table field.
- *
- * @author Manoel Campos da Silva Filho
- */
-class PriorityCloudletsTableBuilderHelper extends CloudletsTableBuilderHelper {
- public PriorityCloudletsTableBuilderHelper(List extends Cloudlet> list) {
- super(list);
- }
-
- @Override
- protected void createTableColumns() {
- super.createTableColumns();
- getPrinter().addColumn("Priority");
- }
-
- @Override
- protected void addDataToRow(Cloudlet cloudlet, List
+ * (application execution is simulated just computing the amount of instructions
+ * that can be run), it doesn't matter which PEs are "running" the application.
+ *
*
+ *
It doesn't use a Red-Black tree (such as the TreeSet), as in real implementations of CFS, to accendingly sort
+ * Cloudlets in the waiting list (runqueue) based on their virtual runtime
+ * (placing the Cloudlets that have run the least at the top of the tree) because
+ * the use of such a data structure added some complexity to the implementation. And once different Cloudlets
+ * may have the same virtual runtime, this introduced some issues when adding or
+ * removing elements in a structure such as the TreeSet, that requires
+ * each value (the virtual runtime in this case) used to sort the Set to be unique.
*
*
* The implementation was based on the book of Robert Love: Linux Kernel Development, 3rd ed. Addison-Wesley, 2010
* and some other references listed below.
*
- *
- *
- * O scheduler é baseado no time-shared mas deve funcionar de maneira diferente.
- *
- *
- *
- * A getCloudletExecutionList deve representar
- * apenas as cloudlets que estão executando de fato no momento atual.
- * A diferença é que no construtor, tal lista deve ser instanciada como um
- * {@link Set} para manter a ordem dos elementos de acordo com o vruntime.
- *
- *
- *
- *
- * Adicionar vruntime ao CloudletExecutionInfo para permitir
- * ordenar a execution list por ele. Isso vai facilitar remover uma cloudlet
- * desta lista, considerando aquela que tiver o maior vruntime (que já rodou mais
- * que as outras).
- *
- *
- *
- *
A lista pode ser ordenada de forma descrescente para
- * permitir usar stream pra pegar o primeiro elemento.
- *
- *
A waiting list é que será de fato a runqueue, contendo
- * a lista de cloudlets que devem rodar em seguida (conforme definição da wikipedia).
- *
- *
Ela, diferente do CloudletSchedulerTimeShared,
- * deve sim ter cloudlets. O CFS deve de fato implementar a preempção,
- * removendo processos na execution list para dar a vez
- * (mesmo que tais processos não tenhma terminado) para outros processos
- * na runqueue (waiting list).
- *
- *
A waiting list sim é que deve ser implementada como uma Red-Black tree.
- *
- *
- *
*
* @author Manoel Campos da Silva Filho
+ * @since CloudSim Plus 1.0
*
* @see Inside the Linux 2.6 Completely Fair Scheduler
* @see Learn Linux, 101: Process execution priorities
* @see Towards achieving fairness in the Linux scheduler
* @see The Linux scheduler
- * @see kernel.org: CFS Design
+ * @see kernel.org: CFS Scheduler Design
+ * @see Linux Scheduler FAQ
*/
public final class CloudletSchedulerCompletelyFair extends CloudletSchedulerTimeShared {
/**
@@ -120,14 +98,12 @@ public final class CloudletSchedulerCompletelyFair extends CloudletSchedulerTime
public CloudletSchedulerCompletelyFair(){
super();
- setCloudletExecList(new TreeSet<>(this::executingCloudletsComparator));
- setCloudletWaitingList(new TreeSet<>(this::waitingCloudletsComparator));
}
/**
* A comparator used to ascendingly sort Cloudlets into the waiting list
* based on their virtual runtime. By this way, the Cloudlets in the beginning
- * of this list will be that ones which have run the least and have to be
+ * of such a list will be that ones which have run the least and have to be
* prioritized when getting Cloudlets from this list to add to the execution
* list.
*
@@ -137,16 +113,8 @@ public CloudletSchedulerCompletelyFair(){
* a positive value if c1 is greater than c2
*/
private int waitingCloudletsComparator(CloudletExecutionInfo c1, CloudletExecutionInfo c2){
- if(c1.equals(c2))
- return 0;
-
double diff = c1.getVirtualRuntime() - c2.getVirtualRuntime();
- /*If the difference between the virtual runtime is equal to zero, the comparator considers
- * that the objects are the same and this causes issues when adding or removing
- * elements into a TreeSet that accepts just unique objects.
- * By this way, if the diff is zero, uses the priorities difference.
- * If the diff is yet zero, uses the IDs difference.*/
if(diff == 0)
diff = c1.getCloudlet().getPriority()-c2.getCloudlet().getPriority();
if(diff == 0)
@@ -155,23 +123,6 @@ private int waitingCloudletsComparator(CloudletExecutionInfo c1, CloudletExecuti
return (int)diff;
}
- /**
- * A comparator used to descendingly sort running Cloudlets into the execution list
- * based on their virtual runtime. By this way, the Cloudlets in the beginning
- * of this list will be that ones which have run the most and thus, are the
- * first to be preempted to allow Cloudlets in the waiting list to run.
- *
- * @param c1 first Cloudlet to compare
- * @param c2 second Cloudlet to compare
- * @return a negative value if c2 is lower than c1, zero if they are equals,
- * a positive value if c2 is greater than c1
- */
- private int executingCloudletsComparator(CloudletExecutionInfo c1, CloudletExecutionInfo c2){
- /*Calling the other comparator just inverting the parameters order will change the sorting
- order.*/
- return waitingCloudletsComparator(c2, c1);
- }
-
/**
* Gets the latency, that is the amount of time (in seconds)
* the scheduler will allow the execution of waiting Cloudlets
@@ -197,9 +148,14 @@ public int getLatency() {
/**
* Sets the latency time (in seconds)
* @param latency the latency to set
+ * @throws IllegalArgumentException when latency is lower than minimum granularity
*/
public void setLatency(int latency) {
- this.latency = latency;
+ if(latency < mininumGranularity){
+ throw new IllegalArgumentException("Latency cannot be lower than the mininum granularity.");
+ }
+
+ this.latency = latency;
}
/**
@@ -222,19 +178,36 @@ protected double computeCloudletTimeSlice(CloudletExecutionInfo cloudlet){
return Math.min(timeslice, getMininumGranularity());
}
- /**
- * Gets the nice value from a Cloudlet based on its priority.
- * The nice value is the opposite of the priority.
- *
- *
As "niceness" is a terminology defined by specific schedulers
- * (such as Linux Schedulers), it is not defined inside the Cloudlet.
- *
- * @param cloudlet Cloudlet to get the nice value
- * @return the cloudlet niceness
- */
- protected double getCloudletNiceness(CloudletExecutionInfo cloudlet){
- return -cloudlet.getCloudlet().getPriority();
- }
+ /**
+ * Gets a list of Cloudlets that are waiting to run, the so called
+ * run queue.
+ *
+ *
+ * NOTE: Different from real implementations, this scheduler uses just one run queue
+ * for all processor cores (PEs). Since CPU context switch is not concerned,
+ * there is no point in using different run queues.
+ *
+ *
+ * @return
+ */
+ @Override
+ protected List getCloudletWaitingList() {
+ return super.getCloudletWaitingList();
+ }
+
+ /**
+ * {@inheritDoc}
+ * The cloudlet waiting list (runqueue) is sorted according to the virtual runtime (vruntime),
+ * which indicates the amount of time the Cloudlet has run.
+ * This runtime increases as the Cloudlet executes.
+ *
+ * @return {@inheritDoc}
+ */
+ @Override
+ protected Optional findSuitableWaitingCloudletToStartExecutingAndRemoveIt() {
+ getCloudletWaitingList().sort(this::waitingCloudletsComparator);
+ return super.findSuitableWaitingCloudletToStartExecutingAndRemoveIt();
+ }
/**
* Gets the weight of the Cloudlet to use the CPU, that is
@@ -255,7 +228,22 @@ protected double getCloudletWeight(CloudletExecutionInfo cloudlet){
return 1024.0/(Math.pow(1.25, getCloudletNiceness(cloudlet)));
}
- /**
+ /**
+ * Gets the nice value from a Cloudlet based on its priority.
+ * The nice value is the opposite of the priority.
+ *
+ *
As "niceness" is a terminology defined by specific schedulers
+ * (such as Linux Schedulers), it is not defined inside the Cloudlet.
+ *
+ * @param cloudlet Cloudlet to get the nice value
+ * @return the cloudlet niceness
+ * @see Man Pages: Nice values for Linux processes
+ */
+ protected double getCloudletNiceness(CloudletExecutionInfo cloudlet){
+ return -cloudlet.getCloudlet().getPriority();
+ }
+
+ /**
* Gets the percentage (in scale from [0 to 1]) that the weight of a Cloudlet
* represents compared to the weight sum of all Cloudlets in the execution list.
*
@@ -299,8 +287,12 @@ public int getMininumGranularity() {
* Cloudlet to execute.
*
* @param mininumGranularity the minimum granularity to set
+ * @throws IllegalArgumentException when minimum granularity is greater than latency
*/
public void setMininumGranularity(int mininumGranularity) {
+ if(mininumGranularity > latency){
+ throw new IllegalArgumentException("Mininum granularity cannot be greater than latency.");
+ }
this.mininumGranularity = mininumGranularity;
}
@@ -320,6 +312,9 @@ public void setMininumGranularity(int mininumGranularity) {
public double processCloudletSubmit(CloudletExecutionInfo rcl, double fileTransferTime) {
rcl.setVirtualRuntime(computeCloudletInitialVirtualRuntime(rcl));
rcl.setTimeSlice(computeCloudletTimeSlice(rcl));
+
+ /*
+ //Code just for debug purposes (can be deleted)
if(rcl.getCloudletId() == 5) {
System.out.println("\tCloudlets submitted:");
Stream.concat(getCloudletExecList().stream(), getCloudletWaitingList().stream())
@@ -327,6 +322,9 @@ public double processCloudletSubmit(CloudletExecutionInfo rcl, double fileTransf
c.getCloudletId(), c.getVirtualRuntime(), c.getTimeSlice()));
}
+ //----------------------------------------------
+ */
+
double result = super.processCloudletSubmit(rcl, fileTransferTime);
return result;
}
@@ -343,7 +341,7 @@ public double updateVmProcessing(double currentTime, List mipsShare) {
double nextExpiringTimeSlice = getCloudletExecList().stream()
.mapToDouble(CloudletExecutionInfo::getTimeSlice)
.min().orElse(Double.MAX_VALUE);
- System.out.printf("\tTime %.2f updateVmProcessing - Next expiring timeslice: %.2f\n", currentTime, nextExpiringTimeSlice);
+ //System.out.printf("\tTime %.2f updateVmProcessing - Next expiring timeslice: %.2f\n", currentTime, nextExpiringTimeSlice);
return nextExpiringTimeSlice;
}
@@ -416,20 +414,15 @@ public boolean canAddCloudletToExecutionList(CloudletExecutionInfo cloudlet) {
return isThereEnoughFreePesForCloudlet(cloudlet);
}
- @Override
- protected boolean removeCloudletFromWaitingList(CloudletExecutionInfo cloudlet) {
- return super.removeCloudletFromWaitingList(cloudlet);
- }
-
/**
* {@inheritDoc}
*
- *
Prior to start executing, a Cloudlet is added to this Collection.
+ *
Prior to start executing, a Cloudlet is added to this list.
* When the Cloudlet vruntime reaches its timeslice (the amount of time
- * it can use the CPU), it is removed from this Collection and added
+ * it can use the CPU), it is removed from this list and added
* back to the {@link #getCloudletWaitingList()}.
*
- *
The sum of the PEs of Cloudlets into this Collection cannot exceeds
+ *
The sum of the PEs of Cloudlets into this list cannot exceeds
* the number of PEs available for the scheduler. If the sum of PEs of such Cloudlets
* is less than the number of existing PEs, there are
* idle PEs. Since the CPU context switch overhead is not regarded
@@ -447,38 +440,13 @@ protected boolean removeCloudletFromWaitingList(CloudletExecutionInfo cloudlet)
* @return
*/
@Override
- public Collection getCloudletExecList() {
+ public List getCloudletExecList() {
return super.getCloudletExecList();
}
- /**
- * Gets a read-only {@link TreeSet} (a implementation of a Red-Black Tree) that stores the list of Cloudlets
- * that are waiting to run, the so called
- * run queue.
- * Each key in this map is the virtual runtime (vruntime),
- * which indicates the amount of time the Cloudlet has run.
- * This runtime increases as the Cloudlet executes, what makes
- * it to change its position inside the map.
- * Each value represents a Cloudlet
- * running into a group of PE (defined by the number of
- * PEs the Cloudlet requires).
- *
- *
- * NOTE: Different from real implementations, this scheduler uses just one run queue
- * for all processor cores (PEs). Since CPU context switch is not concerned,
- * there is no point in using different run queues.
- *
- *
- * @return
- */
- @Override
- public Collection getCloudletWaitingList() {
- return super.getCloudletWaitingList();
- }
-
/**
* Checks which Cloudlets in the execution list has the virtual runtime
- * equals to its allocated time slice and preempt them and gets
+ * equals to its allocated time slice and preempt them, getting
* the most priority Cloudlets in the waiting list (that is those ones
* in the beginning of the list).
*
@@ -501,8 +469,8 @@ protected void moveNextCloudletsFromWaitingToExecList() {
/**
* Checks which Cloudlets in the execution list have an expired virtual
- * runtime (that have reached the execution time slice) and move
- * preempt its execution, moving them to the waiting list.
+ * runtime (that have reached the execution time slice) and
+ * preempts its execution, moving them to the waiting list.
*
* @return The list of preempted Cloudlets, that were removed from the execution list
* and must have their virtual runtime reseted after the next cloudlets are put into
@@ -513,14 +481,16 @@ private List preemptExecCloudletsWithExpiredVRuntimeAndMo
Predicate cloudletThatVirtualRuntimeHasReachedItsTimeSlice =
c -> c.getVirtualRuntime() >= c.getTimeSlice();
- Consumer printCloudlet =
- c->System.out.printf("\t\tid %d vruntime %.2f timeslice: %.2f\n",
- c.getCloudletId(), c.getVirtualRuntime(), c.getTimeSlice());
List expiredVRuntimeCloudlets = getCloudletExecList().stream()
.filter(cloudletThatVirtualRuntimeHasReachedItsTimeSlice)
.collect(toList());
+ /*
+ //Code just for debug purposes (can be erased)--------------------------------------
+ Consumer printCloudlet =
+ c->System.out.printf("\t\tid %d priority %d vruntime %.2f timeslice: %.2f finished so far %d\n",
+ c.getCloudletId(), c.getCloudlet().getPriority(), c.getVirtualRuntime(), c.getTimeSlice(), c.getCloudlet().getCloudletFinishedSoFar());
if(!getCloudletExecList().isEmpty()){
System.out.printf("\tTime %.2f - Running cloudlets: \n", CloudSim.clock());
getCloudletExecList().stream().forEach(printCloudlet);
@@ -532,11 +502,11 @@ private List preemptExecCloudletsWithExpiredVRuntimeAndMo
expiredVRuntimeCloudlets.stream().forEach(printCloudlet);
System.out.println();
}
+ //----------------------------------------------------------------------------------
+ */
for(CloudletExecutionInfo c: expiredVRuntimeCloudlets) {
- if(!removeCloudletFromExecList(c)){
- System.out.printf("Cloudlet %d was not removed from exec list\n", c.getCloudletId());
- }
+ removeCloudletFromExecList(c);
addCloudletToWaitingList(c);
}
diff --git a/cloudsim-plus/src/main/java/org/cloudbus/cloudsim/schedulers/CloudletSchedulerSpaceShared.java b/cloudsim-plus/src/main/java/org/cloudbus/cloudsim/schedulers/CloudletSchedulerSpaceShared.java
index 0b4a60f19..187a1574a 100644
--- a/cloudsim-plus/src/main/java/org/cloudbus/cloudsim/schedulers/CloudletSchedulerSpaceShared.java
+++ b/cloudsim-plus/src/main/java/org/cloudbus/cloudsim/schedulers/CloudletSchedulerSpaceShared.java
@@ -17,11 +17,15 @@
/**
* CloudletSchedulerSpaceShared implements a policy of scheduling performed by a
- * virtual machine to run its {@link Cloudlet Cloudlets}. It consider there will
- * be only one cloudlet per VM. Other cloudlets will be in a waiting list. We
- * consider that file transfer from cloudlets waiting happens before cloudlet
- * execution. I.e., even though cloudlets must wait for CPU, data transfer
- * happens as soon as cloudlets are submitted.
+ * virtual machine to run its {@link Cloudlet Cloudlets}. It considers there will
+ * be only one Cloudlet per VM. Other Cloudlets will be in a waiting list. It also
+ * considers that the time to transfer Cloudlets to the Vm happens before Cloudlet
+ * starts executing. I.e., even though Cloudlets must wait for CPU, data transfer
+ * happens as soon as Cloudlets are submitted.
+ *
+ *
This scheduler does not consider Cloudlets priorities to
+ * define execution order. If actual priorities are defined for Cloudlets, they
+ * are just ignored by the scheduler.
*
* @author Rodrigo N. Calheiros
* @author Anton Beloglazov
diff --git a/cloudsim-plus/src/main/java/org/cloudbus/cloudsim/schedulers/CloudletSchedulerTimeShared.java b/cloudsim-plus/src/main/java/org/cloudbus/cloudsim/schedulers/CloudletSchedulerTimeShared.java
index 3a883e421..775d472e4 100644
--- a/cloudsim-plus/src/main/java/org/cloudbus/cloudsim/schedulers/CloudletSchedulerTimeShared.java
+++ b/cloudsim-plus/src/main/java/org/cloudbus/cloudsim/schedulers/CloudletSchedulerTimeShared.java
@@ -19,29 +19,29 @@
* CloudletSchedulerTimeShared implements a policy of scheduling performed by a
* virtual machine to run its {@link Cloudlet Cloudlets}. Cloudlets execute in
* time-shared manner in VM. Each VM has to have its own instance of a
- * CloudletScheduler.
- *
- *
CPU context switch is the process of removing an application (Cloudlets) that is using
- * a CPU core ({@link Pe}) from the {@link #getCloudletExecList() run queue},
- * to allow other one in the {@link #getCloudletWaitingList() waiting queue}
- * to start executing in the same CPU.
- * This process enables sharing the CPU time between different applications.
- *
- *
+ * CloudletScheduler. This scheduler does not consider Cloudlets priorities to
+ * define execution order. If actual priorities are defined for Cloudlets, they
+ * are just ignored by the scheduler.
+ *
*
- * NOTE: This implementation simplifies the context switch process, not
- * in fact switching cloudlets between the run queue and the waiting queue.
- * It just considers there is not waiting Cloudlet, oversimplifying the
- * problem as if for a simulation second t, the total processing capacity
+ * It also does not perform a preemption process in order to move running
+ * Cloudlets to the waiting list in order to make room for other already waiting
+ * Cloudlets to run.
+ * It just considers there is not waiting Cloudlet, oversimplifying the
+ * problem considering that for a given simulation second t, the total processing capacity
* of the processor cores (in MIPS) is equally divided by the applications that are using them.
- * This in fact is not possible, once just one application can use
- * a CPU core at a time.
- *
- *
However, since the basic CloudletScheduler implementations
- * do not account the context switch overhead, the only impact of this oversimplification
+ * This in fact is not possible, once just one application can use
+ * a CPU core at a time.
+ *
+ * However, since this CloudletScheduler implementation
+ * do not account for the context switch overhead,
+ * the only impact of this oversimplification
* is that if there are Cloudlets of the same length running in the same PEs,
- * they will finish exactly at the same time, while a real time-shared scheduler
+ * they will finish exactly at the same time. On the other hand, on a real time-shared scheduler
* these Cloudlets will finish almost in the same time.
+ *
+ *
+ *
* As an example, consider a scheduler that has 1 PE that is able to execute
* 1000 MI/S (MIPS) and is running Cloudlet 0 and Cloudlet 1, each of having 5000 MI
* of length.
@@ -49,19 +49,21 @@
* the time slice allocated to each Cloudlet to execute is 1 second.
* As at every 1 second a different Cloudlet is allowed to run, the execution
* path will be as follows:
- *
+ *
* Time (second): 00 01 02 03 04 05
* Cloudlet (id): C0 C1 C0 C1 C0 C1
- *
+ *
* As one can see, in a real time-shared scheduler that do not define
* priorities for applications, the 2 Cloudlets will in fact finish in different times.
* In this example, one Cloudlet will finish 1 second after the other.
*
- *
+ *
+ *
* @author Rodrigo N. Calheiros
* @author Anton Beloglazov
* @author Manoel Campos da Silva Filho
* @since CloudSim Toolkit 1.0
+ * @see CloudletSchedulerCompletelyFair
*/
public class CloudletSchedulerTimeShared extends CloudletSchedulerAbstract {
@@ -87,10 +89,10 @@ public CloudletSchedulerTimeShared() {
* @return {@inheritDoc}
*/
@Override
- public Collection getCloudletWaitingList() {
+ protected List getCloudletWaitingList() {
return super.getCloudletWaitingList();
}
-
+
/**
* Moves a Cloudlet that was paused and has just been resumed
* to the Cloudlet execution list.
@@ -123,11 +125,11 @@ public double cloudletResume(int cloudletId) {
/**
* {@inheritDoc}
- *
+ *
* @todo If the method always return an empty list (that is created locally),
* it doesn't make sense to exist. See other implementations such as
* {@link CloudletSchedulerSpaceShared#getCurrentRequestedMips()}
- *
+ *
* @return {@inheritDoc}
*/
@Override
@@ -141,12 +143,12 @@ public List getCurrentRequestedMips() {
* because in the Time Shared Scheduler, the
* CPU capacity from the VM that is managed by the scheduler
* is shared between all running cloudlets.
- *
+ *
* @todo if there is 2 cloudlets requiring 1 PE and there is just 1
* PE, the MIPS capacity of this PE is splited between the 2 cloudlets,
* but the method seen to always return the entire capacity.
* New test cases have to be created to check this.
- *
+ *
* @param rcl {@inheritDoc}
* @param mipsShare {@inheritDoc}
* @return {@inheritDoc}
@@ -194,7 +196,7 @@ public double getCurrentRequestedUtilizationOfBw() {
* It always allow any submitted Cloudlets to be immediately added to the execution list.
* By this way, it doesn't matter what Cloudlet is being submitted, since it will
* always include it in the execution list.
- *
+ *
* @param cloudlet the Cloudlet that will be added to the execution list.
* @return always true to indicate that any submitted Cloudlet can be immediately added to the execution list
*/
@@ -202,5 +204,5 @@ public double getCurrentRequestedUtilizationOfBw() {
public boolean canAddCloudletToExecutionList(CloudletExecutionInfo cloudlet) {
return true;
}
-
+
}
diff --git a/cloudsim-plus/src/main/java/org/cloudsimplus/util/tablebuilder/CloudletsTableBuilderHelper.java b/cloudsim-plus/src/main/java/org/cloudsimplus/util/tablebuilder/CloudletsTableBuilderHelper.java
index f011cf404..4ab75f278 100644
--- a/cloudsim-plus/src/main/java/org/cloudsimplus/util/tablebuilder/CloudletsTableBuilderHelper.java
+++ b/cloudsim-plus/src/main/java/org/cloudsimplus/util/tablebuilder/CloudletsTableBuilderHelper.java
@@ -5,25 +5,25 @@
/**
* A class to help printing simulation results for a list of cloudlets.
- *
+ *
* @author Manoel Campos da Silva Filho
*/
public class CloudletsTableBuilderHelper {
- private TableBuilder printer;
+ private TableBuilder printer;
private List extends Cloudlet> cloudletList;
/**
* Creates new helper object to print the list of cloudlets using the a
* default {@link TextTableBuilder}.
* To use a different {@link TableBuilder}, use the
- * {@link #setPrinter(org.cloudbus.cloudsim.util.TableBuilder)} method.
- *
+ * {@link #setPrinter(TableBuilder)} method.
+ *
* @param list the list of Cloudlets that the data will be included into the table to be printed
- */
+ */
public CloudletsTableBuilderHelper(final List extends Cloudlet> list){
- this.setPrinter(new TextTableBuilder()).setCloudletList(list);
+ this.setPrinter(new TextTableBuilder()).setCloudletList(list);
}
-
+
/**
* Builds the table with the data of the Cloudlet list and shows the results.
*/
@@ -31,7 +31,7 @@ public void build(){
if(printer.getTitle().isEmpty()){
printer.setTitle("SIMULATION RESULTS");
}
-
+
createTableColumns();
cloudletList.stream().forEach(cloudlet -> addDataToRow(cloudlet, printer.newRow()));
printer.print();
diff --git a/cloudsim-plus/src/main/java/org/cloudsimplus/util/tablebuilder/PriorityCloudletsTableBuilderHelper.java b/cloudsim-plus/src/main/java/org/cloudsimplus/util/tablebuilder/PriorityCloudletsTableBuilderHelper.java
new file mode 100644
index 000000000..bd90533f9
--- /dev/null
+++ b/cloudsim-plus/src/main/java/org/cloudsimplus/util/tablebuilder/PriorityCloudletsTableBuilderHelper.java
@@ -0,0 +1,28 @@
+package org.cloudsimplus.util.tablebuilder;
+
+import org.cloudbus.cloudsim.Cloudlet;
+
+import java.util.List;
+
+/**
+ * A helper class to print cloudlets results as a table, including the Cloudlet priority value.
+ *
+ * @author Manoel Campos da Silva Filho
+ */
+public class PriorityCloudletsTableBuilderHelper extends CloudletsTableBuilderHelper {
+ public PriorityCloudletsTableBuilderHelper(List extends Cloudlet> list) {
+ super(list);
+ }
+
+ @Override
+ protected void createTableColumns() {
+ super.createTableColumns();
+ getPrinter().addColumn("Priority");
+ }
+
+ @Override
+ protected void addDataToRow(Cloudlet cloudlet, List