Unverified Commit 60e50b08 authored by Manoel Campos's avatar Manoel Campos
Browse files

Merges PowerSupply to PowerModel classes



- The PowerSupply was just delegating multiple methods to PowerModel.
  PowerSupply was merged into PowerModel and the former removed.
  After this, the way to use PowerModel is as before the release 2.0.0,
  with all benefits of incorporating power-awareness into regular
  classes, namely DatacenterSimple, HostSimple and VmSimple.
- Stores the active state of Hosts in the StateHistory by using
  the Host's active attribute, instead of checking the utilization of CPU.
- Updates Datacenter documentation to show that the computed
  power usage is and estimation. It also shows how to compute actual
  power usage if Host's StateHistory is enabled.
Signed-off-by: default avatarManoel Campos <manoelcampos@gmail.com>
parent fbf90ade
......@@ -4,7 +4,7 @@
<groupId>org.cloudsimplus</groupId>
<artifactId>cloudsim-plus-benchmarks</artifactId>
<version>2.1.0</version>
<version>2.2.0</version>
<name>CloudSim Plus Benchmarks</name>
<description>A module containing benchmarks created using JMH (Java Microbenchmark Harness framework) to assess CloudSim Plus performance</description>
<url>http://cloudsimplus.org</url>
......
......@@ -4,7 +4,7 @@
<groupId>org.cloudsimplus</groupId>
<artifactId>cloudsim-plus-examples</artifactId>
<version>2.1.0</version>
<version>2.2.0</version>
<name>CloudSim Plus Examples</name>
<description>
Ready-to-run examples of how to use CloudSim Plus API.
......
......@@ -55,7 +55,7 @@ import java.util.List;
/**
* A example showing how to show Hosts power consumption.
* Realize that for this goal, you define a {@link PowerModel}
* for each Host by calling {@code host.getPowerSupply().setPowerModel(powerModel)}.
* for each Host by calling {@code host.setPowerModel(powerModel)}.
*
* <p>It creates the number of cloudlets defined in
* {@link #CLOUDLETS}. All cloudlets will required 100% of PEs they are using all the time.
......@@ -168,7 +168,7 @@ public class PowerExample {
* This way, to get the total power consumed for each 10 seconds interval,
* the power consumption is multipled by the time interval.
*/
final double wattsPerInterval = host.getPowerSupply().getPowerModel().getPower(utilizationPercent)*SCHEDULING_INTERVAL;
final double wattsPerInterval = host.getPowerModel().getPower(utilizationPercent)*SCHEDULING_INTERVAL;
totalPower += wattsPerInterval;
System.out.printf("\tTime %6.0f | CPU Utilization %6.2f%% | Power Consumption: %8.2f Watts in %d Seconds\n",
time, utilizationPercent*100, wattsPerInterval, SCHEDULING_INTERVAL);
......@@ -212,7 +212,7 @@ public class PowerExample {
final VmScheduler vmScheduler = new VmSchedulerTimeShared();
final Host host = new HostSimple(ram, bw, storage, peList);
host.getPowerSupply().setPowerModel(powerModel);
host.setPowerModel(powerModel);
host
.setRamProvisioner(ramProvisioner)
.setBwProvisioner(bwProvisioner)
......
......@@ -87,7 +87,7 @@ import java.util.List;
*
* <p>This VmAllocationPolicy considers the power usage of Hosts to place VMs.
* So that, a {@link org.cloudbus.cloudsim.power.models.PowerModel} is being
* set to every created Host by means of {@code host.getPowerSupply().setPowerModel(powerModel)}.</p>
* set to every created Host by means of {@code host.setPowerModel(powerModel)}.</p>
*
* <p>The example uses a {@link UtilizationModelDynamic} that defines the CPU usage of cloudlets
* increases along the simulation time.</p>
......@@ -261,7 +261,7 @@ public final class MigrationExample2_PowerUsage {
int time = 0;
for (int i = 0; i < utilizationHistory.length; i++) {
final double cpuUsage = utilizationHistory[i];
System.out.printf("Time: %6d | %9.2f | %.2f\n", i*SCHEDULE_INTERVAL, cpuUsage, host.getPowerSupply().getPower(cpuUsage));
System.out.printf("Time: %6d | %9.2f | %.2f\n", i*SCHEDULE_INTERVAL, cpuUsage, host.getPowerModel().getPower(cpuUsage));
time += SCHEDULE_INTERVAL;
}
System.out.println();
......@@ -437,7 +437,7 @@ public final class MigrationExample2_PowerUsage {
.setBwProvisioner(new ResourceProvisionerSimple())
.setVmScheduler(new VmSchedulerTimeShared());
host.enableStateHistory();
host.getPowerSupply().setPowerModel(new PowerModelLinear(800, 0.3));
host.setPowerModel(new PowerModelLinear(800, 0.3));
return host;
}
......
......@@ -4,7 +4,7 @@
<groupId>org.cloudsimplus</groupId>
<artifactId>cloudsim-plus-testbeds</artifactId>
<version>2.1.0</version>
<version>2.2.0</version>
<name>CloudSim Plus Testbeds</name>
<description>
A set of more complex and comprehensive CloudSim Plus testbeds used to assess
......
......@@ -291,7 +291,7 @@ public final class VmMigrationWhenCpuMetricIsViolatedExample {
public static Host createHost(int id, int numberOfPes, long mipsByPe) {
List<Pe> peList = createPeList(numberOfPes, mipsByPe);
Host host = new HostSimple(HOST_RAM, HOST_BW, HOST_STORAGE, peList);
host.getPowerSupply().setPowerModel(new PowerModelLinear(1000, 0.7))
host.setPowerModel(new PowerModelLinear(1000, 0.7))
.setRamProvisioner(new ResourceProvisionerSimple())
.setBwProvisioner(new ResourceProvisionerSimple())
.setVmScheduler(new VmSchedulerTimeShared());
......
......@@ -4,7 +4,7 @@
<groupId>org.cloudsimplus</groupId>
<artifactId>cloudsim-plus</artifactId>
<version>2.1.0</version>
<version>2.2.0</version>
<name>CloudSim Plus API</name>
<description>CloudSim Plus: A modern, highly extensible and easier-to-use Java 8 Framework for Modeling and Simulation of Cloud Computing Infrastructures and Services</description>
<url>http://cloudsimplus.org</url>
......
......@@ -231,7 +231,7 @@ public abstract class VmAllocationPolicyMigrationAbstract extends VmAllocationPo
protected double getPowerAfterAllocationDifference(final Host host, final Vm vm){
final double powerAfterAllocation = getPowerAfterAllocation(host, vm);
if (powerAfterAllocation > 0) {
return powerAfterAllocation - host.getPowerSupply().getPower();
return powerAfterAllocation - host.getPowerModel().getPower();
}
return 0;
......@@ -614,7 +614,7 @@ public abstract class VmAllocationPolicyMigrationAbstract extends VmAllocationPo
*/
protected double getPowerAfterAllocation(final Host host, final Vm vm) {
try {
return host.getPowerSupply().getPowerModel().getPower(getMaxUtilizationAfterAllocation(host, vm));
return host.getPowerModel().getPower(getMaxUtilizationAfterAllocation(host, vm));
} catch (Exception e) {
Log.printFormattedLine("[ERROR] Power consumption for Host %d could not be determined: ", host.getId(), e.getMessage());
}
......
......@@ -35,7 +35,7 @@ public class CloudSim implements Simulation {
/**
* CloudSim Plus current version.
*/
public static final String VERSION = "2.1.0";
public static final String VERSION = "2.2.0";
/**
* An array that works as a circular queue with capacity for just 2 elements
......
......@@ -8,6 +8,7 @@
package org.cloudbus.cloudsim.datacenters;
import org.cloudbus.cloudsim.hosts.Host;
import org.cloudbus.cloudsim.power.models.PowerModel;
import org.cloudbus.cloudsim.vms.Vm;
import org.cloudbus.cloudsim.cloudlets.Cloudlet;
import org.cloudbus.cloudsim.core.SimEntity;
......@@ -35,6 +36,12 @@ public interface Datacenter extends SimEntity {
* {@link Datacenter} objects.
*/
Datacenter NULL = new DatacenterNull();
/**
* The default percentage of bandwidth allocated for VM migration, is
* a value is not set.
* @see #setBandwidthPercentForMigration(double)
*/
double DEF_BANDWIDTH_PERCENT_FOR_MIGRATION = 0.5;
/**
* Adds a file into the resource's storage before the experiment starts. If
......@@ -176,4 +183,25 @@ public interface Datacenter extends SimEntity {
* @param bandwidthPercentForMigration the bandwidth migration percentage to set
*/
void setBandwidthPercentForMigration(double bandwidthPercentForMigration);
/**
* Gets an <b>estimation</b> of Datacenter power consumption (in Watts/Second).
* <p>To get actual power consumption, it's required to enable
* {@link Host#getStateHistory() Host's StateHistory}
* by calling {@link Host#enableStateHistory()}
* and use each Host {@link PowerModel} to compute power usage
* based on the CPU utilization got form the StateHistory.
* </p>
*
* @return th <b>estimated</b> power consumption (in Watts/Second)
*/
double getPower();
/**
* Gets an <b>estimation</b> the Datacenter power consumption (in Kilo Watts/Hour).
*
* @return the <b>estimated</b> power consumption (in Kilo Watts/Hour)
* @see #getPower()
*/
double getPowerInKWattsHour();
}
......@@ -63,6 +63,8 @@ final class DatacenterNull implements Datacenter {
}
@Override public double getBandwidthPercentForMigration() { return 0; }
@Override public void setBandwidthPercentForMigration(double bandwidthPercentForMigration) {/**/}
@Override public double getPower() { return 0; }
@Override public double getPowerInKWattsHour() { return 0; }
@Override public SimEntity setState(State state) { return SimEntity.NULL; }
@Override public boolean isStarted() { return false; }
@Override public Simulation getSimulation() { return Simulation.NULL; }
......
......@@ -11,6 +11,7 @@ import org.cloudbus.cloudsim.cloudlets.CloudletExecution;
import org.cloudbus.cloudsim.core.events.SimEvent;
import org.cloudbus.cloudsim.core.predicates.PredicateType;
import org.cloudbus.cloudsim.network.IcmpPacket;
import org.cloudbus.cloudsim.power.models.PowerModel;
import org.cloudbus.cloudsim.util.Conversion;
import org.cloudbus.cloudsim.util.DataCloudTags;
import org.cloudbus.cloudsim.hosts.Host;
......@@ -39,12 +40,6 @@ import static java.util.stream.Collectors.toList;
* @since CloudSim Toolkit 1.0
*/
public class DatacenterSimple extends CloudSimEntity implements Datacenter {
/**
* The default percentage of bandwidth allocated for VM migration, is
* a value is not set.
* @see #setBandwidthPercentForMigration(double)
*/
private static final double DEF_BANDWIDTH_PERCENT_FOR_MIGRATION = 0.5;
/**
* @see #getBandwidthPercentForMigration()
......@@ -725,10 +720,11 @@ public class DatacenterSimple extends CloudSimEntity implements Datacenter {
}
/**
* Gets the total power consumed (in Watts/sec) by all Hosts of the Datacenter since the last time the processing
* of Cloudlets in this Host was updated.
* Gets an <b>estimation</b> of total power consumed (in Watts/sec) by all Hosts of the Datacenter
* since the last time the processing of Cloudlets in this Host was updated.
*
* @return the total power consumed (in Watts/sec) by all Hosts in the elapsed time span
* @return the <b>estimated</b> total power consumed (in Watts/sec) by all Hosts in the elapsed time span
* @see #getPower()
*/
private double getDatacenterPowerUsageForTimeSpan() {
if (getSimulation().clock() - getLastProcessTime() == 0) { //time span
......@@ -740,7 +736,7 @@ public class DatacenterSimple extends CloudSimEntity implements Datacenter {
final double prevCpuUsage = host.getPreviousUtilizationOfCpu();
final double cpuUsage = host.getUtilizationOfCpu();
final double timeFrameHostEnergy =
host.getPowerSupply().getEnergyLinearInterpolation(prevCpuUsage, cpuUsage, getSimulation().clock() - getLastProcessTime());
host.getPowerModel().getEnergyLinearInterpolation(prevCpuUsage, cpuUsage, getSimulation().clock() - getLastProcessTime());
datacenterTimeSpanPowerUse += timeFrameHostEnergy;
}
......@@ -1148,20 +1144,12 @@ public class DatacenterSimple extends CloudSimEntity implements Datacenter {
this.bandwidthPercentForMigration = bandwidthPercentForMigration;
}
/**
* Gets the Datacenter power consumption (in Watts/Second).
*
* @return the power consumption (in Watts/Second)
*/
@Override
public double getPower() {
return power;
}
/**
* Gets the Datacenter power consumption (in Kilo Watts/Hour).
*
* @return the power consumption (in Kilo Watts/Hour)
*/
@Override
public double getPowerInKWattsHour() {
return getPower() / (3600 * 1000);
}
......
......@@ -8,7 +8,6 @@
package org.cloudbus.cloudsim.hosts;
import org.cloudbus.cloudsim.core.Machine;
import org.cloudbus.cloudsim.power.supply.PowerSupply;
import org.cloudbus.cloudsim.power.models.PowerModel;
import org.cloudbus.cloudsim.resources.*;
import org.cloudbus.cloudsim.vms.Vm;
......@@ -512,13 +511,23 @@ public interface Host extends Machine, Comparable<Host> {
double[] getUtilizationHistory();
/**
* Gets the {@link PowerSupply} that enables getting power usage information,
* including the {@link PowerModel}.
* Power information is just available if a {@link PowerModel} is set to the PowerSupply.
* Gets the {@link PowerModel} used by the host
* to define how it consumes power.
* A Host just provides power usage data if a PowerModel is set.
*
* @return the Host's {@link PowerModel}
*/
PowerModel getPowerModel();
/**
* Sets the {@link PowerModel} used by the host
* to define how it consumes power.
* A Host just provides power usage data if a PowerModel is set.
*
* @param powerModel the {@link PowerModel} to set
* @return
*/
PowerSupply getPowerSupply();
Host setPowerModel(PowerModel powerModel);
double getPreviousUtilizationOfCpu();
......
......@@ -2,7 +2,7 @@ package org.cloudbus.cloudsim.hosts;
import org.cloudbus.cloudsim.core.Simulation;
import org.cloudbus.cloudsim.datacenters.Datacenter;
import org.cloudbus.cloudsim.power.supply.PowerSupply;
import org.cloudbus.cloudsim.power.models.PowerModel;
import org.cloudbus.cloudsim.provisioners.ResourceProvisioner;
import org.cloudbus.cloudsim.resources.Pe;
import org.cloudbus.cloudsim.resources.Resource;
......@@ -97,9 +97,7 @@ final class HostNull implements Host {
return Vm.NULL;
}
@Override public <T extends Vm> List<T> getVmCreatedList() { return Collections.EMPTY_LIST; }
@Override public List<Vm> getVmList() {
return Collections.emptyList();
}
@Override public List<Vm> getVmList() { return Collections.emptyList(); }
@Override public VmScheduler getVmScheduler() {
return VmScheduler.NULL;
}
......@@ -165,7 +163,8 @@ final class HostNull implements Host {
@Override public long getUtilizationOfBw() { return 0; }
@Override public long getUtilizationOfRam() { return 0; }
@Override public double[] getUtilizationHistory() { return new double[0]; }
@Override public PowerSupply getPowerSupply() { return PowerSupply.NULL; }
@Override public PowerModel getPowerModel() { return PowerModel.NULL; }
@Override public Host setPowerModel(PowerModel powerModel) { return this; }
@Override public double getPreviousUtilizationOfCpu() { return 0; }
@Override public void enableStateHistory() {/**/}
@Override public void disableStateHistory() {/**/}
......
......@@ -6,8 +6,7 @@
*/
package org.cloudbus.cloudsim.hosts;
import org.cloudbus.cloudsim.power.supply.HostPowerSupply;
import org.cloudbus.cloudsim.power.supply.PowerSupply;
import org.cloudbus.cloudsim.power.models.PowerModel;
import org.cloudbus.cloudsim.resources.*;
import org.cloudbus.cloudsim.util.Log;
import org.cloudbus.cloudsim.util.MathUtil;
......@@ -45,7 +44,7 @@ public class HostSimple implements Host {
* @see #getStateHistory()
*/
private final List<HostStateHistoryEntry> stateHistory;
private final PowerSupply powerSupply;
private PowerModel powerModel;
/**
* @see #getId()
......@@ -167,7 +166,7 @@ public class HostSimple implements Host {
this.provisioners = new ArrayList<>();
this.vmsMigratingIn = new HashSet<>();
this.vmsMigratingOut = new HashSet<>();
this.powerSupply = new HostPowerSupply(this);
this.powerModel = PowerModel.NULL;
stateHistory = new LinkedList<>();
}
......@@ -806,8 +805,20 @@ public class HostSimple implements Host {
}
@Override
public PowerSupply getPowerSupply() {
return powerSupply;
public PowerModel getPowerModel() {
return powerModel;
}
@Override
public Host setPowerModel(final PowerModel powerModel) {
Objects.requireNonNull(powerModel);
if(powerModel.getHost() != null && powerModel.getHost() != Host.NULL && !powerModel.getHost().equals(this)){
throw new IllegalStateException("The given PowerModel is already assigned to another Host. Each Host must have its own PowerModel instance.");
}
this.powerModel = powerModel;
powerModel.setHost(this);
return this;
}
@Override
......@@ -901,7 +912,7 @@ public class HostSimple implements Host {
hostTotalRequestedMips += totalRequestedMips;
}
addStateHistoryEntry(currentTime, getUtilizationOfCpuMips(), hostTotalRequestedMips,getUtilizationOfCpuMips() > 0);
addStateHistoryEntry(currentTime, getUtilizationOfCpuMips(), hostTotalRequestedMips, active);
}
/**
......
......@@ -8,13 +8,15 @@
package org.cloudbus.cloudsim.power.models;
import org.cloudbus.cloudsim.hosts.Host;
import org.cloudbus.cloudsim.power.supply.PowerSupply;
import org.cloudbus.cloudsim.resources.Pe;
/**
* Provides a model for power consumption of hosts, depending on utilization of a critical system
* component, such as CPU.
* <b>This is the fundamental class to enable power-aware Hosts.</b> Despite all Hosts have a {@link PowerSupply} attribute,
* it just provides power usage data if a PowerModel is set using the {@link PowerSupply#setPowerModel(PowerModel)}.
* <b>This is the fundamental class to enable power-aware Hosts.
* However, a Host just provides power usage data if a PowerModel is set using the
* {@link Host#setPowerModel(PowerModel)}.</b>
*
*
* <p>The interface implements the Null Object
* Design Pattern in order to start avoiding {@link NullPointerException} when
......@@ -46,13 +48,31 @@ public interface PowerModel {
PowerModel NULL = new PowerModel() {
@Override public Host getHost() { return Host.NULL; }
@Override public void setHost(Host host) {}
@Override public double getMaxPower() { return 0; }
@Override public double getPower() { return 0; }
@Override public double getPower(double utilization) throws IllegalArgumentException { return 0; }
@Override public double getEnergyLinearInterpolation(double fromUtilization, double toUtilization, double time) { return 0; }
};
Host getHost();
void setHost(Host host);
/**
* Gets the max power that can be consumed by the host (in Watts/Second).
*
* @return the max consumption power (in Watts/Second)
*/
double getMaxPower();
/**
* Gets the current power consumption of the host (in Watts/Second).
* For this moment, it only computes the power consumed by {@link Pe}s.
*
* @return the power consumption (in Watts/Second)
*/
double getPower();
/**
* Gets power consumption (in Watts/Second) of the Power Model, according to the utilization
* percentage of a critical resource, such as CPU.
......@@ -64,4 +84,16 @@ public interface PowerModel {
* between [0 and 1]
*/
double getPower(double utilization) throws IllegalArgumentException;
/**
* Gets an <b>estimation</b> of energy consumption using linear interpolation of the utilization
* change.
* <b>It's required to set a {@link PowerModel} in order to get power usage data.</b>
*
* @param fromUtilization the initial utilization percentage
* @param toUtilization the final utilization percentage
* @param time the time
* @return the <b>estimated</b> energy consumption
*/
double getEnergyLinearInterpolation(double fromUtilization, double toUtilization, double time);
}
......@@ -24,6 +24,11 @@ public abstract class PowerModelAbstract implements PowerModel {
this.host = host;
}
@Override
public double getPower() {
return getPower(host.getUtilizationOfCpu());
}
@Override
public final double getPower(final double utilization) throws IllegalArgumentException {
if (utilization < 0 || utilization > 1) {
......@@ -59,4 +64,18 @@ public abstract class PowerModelAbstract implements PowerModel {
* between [0 and 1]
*/
protected abstract double getPowerInternal(final double utilization) throws IllegalArgumentException;
@Override
public double getEnergyLinearInterpolation(
final double fromUtilization,
final double toUtilization,
final double time)
{
if (fromUtilization == 0) {
return 0;
}
final double fromPower = getPower(fromUtilization);
final double toPower = getPower(toUtilization);
return (fromPower + (toPower - fromPower) / 2) * time;
}
}
......@@ -26,8 +26,12 @@ package org.cloudbus.cloudsim.power.models;
* @since CloudSim Toolkit 3.0
*/
public abstract class PowerModelSpecPower extends PowerModelAbstract {
@Override
public double getMaxPower() {
return getPower(1);
}
@Override
@Override
protected double getPowerInternal(final double utilization) throws IllegalArgumentException {
if (utilization % 0.1 == 0) {
return getPowerData((int) (utilization * 10));
......
......@@ -9,6 +9,6 @@
*
* <p>The most basic PowerModel is the {@link org.cloudbus.cloudsim.power.models.PowerModelLinear}.</p>
*
* @see org.cloudbus.cloudsim.power.supply
* @see org.cloudbus.cloudsim.power.model
*/
package org.cloudbus.cloudsim.power.models;
package org.cloudbus.cloudsim.power.supply;
import org.cloudbus.cloudsim.hosts.Host;
import org.cloudbus.cloudsim.power.models.PowerModel;
import java.util.Objects;
/**
* Provides data about a PM power consumption,
* according to a defined {@link PowerModel}.
*
* @author Manoel Campos da Silva Filho
* @author Anton Beloglazov
* @since CloudSim Plus 1.4
*/
public class HostPowerSupply implements PowerSupply {
private final Host host;
private PowerModel powerModel;
public HostPowerSupply(final Host host) {
this(host, PowerModel.NULL);
}
public HostPowerSupply(final Host host, final PowerModel powerModel) {
this.host = host;
this.powerModel = powerModel;
}
@Override
public double getPower() {
return getPower(host.getUtilizationOfCpu());
}
@Override
public double getPower(final double utilization) {
try {
return powerModel.getPower(utilization);
} catch (IllegalArgumentException e) {
throw new RuntimeException(e);
}
}
@Override
public double getMaxPower() {
return powerModel.getPower(1);
}
@Override
public final Host setPowerModel(final PowerModel powerModel) {
Objects.requireNonNull(powerModel);
this.powerModel = powerModel;
this.powerModel.setHost(host);
return host;
}
@Override
public PowerModel getPowerModel() {
return powerModel;
}
@Override
public double getEnergyLinearInterpolation(
final double fromUtilization,
final double toUtilization,
final double time)
{
if (fromUtilization == 0) {
return 0;
}
final double fromPower = getPower(fromUtilization);
final double toPower = getPower(toUtilization);
return (fromPower + (toPower - fromPower) / 2) * time;
}
}