summaryrefslogtreecommitdiff
path: root/opendc-simulator/opendc-simulator-compute/src/test
diff options
context:
space:
mode:
authorFabian Mastenbroek <mail.fabianm@gmail.com>2022-09-01 14:38:34 +0200
committerFabian Mastenbroek <mail.fabianm@gmail.com>2022-10-21 22:13:04 +0200
commit44215bd668c5fa3efe2f57fc577824478b00af57 (patch)
treeb933228e5e5748716351dc9ce031b4840f254428 /opendc-simulator/opendc-simulator-compute/src/test
parentc1f67a872e2d7ce63ac96f8ca80cbe8b25c62e3b (diff)
refactor(sim/compute): Re-implement using flow2
This change re-implements the OpenDC compute simulator framework using the new flow2 framework for modelling multi-edge flow networks. The re-implementation is written in Java and focusses on performance and clean API surface.
Diffstat (limited to 'opendc-simulator/opendc-simulator-compute/src/test')
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/SimMachineTest.kt224
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/device/SimPsuTest.kt102
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/SimFairShareHypervisorTest.kt146
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/SimSpaceSharedHypervisorTest.kt86
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/cpufreq/ConservativeScalingGovernorTest.kt14
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/cpufreq/OnDemandScalingGovernorTest.kt13
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/cpufreq/PerformanceScalingGovernorTest.kt2
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/cpufreq/PowerSaveScalingGovernorTest.kt4
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/power/PStatePowerDriverTest.kt123
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/power/PowerModelTest.kt27
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/workload/SimFlopsWorkloadTest.kt2
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/workload/SimTraceWorkloadTest.kt72
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/test/resources/spec_machines.yml29
13 files changed, 312 insertions, 532 deletions
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 1eddf82c..f0aae15b 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
@@ -26,6 +26,7 @@ import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.cancel
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch
+import kotlinx.coroutines.yield
import org.junit.jupiter.api.Assertions.assertAll
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.BeforeEach
@@ -38,17 +39,16 @@ import org.opendc.simulator.compute.model.NetworkAdapter
import org.opendc.simulator.compute.model.ProcessingNode
import org.opendc.simulator.compute.model.ProcessingUnit
import org.opendc.simulator.compute.model.StorageDevice
-import org.opendc.simulator.compute.power.ConstantPowerModel
-import org.opendc.simulator.compute.power.LinearPowerModel
-import org.opendc.simulator.compute.power.SimplePowerDriver
+import org.opendc.simulator.compute.power.CpuPowerModels
import org.opendc.simulator.compute.workload.SimFlopsWorkload
+import org.opendc.simulator.compute.workload.SimTrace
import org.opendc.simulator.compute.workload.SimWorkload
-import org.opendc.simulator.compute.workload.SimWorkloadLifecycle
-import org.opendc.simulator.flow.FlowEngine
-import org.opendc.simulator.flow.source.FixedFlowSource
+import org.opendc.simulator.flow2.FlowEngine
+import org.opendc.simulator.flow2.source.SimpleFlowSource
import org.opendc.simulator.kotlin.runSimulation
import org.opendc.simulator.network.SimNetworkSink
import org.opendc.simulator.power.SimPowerSource
+import java.util.concurrent.ThreadLocalRandom
/**
* Test suite for the [SimBareMetalMachine] class.
@@ -61,41 +61,69 @@ class SimMachineTest {
val cpuNode = ProcessingNode("Intel", "Xeon", "amd64", 2)
machineModel = MachineModel(
- cpus = List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 1000.0) },
- memory = List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) },
- net = listOf(NetworkAdapter("Mellanox", "ConnectX-5", 25000.0)),
- storage = listOf(StorageDevice("Samsung", "EVO", 1000.0, 250.0, 250.0))
+ /*cpus*/ List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 1000.0) },
+ /*memory*/ List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) },
+ /*net*/ listOf(NetworkAdapter("Mellanox", "ConnectX-5", 25000.0)),
+ /*storage*/ listOf(StorageDevice("Samsung", "EVO", 1000.0, 250.0, 250.0))
)
}
@Test
fun testFlopsWorkload() = runSimulation {
- val machine = SimBareMetalMachine(
- FlowEngine(coroutineContext, clock),
- machineModel,
- SimplePowerDriver(ConstantPowerModel(0.0))
+ val engine = FlowEngine.create(coroutineContext, clock)
+ val graph = engine.newGraph()
+
+ val machine = SimBareMetalMachine.create(
+ graph,
+ machineModel
)
- machine.runWorkload(SimFlopsWorkload(2_000, utilization = 1.0))
+ machine.runWorkload(SimFlopsWorkload(2_000, /*utilization*/ 1.0))
// Two cores execute 1000 MFlOps per second (1000 ms)
assertEquals(1000, clock.millis())
}
@Test
+ fun testTraceWorkload() = runSimulation {
+ val random = ThreadLocalRandom.current()
+ val builder = SimTrace.builder()
+ repeat(1000000) {
+ val timestamp = it.toLong() * 1000
+ val deadline = timestamp + 1000
+ builder.add(deadline, random.nextDouble(0.0, 4500.0), 1)
+ }
+ val trace = builder.build()
+
+ val engine = FlowEngine.create(coroutineContext, clock)
+ val graph = engine.newGraph()
+ val machine = SimBareMetalMachine.create(
+ graph,
+ machineModel
+ )
+
+ machine.runWorkload(trace.createWorkload(0))
+
+ // Two cores execute 1000 MFlOps per second (1000 ms)
+ assertEquals(1000000000, clock.millis())
+ }
+
+ @Test
fun testDualSocketMachine() = runSimulation {
+ val engine = FlowEngine.create(coroutineContext, clock)
+ val graph = engine.newGraph()
+
val cpuNode = machineModel.cpus[0].node
val machineModel = MachineModel(
- cpus = List(cpuNode.coreCount * 2) { ProcessingUnit(cpuNode, it % 2, 1000.0) },
- memory = List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) }
+ /*cpus*/ List(cpuNode.coreCount * 2) { ProcessingUnit(cpuNode, it % 2, 1000.0) },
+ /*memory*/ List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) }
)
- val machine = SimBareMetalMachine(
- FlowEngine(coroutineContext, clock),
- machineModel,
- SimplePowerDriver(ConstantPowerModel(0.0))
+ val machine = SimBareMetalMachine.create(
+ graph,
+ machineModel
)
- machine.runWorkload(SimFlopsWorkload(2_000, utilization = 1.0))
+ machine.runWorkload(SimFlopsWorkload(2_000, /*utilization*/ 1.0))
// Two sockets with two cores execute 2000 MFlOps per second (500 ms)
assertEquals(500, clock.millis())
@@ -103,42 +131,47 @@ class SimMachineTest {
@Test
fun testPower() = runSimulation {
- val engine = FlowEngine(coroutineContext, clock)
- val machine = SimBareMetalMachine(
- engine,
+ val engine = FlowEngine.create(coroutineContext, clock)
+ val graph = engine.newGraph()
+ val machine = SimBareMetalMachine.create(
+ graph,
machineModel,
- SimplePowerDriver(LinearPowerModel(100.0, 50.0))
+ SimPsuFactories.simple(CpuPowerModels.linear(100.0, 50.0))
)
- val source = SimPowerSource(engine, capacity = 1000.0)
+ val source = SimPowerSource(graph, /*capacity*/ 1000.0f)
source.connect(machine.psu)
coroutineScope {
- launch { machine.runWorkload(SimFlopsWorkload(2_000, utilization = 1.0)) }
+ launch { machine.runWorkload(SimFlopsWorkload(2_000, /*utilization*/ 1.0)) }
+
+ yield()
assertAll(
- { assertEquals(100.0, machine.psu.powerDraw) },
- { assertEquals(100.0, source.powerDraw) }
+ { assertEquals(100.0, machine.psu.powerUsage) },
+ { assertEquals(100.0f, source.powerDraw) }
)
}
}
@Test
fun testCapacityClamp() = runSimulation {
- val machine = SimBareMetalMachine(
- FlowEngine(coroutineContext, clock),
- machineModel,
- SimplePowerDriver(ConstantPowerModel(0.0))
+ val engine = FlowEngine.create(coroutineContext, clock)
+ val graph = engine.newGraph()
+
+ val machine = SimBareMetalMachine.create(
+ graph,
+ machineModel
)
machine.runWorkload(object : SimWorkload {
override fun onStart(ctx: SimMachineContext) {
val cpu = ctx.cpus[0]
- cpu.capacity = cpu.model.frequency + 1000.0
- assertEquals(cpu.model.frequency, cpu.capacity)
- cpu.capacity = -1.0
- assertEquals(0.0, cpu.capacity)
+ cpu.frequency = (cpu.model.frequency + 1000.0)
+ assertEquals(cpu.model.frequency, cpu.frequency)
+ cpu.frequency = -1.0
+ assertEquals(0.0, cpu.frequency)
- ctx.close()
+ ctx.shutdown()
}
override fun onStop(ctx: SimMachineContext) {}
@@ -147,16 +180,18 @@ class SimMachineTest {
@Test
fun testMemory() = runSimulation {
- val machine = SimBareMetalMachine(
- FlowEngine(coroutineContext, clock),
- machineModel,
- SimplePowerDriver(ConstantPowerModel(0.0))
+ val engine = FlowEngine.create(coroutineContext, clock)
+ val graph = engine.newGraph()
+
+ val machine = SimBareMetalMachine.create(
+ graph,
+ machineModel
)
machine.runWorkload(object : SimWorkload {
override fun onStart(ctx: SimMachineContext) {
assertEquals(32_000 * 4.0, ctx.memory.capacity)
- ctx.close()
+ ctx.shutdown()
}
override fun onStop(ctx: SimMachineContext) {}
@@ -165,104 +200,111 @@ class SimMachineTest {
@Test
fun testMemoryUsage() = runSimulation {
- val machine = SimBareMetalMachine(
- FlowEngine(coroutineContext, clock),
- machineModel,
- SimplePowerDriver(ConstantPowerModel(0.0))
+ val engine = FlowEngine.create(coroutineContext, clock)
+ val graph = engine.newGraph()
+
+ val machine = SimBareMetalMachine.create(
+ graph,
+ machineModel
)
machine.runWorkload(object : SimWorkload {
override fun onStart(ctx: SimMachineContext) {
- val lifecycle = SimWorkloadLifecycle(ctx)
- ctx.memory.startConsumer(lifecycle.waitFor(FixedFlowSource(ctx.memory.capacity, utilization = 0.8)))
+ val source = SimpleFlowSource(ctx.graph, ctx.memory.capacity.toFloat(), 1.0f) { ctx.shutdown() }
+ ctx.graph.connect(source.output, ctx.memory.input)
}
override fun onStop(ctx: SimMachineContext) {}
})
- assertEquals(1250, clock.millis())
+ assertEquals(1000, clock.millis())
}
@Test
fun testNetUsage() = runSimulation {
- val engine = FlowEngine(coroutineContext, clock)
- val machine = SimBareMetalMachine(
- engine,
- machineModel,
- SimplePowerDriver(ConstantPowerModel(0.0))
+ val engine = FlowEngine.create(coroutineContext, clock)
+ val graph = engine.newGraph()
+
+ val machine = SimBareMetalMachine.create(
+ graph,
+ machineModel
)
val adapter = (machine.peripherals[0] as SimNetworkAdapter)
- adapter.connect(SimNetworkSink(engine, adapter.bandwidth))
+ adapter.connect(SimNetworkSink(graph, adapter.bandwidth.toFloat()))
machine.runWorkload(object : SimWorkload {
override fun onStart(ctx: SimMachineContext) {
- val lifecycle = SimWorkloadLifecycle(ctx)
- val iface = ctx.net[0]
- iface.tx.startConsumer(lifecycle.waitFor(FixedFlowSource(iface.bandwidth, utilization = 0.8)))
+ val iface = ctx.networkInterfaces[0]
+ val source = SimpleFlowSource(ctx.graph, 800.0f, 0.8f) { ctx.shutdown(); it.close(); }
+ ctx.graph.connect(source.output, iface.tx)
}
override fun onStop(ctx: SimMachineContext) {}
})
- assertEquals(1250, clock.millis())
+ assertEquals(40, clock.millis())
}
@Test
fun testDiskReadUsage() = runSimulation {
- val engine = FlowEngine(coroutineContext, clock)
- val machine = SimBareMetalMachine(
- engine,
- machineModel,
- SimplePowerDriver(ConstantPowerModel(0.0))
+ val engine = FlowEngine.create(coroutineContext, clock)
+ val graph = engine.newGraph()
+
+ val machine = SimBareMetalMachine.create(
+ graph,
+ machineModel
)
machine.runWorkload(object : SimWorkload {
override fun onStart(ctx: SimMachineContext) {
- val lifecycle = SimWorkloadLifecycle(ctx)
- val disk = ctx.storage[0]
- disk.read.startConsumer(lifecycle.waitFor(FixedFlowSource(disk.read.capacity, utilization = 0.8)))
+ val disk = ctx.storageInterfaces[0]
+ val source = SimpleFlowSource(ctx.graph, 800.0f, 0.8f) { ctx.shutdown() }
+ ctx.graph.connect(source.output, disk.read)
}
override fun onStop(ctx: SimMachineContext) {}
})
- assertEquals(1250, clock.millis())
+ assertEquals(4000, clock.millis())
}
@Test
fun testDiskWriteUsage() = runSimulation {
- val engine = FlowEngine(coroutineContext, clock)
- val machine = SimBareMetalMachine(
- engine,
- machineModel,
- SimplePowerDriver(ConstantPowerModel(0.0))
+ val engine = FlowEngine.create(coroutineContext, clock)
+ val graph = engine.newGraph()
+
+ val machine = SimBareMetalMachine.create(
+ graph,
+ machineModel
)
machine.runWorkload(object : SimWorkload {
override fun onStart(ctx: SimMachineContext) {
- val lifecycle = SimWorkloadLifecycle(ctx)
- val disk = ctx.storage[0]
- disk.write.startConsumer(lifecycle.waitFor(FixedFlowSource(disk.write.capacity, utilization = 0.8)))
+ val disk = ctx.storageInterfaces[0]
+ val source = SimpleFlowSource(ctx.graph, 800.0f, 0.8f) { ctx.shutdown() }
+ ctx.graph.connect(source.output, disk.write)
}
override fun onStop(ctx: SimMachineContext) {}
})
- assertEquals(1250, clock.millis())
+ assertEquals(4000, clock.millis())
}
@Test
fun testCancellation() = runSimulation {
- val machine = SimBareMetalMachine(
- FlowEngine(coroutineContext, clock),
- machineModel,
- SimplePowerDriver(ConstantPowerModel(0.0))
+ val engine = FlowEngine.create(coroutineContext, clock)
+ val graph = engine.newGraph()
+
+ val machine = SimBareMetalMachine.create(
+ graph,
+ machineModel
)
try {
coroutineScope {
- launch { machine.runWorkload(SimFlopsWorkload(2_000, utilization = 1.0)) }
+ launch { machine.runWorkload(SimFlopsWorkload(2_000, /*utilization*/ 1.0)) }
cancel()
}
} catch (_: CancellationException) {
@@ -274,19 +316,21 @@ class SimMachineTest {
@Test
fun testConcurrentRuns() = runSimulation {
- val machine = SimBareMetalMachine(
- FlowEngine(coroutineContext, clock),
- machineModel,
- SimplePowerDriver(ConstantPowerModel(0.0))
+ val engine = FlowEngine.create(coroutineContext, clock)
+ val graph = engine.newGraph()
+
+ val machine = SimBareMetalMachine.create(
+ graph,
+ machineModel
)
coroutineScope {
launch {
- machine.runWorkload(SimFlopsWorkload(2_000, utilization = 1.0))
+ machine.runWorkload(SimFlopsWorkload(2_000, /*utilization*/ 1.0))
}
assertThrows<IllegalStateException> {
- machine.runWorkload(SimFlopsWorkload(2_000, utilization = 1.0))
+ machine.runWorkload(SimFlopsWorkload(2_000, /*utilization*/ 1.0))
}
}
}
diff --git a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/device/SimPsuTest.kt b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/device/SimPsuTest.kt
deleted file mode 100644
index 0a6cb29f..00000000
--- a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/device/SimPsuTest.kt
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * 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.device
-
-import io.mockk.every
-import io.mockk.mockk
-import org.junit.jupiter.api.Assertions.assertEquals
-import org.junit.jupiter.api.Test
-import org.junit.jupiter.api.assertThrows
-import org.opendc.simulator.compute.power.PowerDriver
-import org.opendc.simulator.flow.FlowEngine
-import org.opendc.simulator.kotlin.runSimulation
-import org.opendc.simulator.power.SimPowerSource
-
-/**
- * Test suite for [SimPsu]
- */
-internal class SimPsuTest {
-
- @Test
- fun testInvalidInput() {
- assertThrows<IllegalArgumentException> { SimPsu(1.0, emptyMap()) }
- }
-
- @Test
- fun testDoubleConnect() {
- val psu = SimPsu(1.0, mapOf(0.0 to 1.0))
- val cpuLogic = mockk<PowerDriver.Logic>()
- psu.connect(cpuLogic)
- assertThrows<IllegalStateException> { psu.connect(mockk()) }
- }
-
- @Test
- fun testPsuIdle() = runSimulation {
- val ratedOutputPower = 240.0
- val energyEfficiency = mapOf(0.0 to 1.0)
-
- val engine = FlowEngine(coroutineContext, clock)
- val source = SimPowerSource(engine, capacity = ratedOutputPower)
-
- val cpuLogic = mockk<PowerDriver.Logic>()
- every { cpuLogic.computePower() } returns 0.0
-
- val psu = SimPsu(ratedOutputPower, energyEfficiency)
- psu.connect(cpuLogic)
- source.connect(psu)
-
- assertEquals(0.0, source.powerDraw, 0.01)
- }
-
- @Test
- fun testPsuPowerLoss() = runSimulation {
- val ratedOutputPower = 240.0
- // Efficiency of 80 Plus Titanium PSU
- val energyEfficiency = sortedMapOf(
- 0.3 to 0.9,
- 0.7 to 0.92,
- 1.0 to 0.94
- )
-
- val engine = FlowEngine(coroutineContext, clock)
- val source = SimPowerSource(engine, capacity = ratedOutputPower)
-
- val cpuLogic = mockk<PowerDriver.Logic>()
- every { cpuLogic.computePower() } returnsMany listOf(50.0, 100.0, 150.0, 200.0)
-
- val psu = SimPsu(ratedOutputPower, energyEfficiency)
- psu.connect(cpuLogic)
- source.connect(psu)
-
- assertEquals(55.55, source.powerDraw, 0.01)
-
- psu.update()
- assertEquals(108.695, source.powerDraw, 0.01)
-
- psu.update()
- assertEquals(163.043, source.powerDraw, 0.01)
-
- psu.update()
- assertEquals(212.765, source.powerDraw, 0.01)
- }
-}
diff --git a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/SimFairShareHypervisorTest.kt b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/SimFairShareHypervisorTest.kt
index 6b498119..79669d40 100644
--- a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/SimFairShareHypervisorTest.kt
+++ b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/SimFairShareHypervisorTest.kt
@@ -31,20 +31,17 @@ import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertAll
import org.junit.jupiter.api.assertDoesNotThrow
import org.opendc.simulator.compute.SimBareMetalMachine
-import org.opendc.simulator.compute.kernel.cpufreq.PerformanceScalingGovernor
+import org.opendc.simulator.compute.kernel.cpufreq.ScalingGovernors
import org.opendc.simulator.compute.kernel.interference.VmInterferenceModel
import org.opendc.simulator.compute.model.MachineModel
import org.opendc.simulator.compute.model.MemoryUnit
import org.opendc.simulator.compute.model.ProcessingNode
import org.opendc.simulator.compute.model.ProcessingUnit
-import org.opendc.simulator.compute.power.ConstantPowerModel
-import org.opendc.simulator.compute.power.SimplePowerDriver
import org.opendc.simulator.compute.runWorkload
import org.opendc.simulator.compute.workload.SimTrace
import org.opendc.simulator.compute.workload.SimTraceFragment
-import org.opendc.simulator.compute.workload.SimTraceWorkload
-import org.opendc.simulator.flow.FlowEngine
-import org.opendc.simulator.flow.mux.FlowMultiplexerFactory
+import org.opendc.simulator.flow2.FlowEngine
+import org.opendc.simulator.flow2.mux.FlowMultiplexerFactory
import org.opendc.simulator.kotlin.runSimulation
import java.util.SplittableRandom
@@ -58,8 +55,8 @@ internal class SimFairShareHypervisorTest {
fun setUp() {
val cpuNode = ProcessingNode("Intel", "Xeon", "amd64", 1)
model = MachineModel(
- cpus = List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 3200.0) },
- memory = List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) }
+ /*cpus*/ List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 3200.0) },
+ /*memory*/ List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) }
)
}
@@ -70,23 +67,20 @@ internal class SimFairShareHypervisorTest {
fun testOvercommittedSingle() = runSimulation {
val duration = 5 * 60L
val workloadA =
- SimTraceWorkload(
- SimTrace.ofFragments(
- SimTraceFragment(0, duration * 1000, 28.0, 1),
- SimTraceFragment(duration * 1000, duration * 1000, 3500.0, 1),
- SimTraceFragment(duration * 2000, duration * 1000, 0.0, 1),
- SimTraceFragment(duration * 3000, duration * 1000, 183.0, 1)
- )
- )
-
- val engine = FlowEngine(coroutineContext, clock)
- val machine = SimBareMetalMachine(engine, model, SimplePowerDriver(ConstantPowerModel(0.0)))
- val hypervisor = SimHypervisor(engine, FlowMultiplexerFactory.maxMinMultiplexer(), SplittableRandom(1), PerformanceScalingGovernor())
+ SimTrace.ofFragments(
+ SimTraceFragment(0, duration * 1000, 28.0, 1),
+ SimTraceFragment(duration * 1000, duration * 1000, 3500.0, 1),
+ SimTraceFragment(duration * 2000, duration * 1000, 0.0, 1),
+ SimTraceFragment(duration * 3000, duration * 1000, 183.0, 1)
+ ).createWorkload(0)
- launch {
- machine.runWorkload(hypervisor)
- println("Hypervisor finished")
- }
+ val engine = FlowEngine.create(coroutineContext, clock)
+ val graph = engine.newGraph()
+
+ val machine = SimBareMetalMachine.create(graph, model)
+ val hypervisor = SimHypervisor.create(FlowMultiplexerFactory.maxMinMultiplexer(), SplittableRandom(0L), ScalingGovernors.performance())
+
+ launch { machine.runWorkload(hypervisor) }
yield()
val vm = hypervisor.newMachine(model)
@@ -110,31 +104,27 @@ internal class SimFairShareHypervisorTest {
fun testOvercommittedDual() = runSimulation {
val duration = 5 * 60L
val workloadA =
- SimTraceWorkload(
- SimTrace.ofFragments(
- SimTraceFragment(0, duration * 1000, 28.0, 1),
- SimTraceFragment(duration * 1000, duration * 1000, 3500.0, 1),
- SimTraceFragment(duration * 2000, duration * 1000, 0.0, 1),
- SimTraceFragment(duration * 3000, duration * 1000, 183.0, 1)
- )
- )
+ SimTrace.ofFragments(
+ SimTraceFragment(0, duration * 1000, 28.0, 1),
+ SimTraceFragment(duration * 1000, duration * 1000, 3500.0, 1),
+ SimTraceFragment(duration * 2000, duration * 1000, 0.0, 1),
+ SimTraceFragment(duration * 3000, duration * 1000, 183.0, 1)
+ ).createWorkload(0)
val workloadB =
- SimTraceWorkload(
- SimTrace.ofFragments(
- SimTraceFragment(0, duration * 1000, 28.0, 1),
- SimTraceFragment(duration * 1000, duration * 1000, 3100.0, 1),
- SimTraceFragment(duration * 2000, duration * 1000, 0.0, 1),
- SimTraceFragment(duration * 3000, duration * 1000, 73.0, 1)
- )
- )
-
- val engine = FlowEngine(coroutineContext, clock)
- val machine = SimBareMetalMachine(engine, model, SimplePowerDriver(ConstantPowerModel(0.0)))
- val hypervisor = SimHypervisor(engine, FlowMultiplexerFactory.maxMinMultiplexer(), SplittableRandom(1), null)
+ SimTrace.ofFragments(
+ SimTraceFragment(0, duration * 1000, 28.0, 1),
+ SimTraceFragment(duration * 1000, duration * 1000, 3100.0, 1),
+ SimTraceFragment(duration * 2000, duration * 1000, 0.0, 1),
+ SimTraceFragment(duration * 3000, duration * 1000, 73.0, 1)
+ ).createWorkload(0)
- launch {
- machine.runWorkload(hypervisor)
- }
+ val engine = FlowEngine.create(coroutineContext, clock)
+ val graph = engine.newGraph()
+
+ val machine = SimBareMetalMachine.create(graph, model)
+ val hypervisor = SimHypervisor.create(FlowMultiplexerFactory.maxMinMultiplexer(), SplittableRandom(0L), ScalingGovernors.performance())
+
+ launch { machine.runWorkload(hypervisor) }
yield()
coroutineScope {
@@ -163,18 +153,18 @@ internal class SimFairShareHypervisorTest {
fun testMultipleCPUs() = runSimulation {
val cpuNode = ProcessingNode("Intel", "Xeon", "amd64", 2)
val model = MachineModel(
- cpus = List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 3200.0) },
- memory = List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) }
+ /*cpus*/ List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 3200.0) },
+ /*memory*/ List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) }
)
- val engine = FlowEngine(coroutineContext, clock)
- val machine = SimBareMetalMachine(engine, model, SimplePowerDriver(ConstantPowerModel(0.0)))
- val hypervisor = SimHypervisor(engine, FlowMultiplexerFactory.maxMinMultiplexer(), SplittableRandom(1), null)
+ val engine = FlowEngine.create(coroutineContext, clock)
+ val graph = engine.newGraph()
+
+ val machine = SimBareMetalMachine.create(graph, model)
+ val hypervisor = SimHypervisor.create(FlowMultiplexerFactory.maxMinMultiplexer(), SplittableRandom(0L), ScalingGovernors.performance())
assertDoesNotThrow {
- launch {
- machine.runWorkload(hypervisor)
- }
+ launch { machine.runWorkload(hypervisor) }
}
machine.cancel()
@@ -184,39 +174,37 @@ internal class SimFairShareHypervisorTest {
fun testInterference() = runSimulation {
val cpuNode = ProcessingNode("Intel", "Xeon", "amd64", 2)
val model = MachineModel(
- cpus = List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 3200.0) },
- memory = List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) }
+ /*cpus*/ List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 3200.0) },
+ /*memory*/ List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) }
)
val interferenceModel = VmInterferenceModel.builder()
- .addGroup(targetLoad = 0.0, score = 0.9, members = setOf("a", "b"))
- .addGroup(targetLoad = 0.0, score = 0.6, members = setOf("a", "c"))
- .addGroup(targetLoad = 0.1, score = 0.8, members = setOf("a", "n"))
+ .addGroup(setOf("a", "b"), 0.0, 0.9)
+ .addGroup(setOf("a", "c"), 0.0, 0.6)
+ .addGroup(setOf("a", "n"), 0.1, 0.8)
.build()
- val engine = FlowEngine(coroutineContext, clock)
- val machine = SimBareMetalMachine(engine, model, SimplePowerDriver(ConstantPowerModel(0.0)))
- val hypervisor = SimHypervisor(engine, FlowMultiplexerFactory.maxMinMultiplexer(), SplittableRandom(1), null)
+ val engine = FlowEngine.create(coroutineContext, clock)
+ val graph = engine.newGraph()
+
+ val machine = SimBareMetalMachine.create(graph, model)
+ val hypervisor = SimHypervisor.create(FlowMultiplexerFactory.maxMinMultiplexer(), SplittableRandom(0L))
val duration = 5 * 60L
val workloadA =
- SimTraceWorkload(
- SimTrace.ofFragments(
- SimTraceFragment(0, duration * 1000, 0.0, 1),
- SimTraceFragment(duration * 1000, duration * 1000, 28.0, 1),
- SimTraceFragment(duration * 2000, duration * 1000, 3500.0, 1),
- SimTraceFragment(duration * 3000, duration * 1000, 183.0, 1)
- )
- )
+ SimTrace.ofFragments(
+ SimTraceFragment(0, duration * 1000, 0.0, 1),
+ SimTraceFragment(duration * 1000, duration * 1000, 28.0, 1),
+ SimTraceFragment(duration * 2000, duration * 1000, 3500.0, 1),
+ SimTraceFragment(duration * 3000, duration * 1000, 183.0, 1)
+ ).createWorkload(0)
val workloadB =
- SimTraceWorkload(
- SimTrace.ofFragments(
- SimTraceFragment(0, duration * 1000, 0.0, 1),
- SimTraceFragment(duration * 1000, duration * 1000, 28.0, 1),
- SimTraceFragment(duration * 2000, duration * 1000, 3100.0, 1),
- SimTraceFragment(duration * 3000, duration * 1000, 73.0, 1)
- )
- )
+ SimTrace.ofFragments(
+ SimTraceFragment(0, duration * 1000, 0.0, 1),
+ SimTraceFragment(duration * 1000, duration * 1000, 28.0, 1),
+ SimTraceFragment(duration * 2000, duration * 1000, 3100.0, 1),
+ SimTraceFragment(duration * 3000, duration * 1000, 73.0, 1)
+ ).createWorkload(0)
launch {
machine.runWorkload(hypervisor)
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 57fe3766..ba5a5c68 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
@@ -37,16 +37,13 @@ import org.opendc.simulator.compute.model.MachineModel
import org.opendc.simulator.compute.model.MemoryUnit
import org.opendc.simulator.compute.model.ProcessingNode
import org.opendc.simulator.compute.model.ProcessingUnit
-import org.opendc.simulator.compute.power.ConstantPowerModel
-import org.opendc.simulator.compute.power.SimplePowerDriver
import org.opendc.simulator.compute.runWorkload
import org.opendc.simulator.compute.workload.SimFlopsWorkload
import org.opendc.simulator.compute.workload.SimRuntimeWorkload
import org.opendc.simulator.compute.workload.SimTrace
import org.opendc.simulator.compute.workload.SimTraceFragment
-import org.opendc.simulator.compute.workload.SimTraceWorkload
-import org.opendc.simulator.flow.FlowEngine
-import org.opendc.simulator.flow.mux.FlowMultiplexerFactory
+import org.opendc.simulator.flow2.FlowEngine
+import org.opendc.simulator.flow2.mux.FlowMultiplexerFactory
import org.opendc.simulator.kotlin.runSimulation
import java.util.SplittableRandom
@@ -60,8 +57,8 @@ internal class SimSpaceSharedHypervisorTest {
fun setUp() {
val cpuNode = ProcessingNode("Intel", "Xeon", "amd64", 1)
machineModel = MachineModel(
- cpus = List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 3200.0) },
- memory = List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) }
+ /*cpus*/ List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 3200.0) },
+ /*memory*/ List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) }
)
}
@@ -72,18 +69,18 @@ internal class SimSpaceSharedHypervisorTest {
fun testTrace() = runSimulation {
val duration = 5 * 60L
val workloadA =
- SimTraceWorkload(
- SimTrace.ofFragments(
- SimTraceFragment(0, duration * 1000, 28.0, 1),
- SimTraceFragment(duration * 1000, duration * 1000, 3500.0, 1),
- SimTraceFragment(duration * 2000, duration * 1000, 0.0, 1),
- SimTraceFragment(duration * 3000, duration * 1000, 183.0, 1)
- )
- )
-
- val engine = FlowEngine(coroutineContext, clock)
- val machine = SimBareMetalMachine(engine, machineModel, SimplePowerDriver(ConstantPowerModel(0.0)))
- val hypervisor = SimHypervisor(engine, FlowMultiplexerFactory.forwardingMultiplexer(), SplittableRandom(1), null)
+ SimTrace.ofFragments(
+ SimTraceFragment(0, duration * 1000, 28.0, 1),
+ SimTraceFragment(duration * 1000, duration * 1000, 3500.0, 1),
+ SimTraceFragment(duration * 2000, duration * 1000, 0.0, 1),
+ SimTraceFragment(duration * 3000, duration * 1000, 183.0, 1)
+ ).createWorkload(0)
+
+ val engine = FlowEngine.create(coroutineContext, clock)
+ val graph = engine.newGraph()
+
+ val machine = SimBareMetalMachine.create(graph, machineModel)
+ val hypervisor = SimHypervisor.create(FlowMultiplexerFactory.forwardingMultiplexer(), SplittableRandom(0L))
launch { machine.runWorkload(hypervisor) }
val vm = hypervisor.newMachine(machineModel)
@@ -102,10 +99,12 @@ internal class SimSpaceSharedHypervisorTest {
@Test
fun testRuntimeWorkload() = runSimulation {
val duration = 5 * 60L * 1000
- val workload = SimRuntimeWorkload(duration)
- val engine = FlowEngine(coroutineContext, clock)
- val machine = SimBareMetalMachine(engine, machineModel, SimplePowerDriver(ConstantPowerModel(0.0)))
- val hypervisor = SimHypervisor(engine, FlowMultiplexerFactory.forwardingMultiplexer(), SplittableRandom(1), null)
+ val workload = SimRuntimeWorkload(duration, 1.0)
+ val engine = FlowEngine.create(coroutineContext, clock)
+ val graph = engine.newGraph()
+
+ val machine = SimBareMetalMachine.create(graph, machineModel)
+ val hypervisor = SimHypervisor.create(FlowMultiplexerFactory.forwardingMultiplexer(), SplittableRandom(0L))
launch { machine.runWorkload(hypervisor) }
yield()
@@ -125,9 +124,11 @@ internal class SimSpaceSharedHypervisorTest {
fun testFlopsWorkload() = runSimulation {
val duration = 5 * 60L * 1000
val workload = SimFlopsWorkload((duration * 3.2).toLong(), 1.0)
- val engine = FlowEngine(coroutineContext, clock)
- val machine = SimBareMetalMachine(engine, machineModel, SimplePowerDriver(ConstantPowerModel(0.0)))
- val hypervisor = SimHypervisor(engine, FlowMultiplexerFactory.forwardingMultiplexer(), SplittableRandom(1), null)
+ val engine = FlowEngine.create(coroutineContext, clock)
+ val graph = engine.newGraph()
+
+ val machine = SimBareMetalMachine.create(graph, machineModel)
+ val hypervisor = SimHypervisor.create(FlowMultiplexerFactory.forwardingMultiplexer(), SplittableRandom(0L))
launch { machine.runWorkload(hypervisor) }
yield()
@@ -144,21 +145,23 @@ internal class SimSpaceSharedHypervisorTest {
@Test
fun testTwoWorkloads() = runSimulation {
val duration = 5 * 60L * 1000
- val engine = FlowEngine(coroutineContext, clock)
- val machine = SimBareMetalMachine(engine, machineModel, SimplePowerDriver(ConstantPowerModel(0.0)))
- val hypervisor = SimHypervisor(engine, FlowMultiplexerFactory.forwardingMultiplexer(), SplittableRandom(1), null)
+ val engine = FlowEngine.create(coroutineContext, clock)
+ val graph = engine.newGraph()
+
+ val machine = SimBareMetalMachine.create(graph, machineModel)
+ val hypervisor = SimHypervisor.create(FlowMultiplexerFactory.forwardingMultiplexer(), SplittableRandom(0L))
launch { machine.runWorkload(hypervisor) }
yield()
val vm = hypervisor.newMachine(machineModel)
- vm.runWorkload(SimRuntimeWorkload(duration))
+ vm.runWorkload(SimRuntimeWorkload(duration, 1.0))
hypervisor.removeMachine(vm)
yield()
val vm2 = hypervisor.newMachine(machineModel)
- vm2.runWorkload(SimRuntimeWorkload(duration))
+ vm2.runWorkload(SimRuntimeWorkload(duration, 1.0))
hypervisor.removeMachine(vm2)
machine.cancel()
@@ -171,14 +174,18 @@ internal class SimSpaceSharedHypervisorTest {
*/
@Test
fun testConcurrentWorkloadFails() = runSimulation {
- val engine = FlowEngine(coroutineContext, clock)
- val machine = SimBareMetalMachine(engine, machineModel, SimplePowerDriver(ConstantPowerModel(0.0)))
- val hypervisor = SimHypervisor(engine, FlowMultiplexerFactory.forwardingMultiplexer(), SplittableRandom(1), null)
+ val engine = FlowEngine.create(coroutineContext, clock)
+ val graph = engine.newGraph()
+
+ val machine = SimBareMetalMachine.create(graph, machineModel)
+ val hypervisor = SimHypervisor.create(FlowMultiplexerFactory.forwardingMultiplexer(), SplittableRandom(0L))
launch { machine.runWorkload(hypervisor) }
yield()
- hypervisor.newMachine(machineModel)
+ val vm = hypervisor.newMachine(machineModel)
+ launch { vm.runWorkload(SimFlopsWorkload(10_000, 1.0)) }
+ yield()
assertAll(
{ assertFalse(hypervisor.canFit(machineModel)) },
@@ -186,6 +193,7 @@ internal class SimSpaceSharedHypervisorTest {
)
machine.cancel()
+ vm.cancel()
}
/**
@@ -193,9 +201,11 @@ internal class SimSpaceSharedHypervisorTest {
*/
@Test
fun testConcurrentWorkloadSucceeds() = runSimulation {
- val engine = FlowEngine(coroutineContext, clock)
- val machine = SimBareMetalMachine(engine, machineModel, SimplePowerDriver(ConstantPowerModel(0.0)))
- val hypervisor = SimHypervisor(engine, FlowMultiplexerFactory.forwardingMultiplexer(), SplittableRandom(1), null)
+ val engine = FlowEngine.create(coroutineContext, clock)
+ val graph = engine.newGraph()
+
+ val machine = SimBareMetalMachine.create(graph, machineModel)
+ val hypervisor = SimHypervisor.create(FlowMultiplexerFactory.forwardingMultiplexer(), SplittableRandom(0L))
launch { machine.runWorkload(hypervisor) }
yield()
diff --git a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/cpufreq/ConservativeScalingGovernorTest.kt b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/cpufreq/ConservativeScalingGovernorTest.kt
index ef354569..6b182f4c 100644
--- a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/cpufreq/ConservativeScalingGovernorTest.kt
+++ b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/cpufreq/ConservativeScalingGovernorTest.kt
@@ -25,11 +25,10 @@ package org.opendc.simulator.compute.kernel.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]
+ * Test suite for the conservative [ScalingGovernor].
*/
internal class ConservativeScalingGovernorTest {
@Test
@@ -38,7 +37,7 @@ internal class ConservativeScalingGovernorTest {
val minSpeed = cpuCapacity / 2
val defaultThreshold = 0.8
val defaultStepSize = 0.05 * cpuCapacity
- val governor = ConservativeScalingGovernor()
+ val governor = ScalingGovernors.conservative(defaultThreshold)
val policy = mockk<ScalingPolicy>(relaxUnitFun = true)
every { policy.max } returns cpuCapacity
@@ -48,10 +47,8 @@ internal class ConservativeScalingGovernorTest {
every { policy.target } answers { target }
every { policy.target = any() } propertyType Double::class answers { target = value }
- val logic = governor.createLogic(policy)
+ val logic = governor.newGovernor(policy)
logic.onStart()
- assertEquals(defaultThreshold, governor.threshold)
-
logic.onLimit(0.5)
/* Upwards scaling */
@@ -71,7 +68,7 @@ internal class ConservativeScalingGovernorTest {
val minSpeed = firstPState
val threshold = 0.5
val stepSize = 0.02 * cpuCapacity
- val governor = ConservativeScalingGovernor(threshold, stepSize)
+ val governor = ScalingGovernors.conservative(threshold, stepSize)
val policy = mockk<ScalingPolicy>(relaxUnitFun = true)
every { policy.max } returns cpuCapacity
@@ -81,9 +78,8 @@ internal class ConservativeScalingGovernorTest {
every { policy.target } answers { target }
every { policy.target = any() } propertyType Double::class answers { target = value }
- val logic = governor.createLogic(policy)
+ val logic = governor.newGovernor(policy)
logic.onStart()
- assertEquals(threshold, governor.threshold)
logic.onLimit(0.5)
/* Upwards scaling */
diff --git a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/cpufreq/OnDemandScalingGovernorTest.kt b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/cpufreq/OnDemandScalingGovernorTest.kt
index ca759e39..d6a7090b 100644
--- a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/cpufreq/OnDemandScalingGovernorTest.kt
+++ b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/cpufreq/OnDemandScalingGovernorTest.kt
@@ -25,11 +25,10 @@ package org.opendc.simulator.compute.kernel.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]
+ * Test suite for the on-demand [ScalingGovernor].
*/
internal class OnDemandScalingGovernorTest {
@Test
@@ -37,15 +36,14 @@ internal class OnDemandScalingGovernorTest {
val cpuCapacity = 4100.0
val minSpeed = cpuCapacity / 2
val defaultThreshold = 0.8
- val governor = OnDemandScalingGovernor()
+ val governor = ScalingGovernors.ondemand(defaultThreshold)
val policy = mockk<ScalingPolicy>(relaxUnitFun = true)
every { policy.min } returns minSpeed
every { policy.max } returns cpuCapacity
- val logic = governor.createLogic(policy)
+ val logic = governor.newGovernor(policy)
logic.onStart()
- assertEquals(defaultThreshold, governor.threshold)
verify(exactly = 1) { policy.target = minSpeed }
logic.onLimit(0.5)
@@ -60,16 +58,15 @@ internal class OnDemandScalingGovernorTest {
val firstPState = 1000.0
val cpuCapacity = 4100.0
val threshold = 0.5
- val governor = OnDemandScalingGovernor(threshold)
+ val governor = ScalingGovernors.ondemand(threshold)
val policy = mockk<ScalingPolicy>(relaxUnitFun = true)
every { policy.max } returns cpuCapacity
every { policy.min } returns firstPState
- val logic = governor.createLogic(policy)
+ val logic = governor.newGovernor(policy)
logic.onStart()
- assertEquals(threshold, governor.threshold)
verify(exactly = 1) { policy.target = firstPState }
logic.onLimit(0.1)
diff --git a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/cpufreq/PerformanceScalingGovernorTest.kt b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/cpufreq/PerformanceScalingGovernorTest.kt
index a4bb24f2..f03f41fe 100644
--- a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/cpufreq/PerformanceScalingGovernorTest.kt
+++ b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/cpufreq/PerformanceScalingGovernorTest.kt
@@ -34,7 +34,7 @@ internal class PerformanceScalingGovernorTest {
@Test
fun testSetStartLimit() {
val policy = spyk<ScalingPolicy>()
- val logic = PerformanceScalingGovernor().createLogic(policy)
+ val logic = ScalingGovernors.performance().newGovernor(policy)
every { policy.max } returns 4100.0
diff --git a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/cpufreq/PowerSaveScalingGovernorTest.kt b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/cpufreq/PowerSaveScalingGovernorTest.kt
index 662d55fb..4cee8199 100644
--- a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/cpufreq/PowerSaveScalingGovernorTest.kt
+++ b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/cpufreq/PowerSaveScalingGovernorTest.kt
@@ -36,7 +36,7 @@ internal class PowerSaveScalingGovernorTest {
val cpuCapacity = 4100.0
val minSpeed = cpuCapacity / 2
val policy = mockk<ScalingPolicy>(relaxUnitFun = true)
- val logic = PowerSaveScalingGovernor().createLogic(policy)
+ val logic = ScalingGovernors.powerSave().newGovernor(policy)
every { policy.max } returns cpuCapacity
every { policy.min } returns minSpeed
@@ -55,7 +55,7 @@ internal class PowerSaveScalingGovernorTest {
val cpuCapacity = 4100.0
val firstPState = 1000.0
val policy = mockk<ScalingPolicy>(relaxUnitFun = true)
- val logic = PowerSaveScalingGovernor().createLogic(policy)
+ val logic = ScalingGovernors.powerSave().newGovernor(policy)
every { policy.max } returns cpuCapacity
every { policy.min } returns 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
deleted file mode 100644
index 3c0a55a6..00000000
--- a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/power/PStatePowerDriverTest.kt
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * 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.power
-
-import io.mockk.every
-import io.mockk.mockk
-import org.junit.jupiter.api.Assertions.assertEquals
-import org.junit.jupiter.api.Test
-import org.opendc.simulator.compute.SimBareMetalMachine
-import org.opendc.simulator.compute.SimProcessingUnit
-
-/**
- * Test suite for [PStatePowerDriver].
- */
-internal class PStatePowerDriverTest {
- @Test
- fun testPowerBaseline() {
- val machine = mockk<SimBareMetalMachine>()
-
- val driver = PStatePowerDriver(
- sortedMapOf(
- 2800.0 to ConstantPowerModel(200.0),
- 3300.0 to ConstantPowerModel(300.0),
- 3600.0 to ConstantPowerModel(350.0)
- )
- )
-
- val logic = driver.createLogic(machine, emptyList())
- assertEquals(200.0, logic.computePower())
- }
-
- @Test
- fun testPowerWithSingleCpu() {
- val machine = mockk<SimBareMetalMachine>()
- val cpu = mockk<SimProcessingUnit>(relaxUnitFun = true)
-
- every { cpu.capacity } returns 3200.0
- every { cpu.rate } returns 1200.0
-
- val driver = PStatePowerDriver(
- sortedMapOf(
- 2800.0 to ConstantPowerModel(200.0),
- 3300.0 to ConstantPowerModel(300.0),
- 3600.0 to ConstantPowerModel(350.0)
- )
- )
-
- val logic = driver.createLogic(machine, listOf(cpu))
-
- assertEquals(300.0, logic.computePower())
- }
-
- @Test
- fun testPowerWithMultipleCpus() {
- val machine = mockk<SimBareMetalMachine>()
- val cpu = mockk<SimProcessingUnit>(relaxUnitFun = true)
- val cpus = listOf(cpu, cpu)
-
- every { cpus[0].capacity } returns 1000.0
- every { cpus[0].rate } returns 1200.0
-
- every { cpus[1].capacity } returns 3500.0
- every { cpus[1].rate } returns 1200.0
-
- val driver = PStatePowerDriver(
- sortedMapOf(
- 2800.0 to ConstantPowerModel(200.0),
- 3300.0 to ConstantPowerModel(300.0),
- 3600.0 to ConstantPowerModel(350.0)
- )
- )
-
- val logic = driver.createLogic(machine, cpus)
-
- assertEquals(350.0, logic.computePower())
- }
-
- @Test
- fun testPowerBasedOnUtilization() {
- val machine = mockk<SimBareMetalMachine>()
- val cpu = mockk<SimProcessingUnit>(relaxUnitFun = true)
-
- every { cpu.model.frequency } returns 4200.0
-
- val driver = PStatePowerDriver(
- sortedMapOf(
- 2800.0 to LinearPowerModel(200.0, 100.0),
- 3300.0 to LinearPowerModel(250.0, 150.0),
- 4000.0 to LinearPowerModel(300.0, 200.0)
- )
- )
-
- val logic = driver.createLogic(machine, listOf(cpu))
-
- every { cpu.rate } returns 1400.0
- every { cpu.capacity } returns 1400.0
- assertEquals(150.0, logic.computePower())
-
- every { cpu.rate } returns 1400.0
- every { cpu.capacity } returns 4000.0
- assertEquals(235.0, logic.computePower())
- }
-}
diff --git a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/power/PowerModelTest.kt b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/power/PowerModelTest.kt
index 67532d5b..9a6263c5 100644
--- a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/power/PowerModelTest.kt
+++ b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/power/PowerModelTest.kt
@@ -38,7 +38,7 @@ internal class PowerModelTest {
@ParameterizedTest
@MethodSource("MachinePowerModelArgs")
fun `compute power consumption given CPU loads`(
- powerModel: PowerModel,
+ powerModel: CpuPowerModel,
expectedPowerConsumption: Double
) {
val computedPowerConsumption = powerModel.computePower(cpuUtil)
@@ -48,10 +48,10 @@ internal class PowerModelTest {
@ParameterizedTest
@MethodSource("MachinePowerModelArgs")
fun `ignore idle power when computing power consumptions`(
- powerModel: PowerModel,
+ powerModel: CpuPowerModel,
expectedPowerConsumption: Double
) {
- val zeroPowerModel = ZeroIdlePowerDecorator(powerModel)
+ val zeroPowerModel = CpuPowerModels.zeroIdle(powerModel)
assertAll(
{ assertEquals(expectedPowerConsumption, zeroPowerModel.computePower(cpuUtil), epsilon) },
@@ -61,8 +61,9 @@ internal class PowerModelTest {
@Test
fun `compute power draw by the SPEC benchmark model`() {
- val ibm = listOf(58.4, 98.0, 109.0, 118.0, 128.0, 140.0, 153.0, 170.0, 189.0, 205.0, 222.0)
- val powerModel = InterpolationPowerModel(ibm)
+ val powerModel = CpuPowerModels.interpolate(
+ 58.4, 98.0, 109.0, 118.0, 128.0, 140.0, 153.0, 170.0, 189.0, 205.0, 222.0
+ )
assertAll(
{ assertEquals(58.4, powerModel.computePower(0.0)) },
@@ -80,14 +81,14 @@ internal class PowerModelTest {
private companion object {
@JvmStatic
fun MachinePowerModelArgs(): Stream<Arguments> = Stream.of(
- Arguments.of(ConstantPowerModel(0.0), 0.0),
- Arguments.of(LinearPowerModel(350.0, 200.0), 335.0),
- Arguments.of(SquarePowerModel(350.0, 200.0), 321.5),
- Arguments.of(CubicPowerModel(350.0, 200.0), 309.35),
- Arguments.of(SqrtPowerModel(350.0, 200.0), 342.302),
- Arguments.of(MsePowerModel(350.0, 200.0, 1.4), 340.571),
- Arguments.of(AsymptoticPowerModel(350.0, 200.0, 0.3, false), 338.765),
- Arguments.of(AsymptoticPowerModel(350.0, 200.0, 0.3, true), 323.072)
+ Arguments.of(CpuPowerModels.constant(0.0), 0.0),
+ Arguments.of(CpuPowerModels.linear(350.0, 200.0), 335.0),
+ Arguments.of(CpuPowerModels.square(350.0, 200.0), 321.5),
+ Arguments.of(CpuPowerModels.cubic(350.0, 200.0), 309.35),
+ Arguments.of(CpuPowerModels.sqrt(350.0, 200.0), 342.302),
+ Arguments.of(CpuPowerModels.mse(350.0, 200.0, 1.4), 340.571),
+ Arguments.of(CpuPowerModels.asymptotic(350.0, 200.0, 0.3, false), 338.765),
+ Arguments.of(CpuPowerModels.asymptotic(350.0, 200.0, 0.3, true), 323.072)
)
}
}
diff --git a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/workload/SimFlopsWorkloadTest.kt b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/workload/SimFlopsWorkloadTest.kt
index b3e57453..edbc0571 100644
--- a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/workload/SimFlopsWorkloadTest.kt
+++ b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/workload/SimFlopsWorkloadTest.kt
@@ -32,7 +32,7 @@ class SimFlopsWorkloadTest {
@Test
fun testFlopsNonNegative() {
assertThrows<IllegalArgumentException>("FLOPs must be non-negative") {
- SimFlopsWorkload(-1)
+ SimFlopsWorkload(-1, 1.0)
}
}
diff --git a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/workload/SimTraceWorkloadTest.kt b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/workload/SimTraceWorkloadTest.kt
index 83e1f81c..e3b6e6c5 100644
--- a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/workload/SimTraceWorkloadTest.kt
+++ b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/workload/SimTraceWorkloadTest.kt
@@ -31,10 +31,8 @@ import org.opendc.simulator.compute.model.MachineModel
import org.opendc.simulator.compute.model.MemoryUnit
import org.opendc.simulator.compute.model.ProcessingNode
import org.opendc.simulator.compute.model.ProcessingUnit
-import org.opendc.simulator.compute.power.ConstantPowerModel
-import org.opendc.simulator.compute.power.SimplePowerDriver
import org.opendc.simulator.compute.runWorkload
-import org.opendc.simulator.flow.FlowEngine
+import org.opendc.simulator.flow2.FlowEngine
import org.opendc.simulator.kotlin.runSimulation
/**
@@ -48,28 +46,28 @@ class SimTraceWorkloadTest {
val cpuNode = ProcessingNode("Intel", "Xeon", "amd64", 2)
machineModel = MachineModel(
- cpus = List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 1000.0) },
- memory = List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) }
+ /*cpus*/ List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 1000.0) },
+ /*memory*/ List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) }
)
}
@Test
fun testSmoke() = runSimulation {
- val machine = SimBareMetalMachine(
- FlowEngine(coroutineContext, clock),
- machineModel,
- SimplePowerDriver(ConstantPowerModel(0.0))
+ val engine = FlowEngine.create(coroutineContext, clock)
+ val graph = engine.newGraph()
+
+ val machine = SimBareMetalMachine.create(
+ graph,
+ machineModel
)
- val workload = SimTraceWorkload(
+ val workload =
SimTrace.ofFragments(
SimTraceFragment(0, 1000, 2 * 28.0, 2),
SimTraceFragment(1000, 1000, 2 * 3100.0, 2),
SimTraceFragment(2000, 1000, 0.0, 2),
SimTraceFragment(3000, 1000, 2 * 73.0, 2)
- ),
- offset = 0
- )
+ ).createWorkload(0)
machine.runWorkload(workload)
@@ -78,21 +76,21 @@ class SimTraceWorkloadTest {
@Test
fun testOffset() = runSimulation {
- val machine = SimBareMetalMachine(
- FlowEngine(coroutineContext, clock),
- machineModel,
- SimplePowerDriver(ConstantPowerModel(0.0))
+ val engine = FlowEngine.create(coroutineContext, clock)
+ val graph = engine.newGraph()
+
+ val machine = SimBareMetalMachine.create(
+ graph,
+ machineModel
)
- val workload = SimTraceWorkload(
+ val workload =
SimTrace.ofFragments(
SimTraceFragment(0, 1000, 2 * 28.0, 2),
SimTraceFragment(1000, 1000, 2 * 3100.0, 2),
SimTraceFragment(2000, 1000, 0.0, 2),
SimTraceFragment(3000, 1000, 2 * 73.0, 2)
- ),
- offset = 1000
- )
+ ).createWorkload(1000)
machine.runWorkload(workload)
@@ -101,21 +99,21 @@ class SimTraceWorkloadTest {
@Test
fun testSkipFragment() = runSimulation {
- val machine = SimBareMetalMachine(
- FlowEngine(coroutineContext, clock),
- machineModel,
- SimplePowerDriver(ConstantPowerModel(0.0))
+ val engine = FlowEngine.create(coroutineContext, clock)
+ val graph = engine.newGraph()
+
+ val machine = SimBareMetalMachine.create(
+ graph,
+ machineModel
)
- val workload = SimTraceWorkload(
+ val workload =
SimTrace.ofFragments(
SimTraceFragment(0, 1000, 2 * 28.0, 2),
SimTraceFragment(1000, 1000, 2 * 3100.0, 2),
SimTraceFragment(2000, 1000, 0.0, 2),
SimTraceFragment(3000, 1000, 2 * 73.0, 2)
- ),
- offset = 0
- )
+ ).createWorkload(0)
delay(1000L)
machine.runWorkload(workload)
@@ -125,21 +123,21 @@ class SimTraceWorkloadTest {
@Test
fun testZeroCores() = runSimulation {
- val machine = SimBareMetalMachine(
- FlowEngine(coroutineContext, clock),
- machineModel,
- SimplePowerDriver(ConstantPowerModel(0.0))
+ val engine = FlowEngine.create(coroutineContext, clock)
+ val graph = engine.newGraph()
+
+ val machine = SimBareMetalMachine.create(
+ graph,
+ machineModel
)
- val workload = SimTraceWorkload(
+ val workload =
SimTrace.ofFragments(
SimTraceFragment(0, 1000, 2 * 28.0, 2),
SimTraceFragment(1000, 1000, 2 * 3100.0, 2),
SimTraceFragment(2000, 1000, 0.0, 0),
SimTraceFragment(3000, 1000, 2 * 73.0, 2)
- ),
- offset = 0
- )
+ ).createWorkload(0)
machine.runWorkload(workload)
diff --git a/opendc-simulator/opendc-simulator-compute/src/test/resources/spec_machines.yml b/opendc-simulator/opendc-simulator-compute/src/test/resources/spec_machines.yml
deleted file mode 100644
index d51cba80..00000000
--- a/opendc-simulator/opendc-simulator-compute/src/test/resources/spec_machines.yml
+++ /dev/null
@@ -1,29 +0,0 @@
----
-# The power model of an IBM server x3550 (2 x [Xeon X5675 3067 MHz, 6 cores], 16GB).<br/>
-# <a href="http://www.spec.org/power_ssj2008/results/res2011q2/power_ssj2008-20110406-00368.html">
-# http://www.spec.org/power_ssj2008/results/res2011q2/power_ssj2008-20110406-00368.html</a>
-IBMx3550M3_XeonX5675: [58.4, 98.0, 109.0, 118.0, 128.0, 140.0, 153.0, 170.0, 189.0, 205.0, 222.0]
- # The power model of an IBM server x3550 (2 x [Xeon X5670 2933 MHz, 6 cores], 12GB).<br/>
- # <a href="http://www.spec.org/power_ssj2008/results/res2010q2/power_ssj2008-20100315-00239.html">
- # http://www.spec.org/power_ssj2008/results/res2010q2/power_ssj2008-20100315-00239.html</a>
-IBMx3550M3_XeonX5670: [66.0, 107.0, 120.0, 131.0, 143.0, 156.0, 173.0, 191.0, 211.0, 229.0, 247.0]
- # the power model of an IBM server x3250 (1 x [Xeon X3480 3067 MHz, 4 cores], 8GB).<br/>
- # <a href="http://www.spec.org/power_ssj2008/results/res2010q4/power_ssj2008-20101001-00297.html">
- # http://www.spec.org/power_ssj2008/results/res2010q4/power_ssj2008-20101001-00297.html</a>
-IBMx3250M3_XeonX3480: [42.3, 46.7, 49.7, 55.4, 61.8, 69.3, 76.1, 87.0, 96.1, 106.0, 113.0]
- # The power model of an IBM server x3250 (1 x [Xeon X3470 2933 MHz, 4 cores], 8GB).<br/>
- # <a href="http://www.spec.org/power_ssj2008/results/res2009q4/power_ssj2008-20091104-00213.html">
- # http://www.spec.org/power_ssj2008/results/res2009q4/power_ssj2008-20091104-00213.html</a>
-IBMx3250M3_XeonX3470: [41.6, 46.7, 52.3, 57.9, 65.4, 73.0, 80.7, 89.5, 99.6, 105.0, 113.0]
- # The power model of an HP ProLiant ML110 G5 (1 x [Xeon 3075 2660 MHz, 2 cores], 4GB).<br/>
- # <a href="http://www.spec.org/power_ssj2008/results/res2011q1/power_ssj2008-20110124-00339.html">
- # http://www.spec.org/power_ssj2008/results/res2011q1/power_ssj2008-20110124-00339.html</a>
-HPProLiantMl110G5_Xeon3075: [93.7, 97.0, 101.0, 105.0, 110.0, 116.0, 121.0, 125.0, 129.0, 133.0, 135.0]
- # The power model of an HP ProLiant ML110 G4 (1 x [Xeon 3040 1860 MHz, 2 cores], 4GB).<br/>
- # <a href="http://www.spec.org/power_ssj2008/results/res2011q1/power_ssj2008-20110127-00342.html">
- # http://www.spec.org/power_ssj2008/results/res2011q1/power_ssj2008-20110127-00342.html</a>
-HPProLiantMl110G4_Xeon3040: [86.0, 89.4, 92.6, 96.0, 99.5, 102.0, 106.0, 108.0, 112.0, 114.0, 117.0]
- # The power model of an HP ProLiant ML110 G3 (1 x [Pentium D930 3000 MHz, 2 cores], 4GB).<br/>
- # <a href="http://www.spec.org/power_ssj2008/results/res2011q1/power_ssj2008-20110127-00342.html">
- # http://www.spec.org/power_ssj2008/results/res2011q1/power_ssj2008-20110127-00342.html</a>
-HPProLiantMl110G3_PentiumD930: [105.0, 112.0, 118.0, 125.0, 131.0, 137.0, 147.0, 153.0, 157.0, 164.0, 169.0]