summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--simulator/buildSrc/src/main/kotlin/Versions.kt1
-rw-r--r--simulator/buildSrc/src/main/kotlin/dokka-conventions.gradle.kts2
-rw-r--r--simulator/buildSrc/src/main/kotlin/testing-conventions.gradle.kts2
-rw-r--r--simulator/gradle.properties1
-rw-r--r--simulator/input/environments/base.txt4
-rw-r--r--simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimBareMetalDriver.kt12
-rw-r--r--simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/PowerModel.kt32
-rw-r--r--simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/PowerModels.kt42
-rw-r--r--simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/api/CpuPowerModel.kt31
-rw-r--r--simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/api/Powerable.kt (renamed from simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/Powerable.kt)2
-rw-r--r--simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/models/ConstantPowerModel.kt10
-rw-r--r--simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/models/CubicPowerModel.kt26
-rw-r--r--simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/models/InterpolationPowerModel.kt34
-rw-r--r--simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/models/LinearPowerModel.kt25
-rw-r--r--simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/models/SqrtPowerModel.kt26
-rw-r--r--simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/models/SquarePowerModel.kt26
-rw-r--r--simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/models/ZeroIdlePowerDecorator.kt14
-rw-r--r--simulator/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/power/models/package-info.java12
-rw-r--r--simulator/opendc-compute/opendc-compute-simulator/src/test/kotlin/org/opendc/compute/simulator/power/CpuPowerModelTest.kt75
-rw-r--r--simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/sc20/Sc20ClusterEnvironmentReader.kt4
-rw-r--r--simulator/opendc-format/src/main/kotlin/org/opendc/format/environment/sc20/Sc20EnvironmentReader.kt4
-rw-r--r--simulator/opendc-runner-web/src/main/kotlin/org/opendc/runner/web/TopologyParser.kt4
23 files changed, 302 insertions, 89 deletions
diff --git a/.gitignore b/.gitignore
index 45bd066c..71e1c86a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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)
)
)
}