diff options
| author | Hongyu <39747921+HongyuHe@users.noreply.github.com> | 2021-03-06 19:36:46 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-03-06 19:36:46 +0100 |
| commit | 2977dd8a5f1d742193eae79364a284e68269f7b5 (patch) | |
| tree | 3fb378be396d728d30b2769a4610c652cfb71507 | |
| parent | d72ac4b1df32dd5e6bd3faa4fa528dbf8a03f6f1 (diff) | |
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.
23 files changed, 302 insertions, 89 deletions
@@ -5,7 +5,7 @@ .python-version database/opendc_testing/* -# macOS-specific files +# MacOS-specific files .DS_Store # Environment files diff --git a/simulator/buildSrc/src/main/kotlin/Versions.kt b/simulator/buildSrc/src/main/kotlin/Versions.kt index fcf3c778..d1df6284 100644 --- a/simulator/buildSrc/src/main/kotlin/Versions.kt +++ b/simulator/buildSrc/src/main/kotlin/Versions.kt @@ -41,6 +41,7 @@ public class Versions(private val project: Project) { val junitJupiter by version(name = "junit-jupiter") val junitPlatform by version(name = "junit-platform") + val mockk by version() val slf4j by version() val kotlinLogging by version(name = "kotlin-logging") diff --git a/simulator/buildSrc/src/main/kotlin/dokka-conventions.gradle.kts b/simulator/buildSrc/src/main/kotlin/dokka-conventions.gradle.kts index 95183df2..91156cbf 100644 --- a/simulator/buildSrc/src/main/kotlin/dokka-conventions.gradle.kts +++ b/simulator/buildSrc/src/main/kotlin/dokka-conventions.gradle.kts @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2019 atlarge-research + * Copyright (c) 2021 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 diff --git a/simulator/buildSrc/src/main/kotlin/testing-conventions.gradle.kts b/simulator/buildSrc/src/main/kotlin/testing-conventions.gradle.kts index 22ea7905..566b765f 100644 --- a/simulator/buildSrc/src/main/kotlin/testing-conventions.gradle.kts +++ b/simulator/buildSrc/src/main/kotlin/testing-conventions.gradle.kts @@ -35,4 +35,6 @@ tasks.test { dependencies { testImplementation("org.junit.jupiter:junit-jupiter-api:${versions.junitJupiter}") testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${versions.junitJupiter}") + testImplementation("org.junit.jupiter:junit-jupiter-params:${versions.junitJupiter}") + testImplementation("io.mockk:mockk:${versions.mockk}") } diff --git a/simulator/gradle.properties b/simulator/gradle.properties index fb007dde..930be6b5 100644 --- a/simulator/gradle.properties +++ b/simulator/gradle.properties @@ -45,3 +45,4 @@ classgraph.version = 4.8.102 # Dependencies (Testing) junit-jupiter.version = 5.7.1 junit-platform.version = 1.7.1 +mockk.version = 1.10.5 diff --git a/simulator/input/environments/base.txt b/simulator/input/environments/base.txt new file mode 100644 index 00000000..3c5092af --- /dev/null +++ b/simulator/input/environments/base.txt @@ -0,0 +1,4 @@ +ClusterID;ClusterName;Cores;Speed;Memory;numberOfHosts;memoryCapacityPerHost;coreCountPerHost +A01;A01;32;3.2;2048;1;256;32 +B01;B01;48;2.93;1256;6;64;8 +C01;C01;32;3.2;2048;2;128;16 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<String, Any>, machine: SimMachineModel, - powerModel: PowerModel<SimBareMetalDriver> = 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<Double> get() = this.machine.usage - override val powerDraw: Flow<Double> = powerModel(this) + override val powerDraw: Flow<Double> = 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> = (T) -> Flow<Double> 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<BareMetalDriver> = { _ -> 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<BareMetalDriver> = { 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/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<Double> = + driver.usage.map { + computeCpuPower(it) + } +} 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/api/Powerable.kt index dcf74468..780f2a29 100644 --- 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/api/Powerable.kt @@ -22,7 +22,7 @@ * SOFTWARE. */ -package org.opendc.compute.simulator.power +package org.opendc.compute.simulator.power.api import kotlinx.coroutines.flow.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 <a href="http://dx.doi.org/10.1002/cpe.1867">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</a> + */ +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<Arguments> = 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), + ) + } +} diff --git a/simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/sc20/Sc20ClusterEnvironmentReader.kt b/simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/sc20/Sc20ClusterEnvironmentReader.kt index b4c71c4e..6ec8ba4a 100644 --- a/simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/sc20/Sc20ClusterEnvironmentReader.kt +++ b/simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/sc20/Sc20ClusterEnvironmentReader.kt @@ -27,7 +27,7 @@ import org.opendc.compute.core.metal.NODE_CLUSTER import org.opendc.compute.core.metal.service.ProvisioningService import org.opendc.compute.core.metal.service.SimpleProvisioningService import org.opendc.compute.simulator.SimBareMetalDriver -import org.opendc.compute.simulator.power.LinearLoadPowerModel +import org.opendc.compute.simulator.power.models.LinearPowerModel import org.opendc.core.Environment import org.opendc.core.Platform import org.opendc.core.Zone @@ -118,7 +118,7 @@ public class Sc20ClusterEnvironmentReader( // For now we assume a simple linear load model with an idle draw of ~200W and a maximum // power draw of 350W. // Source: https://stackoverflow.com/questions/6128960 - LinearLoadPowerModel(200.0, 350.0) + LinearPowerModel(350.0, 200 / 350.0) ) ) } diff --git a/simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/sc20/Sc20EnvironmentReader.kt b/simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/sc20/Sc20EnvironmentReader.kt index 94237cb9..a58a2524 100644 --- a/simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/sc20/Sc20EnvironmentReader.kt +++ b/simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/sc20/Sc20EnvironmentReader.kt @@ -29,7 +29,7 @@ import kotlinx.coroutines.CoroutineScope import org.opendc.compute.core.metal.service.ProvisioningService import org.opendc.compute.core.metal.service.SimpleProvisioningService import org.opendc.compute.simulator.SimBareMetalDriver -import org.opendc.compute.simulator.power.LinearLoadPowerModel +import org.opendc.compute.simulator.power.models.LinearPowerModel import org.opendc.core.Environment import org.opendc.core.Platform import org.opendc.core.Zone @@ -91,7 +91,7 @@ public class Sc20EnvironmentReader(input: InputStream, mapper: ObjectMapper = ja // For now we assume a simple linear load model with an idle draw of ~200W and a maximum // power draw of 350W. // Source: https://stackoverflow.com/questions/6128960 - LinearLoadPowerModel(200.0, 350.0) + LinearPowerModel(350.0, 200 / 350.0) ) } } diff --git a/simulator/opendc-runner-web/src/main/kotlin/org/opendc/runner/web/TopologyParser.kt b/simulator/opendc-runner-web/src/main/kotlin/org/opendc/runner/web/TopologyParser.kt index 8bd1eefb..f43d0869 100644 --- a/simulator/opendc-runner-web/src/main/kotlin/org/opendc/runner/web/TopologyParser.kt +++ b/simulator/opendc-runner-web/src/main/kotlin/org/opendc/runner/web/TopologyParser.kt @@ -36,7 +36,7 @@ import org.opendc.compute.core.metal.NODE_CLUSTER import org.opendc.compute.core.metal.service.ProvisioningService import org.opendc.compute.core.metal.service.SimpleProvisioningService import org.opendc.compute.simulator.SimBareMetalDriver -import org.opendc.compute.simulator.power.LinearLoadPowerModel +import org.opendc.compute.simulator.power.models.LinearPowerModel import org.opendc.core.Environment import org.opendc.core.Platform import org.opendc.core.Zone @@ -92,7 +92,7 @@ public class TopologyParser(private val collection: MongoCollection<Document>, p "node-$clusterId-$position", mapOf(NODE_CLUSTER to clusterId), SimMachineModel(processors, memoryUnits), - LinearLoadPowerModel(energyConsumptionW, 2 * energyConsumptionW) + LinearPowerModel(2 * energyConsumptionW, .5) ) ) } |
