How to Implement Priority Scheduling Algorithm in ContainerCloudSim?
Share
Condition for Priority Scheduling Algorithm in ContainerCloudSim
Description: The implemented Priority-Based Container Scheduler allocates processing elements (PEs) to containers according to a dynamically assigned priority value. When a container requests CPU resources, it is first added to a waiting queue along with an associated priority score. If no priority has been explicitly assigned, the scheduler computes a meaningful priority level based on the container’s total requested MIPS, giving higher priority to more compute-intensive containers. Once inserted, all waiting containers are sorted in descending order of priority, ensuring that high-priority workloads are always served first.
During allocation, the scheduler sequentially attempts to assign PEs to containers based on this priority order. If sufficient PEs are available, the container is allocated resources immediately; otherwise, it remains in the waiting queue. On deallocation (i.e., when a container finishes execution), the scheduler automatically rechecks the waiting list and allocates resources to the next highest-priority container, ensuring preemptive-like responsiveness without forcibly interrupting running containers.
This approach increases QoS-awareness and responsiveness to critical workloads, making it suitable for environments where latency-sensitive or high-importance containers must be prioritized. However, prolonged dominance of high-priority tasks may cause starvation of lower-priority containers, suggesting that aging or hybrid policies could further enhance fairness.
/**
* A simple example showing how to create a data center with one host, one VM,
* one container and run one cloudlet on it.
*/
public class ContainerCloudSim {
/**
* The cloudlet list.
*/
private static List cloudletList;
/**
* The vmlist.
*/
private static List vmList;
/**
* The vmlist.
*/
private static List containerList;
/**
* The hostList.
*/
private static List hostList;
/**
* Creates main() to run this example.
*
* @param args the args
*/
public static void main(String[] args) {
Log.printLine("Starting ContainerCloudSimExample1...");
try {
/**
* number of cloud Users
*/
int num_user = 1;
/**
* The fields of calender have been initialized with the current
* date and time.
*/
Calendar calendar = Calendar.getInstance();
/**
* Deactivating the event tracing
*/
boolean trace_flag = false;
/**
* 1- Like CloudSim the first step is initializing the CloudSim
* Package before creating any entities.
*
*/
CloudSim.init(num_user, calendar, trace_flag);
/**
* 2- Defining the container allocation Policy. This policy
* determines how Containers are allocated to VMs in the data
* center.
*
*/
ContainerAllocationPolicy containerAllocationPolicy = new PowerContainerAllocationPolicySimple();
/**
* 3- Defining the VM selection Policy. This policy determines which
* VMs should be selected for migration when a host is identified as
* over-loaded.
*
*/
PowerContainerVmSelectionPolicy vmSelectionPolicy = new PowerContainerVmSelectionPolicyMaximumUsage();
/**
* 4- Defining the host selection Policy. This policy determines
* which hosts should be selected as migration destination.
*
*/
HostSelectionPolicy hostSelectionPolicy = new HostSelectionPolicyFirstFit();
/**
* 5- Defining the thresholds for selecting the under-utilized and
* over-utilized hosts.
*/
double overUtilizationThreshold = 0.80;
double underUtilizationThreshold = 0.70;
/**
* 6- The host list is created considering the number of hosts, and
* host types which are specified in the {@link ConstantsExamples}.
*/
hostList = new ArrayList();
hostList = createHostList(ConstantsExamples.NUMBER_HOSTS);
cloudletList = new ArrayList();
vmList = new ArrayList();
/**
* 7- The container allocation policy which defines the allocation
* of VMs to containers.
*/
ContainerVmAllocationPolicy vmAllocationPolicy = new PowerContainerVmAllocationPolicyMigrationAbstractHostSelection(hostList, vmSelectionPolicy,
hostSelectionPolicy, overUtilizationThreshold, underUtilizationThreshold);
/**
* 8- The overbooking factor for allocating containers to VMs. This
* factor is used by the broker for the allocation process.
*/
int overBookingFactor = 80;
ContainerDatacenterBroker broker = createBroker(overBookingFactor);
int brokerId = broker.getId();
/**
* 9- Creating the cloudlet, container and VM lists for submitting
* to the broker.
*/
cloudletList = createContainerCloudletList(brokerId, ConstantsExamples.NUMBER_CLOUDLETS);
containerList = createContainerList(brokerId, ConstantsExamples.NUMBER_CLOUDLETS);
vmList = createVmList(brokerId, ConstantsExamples.NUMBER_VMS);
/**
* 10- The address for logging the statistics of the VMs, containers
* in the data center.
*/
String logAddress = "~/Results";
/**
* 11- Submitting the cloudlet's , container's , and VM's lists to
* the broker.
*/
broker.submitCloudletList(cloudletList.subList(0, containerList.size()));
broker.submitContainerList(containerList);
broker.submitVmList(vmList);
/**
* 12- Determining the simulation termination time according to the
* cloudlet's workload.
*/
CloudSim.terminateSimulation(86400.00);
/**
* 13- Starting the simualtion.
*/
CloudSim.startSimulation();
/**
* 14- Stopping the simualtion.
*/
CloudSim.stopSimulation();
/**
* 15- Printing the results when the simulation is finished.
*/
List newList = broker.getCloudletReceivedList();
printCloudletList(newList);
/**
* It creates a specific name for the experiment which is used for creating
* the Log address folder.
*/
private static String getExperimentName(String... args) {
StringBuilder experimentName = new StringBuilder();
for (int i = 0; i < args.length; ++i) {
if (!args[i].isEmpty()) {
if (i != 0) {
experimentName.append("_");
}
/**
* Prints the Cloudlet objects.
*
* @param list list of Cloudlets
*/
private static void printCloudletList(List list) {
int size = list.size();
ContainerCloudlet cloudlet;
/**
* Create the Virtual machines and add them to the list
*
* @param brokerId
* @param containerVmsNumber
*/
private static ArrayList createVmList(int brokerId, int containerVmsNumber) {
ArrayList containerVms = new ArrayList();
for (int i = 0; i < containerVmsNumber; ++i) {
ArrayList peList = new ArrayList();
int vmType = i / (int) Math.ceil((double) containerVmsNumber / 4.0D);
for (int j = 0; j < 5; ++j) {// 5 = No of PEs
peList.add(new ContainerPe(j, new ContainerPeProvisionerSimple((double) ConstantsExamples.VM_MIPS[vmType])));
}
// Change this line to use FCFS scheduler instead of time-shared
containerVms.add(new PowerContainerVm(IDs.pollId(ContainerVm.class), brokerId,
(double) ConstantsExamples.VM_MIPS[vmType], (float) ConstantsExamples.VM_RAM[vmType],
ConstantsExamples.VM_BW, ConstantsExamples.VM_SIZE, "Xen",
new ContainerSchedulerPriority(peList), // Using FCFS scheduler here
new ContainerRamProvisionerSimple(ConstantsExamples.VM_RAM[vmType]),
new ContainerBwProvisionerSimple(ConstantsExamples.VM_BW),
peList, ConstantsExamples.SCHEDULING_INTERVAL));
}
return containerVms;
}
/**
* Create the host list considering the specs listed in the
* {@link ConstantsExamples}.
*
* @param hostsNumber
* @return
*/
public static List createHostList(int hostsNumber) {
ArrayList hostList = new ArrayList();
for (int i = 0; i < hostsNumber; ++i) {
int hostType = i / (int) Math.ceil((double) hostsNumber / 3.0D);
ArrayList peList = new ArrayList();
for (int j = 0; j < ConstantsExamples.HOST_PES[hostType]; ++j) {
peList.add(new ContainerVmPe(j,
new ContainerVmPeProvisionerSimple((double) ConstantsExamples.HOST_MIPS[hostType])));
}
hostList.add(new PowerContainerHostUtilizationHistory(IDs.pollId(ContainerHost.class),
new ContainerVmRamProvisionerSimple(ConstantsExamples.HOST_RAM[hostType]),
new ContainerVmBwProvisionerSimple(1000000L), 1000000L, peList,
new ContainerVmSchedulerTimeSharedOverSubscription(peList),
ConstantsExamples.HOST_POWER[hostType]));
}
/**
* create the containers for hosting the cloudlets and binding them
* together.
*
* @param brokerId
* @param containersNumber
* @return
*/
public static List createContainerList(int brokerId, int containersNumber) {
ArrayList containers = new ArrayList();
for (int i = 0; i < containersNumber; ++i) {
int containerType = i / (int) Math.ceil((double) containersNumber / 3.0D);
public class ContainerSchedulerPriority extends ContainerScheduler {
// Priority queue to manage containers based on priority
private List waitingContainers;
private Map containerPriorities;
public ContainerSchedulerPriority(List pelist) {
super(pelist);
this.waitingContainers = new ArrayList<>();
this.containerPriorities = new HashMap<>();
}
// Method to set priority for a container
public void setContainerPriority(Container container, int priority) {
containerPriorities.put(container, priority);
}
@Override
public boolean allocatePesForContainer(Container container, List mipsShare) {
// Add container to waiting queue
waitingContainers.add(container);
if (!containerPriorities.containsKey(container)) {
int priority = calculateMeaningfulPriority(container);
containerPriorities.put(container, priority);
}
waitingContainers.add(container);
// Log the current priorities before sorting
Log.printLine("Before sorting - Waiting containers and priorities:");
for (Container c : waitingContainers) {
int p = containerPriorities.getOrDefault(c, 0);
Log.printLine(" Container #" + c.getId() + " -> Priority: " + p);
}
// Sort by priority (higher priority first)
Collections.sort(waitingContainers, (c1, c2) -> {
int p1 = containerPriorities.getOrDefault(c1, 0);
int p2 = containerPriorities.getOrDefault(c2, 0);
return Integer.compare(p2, p1); // Higher priority first
});
// Log after sorting to verify
Log.printLine("After sorting - Waiting containers in priority order:");
for (Container c : waitingContainers) {
int p = containerPriorities.getOrDefault(c, 0);
Log.printLine(" Container #" + c.getId() + " -> Priority: " + p);
}
// Sort using external priority mapping
Collections.sort(waitingContainers, new Comparator() {
@Override
public int compare(Container c1, Container c2) {
int p1 = containerPriorities.getOrDefault(c1, 0);
int p2 = containerPriorities.getOrDefault(c2, 0);
return Integer.compare(p2, p1); // Higher priority first
}
});
// Sort containers based on priority (higher priority first)
Collections.sort(waitingContainers, new Comparator() {
@Override
public int compare(Container c1, Container c2) {
return Integer.compare(c2.getPriority(), c1.getPriority());
}
});
// Try to allocate resources for each container in priority order
for (Container waitingContainer : waitingContainers) {
if (waitingContainer.getContainerPeAllocation() == null) {
if (tryAllocateResources(waitingContainer, mipsShare)) {
Log.printConcatLine("Priority: Allocated PEs for Container ID ",
waitingContainer.getId(), " with priority ",
waitingContainer.getPriority());
waitingContainers.remove(waitingContainer);
return true;
}
}
}
Log.printLine("Priority: Not enough resources for container ID" + container.getId()
+ "with priority " + container.getPriority());
return false;
}
private int calculateMeaningfulPriority(Container container) {
// Higher priority for containers with higher resource demands
double totalMips = container.getCurrentRequestedMips().stream()
.mapToDouble(Double::doubleValue).sum();
if (totalMips > 15000) {
return 1; // High priority for demanding containers
} else if (totalMips > 10000) {
return 2; // Medium-high priority
} else if (totalMips > 5000) {
return 3; // Medium priority
} else {
return 4; // Low priority for lightweight containers
}
}
private boolean tryAllocateResources(Container container, List mipsShare) {
Log.printConcatLine("Priority: Trying to allocate PEs for Container ID ",
container.getId(), " with priority ", container.getPriority());
if (getPeCapacity() < mipsShare.size()) {
Log.printLine("Priority: Not enough PE capacity. Needed: "
+ mipsShare.size() + ", Available: " + getPeCapacity());
return false;
}
List allocatedPes = new ArrayList<>();
for (int i = 0; i < mipsShare.size(); i++) {
ContainerPe pe = getPeList().get(i);
allocatedPes.add(pe);
Log.printLine("Priority: Allocated PE #" + i + " with MIPS: "
+ pe.getMips() + " to Container ID: " + container.getId());
}
@Override
public void deallocatePesForContainer(Container container) {
if (container != null) {
Log.printLine("Priority: Deallocating PEs for Container ID " + container.getId());
container.setCurrentAllocatedMips(null);
getMipsMap().remove(container.getUid());
getPeMap().remove(container.getUid());
// When a container finishes, try to allocate waiting containers
if (!waitingContainers.isEmpty()) {
Container nextContainer = waitingContainers.get(0);
allocatePesForContainer(nextContainer, nextContainer.getCurrentRequestedMips());
}
}
}
}