From 2977dd8a5f1d742193eae79364a284e68269f7b5 Mon Sep 17 00:00:00 2001 From: Hongyu <39747921+HongyuHe@users.noreply.github.com> Date: Sat, 6 Mar 2021 19:36:46 +0100 Subject: sim: Implement energy models from CloudSim (#79) This commit implements the energy models that are present in CloudSim: 1. Constant 2. Linear 3. Cubic 4. Square root 5. Interpolation based on data. --- .../opendc/compute/simulator/SimBareMetalDriver.kt | 12 ++-- .../opendc/compute/simulator/power/PowerModel.kt | 32 --------- .../opendc/compute/simulator/power/PowerModels.kt | 42 ------------ .../opendc/compute/simulator/power/Powerable.kt | 37 ----------- .../compute/simulator/power/api/CpuPowerModel.kt | 31 +++++++++ .../compute/simulator/power/api/Powerable.kt | 37 +++++++++++ .../simulator/power/models/ConstantPowerModel.kt | 10 +++ .../simulator/power/models/CubicPowerModel.kt | 26 ++++++++ .../power/models/InterpolationPowerModel.kt | 34 ++++++++++ .../simulator/power/models/LinearPowerModel.kt | 25 ++++++++ .../simulator/power/models/SqrtPowerModel.kt | 26 ++++++++ .../simulator/power/models/SquarePowerModel.kt | 26 ++++++++ .../power/models/ZeroIdlePowerDecorator.kt | 14 ++++ .../simulator/power/models/package-info.java | 12 ++++ .../compute/simulator/power/CpuPowerModelTest.kt | 75 ++++++++++++++++++++++ 15 files changed, 322 insertions(+), 117 deletions(-) delete mode 100644 simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/PowerModel.kt delete mode 100644 simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/PowerModels.kt delete mode 100644 simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/Powerable.kt create mode 100644 simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/api/CpuPowerModel.kt create mode 100644 simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/api/Powerable.kt create mode 100644 simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/models/ConstantPowerModel.kt create mode 100644 simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/models/CubicPowerModel.kt create mode 100644 simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/models/InterpolationPowerModel.kt create mode 100644 simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/models/LinearPowerModel.kt create mode 100644 simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/models/SqrtPowerModel.kt create mode 100644 simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/models/SquarePowerModel.kt create mode 100644 simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/models/ZeroIdlePowerDecorator.kt create mode 100644 simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/models/package-info.java create mode 100644 simulator/opendc-compute/opendc-compute-simulator/src/test/kotlin/org/opendc/compute/simulator/power/CpuPowerModelTest.kt (limited to 'simulator/opendc-compute') diff --git a/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimBareMetalDriver.kt b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimBareMetalDriver.kt index 7a978a53..1e459e6f 100644 --- a/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimBareMetalDriver.kt +++ b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimBareMetalDriver.kt @@ -34,9 +34,9 @@ import org.opendc.compute.core.metal.Node import org.opendc.compute.core.metal.NodeEvent import org.opendc.compute.core.metal.NodeState import org.opendc.compute.core.metal.driver.BareMetalDriver -import org.opendc.compute.simulator.power.ConstantPowerModel -import org.opendc.compute.simulator.power.PowerModel -import org.opendc.compute.simulator.power.Powerable +import org.opendc.compute.simulator.power.api.CpuPowerModel +import org.opendc.compute.simulator.power.api.Powerable +import org.opendc.compute.simulator.power.models.ConstantPowerModel import org.opendc.core.services.ServiceRegistry import org.opendc.simulator.compute.SimBareMetalMachine import org.opendc.simulator.compute.SimExecutionContext @@ -59,7 +59,7 @@ import kotlin.random.Random * @param name An optional name of the machine. * @param metadata The initial metadata of the node. * @param machine The machine model to simulate. - * @param powerModel The power model of this machine. + * @param cpuPowerModel The CPU power model of this machine. */ @OptIn(ExperimentalCoroutinesApi::class) public class SimBareMetalDriver( @@ -69,7 +69,7 @@ public class SimBareMetalDriver( name: String, metadata: Map, machine: SimMachineModel, - powerModel: PowerModel = ConstantPowerModel(0.0) + cpuPowerModel: CpuPowerModel = ConstantPowerModel(0.0), ) : BareMetalDriver, FailureDomain, Powerable { /** * The flavor that corresponds to this machine. @@ -100,7 +100,7 @@ public class SimBareMetalDriver( override val usage: Flow get() = this.machine.usage - override val powerDraw: Flow = powerModel(this) + override val powerDraw: Flow = cpuPowerModel.getPowerDraw(this) /** * The internal random instance. diff --git a/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/PowerModel.kt b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/PowerModel.kt deleted file mode 100644 index 174a510b..00000000 --- a/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/PowerModel.kt +++ /dev/null @@ -1,32 +0,0 @@ -/* - * MIT License - * - * Copyright (c) 2020 atlarge-research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.compute.simulator.power - -import kotlinx.coroutines.flow.Flow - -/** - * A model for computing the power draw based on some value. - */ -public typealias PowerModel = (T) -> Flow diff --git a/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/PowerModels.kt b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/PowerModels.kt deleted file mode 100644 index 651eba6e..00000000 --- a/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/PowerModels.kt +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2020 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.compute.simulator.power - -import kotlinx.coroutines.flow.flowOf -import kotlinx.coroutines.flow.map -import org.opendc.compute.core.metal.driver.BareMetalDriver - -/** - * A power model which emits a single value. - */ -public fun ConstantPowerModel(value: Double): PowerModel = { _ -> flowOf(value) } - -/** - * A power model that assumes a naive linear relation between power usage and host CPU utilization. - * - * @param idle The power draw in Watts on idle. - * @param max The maximum power draw in Watts of the server. - */ -public fun LinearLoadPowerModel(idle: Double, max: Double): PowerModel = { driver -> - driver.usage.map { load -> (max - idle) * load + idle } -} diff --git a/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/Powerable.kt b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/Powerable.kt deleted file mode 100644 index dcf74468..00000000 --- a/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/Powerable.kt +++ /dev/null @@ -1,37 +0,0 @@ -/* - * MIT License - * - * Copyright (c) 2020 atlarge-research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.compute.simulator.power - -import kotlinx.coroutines.flow.Flow - -/** - * An entity that is uses power from some power source. - */ -public interface Powerable { - /** - * The power draw at the device's power supply in watts (W).w - */ - public val powerDraw: Flow -} diff --git a/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/api/CpuPowerModel.kt b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/api/CpuPowerModel.kt new file mode 100644 index 00000000..ee9e130b --- /dev/null +++ b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/api/CpuPowerModel.kt @@ -0,0 +1,31 @@ +package org.opendc.compute.simulator.power.api + +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map +import org.opendc.compute.core.metal.driver.BareMetalDriver + +public interface CpuPowerModel { + /** + * Computes CPU power consumption for each host. + * + * @param cpuUtil The CPU utilization percentage. + * @return A [Double] value of CPU power consumption. + * @throws IllegalArgumentException Will throw an error if [cpuUtil] is out of range. + */ + @Throws(IllegalArgumentException::class) + public fun computeCpuPower(cpuUtil: Double): Double + + /** + * Emits the values of power consumption for servers. + * + * @param driver A [BareMetalDriver] that offers host CPU utilization. + * @param withoutIdle A [Boolean] flag indicates whether (false) add a constant + * power consumption value when the server is idle or (true) not + * with a default value being false. + * @return A [Flow] of values representing the server power draw. + */ + public fun getPowerDraw(driver: BareMetalDriver, withoutIdle: Boolean = false): Flow = + driver.usage.map { + computeCpuPower(it) + } +} diff --git a/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/api/Powerable.kt b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/api/Powerable.kt new file mode 100644 index 00000000..780f2a29 --- /dev/null +++ b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/api/Powerable.kt @@ -0,0 +1,37 @@ +/* + * MIT License + * + * Copyright (c) 2020 atlarge-research + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.opendc.compute.simulator.power.api + +import kotlinx.coroutines.flow.Flow + +/** + * An entity that is uses power from some power source. + */ +public interface Powerable { + /** + * The power draw at the device's power supply in watts (W).w + */ + public val powerDraw: Flow +} diff --git a/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/models/ConstantPowerModel.kt b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/models/ConstantPowerModel.kt new file mode 100644 index 00000000..5e80827b --- /dev/null +++ b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/models/ConstantPowerModel.kt @@ -0,0 +1,10 @@ +package org.opendc.compute.simulator.power.models + +import org.opendc.compute.simulator.power.api.CpuPowerModel + +/** + * A power model which produces a constant value [constant]. + */ +public class ConstantPowerModel(private val constant: Double) : CpuPowerModel { + public override fun computeCpuPower(cpuUtil: Double): Double = constant +} diff --git a/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/models/CubicPowerModel.kt b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/models/CubicPowerModel.kt new file mode 100644 index 00000000..9008a987 --- /dev/null +++ b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/models/CubicPowerModel.kt @@ -0,0 +1,26 @@ +package org.opendc.compute.simulator.power.models + +import org.opendc.compute.simulator.power.api.CpuPowerModel +import kotlin.math.pow + +/** + * The cubic power model partially adapted from CloudSim. + * + * @param maxPower The maximum power draw in Watts of the server. + * @param staticPowerPercent The static power percentage. + * @property staticPower The static power consumption that is not dependent on resource usage. + * It is the amount of energy consumed even when the host is idle. + * @property constPower The constant power consumption for each fraction of resource used. + */ +public class CubicPowerModel( + private var maxPower: Double, + staticPowerPercent: Double +) : CpuPowerModel { + private var staticPower: Double = staticPowerPercent * maxPower + private var constPower: Double = (maxPower - staticPower) / 100.0.pow(3) + + public override fun computeCpuPower(cpuUtil: Double): Double { + require(cpuUtil in 0.0..1.0) { "CPU utilization must be in [0, 1]" } + return staticPower + constPower * (cpuUtil * 100).pow(3) + } +} diff --git a/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/models/InterpolationPowerModel.kt b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/models/InterpolationPowerModel.kt new file mode 100644 index 00000000..b01957e4 --- /dev/null +++ b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/models/InterpolationPowerModel.kt @@ -0,0 +1,34 @@ +package org.opendc.compute.simulator.power.models + +import org.opendc.compute.simulator.power.api.CpuPowerModel +import kotlin.math.ceil +import kotlin.math.floor + +/** + * The linear interpolation power model partially adapted from CloudSim. + * + * @param maxPower The maximum power draw in Watts of the server. + * @param staticPowerPercent The static power percentage. + * @property staticPower The static power consumption that is not dependent on resource usage. + * It is the amount of energy consumed even when the host is idle. + * @property constPower The constant power consumption for each fraction of resource used. + */ +public abstract class InterpolationPowerModel : CpuPowerModel { + + public override fun computeCpuPower(cpuUtil: Double): Double { + require(cpuUtil in 0.0..1.0) { "CPU utilization must be in [0, 1]" } + + val cpuUtilFlr = floor(cpuUtil * 10).toInt() + val cpuUtilCil = ceil(cpuUtil * 10).toInt() + val power1: Double = getPowerData(cpuUtilFlr) + val power2: Double = getPowerData(cpuUtilCil) + val delta = (power2 - power1) / 10 + + return if (cpuUtil % 0.1 == 0.0) + getPowerData((cpuUtil * 10).toInt()) + else + power1 + delta * (cpuUtil - cpuUtilFlr.toDouble() / 10) * 100 + } + + public abstract fun getPowerData(index: Int): Double +} diff --git a/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/models/LinearPowerModel.kt b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/models/LinearPowerModel.kt new file mode 100644 index 00000000..913095ad --- /dev/null +++ b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/models/LinearPowerModel.kt @@ -0,0 +1,25 @@ +package org.opendc.compute.simulator.power.models + +import org.opendc.compute.simulator.power.api.CpuPowerModel + +/** + * The linear power model partially adapted from CloudSim. + * + * @param maxPower The maximum power draw in Watts of the server. + * @param staticPowerPercent The static power percentage. + * @property staticPower The static power consumption that is not dependent on resource usage. + * It is the amount of energy consumed even when the host is idle. + * @property constPower The constant power consumption for each fraction of resource used. + */ +public class LinearPowerModel( + private var maxPower: Double, + staticPowerPercent: Double +) : CpuPowerModel { + private var staticPower: Double = staticPowerPercent * maxPower + private var constPower: Double = (maxPower - staticPower) / 100 + + public override fun computeCpuPower(cpuUtil: Double): Double { + require(cpuUtil in 0.0..1.0) { "CPU utilization must be in [0, 1]" } + return staticPower + constPower * cpuUtil * 100 + } +} diff --git a/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/models/SqrtPowerModel.kt b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/models/SqrtPowerModel.kt new file mode 100644 index 00000000..85d94ffc --- /dev/null +++ b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/models/SqrtPowerModel.kt @@ -0,0 +1,26 @@ +package org.opendc.compute.simulator.power.models + +import org.opendc.compute.simulator.power.api.CpuPowerModel +import kotlin.math.sqrt + +/** + * The square root power model partially adapted from CloudSim. + * + * @param maxPower The maximum power draw in Watts of the server. + * @param staticPowerPercent The static power percentage. + * @property staticPower The static power consumption that is not dependent on resource usage. + * It is the amount of energy consumed even when the host is idle. + * @property constPower The constant power consumption for each fraction of resource used. + */ +public class SqrtPowerModel( + private var maxPower: Double, + staticPowerPercent: Double +) : CpuPowerModel { + private var staticPower: Double = staticPowerPercent * maxPower + private var constPower: Double = (maxPower - staticPower) / sqrt(100.0) + + override fun computeCpuPower(cpuUtil: Double): Double { + require(cpuUtil in 0.0..1.0) { "CPU utilization must be in [0, 1]" } + return staticPower + constPower * sqrt(cpuUtil * 100) + } +} diff --git a/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/models/SquarePowerModel.kt b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/models/SquarePowerModel.kt new file mode 100644 index 00000000..5f44aa3c --- /dev/null +++ b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/models/SquarePowerModel.kt @@ -0,0 +1,26 @@ +package org.opendc.compute.simulator.power.models + +import org.opendc.compute.simulator.power.api.CpuPowerModel +import kotlin.math.pow + +/** + * The square power model partially adapted from CloudSim. + * + * @param maxPower The maximum power draw in Watts of the server. + * @param staticPowerPercent The static power percentage. + * @property staticPower The static power consumption that is not dependent on resource usage. + * It is the amount of energy consumed even when the host is idle. + * @property constPower The constant power consumption for each fraction of resource used. + */ +public class SquarePowerModel( + private var maxPower: Double, + staticPowerPercent: Double +) : CpuPowerModel { + private var staticPower: Double = staticPowerPercent * maxPower + private var constPower: Double = (maxPower - staticPower) / 100.0.pow(2) + + override fun computeCpuPower(cpuUtil: Double): Double { + require(cpuUtil in 0.0..1.0) { "CPU utilization must be in [0, 1]" } + return staticPower + constPower * (cpuUtil * 100).pow(2) + } +} diff --git a/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/models/ZeroIdlePowerDecorator.kt b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/models/ZeroIdlePowerDecorator.kt new file mode 100644 index 00000000..938e5607 --- /dev/null +++ b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/models/ZeroIdlePowerDecorator.kt @@ -0,0 +1,14 @@ +package org.opendc.compute.simulator.power.models + +import org.opendc.compute.simulator.power.api.CpuPowerModel + +/** + * A decorator for ignoring the idle power when computing energy consumption of components. + * + * @param cpuModelWrappee The wrappe of a [CpuPowerModel]. + */ +public class ZeroIdlePowerDecorator(private val cpuModelWrappee: CpuPowerModel) : CpuPowerModel { + override fun computeCpuPower(cpuUtil: Double): Double { + return if (cpuUtil == 0.0) 0.0 else cpuModelWrappee.computeCpuPower(cpuUtil) + } +} diff --git a/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/models/package-info.java b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/models/package-info.java new file mode 100644 index 00000000..9354f1f9 --- /dev/null +++ b/simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/models/package-info.java @@ -0,0 +1,12 @@ +/** + * Contains a set of energy models, which are developed based on that of the following cloud simulators. + * N.B. Different configurations and new features may have been introduced. + * + * CloudSim: + * @see Anton Beloglazov, and Rajkumar Buyya, "Optimal Online Deterministic + * Algorithms and Adaptive Heuristics for Energy and Performance Efficient Dynamic Consolidation of Virtual Machines in + * Cloud Data Centers", Concurrency and Computation: Practice and Experience (CCPE), Volume 24, + * Issue 13, Pages: 1397-1420, John Wiley & Sons, Ltd, New York, USA, 2012 + */ +package org.opendc.compute.simulator.power.models; +// rest of the file is empty diff --git a/simulator/opendc-compute/opendc-compute-simulator/src/test/kotlin/org/opendc/compute/simulator/power/CpuPowerModelTest.kt b/simulator/opendc-compute/opendc-compute-simulator/src/test/kotlin/org/opendc/compute/simulator/power/CpuPowerModelTest.kt new file mode 100644 index 00000000..7b0c7515 --- /dev/null +++ b/simulator/opendc-compute/opendc-compute-simulator/src/test/kotlin/org/opendc/compute/simulator/power/CpuPowerModelTest.kt @@ -0,0 +1,75 @@ +package org.opendc.compute.simulator.power + +import io.mockk.* +import kotlinx.coroutines.flow.* +import kotlinx.coroutines.runBlocking +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.Arguments +import org.junit.jupiter.params.provider.MethodSource +import org.opendc.compute.core.metal.driver.BareMetalDriver +import org.opendc.compute.simulator.power.api.CpuPowerModel +import org.opendc.compute.simulator.power.models.* +import java.util.stream.Stream +import kotlin.math.pow + +internal class CpuPowerModelTest { + private val epsilon = 10.0.pow(-3) + private val cpuUtil = .9 + + @ParameterizedTest + @MethodSource("cpuPowerModelArgs") + fun `compute power consumption given CPU loads`( + powerModel: CpuPowerModel, + expectedPowerConsumption: Double + ) { + val computedPowerConsumption = powerModel.computeCpuPower(cpuUtil) + assertEquals(expectedPowerConsumption, computedPowerConsumption, epsilon) + } + + @ParameterizedTest + @MethodSource("cpuPowerModelArgs") + fun `ignore idle power when computing power consumptions`( + powerModel: CpuPowerModel, + expectedPowerConsumption: Double + ) { + val zeroPowerModel = ZeroIdlePowerDecorator(powerModel) + val computedPowerConsumption = zeroPowerModel.computeCpuPower(0.0) + assertEquals(0.0, computedPowerConsumption) + } + + @ParameterizedTest + @MethodSource("cpuPowerModelArgs") + fun `emit power draw for hosts by different models`( + powerModel: CpuPowerModel, + expectedPowerConsumption: Double + ) { + val cpuLoads = flowOf(cpuUtil, cpuUtil, cpuUtil) + val bareMetalDriver = mockkClass(BareMetalDriver::class) + every { bareMetalDriver.usage } returns cpuLoads + + runBlocking { + val serverPowerDraw = powerModel.getPowerDraw(bareMetalDriver) + + assertEquals(serverPowerDraw.count(), cpuLoads.count()) + assertEquals( + serverPowerDraw.first().toDouble(), + flowOf(expectedPowerConsumption).first().toDouble(), + epsilon + ) + } + verify(exactly = 1) { bareMetalDriver.usage } + } + + @Suppress("unused") + private companion object { + @JvmStatic + fun cpuPowerModelArgs(): Stream = Stream.of( + Arguments.of(ConstantPowerModel(0.0), 0.0), + Arguments.of(LinearPowerModel(350.0, 200 / 350.0), 335.0), + Arguments.of(SquarePowerModel(350.0, 200 / 350.0), 321.5), + Arguments.of(CubicPowerModel(350.0, 200 / 350.0), 309.35), + Arguments.of(SqrtPowerModel(350.0, 200 / 350.0), 342.302), + ) + } +} -- cgit v1.2.3