diff --git a/cloudsim-plus-examples/src/main/java/org/cloudsimplus/examples/HostFaultInjectionExample1.java b/cloudsim-plus-examples/src/main/java/org/cloudsimplus/examples/HostFaultInjectionExample1.java index 9a99b211d..85d2e7aeb 100644 --- a/cloudsim-plus-examples/src/main/java/org/cloudsimplus/examples/HostFaultInjectionExample1.java +++ b/cloudsim-plus-examples/src/main/java/org/cloudsimplus/examples/HostFaultInjectionExample1.java @@ -21,17 +21,10 @@ * You should have received a copy of the GNU General Public License * along with CloudSim Plus. If not, see . */ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ package org.cloudsimplus.examples; -import org.cloudbus.cloudsim.distributions.PoissonDistribution; import java.util.ArrayList; import java.util.List; -import org.cloudbus.cloudsim.allocationpolicies.VmAllocationPolicy; import org.cloudbus.cloudsim.allocationpolicies.VmAllocationPolicySimple; import org.cloudbus.cloudsim.cloudlets.Cloudlet; import org.cloudbus.cloudsim.cloudlets.CloudletSimple; @@ -47,7 +40,6 @@ import org.cloudbus.cloudsim.schedulers.vm.VmSchedulerTimeShared; import org.cloudbus.cloudsim.core.CloudSim; import org.cloudbus.cloudsim.datacenters.DatacenterSimple; -import org.cloudbus.cloudsim.distributions.UniformDistr; import org.cloudbus.cloudsim.hosts.Host; import org.cloudbus.cloudsim.hosts.HostSimple; import org.cloudbus.cloudsim.provisioners.PeProvisionerSimple; @@ -57,7 +49,6 @@ import org.cloudbus.cloudsim.schedulers.vm.VmScheduler; import org.cloudsimplus.builders.tables.CloudletsTableBuilder; import org.cloudbus.cloudsim.utilizationmodels.UtilizationModel; -import org.cloudbus.cloudsim.utilizationmodels.UtilizationModelDynamic; import org.cloudbus.cloudsim.utilizationmodels.UtilizationModelFull; import org.cloudbus.cloudsim.vms.VmSimple; import org.cloudsimplus.faultinjection.HostFaultInjection; @@ -67,22 +58,22 @@ * using {@link HostFaultInjection} objects. * * @author raysaoliveira + * @since CloudSim Plus 1.2.0 */ public final class HostFaultInjectionExample1 { - private static final int SCHEDULE_TIME_TO_PROCESS_DATACENTER_EVENTS = 19; + private static final int SCHEDULE_TIME_TO_PROCESS_DATACENTER_EVENTS = 5; private static final double DATACENTER_COST_PER_CPU = 3.0; private static final double DATACENTER_COST_PER_RAM = 0.05; private static final double DATACENTER_COST_PER_STORAGE = 0.001; private static final double DATACENTER_COST_PER_BW = 0.0; private static final int HOST_MIPS_BY_PE = 1000; - private static final int HOST_PES = 2; + private static final int HOST_PES = 6; private static final long HOST_RAM = 500000; //host memory (MEGABYTE) private static final long HOST_STORAGE = 1000000; //host storage private static final long HOST_BW = 100000000L; private List hostList; - /** * The percentage of host CPU usage that trigger VM migration due to over @@ -94,40 +85,21 @@ public final class HostFaultInjectionExample1 { private static final long VM_SIZE = 1000; //image size (MEGABYTE) private static final int VM_RAM = 10000; //vm memory (MEGABYTE) private static final long VM_BW = 100000; - private static final int VM_PES = 1; //number of cpus + private static final int VM_PES = 2; //number of cpus - private static final int CLOUDLET_PES = 1; - private static final long CLOUDLET_LENGHT = 30000; + private static final int CLOUDLET_PES = 2; + private static final long CLOUDLET_LENGHT = 200000; private static final long CLOUDLET_FILESIZE = 300; private static final long CLOUDLET_OUTPUTSIZE = 300; - /** - * The percentage of CPU that a cloudlet will use when it starts executing - * (in scale from 0 to 1, where 1 is 100%). For each cloudlet create, this - * value is used as a base to define CPU usage. - * - * @see #createAndSubmitCloudlets(DatacenterBroker) - */ - private static final double CLOUDLET_INITIAL_CPU_USAGE_PERCENT = 0.8; - - /** - * Defines the speed (in percentage) that CPU usage of a cloudlet will - * increase during the simulation tie. (in scale from 0 to 1, where 1 is - * 100%). - * - * @see #createAndSubmitCloudletsWithDynamicCpuUtilization(double, double, - * Vm, DatacenterBroker) - */ - public static final double CLOUDLET_CPU_USAGE_INCREMENT_PER_SECOND = 0.05; - /** * Number of Hosts to create for each Datacenter. * The number of elements in this array defines the number of Datacenters to be created. */ private static final int HOSTS = 2; - private static final int VMS = 2; + private static final int VMS = 4; - private static final int CLOUDLETS_BY_VM = 1; + private static final int CLOUDLETS_BY_VM = 2; private final List vmlist = new ArrayList<>(); private CloudSim simulation; @@ -162,19 +134,6 @@ public HostFaultInjectionExample1() { System.out.println("A cloudlet 2 deveria terminar no segundo 40, pois ela iniciou em 10, mas ela não termina"); } - public void createAndSubmitCloudlets(DatacenterBroker broker) { - double initialCloudletCpuUtilizationPercentage = CLOUDLET_INITIAL_CPU_USAGE_PERCENT; - final int numberOfCloudlets = VMS - 1; - for (int i = 0; i < numberOfCloudlets; i++) { - createAndSubmitCloudletsWithStaticCpuUtilization( - initialCloudletCpuUtilizationPercentage, vmlist.get(i), broker); - initialCloudletCpuUtilizationPercentage += 0.15; - } - //Create one last cloudlet which CPU usage increases dynamically - Vm lastVm = vmlist.get(vmlist.size() - 1); - createAndSubmitCloudletsWithDynamicCpuUtilization(0.2, 1, lastVm, broker); - } - public void createAndSubmitVms(DatacenterBroker broker) { for (int i = 0; i < VMS; i++) { Vm vm = createVm(broker); @@ -206,92 +165,28 @@ public Vm createVm(DatacenterBroker broker) { * {@link #CLOUDLETS_BY_VM} and submits them to the * given broker. * - * @param cloudletInitialCpuUsagePercent the percentage of CPU utilization - * that created Cloudlets will use when they start to execute. If this value - * is greater than 1 (100%), it will be changed to 1. - * @param maxCloudletCpuUtilizationPercentage the maximum percentage of CPU - * utilization that created Cloudlets are allowed to use. If this value is - * greater than 1 (100%), it will be changed to 1. - * @param hostingVm the VM that will run the Cloudlets * @param broker the broker that the created Cloudlets belong to - * @param progressiveCpuUsage if the CPU usage of created Cloudlets have to - * change along the execution time or not, according to the - * {@link #getCpuUtilizationIncrement(org.cloudbus.cloudsim.utilizationmodels.UtilizationModelDynamic)} * @return the List of created Cloudlets */ public List createAndSubmitCloudlets( - double cloudletInitialCpuUsagePercent, - double maxCloudletCpuUtilizationPercentage, - Vm hostingVm, - DatacenterBroker broker, - boolean progressiveCpuUsage) { - cloudletInitialCpuUsagePercent = Math.min(cloudletInitialCpuUsagePercent, 1); - maxCloudletCpuUtilizationPercentage = Math.min(maxCloudletCpuUtilizationPercentage, 1); + DatacenterBroker broker) { final List list = new ArrayList<>(CLOUDLETS_BY_VM); - UtilizationModel utilizationModelFull = new UtilizationModelFull(); - int cloudletId; + UtilizationModel utilizationModel = new UtilizationModelFull(); for (int i = 0; i < CLOUDLETS_BY_VM; i++) { - cloudletId = hostingVm.getId() + i; - UtilizationModelDynamic cpuUtilizationModel; - if (progressiveCpuUsage) { - cpuUtilizationModel - = new UtilizationModelDynamic(cloudletInitialCpuUsagePercent) - .setUtilizationUpdateFunction(this::getCpuUtilizationIncrement); - } else { - cpuUtilizationModel = new UtilizationModelDynamic(cloudletInitialCpuUsagePercent); - } - cpuUtilizationModel.setMaxResourceUtilization(maxCloudletCpuUtilizationPercentage); - Cloudlet c - = new CloudletSimple( - cloudletId, CLOUDLET_LENGHT, CLOUDLET_PES) + = new CloudletSimple(CLOUDLET_LENGHT, CLOUDLET_PES) .setFileSize(CLOUDLET_FILESIZE) .setOutputSize(CLOUDLET_OUTPUTSIZE) - .setUtilizationModelCpu(cpuUtilizationModel) - .setUtilizationModelRam(utilizationModelFull) - .setUtilizationModelBw(utilizationModelFull); + .setUtilizationModel(utilizationModel); c.setBroker(broker); list.add(c); } broker.submitCloudletList(list); - for (Cloudlet c : list) { - broker.bindCloudletToVm(c, hostingVm); - } return list; } - /** - * Increments the CPU resource utilization, that is defined in percentage - * values. - * - * @return the new resource utilization after the increment - */ - private double getCpuUtilizationIncrement(UtilizationModelDynamic um) { - return um.getUtilization() + um.getTimeSpan() * CLOUDLET_CPU_USAGE_INCREMENT_PER_SECOND; - } - - public List createAndSubmitCloudletsWithDynamicCpuUtilization( - double initialCloudletCpuUtilizationPercentage, - double maxCloudletCpuUtilizationPercentage, - Vm hostingVm, - DatacenterBroker broker) { - return createAndSubmitCloudlets( - initialCloudletCpuUtilizationPercentage, - maxCloudletCpuUtilizationPercentage, hostingVm, broker, true); - } - - public List createAndSubmitCloudletsWithStaticCpuUtilization( - double initialCloudletCpuUtilizationPercentage, - Vm hostingVm, - DatacenterBroker broker) { - return createAndSubmitCloudlets( - initialCloudletCpuUtilizationPercentage, - initialCloudletCpuUtilizationPercentage, - hostingVm, broker, false); - } - private Datacenter createDatacenter(int numberOfHosts) { hostList = new ArrayList<>(); for (int i = 0; i < numberOfHosts; i++) { @@ -307,15 +202,8 @@ private Datacenter createDatacenter(int numberOfHosts) { .setCostPerStorage(DATACENTER_COST_PER_STORAGE) .setCostPerBw(DATACENTER_COST_PER_BW); - /*@todo nao está sendo usado por enquanto, apenas para evitar migração - PowerVmAllocationPolicyMigrationWorstFitStaticThreshold allocationPolicy - = new PowerVmAllocationPolicyMigrationWorstFitStaticThreshold( - new PowerVmSelectionPolicyMinimumUtilization(), - HOST_USAGE_THRESHOLD_VM_MIGRATION);*/ - Datacenter dc = new DatacenterSimple(simulation, characteristics, new VmAllocationPolicySimple()); dc - //.setMigrationsEnabled(false) .setSchedulingInterval(SCHEDULE_TIME_TO_PROCESS_DATACENTER_EVENTS) .setLog(false); return dc; @@ -355,24 +243,18 @@ public List createPeList(int numberOfPEs, long mips) { * @param datacenter */ private void createFaultInjectionForHosts(Datacenter datacenter) { - final int MAX_TIME_TO_GENERATE_FAILURE = 10; + final int MAX_FAILURE_DELAY_SECONDS = 10; //final long seed = System.currentTimeMillis(); - final long seed = 49998811; - final double lambda = 0.2; + long seed = 3412125; + final double meanFailureNumberPerMinute = 0.4; - UniformDistr failedPesGenerator = new UniformDistr(seed); - UniformDistr failureDelayGenerator = new UniformDistr(1, MAX_TIME_TO_GENERATE_FAILURE, seed); - int i = 0; for (Host host: datacenter.getHostList()) { - PoissonDistribution poisson = new PoissonDistribution(lambda, seed + i++); - if (poisson.eventsHappened()) { - HostFaultInjection fault = new HostFaultInjection(host); - fault.setFailedPesGenerator(failedPesGenerator); - fault.setFailureDelayGenerator(failureDelayGenerator); - fault.setVmCloner(this::cloneVm); - fault.setCloudletsCloner(this::cloneCloudlets); - Log.printFormattedLine("\tFault Injection created for %s.", host); - } + HostFaultInjection fault = new HostFaultInjection(host, meanFailureNumberPerMinute, seed++); + fault.setMaxFailureDelay(MAX_FAILURE_DELAY_SECONDS); + fault.setVmCloner(this::cloneVm); + fault.setCloudletsCloner(this::cloneCloudlets); + Log.printFormattedLine("\tFault Injection created for %s.", host); + break; //cria apenas para o primeiro host, so pra teste } } diff --git a/cloudsim-plus-testbeds/src/main/java/org/cloudsimplus/sla/CreateCloudletRandomlyExample.java b/cloudsim-plus-testbeds/src/main/java/org/cloudsimplus/sla/CreateCloudletRandomlyExample.java index 392a78724..15719243d 100644 --- a/cloudsim-plus-testbeds/src/main/java/org/cloudsimplus/sla/CreateCloudletRandomlyExample.java +++ b/cloudsim-plus-testbeds/src/main/java/org/cloudsimplus/sla/CreateCloudletRandomlyExample.java @@ -28,7 +28,7 @@ */ package org.cloudsimplus.sla; -import org.cloudbus.cloudsim.distributions.PoissonDistribution; +import org.cloudbus.cloudsim.distributions.PoissonProcess; import java.util.ArrayList; import java.util.List; import org.cloudbus.cloudsim.cloudlets.Cloudlet; @@ -148,7 +148,7 @@ public CreateCloudletRandomlyExample() { long seed = System.currentTimeMillis(); //creates a poisson process that checks the arrival of 1 (k) cloudlet //1 is the default value for k - PoissonDistribution poisson = new PoissonDistribution(MEAN_CUSTOMERS_ARRIVAL_PER_MINUTE, seed); + PoissonProcess poisson = new PoissonProcess(MEAN_CUSTOMERS_ARRIVAL_PER_MINUTE, seed); int totalArrivedCustomers = 0; int cloudletId = 0; for (int minute = 0; minute < MAX_TIME_FOR_CLOUDLET_ARRIVAL; minute++) { diff --git a/cloudsim-plus-testbeds/src/main/java/org/cloudsimplus/sla/HostFaultInjection.java b/cloudsim-plus-testbeds/src/main/java/org/cloudsimplus/sla/HostFaultInjection.java deleted file mode 100644 index 4714e61a7..000000000 --- a/cloudsim-plus-testbeds/src/main/java/org/cloudsimplus/sla/HostFaultInjection.java +++ /dev/null @@ -1,437 +0,0 @@ -/** - * CloudSim Plus: A modern, highly-extensible and easier-to-use Framework for - * Modeling and Simulation of Cloud Computing Infrastructures and Services. - * http://cloudsimplus.org - * - * Copyright (C) 2015-2016 Universidade da Beira Interior (UBI, Portugal) and - * the Instituto Federal de Educação Ciência e Tecnologia do Tocantins (IFTO, Brazil). - * - * This file is part of CloudSim Plus. - * - * CloudSim Plus is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * CloudSim Plus is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with CloudSim Plus. If not, see . - */ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.cloudsimplus.sla; - -import org.cloudsimplus.faultinjection.HostFaultInjection; -import org.cloudbus.cloudsim.distributions.PoissonDistribution; -import java.util.ArrayList; -import java.util.List; -import org.cloudbus.cloudsim.allocationpolicies.VmAllocationPolicy; -import org.cloudbus.cloudsim.allocationpolicies.VmAllocationPolicySimple; -import org.cloudbus.cloudsim.cloudlets.Cloudlet; -import org.cloudbus.cloudsim.cloudlets.CloudletSimple; -import org.cloudbus.cloudsim.schedulers.cloudlet.CloudletSchedulerTimeShared; -import org.cloudbus.cloudsim.datacenters.Datacenter; -import org.cloudbus.cloudsim.brokers.DatacenterBroker; -import org.cloudbus.cloudsim.datacenters.DatacenterCharacteristics; -import org.cloudbus.cloudsim.datacenters.DatacenterCharacteristicsSimple; -import org.cloudbus.cloudsim.util.Log; -import org.cloudbus.cloudsim.resources.Pe; -import org.cloudbus.cloudsim.vms.Vm; -import org.cloudbus.cloudsim.brokers.DatacenterBrokerSimple; -import org.cloudbus.cloudsim.schedulers.vm.VmSchedulerTimeShared; -import org.cloudbus.cloudsim.core.CloudSim; -import org.cloudbus.cloudsim.datacenters.DatacenterSimple; -import org.cloudbus.cloudsim.distributions.UniformDistr; -import org.cloudbus.cloudsim.hosts.Host; -import org.cloudbus.cloudsim.hosts.HostSimple; -import org.cloudbus.cloudsim.provisioners.PeProvisionerSimple; -import org.cloudbus.cloudsim.provisioners.ResourceProvisioner; -import org.cloudbus.cloudsim.provisioners.ResourceProvisionerSimple; -import org.cloudbus.cloudsim.resources.PeSimple; -import org.cloudbus.cloudsim.schedulers.vm.VmScheduler; -import org.cloudsimplus.builders.tables.CloudletsTableBuilder; -import org.cloudbus.cloudsim.utilizationmodels.UtilizationModel; -import org.cloudbus.cloudsim.utilizationmodels.UtilizationModelDynamic; -import org.cloudbus.cloudsim.utilizationmodels.UtilizationModelFull; -import org.cloudbus.cloudsim.vms.VmSimple; - -/** - * Example which shows how to inject random {@link Pe} faults into Hosts - * using {@link HostFaultInjection} objects. - * - * @author raysaoliveira - */ -public final class HostFaultInjection { - - private static final int SCHEDULE_TIME_TO_PROCESS_DATACENTER_EVENTS = 19; - private static final double DATACENTER_COST_PER_CPU = 3.0; - private static final double DATACENTER_COST_PER_RAM = 0.05; - private static final double DATACENTER_COST_PER_STORAGE = 0.001; - private static final double DATACENTER_COST_PER_BW = 0.0; - - private static final int HOST_MIPS_BY_PE = 1000; - private static final int HOST_PES = 2; - private static final long HOST_RAM = 500000; //host memory (MEGABYTE) - private static final long HOST_STORAGE = 1000000; //host storage - private static final long HOST_BW = 100000000L; - private List hostList; - - - /** - * The percentage of host CPU usage that trigger VM migration due to over - * utilization (in scale from 0 to 1, where 1 is 100%). - */ - private static final double HOST_USAGE_THRESHOLD_VM_MIGRATION = 0.5; - - private static final int VM_MIPS = 1000; - private static final long VM_SIZE = 1000; //image size (MEGABYTE) - private static final int VM_RAM = 10000; //vm memory (MEGABYTE) - private static final long VM_BW = 100000; - private static final int VM_PES = 1; //number of cpus - - private static final int CLOUDLET_PES = 1; - private static final long CLOUDLET_LENGHT = 30000; - private static final long CLOUDLET_FILESIZE = 300; - private static final long CLOUDLET_OUTPUTSIZE = 300; - - /** - * The percentage of CPU that a cloudlet will use when it starts executing - * (in scale from 0 to 1, where 1 is 100%). For each cloudlet create, this - * value is used as a base to define CPU usage. - * - * @see #createAndSubmitCloudlets(DatacenterBroker) - */ - private static final double CLOUDLET_INITIAL_CPU_USAGE_PERCENT = 0.8; - - /** - * Defines the speed (in percentage) that CPU usage of a cloudlet will - * increase during the simulation tie. (in scale from 0 to 1, where 1 is - * 100%). - * - * @see #createAndSubmitCloudletsWithDynamicCpuUtilization(double, double, - * Vm, DatacenterBroker) - */ - public static final double CLOUDLET_CPU_USAGE_INCREMENT_PER_SECOND = 0.05; - - /** - * Number of Hosts to create for each Datacenter. - * The number of elements in this array defines the number of Datacenters to be created. - */ - private static final int HOSTS = 2; - private static final int VMS = 2; - - private static final int CLOUDLETS_BY_VM = 1; - - private final List vmlist = new ArrayList<>(); - private CloudSim simulation; - - /** - * Starts the example. - * - * @param args - */ - public static void main(String[] args) { - new HostFaultInjection(); - } - - public HostFaultInjection() { - Log.printConcatLine("Starting ", getClass().getSimpleName(), "..."); - - simulation = new CloudSim(); - - Datacenter datacenter = createDatacenter(HOSTS); - createFaultInjectionForHosts(datacenter); - - DatacenterBroker broker = new DatacenterBrokerSimple(simulation); - createAndSubmitVms(broker); - createAndSubmitCloudlets(broker); - - simulation.start(); - - new CloudletsTableBuilder(broker.getCloudletsFinishedList()).build(); - - Log.printConcatLine(getClass().getSimpleName(), " finished!"); - //@todo ver a mensagem abaixo - System.out.println("A cloudlet 2 deveria terminar no segundo 40, pois ela iniciou em 10, mas ela não termina"); - } - - public void createAndSubmitCloudlets(DatacenterBroker broker) { - double initialCloudletCpuUtilizationPercentage = CLOUDLET_INITIAL_CPU_USAGE_PERCENT; - final int numberOfCloudlets = VMS - 1; - for (int i = 0; i < numberOfCloudlets; i++) { - createAndSubmitCloudletsWithStaticCpuUtilization( - initialCloudletCpuUtilizationPercentage, vmlist.get(i), broker); - initialCloudletCpuUtilizationPercentage += 0.15; - } - //Create one last cloudlet which CPU usage increases dynamically - Vm lastVm = vmlist.get(vmlist.size() - 1); - createAndSubmitCloudletsWithDynamicCpuUtilization(0.2, 1, lastVm, broker); - } - - public void createAndSubmitVms(DatacenterBroker broker) { - for (int i = 0; i < VMS; i++) { - Vm vm = createVm(broker); - vmlist.add(vm); - } - broker.submitVmList(vmlist); - } - - /** - * - * @param broker - * @return - * - * @todo @author manoelcampos The use of other CloudletScheduler instead of - * CloudletSchedulerDynamicWorkload makes the Host CPU usage not be updated - * (and maybe VM CPU usage too). - */ - public Vm createVm(DatacenterBroker broker) { - Vm vm = new VmSimple(vmlist.size(), VM_MIPS, VM_PES); - vm - .setRam(VM_RAM).setBw(VM_BW).setSize(VM_SIZE) - .setBroker(broker) - .setCloudletScheduler(new CloudletSchedulerTimeShared()); - return vm; - } - - /** - * Creates the number of Cloudlets defined in - * {@link #CLOUDLETS_BY_VM} and submits them to the - * given broker. - * - * @param cloudletInitialCpuUsagePercent the percentage of CPU utilization - * that created Cloudlets will use when they start to execute. If this value - * is greater than 1 (100%), it will be changed to 1. - * @param maxCloudletCpuUtilizationPercentage the maximum percentage of CPU - * utilization that created Cloudlets are allowed to use. If this value is - * greater than 1 (100%), it will be changed to 1. - * @param hostingVm the VM that will run the Cloudlets - * @param broker the broker that the created Cloudlets belong to - * @param progressiveCpuUsage if the CPU usage of created Cloudlets have to - * change along the execution time or not, according to the - * {@link #getCpuUtilizationIncrement(org.cloudbus.cloudsim.utilizationmodels.UtilizationModelDynamic)} - * @return the List of created Cloudlets - */ - public List createAndSubmitCloudlets( - double cloudletInitialCpuUsagePercent, - double maxCloudletCpuUtilizationPercentage, - Vm hostingVm, - DatacenterBroker broker, - boolean progressiveCpuUsage) { - cloudletInitialCpuUsagePercent = Math.min(cloudletInitialCpuUsagePercent, 1); - maxCloudletCpuUtilizationPercentage = Math.min(maxCloudletCpuUtilizationPercentage, 1); - final List list = new ArrayList<>(CLOUDLETS_BY_VM); - UtilizationModel utilizationModelFull = new UtilizationModelFull(); - int cloudletId; - for (int i = 0; i < CLOUDLETS_BY_VM; i++) { - cloudletId = hostingVm.getId() + i; - UtilizationModelDynamic cpuUtilizationModel; - if (progressiveCpuUsage) { - cpuUtilizationModel - = new UtilizationModelDynamic(cloudletInitialCpuUsagePercent) - .setUtilizationUpdateFunction(this::getCpuUtilizationIncrement); - } else { - cpuUtilizationModel = new UtilizationModelDynamic(cloudletInitialCpuUsagePercent); - } - cpuUtilizationModel.setMaxResourceUtilization(maxCloudletCpuUtilizationPercentage); - - Cloudlet c - = new CloudletSimple( - cloudletId, CLOUDLET_LENGHT, CLOUDLET_PES) - .setFileSize(CLOUDLET_FILESIZE) - .setOutputSize(CLOUDLET_OUTPUTSIZE) - .setUtilizationModelCpu(cpuUtilizationModel) - .setUtilizationModelRam(utilizationModelFull) - .setUtilizationModelBw(utilizationModelFull); - c.setBroker(broker); - list.add(c); - } - - broker.submitCloudletList(list); - for (Cloudlet c : list) { - broker.bindCloudletToVm(c, hostingVm); - } - - return list; - } - - /** - * Increments the CPU resource utilization, that is defined in percentage - * values. - * - * @return the new resource utilization after the increment - */ - private double getCpuUtilizationIncrement(UtilizationModelDynamic um) { - return um.getUtilization() + um.getTimeSpan() * CLOUDLET_CPU_USAGE_INCREMENT_PER_SECOND; - } - - public List createAndSubmitCloudletsWithDynamicCpuUtilization( - double initialCloudletCpuUtilizationPercentage, - double maxCloudletCpuUtilizationPercentage, - Vm hostingVm, - DatacenterBroker broker) { - return createAndSubmitCloudlets( - initialCloudletCpuUtilizationPercentage, - maxCloudletCpuUtilizationPercentage, hostingVm, broker, true); - } - - public List createAndSubmitCloudletsWithStaticCpuUtilization( - double initialCloudletCpuUtilizationPercentage, - Vm hostingVm, - DatacenterBroker broker) { - return createAndSubmitCloudlets( - initialCloudletCpuUtilizationPercentage, - initialCloudletCpuUtilizationPercentage, - hostingVm, broker, false); - } - - private Datacenter createDatacenter(int numberOfHosts) { - hostList = new ArrayList<>(); - for (int i = 0; i < numberOfHosts; i++) { - hostList.add(createHost()); - Log.printConcatLine("#Created host ", i, " with ", HOST_MIPS_BY_PE, " mips x ", HOST_PES); - } - Log.printLine(); - - DatacenterCharacteristics characteristics - = new DatacenterCharacteristicsSimple(hostList) - .setCostPerSecond(DATACENTER_COST_PER_CPU) - .setCostPerMem(DATACENTER_COST_PER_RAM) - .setCostPerStorage(DATACENTER_COST_PER_STORAGE) - .setCostPerBw(DATACENTER_COST_PER_BW); - - /*@todo nao está sendo usado por enquanto, apenas para evitar migração - PowerVmAllocationPolicyMigrationWorstFitStaticThreshold allocationPolicy - = new PowerVmAllocationPolicyMigrationWorstFitStaticThreshold( - new PowerVmSelectionPolicyMinimumUtilization(), - HOST_USAGE_THRESHOLD_VM_MIGRATION);*/ - - Datacenter dc = new DatacenterSimple(simulation, characteristics, new VmAllocationPolicySimple()); - dc - //.setMigrationsEnabled(false) - .setSchedulingInterval(SCHEDULE_TIME_TO_PROCESS_DATACENTER_EVENTS) - .setLog(false); - return dc; - } - - /** - * Creates a Host. - * @return - */ - public Host createHost() { - List pesList = new ArrayList<>(HOST_PES); - for (int i = 0; i < HOST_PES; i++) { - pesList.add(new PeSimple(HOST_MIPS_BY_PE, new PeProvisionerSimple())); - } - - ResourceProvisioner ramProvisioner = new ResourceProvisionerSimple(); - ResourceProvisioner bwProvisioner = new ResourceProvisionerSimple(); - VmScheduler vmScheduler = new VmSchedulerTimeShared(); - final int id = hostList.size(); - return new HostSimple(HOST_RAM, HOST_BW, HOST_STORAGE, pesList) - .setRamProvisioner(ramProvisioner) - .setBwProvisioner(bwProvisioner) - .setVmScheduler(vmScheduler); - } - - public List createPeList(int numberOfPEs, long mips) { - List list = new ArrayList<>(numberOfPEs); - for (int i = 0; i < numberOfPEs; i++) { - list.add(new PeSimple(mips, new PeProvisionerSimple())); - } - return list; - } - - /** - * Creates the fault injection for host - * - * @param datacenter - */ - private void createFaultInjectionForHosts(Datacenter datacenter) { - final int MAX_TIME_TO_GENERATE_FAILURE = 10; - //final long seed = System.currentTimeMillis(); - final long seed = 49998811; - - - UniformDistr failedPesGenerator = new UniformDistr(seed); - UniformDistr failureDelayGenerator = new UniformDistr(1, MAX_TIME_TO_GENERATE_FAILURE, seed); - int i = 0; - for (Host host: datacenter.getHostList()) { - PoissonDistribution poisson = new PoissonDistribution(0.2, seed + i++); - if (poisson.eventsHappened()) { - HostFaultInjection fault = new HostFaultInjection(host); - fault.setFailedPesGenerator(failedPesGenerator); - fault.setFailureDelayGenerator(failureDelayGenerator); - fault.setVmCloner(this::cloneVm); - fault.setCloudletsCloner(this::cloneCloudlets); - Log.printFormattedLine("\tFault Injection created for %s.", host); - } - } - } - - /** - * Clones a VM by creating another one with the same configurations of a given VM. - * @param vm the VM to be cloned - * @return the cloned (new) VM. - * - * @see #createFaultInjectionForHosts(org.cloudbus.cloudsim.datacenters.Datacenter) - */ - private Vm cloneVm(Vm vm){ - Vm clone = new VmSimple((long)vm.getMips(), (int)vm.getNumberOfPes()); - clone.setDescription("Clone of VM " + vm.getId()); - clone - .setSize(vm.getStorage().getCapacity()) - .setBw(vm.getBw().getCapacity()) - .setRam(vm.getBw().getCapacity()) - .setCloudletScheduler(new CloudletSchedulerTimeShared()); - Log.printFormattedLine("\n\n#Cloning VM %d\n\tMips %.2f Number of Pes: %d ", vm.getId(), clone.getMips(), clone.getNumberOfPes()); - - return clone; - } - - /** - * Clones each Cloudlet associated to a given VM. - * The method is called when a VM is destroyed due to a - * Host failure and a snapshot from that VM (a clone) - * is started into another Host. - * In this case, all the Cloudlets which were running inside - * the destroyed VM will be recreated from scratch into the VM clone, - * re-starting their execution from the beginning. - * - * @param sourceVm the VM to clone its Cloudlets - * @return the List of cloned Cloudlets. - * @see #createFaultInjectionForHosts(org.cloudbus.cloudsim.datacenters.Datacenter) - */ - private List cloneCloudlets(Vm sourceVm){ - final List sourceVmCloudlets = sourceVm.getCloudletScheduler().getCloudletList(); - final List clonedCloudlets = new ArrayList<>(sourceVmCloudlets.size()); - for(Cloudlet cl: sourceVmCloudlets){ - clonedCloudlets.add(cloneCloudlet(cl)); - } - - return clonedCloudlets; - } - - /** - * Creates a clone from a given Cloudlet. - * @param sourceCloudlet the Cloudlet to be cloned. - * @return the cloned (new) cloudlet - */ - private Cloudlet cloneCloudlet(Cloudlet sourceCloudlet) { - Cloudlet clone = new CloudletSimple(sourceCloudlet.getLength(), (int)sourceCloudlet.getNumberOfPes()); - clone - .setUtilizationModelBw(sourceCloudlet.getUtilizationModelBw()) - .setUtilizationModelCpu(sourceCloudlet.getUtilizationModelCpu()) - .setUtilizationModelRam(sourceCloudlet.getUtilizationModelRam()); - return clone; - - } - -} diff --git a/cloudsim-plus-testbeds/src/main/java/org/cloudsimplus/sla/tasktimecompletion/CloudletTaskTimeCompletionMinimizationExperiment.java b/cloudsim-plus-testbeds/src/main/java/org/cloudsimplus/sla/tasktimecompletion/CloudletTaskTimeCompletionMinimizationExperiment.java index 24c777ac6..17d1fad3c 100644 --- a/cloudsim-plus-testbeds/src/main/java/org/cloudsimplus/sla/tasktimecompletion/CloudletTaskTimeCompletionMinimizationExperiment.java +++ b/cloudsim-plus-testbeds/src/main/java/org/cloudsimplus/sla/tasktimecompletion/CloudletTaskTimeCompletionMinimizationExperiment.java @@ -52,6 +52,7 @@ import org.cloudbus.cloudsim.provisioners.ResourceProvisionerSimple; import org.cloudbus.cloudsim.resources.Pe; import org.cloudbus.cloudsim.resources.PeSimple; +import org.cloudbus.cloudsim.schedulers.cloudlet.CloudletSchedulerCompletelyFair; import org.cloudbus.cloudsim.schedulers.cloudlet.CloudletSchedulerTimeShared; import org.cloudbus.cloudsim.schedulers.vm.VmScheduler; import org.cloudbus.cloudsim.schedulers.vm.VmSchedulerTimeShared; @@ -292,36 +293,10 @@ private Vm createVm() { Vm vm = new VmSimple(id, 1000, pes) .setRam(512).setBw(1000).setSize(10000).setBroker(broker0) - .setCloudletScheduler(new CloudletSchedulerTimeShared()); + .setCloudletScheduler(new CloudletSchedulerCompletelyFair()); return vm; } - /** - * Creates a {@link HorizontalVmScaling} object for a given VM. - * - * @param vm the VM in which the Horizontal Scaling will be created - */ - private void createHorizontalVmScaling(Vm vm) { - HorizontalVmScaling horizontalScaling = new HorizontalVmScalingSimple(); - horizontalScaling - .setVmSupplier(this::createVm) - .setOverloadPredicate(this::isVmOverloaded); - vm.setHorizontalScaling(horizontalScaling); - } - - /** - * A {@link Predicate} that checks if a given VM is overloaded or not based - * on CPU usage. A reference to this method is assigned to each Horizontal - * VM Scaling created. - * - * @param vm the VM to check if it is overloaded - * @return true if the VM is overloaded, false otherwise - * @see #createHorizontalVmScaling(Vm) - */ - private boolean isVmOverloaded(Vm vm) { - return vm.getCurrentCpuPercentUse() > cpuUtilizationSlaContract; - } - @Override protected List createHosts() { hostList = new ArrayList<>(HOSTS); @@ -357,8 +332,8 @@ protected DatacenterBroker createBroker() { } /** - * Computes the TaskTimeCompletion average for all finished Cloudlets on this - * experiment. + * Computes the TaskTimeCompletion average for all finished Cloudlets on + * this experiment. * * @return the TaskTimeCompletion average */ @@ -442,6 +417,20 @@ protected DatacenterBroker createBroker() { return totalCost; } + /** + * Shows the wait time of cloudlets + * + * @param cloudlet list of cloudlets + */ + public void waitTimeAverage(List cloudlet) { + double waitTime = 0, quant = 0; + for (Cloudlet cloudlets : cloudlet) { + waitTime += cloudlets.getWaitingTime(); + quant++; + } + System.out.println("\n# The wait time is: " + waitTime / quant); + } + /** * A main method just for test purposes. * @@ -460,5 +449,6 @@ public static void main(String[] args) throws FileNotFoundException, IOException exp.getCloudletsTaskTimeCompletionAverage(); exp.getPercentageOfCloudletsMeetingTaskTimeCompletion(); double totalCost = exp.getTotalCostPrice(); + exp.waitTimeAverage(exp.getCloudletList()); } } diff --git a/cloudsim-plus-testbeds/src/main/java/org/cloudsimplus/sla/tasktimecompletion/CloudletTaskTimeCompletionMinimizationRunner.java b/cloudsim-plus-testbeds/src/main/java/org/cloudsimplus/sla/tasktimecompletion/CloudletTaskTimeCompletionMinimizationRunner.java index be56a6449..bdab60651 100644 --- a/cloudsim-plus-testbeds/src/main/java/org/cloudsimplus/sla/tasktimecompletion/CloudletTaskTimeCompletionMinimizationRunner.java +++ b/cloudsim-plus-testbeds/src/main/java/org/cloudsimplus/sla/tasktimecompletion/CloudletTaskTimeCompletionMinimizationRunner.java @@ -46,8 +46,8 @@ final class CloudletTaskTimeCompletionMinimizationRunner extends ExperimentRunne */ static final long[] CLOUDLET_LENGTHS = {10000, 14000, 20000, 40000}; static final int[] VM_PES = {2, 4}; - static final int VMS = 4; - static final int CLOUDLETS = 8; + static final int VMS = 30; + static final int CLOUDLETS = 50; /** * The TaskTimeCompletion average for all the experiments. @@ -83,7 +83,7 @@ final class CloudletTaskTimeCompletionMinimizationRunner extends ExperimentRunne */ public static void main(String[] args) { new CloudletTaskTimeCompletionMinimizationRunner() - .setSimulationRuns(500) + .setSimulationRuns(300) .setApplyAntitheticVariatesTechnique(true) .setNumberOfBatches(5) //Comment this or set to 0 to disable the "Batch Means Method" .setBaseSeed(1475098589732L) //Comment this to use the current time as base seed 1475098589732L diff --git a/cloudsim-plus-testbeds/src/main/java/org/cloudsimplus/sla/tasktimecompletion/CloudletTaskTimeCompletionWithoutMinimizationRunner.java b/cloudsim-plus-testbeds/src/main/java/org/cloudsimplus/sla/tasktimecompletion/CloudletTaskTimeCompletionWithoutMinimizationRunner.java index 95bd9bc84..838cb3eae 100644 --- a/cloudsim-plus-testbeds/src/main/java/org/cloudsimplus/sla/tasktimecompletion/CloudletTaskTimeCompletionWithoutMinimizationRunner.java +++ b/cloudsim-plus-testbeds/src/main/java/org/cloudsimplus/sla/tasktimecompletion/CloudletTaskTimeCompletionWithoutMinimizationRunner.java @@ -47,8 +47,8 @@ public class CloudletTaskTimeCompletionWithoutMinimizationRunner extends Experim */ static final long[] CLOUDLET_LENGTHS = {10000, 14000, 20000, 40000}; static final int[] VM_PES = {2, 4}; - static final int VMS = 4; - static final int CLOUDLETS = 8; + static final int VMS = 30; + static final int CLOUDLETS = 50; /** * The TaskTimeCompletion average for all the experiments. @@ -84,7 +84,7 @@ public class CloudletTaskTimeCompletionWithoutMinimizationRunner extends Experim */ public static void main(String[] args) { new CloudletTaskTimeCompletionWithoutMinimizationRunner() - .setSimulationRuns(500) + .setSimulationRuns(300) .setApplyAntitheticVariatesTechnique(true) .setNumberOfBatches(5) //Comment this or set to 0 to disable the "Batch Means Method" .setBaseSeed(1475098589732L) //Comment this to use the current time as base seed 1475098589732L diff --git a/cloudsim-plus-testbeds/src/main/java/org/cloudsimplus/sla/tasktimecompletion/CloudletTaskTimeCompletionWorkLoadExperimet.java b/cloudsim-plus-testbeds/src/main/java/org/cloudsimplus/sla/tasktimecompletion/CloudletTaskTimeCompletionWorkLoadExperimet.java index fb69328b8..ff52f04b2 100644 --- a/cloudsim-plus-testbeds/src/main/java/org/cloudsimplus/sla/tasktimecompletion/CloudletTaskTimeCompletionWorkLoadExperimet.java +++ b/cloudsim-plus-testbeds/src/main/java/org/cloudsimplus/sla/tasktimecompletion/CloudletTaskTimeCompletionWorkLoadExperimet.java @@ -105,7 +105,7 @@ public class CloudletTaskTimeCompletionWorkLoadExperimet extends SimulationExper * Different lengths that will be randomly assigned to created Cloudlets. */ private static final long[] CLOUDLET_LENGTHS = {20000, 40000, 14000, 10000, 10000}; - private static final int[] VM_PES = {2, 4}; + private static final int[] VM_PES = {2}; /** * Sorts the Cloudlets before submitting them to the Broker, so that @@ -170,7 +170,7 @@ protected List createCloudlets(DatacenterBroker broker) { cloudletList = new ArrayList<>(); try { workloadFileReader = new WorkloadFileReader("/Users/raysaoliveira/Desktop/Mestrado/cloudsim-plus/cloudsim-plus-testbeds/src/main/resources/METACENTRUM-2009-2.swf", 1); - cloudletList = workloadFileReader.generateWorkload().subList(0, 800); + cloudletList = workloadFileReader.generateWorkload().subList(0, 1000); } catch (FileNotFoundException ex) { Logger.getLogger(CloudletTaskTimeCompletionWorkLoadExperimet.class.getName()).log(Level.SEVERE, null, ex); } catch (IOException ex) { @@ -277,32 +277,6 @@ private Vm createVm() { return vm; } - /** - * Creates a {@link HorizontalVmScaling} object for a given VM. - * - * @param vm the VM in which the Horizontal Scaling will be created - */ - private void createHorizontalVmScaling(Vm vm) { - HorizontalVmScaling horizontalScaling = new HorizontalVmScalingSimple(); - horizontalScaling - .setVmSupplier(this::createVm) - .setOverloadPredicate(this::isVmOverloaded); - vm.setHorizontalScaling(horizontalScaling); - } - - /** - * A {@link Predicate} that checks if a given VM is overloaded or not based - * on CPU usage. A reference to this method is assigned to - * each Horizontal VM Scaling created. - * - * @param vm the VM to check if it is overloaded - * @return true if the VM is overloaded, false otherwise - * @see #createHorizontalVmScaling(Vm) - */ - private boolean isVmOverloaded(Vm vm) { - return vm.getCurrentCpuPercentUse() > cpuUtilizationSlaContract; - } - @Override protected List createHosts() { hostList = new ArrayList<>(HOSTS); @@ -404,6 +378,21 @@ protected DatacenterBroker createBroker() { return sumPesVms / sumPesCloudlets; } + + /** + * Shows the wait time of cloudlets + * + * @param cloudlet list of cloudlets + */ + public void waitTimeAverage(List cloudlet) { + double waitTime = 0, quant = 0; + for (Cloudlet cloudlets : cloudlet) { + waitTime += cloudlets.getWaitingTime(); + quant++; + } + System.out.println("\n# The wait time is: " + waitTime/quant); + } + /** * A main method just for test purposes. @@ -423,5 +412,6 @@ public static void main(String[] args) throws FileNotFoundException, IOException exp.getCloudletsTaskTimeCompletionAverage(); exp.getPercentageOfCloudletsMeetingTaskTimeCompletion(); exp.getRatioOfExistingVmPesToRequiredCloudletPes(); + exp.waitTimeAverage(exp.getCloudletList()); } } diff --git a/cloudsim-plus-testbeds/src/main/java/org/cloudsimplus/sla/tasktimecompletion/CloudletTaskTimeCompletionWorkLoadRunner.java b/cloudsim-plus-testbeds/src/main/java/org/cloudsimplus/sla/tasktimecompletion/CloudletTaskTimeCompletionWorkLoadRunner.java index 56930765f..240247fb6 100644 --- a/cloudsim-plus-testbeds/src/main/java/org/cloudsimplus/sla/tasktimecompletion/CloudletTaskTimeCompletionWorkLoadRunner.java +++ b/cloudsim-plus-testbeds/src/main/java/org/cloudsimplus/sla/tasktimecompletion/CloudletTaskTimeCompletionWorkLoadRunner.java @@ -47,7 +47,7 @@ public class CloudletTaskTimeCompletionWorkLoadRunner extends ExperimentRunnerPoisson Distribution * @see Poisson Point Process * * @author Manoel Campos da Silva Filho + * @since CloudSim Plus 1.2.0 */ -public class PoissonDistribution extends ContinuousDistributionAbstract { +public class PoissonProcess { + /** + * A random number generator that returns values between [0 and 1[. + */ + private ContinuousDistribution rand; + /** * @see #getLambda() */ @@ -50,33 +55,53 @@ public class PoissonDistribution extends ContinuousDistributionAbstract { private int k; /** - * Creates a new Poisson process that considers you want to check - * the probability of 1 event ({@link #getK() k}) to happen at each time. + * Creates a new Poisson process to check + * the probability of 1 event ({@link #getK() k}) to happen at each time + * interval. * - * @param lambda average number of events by interval + * @param lambda the average number of events that happen at each 1 time unit. * @param seed the seed to initialize the uniform random number generator * @see #setK(int) + * @see #setLambda(double) */ - public PoissonDistribution(double lambda, long seed){ - super(new UniformRealDistribution(0, 1), seed); + public PoissonProcess(double lambda, long seed){ + this.rand = new UniformDistr(seed); this.k = 1; this.setLambda(lambda); } - + /** + * Creates a new Poisson process that considers you want to check + * the probability of 1 event ({@link #getK() k}) to happen at each time. * - * @return the average number of events that happen at each single time unit. - * It is also called the event rate or rate parameter. + * @param lambda average number of events by interval + * + * @see #setK(int) + */ + public PoissonProcess(double lambda){ + this(lambda, -1); + } + + /** + * Gets the average number of events that are expected to happen at each 1 time unit. + * It is the expected number of events to happen each time, + * also called the event rate or rate parameter. * - * If the unit is minute, it means the average number of arrivals - * at each minute. + *

If the unit is minute, this value means the average number of arrivals + * at each minute. It's the inverse of the {@link #getInterarrivalMeanTime()}.

+ * @return */ public double getLambda(){ return lambda; } /** - * Sets the average number of events that happen at each single time unit. + * Sets the average number of events that are expected to happen at each 1 time unit. + * It is the expected number of events to happen each time, + * also called the event rate or rate parameter. + * + *

If the unit is minute, this value means the average number of arrivals + * at each minute. It's the inverse of the {@link #getInterarrivalMeanTime()}.

* @param lambda the value to set */ private void setLambda(double lambda) { @@ -84,7 +109,8 @@ private void setLambda(double lambda) { } /** - * Gets the probability to arrive {@link #getK() K} events in the current time. + * Gets the probability to arrive {@link #getK() K} events in the current time, + * considering the expected average arrival time {@link #getLambda() lambda}. * @return * @see Poisson distribution */ @@ -102,7 +128,7 @@ public double eventsArrivalProbability(){ * @see #eventsArrivalProbability() */ public boolean eventsHappened(){ - return sample() >= eventsArrivalProbability(); + return rand.sample() >= eventsArrivalProbability(); } /** @@ -124,8 +150,8 @@ public void setK(int k) { } /** - * - * @return the mean time between arrival of two events. + * Gets the mean time between arrival of two events. + * @return */ public double getInterarrivalMeanTime(){ final double oneMinute = 1.0; @@ -153,14 +179,14 @@ public static void main(String args[]){ final int SIMULATION_TIME_LENGHT = 25; //If the arrival of each customers must be shown. - final boolean showCustomerArrivals = false; + final boolean showCustomerArrivals = true; /* * Number of simulations to run. */ int NUMBER_OF_SIMULATIONS = 100; - BiConsumer printArrivals = (poisson, minute) -> { + BiConsumer printArrivals = (poisson, minute) -> { if(showCustomerArrivals) System.out.printf("%d customers arrived at minute %d\n", poisson.getK(), minute); }; @@ -169,10 +195,10 @@ public static void main(String args[]){ * A {@link Function} to simulate the arrival of customers for a given time period. * This is just a method to test the implementation. * - * @param poisson the PoissonDistribution object that will compute the customer arrivals probabilities + * @param poisson the PoissonProcess object that will compute the customer arrivals probabilities * @return the number of arrived customers */ - Function runSimulation = poisson -> { + Function runSimulation = poisson -> { /*We want to check the probability of 1 customer to arrive at each single minute. The default k value is 1, so we dont need to set it.*/ final int totalArrivedCustomers = @@ -191,10 +217,10 @@ public static void main(String args[]){ }; int customersArrivedInAllSimulations = 0; - PoissonDistribution poisson = null; + PoissonProcess poisson = null; for(int i = 0; i < NUMBER_OF_SIMULATIONS; i++){ long seed=System.currentTimeMillis(); - poisson = new PoissonDistribution(MEAN_CUSTOMERS_ARRIVAL_PER_MINUTE, seed); + poisson = new PoissonProcess(MEAN_CUSTOMERS_ARRIVAL_PER_MINUTE, seed); System.out.printf("Simulation number %d\n", i); customersArrivedInAllSimulations += runSimulation.apply(poisson); } diff --git a/cloudsim-plus/src/main/java/org/cloudbus/cloudsim/schedulers/cloudlet/CloudletSchedulerCompletelyFair.java b/cloudsim-plus/src/main/java/org/cloudbus/cloudsim/schedulers/cloudlet/CloudletSchedulerCompletelyFair.java index 7c6fb3b95..7df9df539 100644 --- a/cloudsim-plus/src/main/java/org/cloudbus/cloudsim/schedulers/cloudlet/CloudletSchedulerCompletelyFair.java +++ b/cloudsim-plus/src/main/java/org/cloudbus/cloudsim/schedulers/cloudlet/CloudletSchedulerCompletelyFair.java @@ -209,7 +209,7 @@ protected double computeCloudletTimeSlice(CloudletExecutionInfo cloudlet){ } /** - * Gets a list of Cloudlets that are waiting to run, the so called + * Gets a read-only list of Cloudlets which are waiting to run, the so called * run queue. * *

diff --git a/cloudsim-plus/src/main/java/org/cloudsimplus/faultinjection/HostFaultInjection.java b/cloudsim-plus/src/main/java/org/cloudsimplus/faultinjection/HostFaultInjection.java index c32712eae..42855597c 100644 --- a/cloudsim-plus/src/main/java/org/cloudsimplus/faultinjection/HostFaultInjection.java +++ b/cloudsim-plus/src/main/java/org/cloudsimplus/faultinjection/HostFaultInjection.java @@ -41,28 +41,27 @@ import org.cloudbus.cloudsim.vms.Vm; import org.cloudbus.cloudsim.core.*; import org.cloudbus.cloudsim.distributions.ContinuousDistribution; +import org.cloudbus.cloudsim.distributions.PoissonProcess; import org.cloudbus.cloudsim.distributions.UniformDistr; import org.cloudbus.cloudsim.resources.Pe; import org.cloudbus.cloudsim.resources.Pe.Status; /** - * This class shows how to generate a fault. In this case the fault is in the - * host. - * - * Notes: This class does not work with the injection fault in time 0. Only - * works after the creation of cloudlets and VMs, because when destroying the - * VM, the cloudlet is not returned to be chosen by another VM that did not - * fail, thus causing error in the simulator. + * Generates random failures for the {@link Pe}'s of a specific {@link Host}. + * The events happens in the following order: + *

    + *
  1. a failure is injected randomly;
  2. + *
  3. a delay is defined for the failure to actually happen;
  4. + *
  5. the number of PEs to fail is randomly generated.
  6. + *
* * @author raysaoliveira - * - * see https://blogs.sap.com/2014/07/21/equipment-availability-vs-reliability/ - * + * @since CloudSim Plus 1.2.0 + * @see https://blogs.sap.com/2014/07/21/equipment-availability-vs-reliability/ */ public class HostFaultInjection extends CloudSimEntity { private Host host; - private ContinuousDistribution failedPesGenerator; - private ContinuousDistribution failureDelayGenerator; + private ContinuousDistribution random; /** * @todo The class has multiple responsibilities. @@ -73,23 +72,26 @@ public class HostFaultInjection extends CloudSimEntity { */ private UnaryOperator vmCloner; private Function> cloudletsCloner; + private PoissonProcess failureInjectionGenerator; + + private double maxFailureDelay; /** - * Creates a fault injection mechanism for a host that will generate - * failures with a delay and number of failed PEs generated using a Uniform - * Pseudo Random Number Generator (PRNG) for each one. + * Creates a fault injection mechanism for a host that will inject + * failures with a delay and number of failed PEs generated using a given + * Pseudo Random Number Generator (PRNG). * - * @param host the Host the faults will be generated on - * @see - * #setFailureDelayGenerator(org.cloudbus.cloudsim.distributions.ContinuousDistribution) - * @see - * #setFailedPesGenerator(org.cloudbus.cloudsim.distributions.ContinuousDistribution) + * @param host the Host to which failures may be randomly generated + * @param meanFailuresPerMinute the average number of failures expected to happen each minute. + * @param seed the seed to initialize the internal uniform random number generator + * @see #setMaxFailureDelay(double) */ - public HostFaultInjection(Host host) { + public HostFaultInjection(Host host, double meanFailuresPerMinute, long seed) { super(host.getSimulation()); this.setHost(host); - this.failedPesGenerator = new UniformDistr(); - this.failureDelayGenerator = new UniformDistr(); + this.maxFailureDelay = 0; + this.failureInjectionGenerator = new PoissonProcess(meanFailuresPerMinute, seed); + this.random = new UniformDistr(seed); /*Sets a default vmCloner which in fact doesn't clone a VM, just returns the Vm.NULL object. @@ -104,15 +106,31 @@ public HostFaultInjection(Host host) { return Vm.NULL; }; this.cloudletsCloner = vm -> { - Log.printFormattedLine("%s: You should define a Cloudlets Cloner Function to re-create the List of running Cloudlets from a faulty VM into the Cloned VM when there is a Host failure", + Log.printFormattedLine( + "%s: You should define a Cloudlets Cloner Function to re-create the List of running Cloudlets from a faulty VM into the Cloned VM when there is a Host failure", getClass().getSimpleName()); return Collections.EMPTY_LIST; }; - } + } @Override protected void startEntity() { - double delay = failureDelayGenerator.sample() + 1; + scheduleFailureCheck(); + } + + /** + * Schedules a message to be processed internally to check, + * at every 1 minute, if a failure must be injected or not. + */ + private void scheduleFailureCheck() { + if( getSimulation().clock() > 400){ + return; + } + + /*The number of failures is defined in minutes, + so at each 60 seconds it checks if a failure has to be generated + or not.*/ + final double delay = 60; schedule(getId(), delay, CloudSimTags.HOST_FAILURE); } @@ -120,7 +138,7 @@ protected void startEntity() { public void processEvent(SimEvent ev) { switch (ev.getTag()) { case CloudSimTags.HOST_FAILURE: - generateFailure(); + tryGenerateFailure(); break; default: Log.printLine(getName() + ": unknown event type"); @@ -132,42 +150,54 @@ public void processEvent(SimEvent ev) { public void shutdownEntity() {/**/} /** - * Generates a failure on Host's PEs or not, according to the number of PEs + * Try to generates a failure on Host's PEs or not, according to the number of PEs * to be set to failed, returned by the {@link #failedPesGenerator} * PRNG. * * @return true if the failure was generated, false * otherwise */ - private boolean generateFailure() { - final int numberOfFailedPes = generateHostPesFailures(); - final long hostWorkingPes = host.getNumberOfWorkingPes(); - final long vmsRequiredPes = getPesSumOfWorkingVms(); - Log.printFormattedLine("\t%.2f: Generated %d PEs failures for %s", getSimulation().clock(), numberOfFailedPes, host); - if(vmsRequiredPes == 0){ - System.out.printf("\t Number of VMs: %d\n", host.getVmList().size()); + private boolean tryGenerateFailure() { + try { + if(!failureInjectionGenerator.eventsHappened()){ + return false; + } + + final int numberOfFailedPes = generateHostPesFailures(); + final long hostWorkingPes = host.getNumberOfWorkingPes(); + final long vmsRequiredPes = getPesSumOfWorkingVms(); + Log.printFormattedLine("%.2f: %s: Generated %d PEs failures for %s", + getSimulation().clock(), getClass().getSimpleName(), + numberOfFailedPes, host); + if(vmsRequiredPes == 0){ + Log.printFormattedLine("\tNumber of VMs: %d", host.getVmList().size()); + } + Log.printFormattedLine("\tWorking PEs: %d | VMs required PEs: %d", hostWorkingPes, vmsRequiredPes); + if(hostWorkingPes == 0){ + //double clockInicioFalha = getSimulation().clock(); + //Log.printFormattedLine("\n#Inicio Falha no Host %d : %f", host.getId(),clockInicioFalha); + setAllVmsToFailed(); + + } else if (hostWorkingPes >= vmsRequiredPes) { + logNoVmFailure(); + } else { + deallocateFailedHostPesFromVms(); + } + + return numberOfFailedPes > 0; + } finally { + /*schedules the failure check for the next minute + to see if a failure will be injected at that time.*/ + scheduleFailureCheck(); } - System.out.printf("\t Working PEs: %d | VMs required PEs: %d\n", hostWorkingPes, vmsRequiredPes); - if(hostWorkingPes == 0){ - //double clockInicioFalha = getSimulation().clock(); - //Log.printFormattedLine("\n#Inicio Falha no Host %d : %f", host.getId(),clockInicioFalha); - setAllVmsToFailed(); - - } else if (hostWorkingPes >= vmsRequiredPes) { - logNoVmFailure(); - } else { - deallocateFailedHostPesFromVms(); - } - - return numberOfFailedPes > 0; } /** * Sets all VMs to failed when all Host PEs failed. */ private void setAllVmsToFailed() { - Log.printFormattedLine("\t%.2f: %s -> All the %d PEs failed, affecting all its %d VMs.\n", - getSimulation().clock(), host, host.getNumberOfPes(), host.getVmList().size()); + Log.printFormattedLine("\tAll the %d PEs failed, affecting all its %d VMs.\n", + host.getNumberOfPes(), host.getVmList().size()); host.getVmList().stream().forEach(this::setVmToFailedAndCreateClone); } @@ -178,10 +208,10 @@ private void setAllVmsToFailed() { private void logNoVmFailure() { final int vmsRequiredPes = (int)getPesSumOfWorkingVms(); Log.printFormattedLine( - "\t%.2f: %s -> Number of failed PEs is less than PEs required by all its %d VMs, thus it doesn't affect any VM.", - getSimulation().clock(), host, host.getVmList().size()); - Log.printFormattedLine("\t %s -> Total PEs: %d | Failed PEs: %d | Working PEs: %d | Current PEs required by VMs: %d.\n", - host, host.getNumberOfPes(), host.getNumberOfFailedPes(), host.getNumberOfWorkingPes(), + "\tNumber of failed PEs is less than PEs required by all its %d VMs, thus it doesn't affect any VM.", + host.getVmList().size()); + Log.printFormattedLine("\tTotal PEs: %d | Failed PEs: %d | Working PEs: %d | Current PEs required by VMs: %d.\n", + host.getNumberOfPes(), host.getNumberOfFailedPes(), host.getNumberOfWorkingPes(), vmsRequiredPes); } @@ -189,16 +219,32 @@ private void deallocateFailedHostPesFromVms() { final int hostWorkingPes = (int)host.getNumberOfWorkingPes(); final int vmsRequiredPes = (int)getPesSumOfWorkingVms(); - int i = 0; int failedPesToRemoveFromVms = vmsRequiredPes-hostWorkingPes; final int affectedVms = Math.min(host.getVmList().size(), failedPesToRemoveFromVms); Log.printFormattedLine( - "\t%.2f: %s -> %d PEs failed, from a total of %d PEs. There are %d PEs working.", - getSimulation().clock(), host, host.getNumberOfFailedPes(), + "\t%d PEs failed, from a total of %d PEs. There are %d PEs working.", + host.getNumberOfFailedPes(), host.getNumberOfPes(), host.getNumberOfWorkingPes()); Log.printFormattedLine( - "\t %d VMs affected from a total of %d. %d PEs are going to be removed from VMs", + "\t%d VMs affected from a total of %d. %d PEs are going to be removed from VMs", affectedVms, host.getVmList().size(), failedPesToRemoveFromVms); + cyclicallyRemoveFailedHostPesFromVms(failedPesToRemoveFromVms, affectedVms); + + Log.printLine(); + setVmsToFailed(); + } + + /** + * Removes one physical failed PE from one affected VM at a time. + * The affected VMs are dealt as a circular list, visiting + * one VM at a time to remove 1 PE from it, + * until all the failed PEs are removed. + * + * @param failedPesToRemoveFromVms number of physical PEs to remove + * @param affectedVms number of VMs affected by PEs failures + */ + private void cyclicallyRemoveFailedHostPesFromVms(int failedPesToRemoveFromVms, final int affectedVms) { + int i = 0; while(failedPesToRemoveFromVms-- > 0){ i = i % affectedVms; Vm vm = host.getVmList().get(i); @@ -208,13 +254,10 @@ private void deallocateFailedHostPesFromVms() { //remove 1 failed PE from the VM vm.getProcessor().removeCapacity(1); Log.printFormattedLine( - "\t Removing 1 PE from VM %d due to Host PE failure. New VM PEs Number: %d\n", + "\tRemoving 1 PE from VM %d due to Host PE failure. New VM PEs Number: %d\n", vm.getId(), vm.getNumberOfPes()); i++; } - - Log.printLine(); - setVmsToFailed(); } /** @@ -256,9 +299,7 @@ private void setVmToFailedAndCreateClone(Vm vm) { List cloudlets = cloudletsCloner.apply(vm); cloudlets.stream().forEach(c -> setBrokerToEntity(c, broker)); - vm.setFailed(true); - Log.printFormattedLine("#Vm %d is being destroying...", vm.getId()); /* As the broker is expected to request vm creation and destruction, @@ -284,11 +325,16 @@ private void setBrokerToEntity(CustomerEntity entity, DatacenterBroker broker) { } } + /** + * Generates random failures for the Host's PEs. + * @return + */ private int generateHostPesFailures() { final int numberOfFailedPes = generateNumberOfFailedPes(); for (int i = 0; i < numberOfFailedPes; i++) { host.getPeList().get(i).setStatus(Pe.Status.FAILED); } + return numberOfFailedPes; } @@ -304,8 +350,7 @@ private long getPesSumOfWorkingVms() { } /** - * Generates a number of PEs that will fail for the host using the - * {@link #failedPesGenerator}, + * Randomly generates a number of PEs which will fail for the host. * * @return the generated number of failed PEs for the host */ @@ -313,7 +358,7 @@ private int generateNumberOfFailedPes() { /*the random generator return values from [0 to 1] and multiplying by the number of PEs we get a number between 0 and numbero of PEs*/ - return (int) (failedPesGenerator.sample() * host.getPeList().size() + 1); + return (int) (random.sample() * host.getPeList().size() + 1); } /** @@ -341,45 +386,49 @@ public Host getHost() { * * @param host the host to set */ - private void setHost(Host host) { + protected final void setHost(Host host) { Objects.requireNonNull(host); this.host = host; } /** - * Sets the pseudo random number generator (PRNG) that is used to define the - * number of PEs to be set as failed for the related host. + * Sets the maximum delay after a fault be injected + * that it will in fact happen (default is 0). * - *

The PRNG must return values between [0 and 1[. - * The actual number of failed PEs depends on each Host, - * therefore it is computed internally.

+ *

+ * This is used to define, randomly + * the actual time, after the time the fault was + * injected, that it will happen. + * For instance, if a fault is generated + * and a value 5 is chosen between 0 and the maximum delay, + * the fault will actually happen just after 5 seconds + * it was generated.

* - * @param failedPesGenerator the failedPesGenerator to set - * @see #setFailureDelayGenerator(org.cloudbus.cloudsim.distributions.ContinuousDistribution) + * @param maxFailureDelay the max delay to set (in seconds) */ - public void setFailedPesGenerator(ContinuousDistribution failedPesGenerator) { - Objects.requireNonNull(failedPesGenerator); - this.failedPesGenerator = failedPesGenerator; + public void setMaxFailureDelay(double maxFailureDelay) { + this.maxFailureDelay = maxFailureDelay; } /** - * Sets the pseudo random number generator used to randomly define - * the delay before the failure is injected. + * Gets the maximum delay after a fault be injected + * that it will in fact happen (in seconds). * *

- * For instance, if the generator returns values between 1 and 10 - * and the value 5 is generated, - * when a failure is injected, it will in fact happen just after 5 - * seconds from the current simulation time.

+ * This is used to define, randomly + * the actual time, after the time the fault was + * injected, that it will happen. + * For instance, if a fault is generated + * and a value 5 is chosen between 0 and the maximum delay, + * the fault will actually happen just after 5 seconds + * it was generated.

* - * @param failureDelayGenerator the pseudo random number generator to set - * @see #setFailedPesGenerator(org.cloudbus.cloudsim.distributions.ContinuousDistribution) + * @return the maximum failure delay (in seconds) */ - public void setFailureDelayGenerator(ContinuousDistribution failureDelayGenerator) { - Objects.requireNonNull(failureDelayGenerator); - this.failureDelayGenerator = failureDelayGenerator; - } - + public double getMaxFailureDelay() { + return this.maxFailureDelay; + } + /** * Sets a {@link UnaryOperator} that creates a clone of a {@link Vm} * when all Host PEs fail or all VM's PEs are deallocated @@ -423,4 +472,11 @@ public void setCloudletsCloner(Function> cloudletsCloner) { this.cloudletsCloner = cloudletsCloner; } + /** + * Gets the average number of failures expected to happen each minute. + * @return + */ + public double getMeanFailuresPerMinute() { + return failureInjectionGenerator.getLambda(); + } }