summaryrefslogtreecommitdiff
path: root/opendc-simulator/opendc-simulator-compute
diff options
context:
space:
mode:
authorHongyu <39747921+HongyuHe@users.noreply.github.com>2021-06-21 00:59:04 +0200
committerGitHub <noreply@github.com>2021-06-21 00:59:04 +0200
commitb8b0f39028af90fa54b42a00214b2ea9a5e48e2e (patch)
treea1e3c1032f542a8a9e95c4dacaa0da53b8050f13 /opendc-simulator/opendc-simulator-compute
parent5649bdc3fe77b40a112d8478460aab30ee08de58 (diff)
parent85e8303f12b319e2eb231584324327f28d43fc2c (diff)
simulator: Add Linux CPU frequency scaling governors
This change adds the CPU frequency scaling governors including the conservative and on-demand governors that are found in the Linux kernel. # Implementation Notes * A `ScalingPolicy` has been added to aid the frequency scaling process.
Diffstat (limited to 'opendc-simulator/opendc-simulator-compute')
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimAbstractHypervisor.kt19
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/ConservativeScalingGovernor.kt65
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/OnDemandScalingGovernor.kt50
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/PerformanceScalingGovernor.kt10
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/PowerSaveScalingGovernor.kt36
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/ScalingGovernor.kt6
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/ScalingPolicy.kt51
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/power/PStatePowerDriver.kt6
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/power/SimplePowerDriver.kt4
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/cpufreq/ConservativeScalingGovernorTest.kt98
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/cpufreq/OnDemandScalingGovernorTest.kt81
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/cpufreq/PerformanceScalingGovernorTest.kt19
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/cpufreq/PowerSaveScalingGovernorTest.kt72
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/power/PStatePowerDriverTest.kt10
14 files changed, 496 insertions, 31 deletions
diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimAbstractHypervisor.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimAbstractHypervisor.kt
index 57c25b86..d24ed1f3 100644
--- a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimAbstractHypervisor.kt
+++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimAbstractHypervisor.kt
@@ -23,6 +23,7 @@
package org.opendc.simulator.compute
import org.opendc.simulator.compute.cpufreq.ScalingGovernor
+import org.opendc.simulator.compute.cpufreq.ScalingPolicy
import org.opendc.simulator.compute.interference.PerformanceInterferenceModel
import org.opendc.simulator.compute.model.ProcessingUnit
import org.opendc.simulator.resources.*
@@ -100,11 +101,12 @@ public abstract class SimAbstractHypervisor(
switch = createSwitch(ctx)
for (cpu in ctx.cpus) {
- val governor = scalingGovernor?.createLogic(cpu)
+ val governor = scalingGovernor?.createLogic(ScalingPolicyImpl(cpu))
if (governor != null) {
governors.add(governor)
governor.onStart()
}
+
switch.addInput(cpu)
}
}
@@ -146,4 +148,19 @@ public abstract class SimAbstractHypervisor(
override fun toString(): String = "SimAbstractHypervisor.VCpu[model=$model]"
}
+
+ /**
+ * A [ScalingPolicy] for a physical CPU of the hypervisor.
+ */
+ private class ScalingPolicyImpl(override val cpu: SimProcessingUnit) : ScalingPolicy {
+ override var target: Double
+ get() = cpu.capacity
+ set(value) {
+ cpu.capacity = value
+ }
+
+ override val max: Double = cpu.model.frequency
+
+ override val min: Double = 0.0
+ }
}
diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/ConservativeScalingGovernor.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/ConservativeScalingGovernor.kt
new file mode 100644
index 00000000..562c0b73
--- /dev/null
+++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/ConservativeScalingGovernor.kt
@@ -0,0 +1,65 @@
+/*
+ * 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
+ * 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.simulator.compute.cpufreq
+
+/**
+ * A CPUFreq [ScalingGovernor] that models the conservative scaling governor in the Linux kernel.
+ */
+public class ConservativeScalingGovernor(public val threshold: Double = 0.8, private val stepSize: Double = -1.0) : ScalingGovernor {
+ override fun createLogic(policy: ScalingPolicy): ScalingGovernor.Logic = object : ScalingGovernor.Logic {
+ /**
+ * The step size to use.
+ */
+ private val stepSize = if (this@ConservativeScalingGovernor.stepSize < 0) {
+ // https://github.com/torvalds/linux/blob/master/drivers/cpufreq/cpufreq_conservative.c#L33
+ policy.max * 0.05
+ } else {
+ this@ConservativeScalingGovernor.stepSize.coerceAtMost(policy.max)
+ }
+
+ /**
+ * The previous load of the CPU.
+ */
+ private var previousLoad = threshold
+
+ override fun onStart() {
+ policy.target = policy.min
+ }
+
+ override fun onLimit(load: Double) {
+ val currentTarget = policy.target
+ if (load > threshold) {
+ // Check for load increase (see: https://github.com/torvalds/linux/blob/master/drivers/cpufreq/cpufreq_conservative.c#L102)
+ val step = when {
+ load > previousLoad -> stepSize
+ load < previousLoad -> -stepSize
+ else -> 0.0
+ }
+ policy.target = (currentTarget + step).coerceIn(policy.min, policy.max)
+ }
+ previousLoad = load
+ }
+ }
+
+ override fun toString(): String = "ConservativeScalingGovernor[threshold=$threshold,stepSize=$stepSize]"
+}
diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/OnDemandScalingGovernor.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/OnDemandScalingGovernor.kt
new file mode 100644
index 00000000..2c4a83f1
--- /dev/null
+++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/OnDemandScalingGovernor.kt
@@ -0,0 +1,50 @@
+/*
+ * 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
+ * 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.simulator.compute.cpufreq
+
+/**
+ * A CPUFreq [ScalingGovernor] that models the on-demand scaling governor in the Linux kernel.
+ */
+public class OnDemandScalingGovernor(public val threshold: Double = 0.8) : ScalingGovernor {
+ override fun createLogic(policy: ScalingPolicy): ScalingGovernor.Logic = object : ScalingGovernor.Logic {
+ /**
+ * The multiplier used for the linear frequency scaling.
+ */
+ private val multiplier = (policy.max - policy.min) / 100
+
+ override fun onStart() {
+ policy.target = policy.min
+ }
+
+ override fun onLimit(load: Double) {
+ policy.target = if (load < threshold) {
+ /* Proportional scaling (see: https://github.com/torvalds/linux/blob/master/drivers/cpufreq/cpufreq_ondemand.c#L151). */
+ policy.min + load * multiplier
+ } else {
+ policy.max
+ }
+ }
+ }
+
+ override fun toString(): String = "OnDemandScalingGovernor[threshold=$threshold]"
+}
diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/PerformanceScalingGovernor.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/PerformanceScalingGovernor.kt
index 245877be..8b1d49f6 100644
--- a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/PerformanceScalingGovernor.kt
+++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/PerformanceScalingGovernor.kt
@@ -22,17 +22,15 @@
package org.opendc.simulator.compute.cpufreq
-import org.opendc.simulator.compute.SimProcessingUnit
-
/**
* A CPUFreq [ScalingGovernor] that causes the highest possible frequency to be requested from the resource.
*/
public class PerformanceScalingGovernor : ScalingGovernor {
- override fun createLogic(cpu: SimProcessingUnit): ScalingGovernor.Logic = object : ScalingGovernor.Logic {
+ override fun createLogic(policy: ScalingPolicy): ScalingGovernor.Logic = object : ScalingGovernor.Logic {
override fun onStart() {
- cpu.capacity = cpu.model.frequency
+ policy.target = policy.max
}
-
- override fun toString(): String = "PerformanceScalingGovernor.Logic"
}
+
+ override fun toString(): String = "PerformanceScalingGovernor"
}
diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/PowerSaveScalingGovernor.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/PowerSaveScalingGovernor.kt
new file mode 100644
index 00000000..0889980c
--- /dev/null
+++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/PowerSaveScalingGovernor.kt
@@ -0,0 +1,36 @@
+/*
+ * 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
+ * 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.simulator.compute.cpufreq
+
+/**
+ * A CPUFreq [ScalingGovernor] that causes the lowest possible frequency to be requested from the resource.
+ */
+public class PowerSaveScalingGovernor : ScalingGovernor {
+ override fun createLogic(policy: ScalingPolicy): ScalingGovernor.Logic = object : ScalingGovernor.Logic {
+ override fun onStart() {
+ policy.target = policy.min
+ }
+ }
+
+ override fun toString(): String = "PowerSaveScalingGovernor"
+}
diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/ScalingGovernor.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/ScalingGovernor.kt
index b7e7ffc6..3fb93ad9 100644
--- a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/ScalingGovernor.kt
+++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/ScalingGovernor.kt
@@ -22,8 +22,6 @@
package org.opendc.simulator.compute.cpufreq
-import org.opendc.simulator.compute.SimProcessingUnit
-
/**
* A [ScalingGovernor] in the CPUFreq subsystem of OpenDC is responsible for scaling the frequency of simulated CPUs
* independent of the particular implementation of the CPU.
@@ -35,9 +33,9 @@ import org.opendc.simulator.compute.SimProcessingUnit
*/
public interface ScalingGovernor {
/**
- * Create the scaling logic for the specified [cpu]
+ * Create the scaling logic for the specified [policy]
*/
- public fun createLogic(cpu: SimProcessingUnit): Logic
+ public fun createLogic(policy: ScalingPolicy): Logic
/**
* The logic of the scaling governor.
diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/ScalingPolicy.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/ScalingPolicy.kt
new file mode 100644
index 00000000..0552d279
--- /dev/null
+++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/ScalingPolicy.kt
@@ -0,0 +1,51 @@
+/*
+ * 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
+ * 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.simulator.compute.cpufreq
+
+import org.opendc.simulator.compute.SimProcessingUnit
+
+/**
+ * An interface that holds the state managed by a [ScalingGovernor] and used by the underlying machine to control the
+ * CPU frequencies.
+ */
+public interface ScalingPolicy {
+ /**
+ * The processing unit that is associated with this policy.
+ */
+ public val cpu: SimProcessingUnit
+
+ /**
+ * The target frequency which the CPU should attempt to attain.
+ */
+ public var target: Double
+
+ /**
+ * The minimum frequency to which the CPU may scale.
+ */
+ public val min: Double
+
+ /**
+ * The maximum frequency to which the CPU may scale.
+ */
+ public val max: Double
+}
diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/power/PStatePowerDriver.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/power/PStatePowerDriver.kt
index 6328c8e4..6577fbfc 100644
--- a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/power/PStatePowerDriver.kt
+++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/power/PStatePowerDriver.kt
@@ -37,7 +37,7 @@ public class PStatePowerDriver(states: Map<Double, PowerModel>) : PowerDriver {
/**
* The P-States defined by the user and ordered by key.
*/
- private val states = TreeMap(states)
+ private val states: TreeMap<Double, PowerModel> = TreeMap(states)
override fun createLogic(machine: SimMachine, cpus: List<SimProcessingUnit>): PowerDriver.Logic = object : PowerDriver.Logic {
override fun computePower(): Double {
@@ -54,7 +54,7 @@ public class PStatePowerDriver(states: Map<Double, PowerModel>) : PowerDriver {
val utilization = totalSpeed / (actualFreq * cpus.size)
return model.computePower(utilization)
}
-
- override fun toString(): String = "PStatePowerDriver.Logic"
}
+
+ override fun toString(): String = "PStatePowerDriver[states=$states]"
}
diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/power/SimplePowerDriver.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/power/SimplePowerDriver.kt
index 5c5ceff5..e43c89ac 100644
--- a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/power/SimplePowerDriver.kt
+++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/power/SimplePowerDriver.kt
@@ -33,7 +33,7 @@ public class SimplePowerDriver(private val model: PowerModel) : PowerDriver {
override fun computePower(): Double {
return model.computePower(machine.usage.value)
}
-
- override fun toString(): String = "SimplePowerDriver.Logic"
}
+
+ override fun toString(): String = "SimplePowerDriver[model=$model]"
}
diff --git a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/cpufreq/ConservativeScalingGovernorTest.kt b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/cpufreq/ConservativeScalingGovernorTest.kt
new file mode 100644
index 00000000..59817f1d
--- /dev/null
+++ b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/cpufreq/ConservativeScalingGovernorTest.kt
@@ -0,0 +1,98 @@
+/*
+ * 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
+ * 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.simulator.compute.cpufreq
+
+import io.mockk.every
+import io.mockk.mockk
+import io.mockk.verify
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.Test
+
+/**
+ * Test suite for the [ConservativeScalingGovernor]
+ */
+internal class ConservativeScalingGovernorTest {
+ @Test
+ fun testSetStartLimitWithoutPStates() {
+ val cpuCapacity = 4100.0
+ val minSpeed = cpuCapacity / 2
+ val defaultThreshold = 0.8
+ val defaultStepSize = 0.05 * cpuCapacity
+ val governor = ConservativeScalingGovernor()
+
+ val policy = mockk<ScalingPolicy>(relaxUnitFun = true)
+ every { policy.max } returns cpuCapacity
+ every { policy.min } returns minSpeed
+
+ var target = 0.0
+ every { policy.target } answers { target }
+ every { policy.target = any() } propertyType Double::class answers { target = value }
+
+ val logic = governor.createLogic(policy)
+ logic.onStart()
+ assertEquals(defaultThreshold, governor.threshold)
+
+ logic.onLimit(0.5)
+
+ /* Upwards scaling */
+ logic.onLimit(defaultThreshold + 0.2)
+
+ /* Downwards scaling */
+ logic.onLimit(defaultThreshold + 0.1)
+
+ verify(exactly = 2) { policy.target = minSpeed }
+ verify(exactly = 1) { policy.target = minSpeed + defaultStepSize }
+ }
+
+ @Test
+ fun testSetStartLimitWithPStatesAndParams() {
+ val firstPState = 1000.0
+ val cpuCapacity = 4100.0
+ val minSpeed = firstPState
+ val threshold = 0.5
+ val stepSize = 0.02 * cpuCapacity
+ val governor = ConservativeScalingGovernor(threshold, stepSize)
+
+ val policy = mockk<ScalingPolicy>(relaxUnitFun = true)
+ every { policy.max } returns cpuCapacity
+ every { policy.min } returns firstPState
+
+ var target = 0.0
+ every { policy.target } answers { target }
+ every { policy.target = any() } propertyType Double::class answers { target = value }
+
+ val logic = governor.createLogic(policy)
+ logic.onStart()
+ assertEquals(threshold, governor.threshold)
+ logic.onLimit(0.5)
+
+ /* Upwards scaling */
+ logic.onLimit(threshold + 0.2)
+
+ /* Downwards scaling */
+ logic.onLimit(threshold + 0.1)
+
+ verify(exactly = 2) { policy.target = minSpeed }
+ verify(exactly = 1) { policy.target = minSpeed + stepSize }
+ }
+}
diff --git a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/cpufreq/OnDemandScalingGovernorTest.kt b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/cpufreq/OnDemandScalingGovernorTest.kt
new file mode 100644
index 00000000..c0c25c97
--- /dev/null
+++ b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/cpufreq/OnDemandScalingGovernorTest.kt
@@ -0,0 +1,81 @@
+/*
+ * 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
+ * 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.simulator.compute.cpufreq
+
+import io.mockk.every
+import io.mockk.mockk
+import io.mockk.verify
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.Test
+
+/**
+ * Test suite for the [OnDemandScalingGovernor]
+ */
+internal class OnDemandScalingGovernorTest {
+ @Test
+ fun testSetStartLimitWithoutPStates() {
+ val cpuCapacity = 4100.0
+ val minSpeed = cpuCapacity / 2
+ val defaultThreshold = 0.8
+ val governor = OnDemandScalingGovernor()
+
+ val policy = mockk<ScalingPolicy>(relaxUnitFun = true)
+ every { policy.min } returns minSpeed
+ every { policy.max } returns cpuCapacity
+
+ val logic = governor.createLogic(policy)
+ logic.onStart()
+ assertEquals(defaultThreshold, governor.threshold)
+ verify(exactly = 1) { policy.target = minSpeed }
+
+ logic.onLimit(0.5)
+ verify(exactly = 1) { policy.target = minSpeed + 0.5 * (cpuCapacity - minSpeed) / 100 }
+
+ logic.onLimit(defaultThreshold)
+ verify(exactly = 1) { policy.target = cpuCapacity }
+ }
+
+ @Test
+ fun testSetStartLimitWithPStatesAndParams() {
+ val firstPState = 1000.0
+ val cpuCapacity = 4100.0
+ val threshold = 0.5
+ val governor = OnDemandScalingGovernor(threshold)
+
+ val policy = mockk<ScalingPolicy>(relaxUnitFun = true)
+ every { policy.max } returns cpuCapacity
+ every { policy.min } returns firstPState
+
+ val logic = governor.createLogic(policy)
+
+ logic.onStart()
+ assertEquals(threshold, governor.threshold)
+ verify(exactly = 1) { policy.target = firstPState }
+
+ logic.onLimit(0.1)
+ verify(exactly = 1) { policy.target = firstPState + 0.1 * (cpuCapacity - firstPState) / 100 }
+
+ logic.onLimit(threshold)
+ verify(exactly = 1) { policy.target = cpuCapacity }
+ }
+}
diff --git a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/cpufreq/PerformanceScalingGovernorTest.kt b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/cpufreq/PerformanceScalingGovernorTest.kt
index 8e8b09c8..d7bd6193 100644
--- a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/cpufreq/PerformanceScalingGovernorTest.kt
+++ b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/cpufreq/PerformanceScalingGovernorTest.kt
@@ -23,10 +23,9 @@
package org.opendc.simulator.compute.cpufreq
import io.mockk.every
-import io.mockk.mockk
+import io.mockk.spyk
import io.mockk.verify
import org.junit.jupiter.api.Test
-import org.opendc.simulator.compute.SimProcessingUnit
/**
* Test suite for the [PerformanceScalingGovernor]
@@ -34,16 +33,18 @@ import org.opendc.simulator.compute.SimProcessingUnit
internal class PerformanceScalingGovernorTest {
@Test
fun testSetStartLimit() {
- val cpu = mockk<SimProcessingUnit>(relaxUnitFun = true)
+ val policy = spyk<ScalingPolicy>()
+ val logic = PerformanceScalingGovernor().createLogic(policy)
- every { cpu.model.frequency } returns 4100.0
- every { cpu.speed } returns 2100.0
-
- val logic = PerformanceScalingGovernor().createLogic(cpu)
+ every { policy.max } returns 4100.0
logic.onStart()
- logic.onLimit(1.0)
+ verify(exactly = 1) { policy.target = 4100.0 }
- verify(exactly = 1) { cpu.capacity = 4100.0 }
+ logic.onLimit(0.0)
+ verify(exactly = 1) { policy.target = 4100.0 }
+
+ logic.onLimit(1.0)
+ verify(exactly = 1) { policy.target = 4100.0 }
}
}
diff --git a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/cpufreq/PowerSaveScalingGovernorTest.kt b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/cpufreq/PowerSaveScalingGovernorTest.kt
new file mode 100644
index 00000000..8d841981
--- /dev/null
+++ b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/cpufreq/PowerSaveScalingGovernorTest.kt
@@ -0,0 +1,72 @@
+/*
+ * 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
+ * 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.simulator.compute.cpufreq
+
+import io.mockk.every
+import io.mockk.mockk
+import io.mockk.verify
+import org.junit.jupiter.api.Test
+
+/**
+ * Test suite for the [PowerSaveScalingGovernor]
+ */
+internal class PowerSaveScalingGovernorTest {
+ @Test
+ fun testSetStartLimitWithoutPStates() {
+ val cpuCapacity = 4100.0
+ val minSpeed = cpuCapacity / 2
+ val policy = mockk<ScalingPolicy>(relaxUnitFun = true)
+ val logic = PowerSaveScalingGovernor().createLogic(policy)
+
+ every { policy.max } returns cpuCapacity
+ every { policy.min } returns minSpeed
+
+ logic.onStart()
+
+ logic.onLimit(0.0)
+ verify(exactly = 1) { policy.target = minSpeed }
+
+ logic.onLimit(1.0)
+ verify(exactly = 1) { policy.target = minSpeed }
+ }
+
+ @Test
+ fun testSetStartLimitWithPStates() {
+ val cpuCapacity = 4100.0
+ val firstPState = 1000.0
+ val policy = mockk<ScalingPolicy>(relaxUnitFun = true)
+ val logic = PowerSaveScalingGovernor().createLogic(policy)
+
+ every { policy.max } returns cpuCapacity
+ every { policy.min } returns firstPState
+
+ logic.onStart()
+ verify(exactly = 1) { policy.target = firstPState }
+
+ logic.onLimit(0.0)
+ verify(exactly = 1) { policy.target = firstPState }
+
+ logic.onLimit(1.0)
+ verify(exactly = 1) { policy.target = firstPState }
+ }
+}
diff --git a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/power/PStatePowerDriverTest.kt b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/power/PStatePowerDriverTest.kt
index 35fd7c4c..c39859bf 100644
--- a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/power/PStatePowerDriverTest.kt
+++ b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/power/PStatePowerDriverTest.kt
@@ -52,7 +52,7 @@ internal class PStatePowerDriverTest {
@Test
fun testPowerWithSingleCpu() {
val machine = mockk<SimBareMetalMachine>()
- val cpu = mockk<SimProcessingUnit>()
+ val cpu = mockk<SimProcessingUnit>(relaxUnitFun = true)
every { cpu.capacity } returns 3200.0
every { cpu.speed } returns 1200.0
@@ -73,10 +73,8 @@ internal class PStatePowerDriverTest {
@Test
fun testPowerWithMultipleCpus() {
val machine = mockk<SimBareMetalMachine>()
- val cpus = listOf(
- mockk<SimProcessingUnit>(),
- mockk()
- )
+ val cpu = mockk<SimProcessingUnit>(relaxUnitFun = true)
+ val cpus = listOf(cpu, cpu)
every { cpus[0].capacity } returns 1000.0
every { cpus[0].speed } returns 1200.0
@@ -100,7 +98,7 @@ internal class PStatePowerDriverTest {
@Test
fun testPowerBasedOnUtilization() {
val machine = mockk<SimBareMetalMachine>()
- val cpu = mockk<SimProcessingUnit>()
+ val cpu = mockk<SimProcessingUnit>(relaxUnitFun = true)
every { cpu.model.frequency } returns 4200.0