summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFabian Mastenbroek <mail.fabianm@gmail.com>2021-08-25 21:03:34 +0200
committerGitHub <noreply@github.com>2021-08-25 21:03:34 +0200
commit719d4eb5856ecfe1900b305e682c3c5b7749793c (patch)
tree276eddd32297cf370ca37504ac0ef770f55ec4fe
parent4f333808d823abadd603ef2221092d82dc0f02b4 (diff)
parentb0f6402f60ddbba1aad7e198fe6757792337f4d4 (diff)
merge: Measure power draw in SimHost without PSU overhead
This pull request implements power draw reporting in SimHost where the power draw is computed without PSU overhead. * Remove usage and speed fields from SimMachine * Measure power draw without PSU overhead **Breaking API Changes** * `SimMachine.usage` and `SimMachine.speed` fields are removed.
-rw-r--r--opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimHost.kt2
-rw-r--r--opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/monitor/ExperimentMetricExporter.kt14
-rw-r--r--opendc-experiments/opendc-experiments-capelin/src/test/kotlin/org/opendc/experiments/capelin/CapelinIntegrationTest.kt5
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimAbstractMachine.kt40
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimBareMetalMachine.kt18
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimMachine.kt6
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimAbstractHypervisor.kt2
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/power/SimplePowerDriver.kt11
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/SimMachineTest.kt41
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/SimHypervisorTest.kt11
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/SimSpaceSharedHypervisorTest.kt18
11 files changed, 34 insertions, 134 deletions
diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimHost.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimHost.kt
index dcc525cb..20e5a9db 100644
--- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimHost.kt
+++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimHost.kt
@@ -114,7 +114,7 @@ public class SimHost(
_interferedWork.add(interferedWork)
_cpuDemand.record(cpuDemand)
_cpuUsage.record(cpuUsage)
- _powerUsage.record(machine.psu.powerDraw)
+ _powerUsage.record(machine.powerDraw)
}
}
)
diff --git a/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/monitor/ExperimentMetricExporter.kt b/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/monitor/ExperimentMetricExporter.kt
index e9c817de..42b7cbb8 100644
--- a/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/monitor/ExperimentMetricExporter.kt
+++ b/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/monitor/ExperimentMetricExporter.kt
@@ -60,7 +60,7 @@ public class ExperimentMetricExporter(
when (metric.name) {
"cpu.demand" -> mapDoubleSummary(metric, hostMetrics) { m, v -> m.cpuDemand = v }
"cpu.usage" -> mapDoubleSummary(metric, hostMetrics) { m, v -> m.cpuUsage = v }
- "power.usage" -> mapDoubleGauge(metric, hostMetrics) { m, v -> m.powerDraw = v }
+ "power.usage" -> mapDoubleSummary(metric, hostMetrics) { m, v -> m.powerDraw = v }
"cpu.work.total" -> mapDoubleSum(metric, hostMetrics) { m, v -> m.totalWork = v }
"cpu.work.granted" -> mapDoubleSum(metric, hostMetrics) { m, v -> m.grantedWork = v }
"cpu.work.overcommit" -> mapDoubleSum(metric, hostMetrics) { m, v -> m.overcommittedWork = v }
@@ -103,18 +103,6 @@ public class ExperimentMetricExporter(
}
}
- private fun mapDoubleGauge(data: MetricData?, hostMetrics: MutableMap<String, HostMetrics>, block: (HostMetrics, Double) -> Unit) {
- val points = data?.doubleGaugeData?.points ?: emptyList()
- for (point in points) {
- val uid = point.attributes[ResourceAttributes.HOST_ID]
- val hostMetric = hostMetrics[uid]
-
- if (hostMetric != null) {
- block(hostMetric, point.value)
- }
- }
- }
-
private fun mapLongSum(data: MetricData?, hostMetrics: MutableMap<String, HostMetrics>, block: (HostMetrics, Long) -> Unit) {
val points = data?.longSumData?.points ?: emptyList()
for (point in points) {
diff --git a/opendc-experiments/opendc-experiments-capelin/src/test/kotlin/org/opendc/experiments/capelin/CapelinIntegrationTest.kt b/opendc-experiments/opendc-experiments-capelin/src/test/kotlin/org/opendc/experiments/capelin/CapelinIntegrationTest.kt
index 8008c944..e4d3fed3 100644
--- a/opendc-experiments/opendc-experiments-capelin/src/test/kotlin/org/opendc/experiments/capelin/CapelinIntegrationTest.kt
+++ b/opendc-experiments/opendc-experiments-capelin/src/test/kotlin/org/opendc/experiments/capelin/CapelinIntegrationTest.kt
@@ -123,7 +123,8 @@ class CapelinIntegrationTest {
{ assertEquals(220346369753, monitor.totalWork) { "Incorrect requested burst" } },
{ assertEquals(206667809529, monitor.totalGrantedWork) { "Incorrect granted burst" } },
{ assertEquals(1151611104, monitor.totalOvercommittedWork) { "Incorrect overcommitted burst" } },
- { assertEquals(0, monitor.totalInterferedWork) { "Incorrect interfered burst" } }
+ { assertEquals(0, monitor.totalInterferedWork) { "Incorrect interfered burst" } },
+ { assertEquals(1.7671768767192196E7, monitor.totalPowerDraw, 0.01) { "Incorrect power draw" } },
)
}
@@ -287,6 +288,7 @@ class CapelinIntegrationTest {
var totalGrantedWork = 0L
var totalOvercommittedWork = 0L
var totalInterferedWork = 0L
+ var totalPowerDraw = 0.0
override fun reportHostData(
time: Long,
@@ -304,6 +306,7 @@ class CapelinIntegrationTest {
totalGrantedWork += grantedWork.toLong()
totalOvercommittedWork += overcommittedWork.toLong()
totalInterferedWork += interferedWork.toLong()
+ totalPowerDraw += powerDraw
}
override fun close() {}
diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimAbstractMachine.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimAbstractMachine.kt
index f416643e..266db0dd 100644
--- a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimAbstractMachine.kt
+++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimAbstractMachine.kt
@@ -23,8 +23,6 @@
package org.opendc.simulator.compute
import kotlinx.coroutines.*
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.StateFlow
import org.opendc.simulator.compute.device.SimNetworkAdapter
import org.opendc.simulator.compute.device.SimPeripheral
import org.opendc.simulator.compute.model.MachineModel
@@ -49,20 +47,6 @@ public abstract class SimAbstractMachine(
final override val model: MachineModel
) : SimMachine, SimResourceSystem {
/**
- * A [StateFlow] representing the CPU usage of the simulated machine.
- */
- private val _usage = MutableStateFlow(0.0)
- public final override val usage: StateFlow<Double>
- get() = _usage
-
- /**
- * The speed of the CPU cores.
- */
- public val speed: DoubleArray
- get() = _speed
- private var _speed = doubleArrayOf()
-
- /**
* The resources allocated for this machine.
*/
protected abstract val cpus: List<SimProcessingUnit>
@@ -106,10 +90,6 @@ public abstract class SimAbstractMachine(
val ctx = Context(meta)
- // Before the workload starts, initialize the initial power draw
- _speed = DoubleArray(model.cpus.size) { 0.0 }
- updateUsage(0.0)
-
return suspendCancellableCoroutine { cont ->
this.cont = cont
@@ -136,26 +116,6 @@ public abstract class SimAbstractMachine(
cancel()
}
- /* SimResourceSystem */
- override fun onConverge(timestamp: Long) {
- val totalCapacity = model.cpus.sumOf { it.frequency }
- val cpus = cpus
- var totalSpeed = 0.0
- for (cpu in cpus) {
- _speed[cpu.model.id] = cpu.speed
- totalSpeed += cpu.speed
- }
-
- updateUsage(totalSpeed / totalCapacity)
- }
-
- /**
- * This method is invoked when the usage of the machine is updated.
- */
- protected open fun updateUsage(usage: Double) {
- _usage.value = usage
- }
-
/**
* Cancel the workload that is currently running on the machine.
*/
diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimBareMetalMachine.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimBareMetalMachine.kt
index 887f0885..639ca450 100644
--- a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimBareMetalMachine.kt
+++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimBareMetalMachine.kt
@@ -32,7 +32,7 @@ import org.opendc.simulator.resources.SimResourceInterpreter
/**
* A simulated bare-metal machine that is able to run a single workload.
*
- * A [SimBareMetalMachine] is a stateful object and you should be careful when operating this object concurrently. For
+ * A [SimBareMetalMachine] is a stateful object, and you should be careful when operating this object concurrently. For
* example, the class expects only a single concurrent call to [run].
*
* @param interpreter The [SimResourceInterpreter] to drive the simulation.
@@ -49,19 +49,29 @@ public class SimBareMetalMachine(
parent: SimResourceSystem? = null,
) : SimAbstractMachine(interpreter, parent, model) {
/**
+ * The power draw of the machine onto the PSU.
+ */
+ public val powerDraw: Double
+ get() = powerDriverLogic.computePower()
+
+ /**
* The processing units of the machine.
*/
override val cpus: List<SimProcessingUnit> = model.cpus.map { cpu ->
Cpu(SimResourceSource(cpu.frequency, interpreter, this@SimBareMetalMachine), cpu)
}
- override fun updateUsage(usage: Double) {
- super.updateUsage(usage)
+ /**
+ * The logic of the power driver.
+ */
+ private val powerDriverLogic = powerDriver.createLogic(this, cpus)
+
+ override fun onConverge(timestamp: Long) {
psu.update()
}
init {
- psu.connect(powerDriver.createLogic(this, cpus))
+ psu.connect(powerDriverLogic)
}
/**
diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimMachine.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimMachine.kt
index 0f4674d5..d8dd8205 100644
--- a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimMachine.kt
+++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimMachine.kt
@@ -22,7 +22,6 @@
package org.opendc.simulator.compute
-import kotlinx.coroutines.flow.StateFlow
import org.opendc.simulator.compute.device.SimPeripheral
import org.opendc.simulator.compute.model.MachineModel
import org.opendc.simulator.compute.workload.SimWorkload
@@ -42,11 +41,6 @@ public interface SimMachine : AutoCloseable {
public val peripherals: List<SimPeripheral>
/**
- * A [StateFlow] representing the CPU usage of the simulated machine.
- */
- public val usage: StateFlow<Double>
-
- /**
* Run the specified [SimWorkload] on this machine and suspend execution util the workload has finished.
*/
public suspend fun run(workload: SimWorkload, meta: Map<String, Any> = emptyMap())
diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimAbstractHypervisor.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimAbstractHypervisor.kt
index 6002270a..98271fb0 100644
--- a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimAbstractHypervisor.kt
+++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimAbstractHypervisor.kt
@@ -145,6 +145,8 @@ public abstract class SimAbstractHypervisor(
interferenceDomain?.leave(interferenceKey)
}
}
+
+ override fun onConverge(timestamp: Long) {}
}
/**
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 e43c89ac..bf7aeff1 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
@@ -30,8 +30,17 @@ import org.opendc.simulator.compute.SimProcessingUnit
*/
public class SimplePowerDriver(private val model: PowerModel) : PowerDriver {
override fun createLogic(machine: SimMachine, cpus: List<SimProcessingUnit>): PowerDriver.Logic = object : PowerDriver.Logic {
+
override fun computePower(): Double {
- return model.computePower(machine.usage.value)
+ var targetFreq = 0.0
+ var totalSpeed = 0.0
+
+ for (cpu in cpus) {
+ targetFreq += cpu.capacity
+ totalSpeed += cpu.speed
+ }
+
+ return model.computePower(totalSpeed / targetFreq)
}
}
diff --git a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/SimMachineTest.kt b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/SimMachineTest.kt
index 19808a77..81268879 100644
--- a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/SimMachineTest.kt
+++ b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/SimMachineTest.kt
@@ -23,9 +23,7 @@
package org.opendc.simulator.compute
import kotlinx.coroutines.*
-import kotlinx.coroutines.flow.toList
import org.junit.jupiter.api.*
-import org.junit.jupiter.api.Assertions.assertArrayEquals
import org.junit.jupiter.api.Assertions.assertEquals
import org.opendc.simulator.compute.device.SimNetworkAdapter
import org.opendc.simulator.compute.model.*
@@ -101,45 +99,6 @@ class SimMachineTest {
}
@Test
- fun testUsage() = runBlockingSimulation {
- val machine = SimBareMetalMachine(
- SimResourceInterpreter(coroutineContext, clock),
- machineModel,
- SimplePowerDriver(ConstantPowerModel(0.0))
- )
-
- val res = mutableListOf<Double>()
- val job = launch { machine.usage.toList(res) }
-
- try {
- machine.run(SimFlopsWorkload(2_000, utilization = 1.0))
- yield()
- job.cancel()
- assertEquals(listOf(0.0, 1.0, 0.0), res) { "Machine is fully utilized" }
- } finally {
- machine.close()
- }
- }
-
- @Test
- fun testSpeed() = runBlockingSimulation {
- val machine = SimBareMetalMachine(
- SimResourceInterpreter(coroutineContext, clock),
- machineModel,
- SimplePowerDriver(ConstantPowerModel(0.0))
- )
-
- try {
- coroutineScope {
- launch { machine.run(SimFlopsWorkload(2_000, utilization = 1.0)) }
- assertArrayEquals(doubleArrayOf(1000.0, 1000.0), machine.speed)
- }
- } finally {
- machine.close()
- }
- }
-
- @Test
fun testPower() = runBlockingSimulation {
val interpreter = SimResourceInterpreter(coroutineContext, clock)
val machine = SimBareMetalMachine(
diff --git a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/SimHypervisorTest.kt b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/SimHypervisorTest.kt
index 918271d1..8dea0045 100644
--- a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/SimHypervisorTest.kt
+++ b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/SimHypervisorTest.kt
@@ -22,11 +22,7 @@
package org.opendc.simulator.compute.kernel
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.coroutineScope
-import kotlinx.coroutines.flow.toList
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.yield
+import kotlinx.coroutines.*
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
@@ -108,19 +104,14 @@ internal class SimHypervisorTest {
}
yield()
val vm = hypervisor.createMachine(model)
- val res = mutableListOf<Double>()
- val job = launch { machine.usage.toList(res) }
-
vm.run(workloadA)
yield()
- job.cancel()
machine.close()
assertAll(
{ assertEquals(1113300.0, listener.totalRequestedWork, "Requested Burst does not match") },
{ assertEquals(1023300.0, listener.totalGrantedWork, "Granted Burst does not match") },
{ assertEquals(90000.0, listener.totalOvercommittedWork, "Overcommissioned Burst does not match") },
- { assertEquals(listOf(0.0, 0.00875, 1.0, 0.0, 0.0571875, 0.0), res) { "VM usage is correct" } },
{ assertEquals(1200000, clock.millis()) { "Current time is correct" } }
)
}
diff --git a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/SimSpaceSharedHypervisorTest.kt b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/SimSpaceSharedHypervisorTest.kt
index 80496992..3d3feb2a 100644
--- a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/SimSpaceSharedHypervisorTest.kt
+++ b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/SimSpaceSharedHypervisorTest.kt
@@ -23,7 +23,6 @@
package org.opendc.simulator.compute.kernel
import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.launch
import kotlinx.coroutines.yield
import org.junit.jupiter.api.Assertions.*
@@ -64,9 +63,6 @@ internal class SimSpaceSharedHypervisorTest {
*/
@Test
fun testTrace() = runBlockingSimulation {
- val usagePm = mutableListOf<Double>()
- val usageVm = mutableListOf<Double>()
-
val duration = 5 * 60L
val workloadA =
SimTraceWorkload(
@@ -84,27 +80,15 @@ internal class SimSpaceSharedHypervisorTest {
)
val hypervisor = SimSpaceSharedHypervisor(interpreter)
- val colA = launch { machine.usage.toList(usagePm) }
launch { machine.run(hypervisor) }
-
- yield()
-
val vm = hypervisor.createMachine(machineModel)
- val colB = launch { vm.usage.toList(usageVm) }
vm.run(workloadA)
yield()
vm.close()
machine.close()
- colA.cancel()
- colB.cancel()
- assertAll(
- { assertEquals(listOf(0.0, 0.00875, 1.0, 0.0, 0.0571875, 0.0), usagePm) { "Correct PM usage" } },
- // Temporary limitation is that VMs do not emit usage information
- // { assertEquals(listOf(0.0, 0.00875, 1.0, 0.0, 0.0571875, 0.0), usageVm) { "Correct VM usage" } },
- { assertEquals(5 * 60L * 4000, clock.millis()) { "Took enough time" } }
- )
+ assertEquals(5 * 60L * 4000, clock.millis()) { "Took enough time" }
}
/**