diff options
4 files changed, 49 insertions, 67 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 56b1c8d1..0fa91d52 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 @@ -35,17 +35,11 @@ import org.opendc.compute.simulator.internal.Guest import org.opendc.compute.simulator.internal.GuestListener import org.opendc.simulator.compute.* import org.opendc.simulator.compute.kernel.SimHypervisor -import org.opendc.simulator.compute.kernel.SimHypervisorProvider -import org.opendc.simulator.compute.kernel.cpufreq.PerformanceScalingGovernor -import org.opendc.simulator.compute.kernel.cpufreq.ScalingGovernor import org.opendc.simulator.compute.kernel.interference.VmInterferenceDomain import org.opendc.simulator.compute.model.MachineModel import org.opendc.simulator.compute.model.MemoryUnit -import org.opendc.simulator.compute.power.ConstantPowerModel -import org.opendc.simulator.compute.power.PowerDriver -import org.opendc.simulator.compute.power.SimplePowerDriver import org.opendc.simulator.compute.workload.SimWorkload -import org.opendc.simulator.flow.FlowEngine +import java.time.Clock import java.time.Duration import java.time.Instant import java.util.* @@ -57,40 +51,21 @@ import kotlin.coroutines.CoroutineContext public class SimHost( override val uid: UUID, override val name: String, - model: MachineModel, override val meta: Map<String, Any>, private val context: CoroutineContext, - engine: FlowEngine, - hypervisorProvider: SimHypervisorProvider, - random: SplittableRandom, - scalingGovernor: ScalingGovernor = PerformanceScalingGovernor(), - powerDriver: PowerDriver = SimplePowerDriver(ConstantPowerModel(0.0)), + private val clock: Clock, + private val machine: SimBareMetalMachine, + private val hypervisor: SimHypervisor, private val mapper: SimWorkloadMapper = SimMetaWorkloadMapper(), private val interferenceDomain: VmInterferenceDomain? = null, private val optimize: Boolean = false ) : Host, AutoCloseable { /** - * The clock instance used by the host. - */ - private val clock = engine.clock - - /** * The event listeners registered with this host. */ private val listeners = mutableListOf<HostListener>() /** - * The machine to run on. - */ - public val machine: SimBareMetalMachine = SimBareMetalMachine(engine, model.optimize(), powerDriver) - - /** - * The hypervisor to run multiple workloads. - */ - private val hypervisor: SimHypervisor = hypervisorProvider - .create(engine, random, scalingGovernor = scalingGovernor) - - /** * The virtual machines running on the hypervisor. */ private val guests = HashMap<Server, Guest>() @@ -109,7 +84,11 @@ public class SimHost( field = value } - override val model: HostModel = HostModel(model.cpus.sumOf { it.frequency }, model.cpus.size, model.memory.sumOf { it.size }) + override val model: HostModel = HostModel( + machine.model.cpus.sumOf { it.frequency }, + machine.model.cpus.size, + machine.model.memory.sumOf { it.size } + ) /** * The [GuestListener] that listens for guest events. @@ -341,26 +320,8 @@ public class SimHost( val processingUnits = (0 until cpuCount).map { originalCpu.copy(id = it, node = processingNode, frequency = cpuCapacity) } val memoryUnits = listOf(MemoryUnit("Generic", "Generic", 3200.0, memorySize)) - return MachineModel(processingUnits, memoryUnits).optimize() - } - - /** - * Optimize the [MachineModel] for simulation. - */ - private fun MachineModel.optimize(): MachineModel { - if (!optimize) { - return this - } - - val originalCpu = cpus[0] - val freq = cpus.sumOf { it.frequency } - val processingNode = originalCpu.node.copy(coreCount = 1) - val processingUnits = listOf(originalCpu.copy(frequency = freq, node = processingNode)) - - val memorySize = memory.sumOf { it.size } - val memoryUnits = listOf(MemoryUnit("Generic", "Generic", 3200.0, memorySize)) - - return MachineModel(processingUnits, memoryUnits) + val model = MachineModel(processingUnits, memoryUnits) + return if (optimize) model.optimize() else model } private var _lastReport = clock.millis() diff --git a/opendc-compute/opendc-compute-simulator/src/test/kotlin/org/opendc/compute/simulator/SimHostTest.kt b/opendc-compute/opendc-compute-simulator/src/test/kotlin/org/opendc/compute/simulator/SimHostTest.kt index 0b2285e5..06500a06 100644 --- a/opendc-compute/opendc-compute-simulator/src/test/kotlin/org/opendc/compute/simulator/SimHostTest.kt +++ b/opendc-compute/opendc-compute-simulator/src/test/kotlin/org/opendc/compute/simulator/SimHostTest.kt @@ -30,11 +30,14 @@ import org.junit.jupiter.api.assertAll import org.opendc.compute.api.* import org.opendc.compute.service.driver.Host import org.opendc.compute.service.driver.HostListener -import org.opendc.simulator.compute.kernel.SimFairShareHypervisorProvider +import org.opendc.simulator.compute.SimBareMetalMachine +import org.opendc.simulator.compute.kernel.SimFairShareHypervisor 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.workload.SimTrace import org.opendc.simulator.compute.workload.SimTraceFragment import org.opendc.simulator.compute.workload.SimTraceWorkload @@ -67,16 +70,16 @@ internal class SimHostTest { fun testOvercommitted() = runBlockingSimulation { val duration = 5 * 60L val engine = FlowEngine(coroutineContext, clock) - val random = SplittableRandom(1) + val machine = SimBareMetalMachine(engine, machineModel, SimplePowerDriver(ConstantPowerModel(0.0))) + val hypervisor = SimFairShareHypervisor(engine, null, SplittableRandom(1)) val host = SimHost( uid = UUID.randomUUID(), name = "test", - model = machineModel, meta = emptyMap(), coroutineContext, - engine, - SimFairShareHypervisorProvider(), - random, + clock, + machine, + hypervisor ) val vmImageA = MockImage( UUID.randomUUID(), @@ -151,16 +154,16 @@ internal class SimHostTest { fun testFailure() = runBlockingSimulation { val duration = 5 * 60L val engine = FlowEngine(coroutineContext, clock) - val random = SplittableRandom(1) + val machine = SimBareMetalMachine(engine, machineModel, SimplePowerDriver(ConstantPowerModel(0.0))) + val hypervisor = SimFairShareHypervisor(engine, null, SplittableRandom(1)) val host = SimHost( uid = UUID.randomUUID(), name = "test", - model = machineModel, meta = emptyMap(), coroutineContext, - engine, - SimFairShareHypervisorProvider(), - random + clock, + machine, + hypervisor ) val image = MockImage( UUID.randomUUID(), diff --git a/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/ComputeServiceHelper.kt b/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/ComputeServiceHelper.kt index 879ef072..92652329 100644 --- a/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/ComputeServiceHelper.kt +++ b/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/ComputeServiceHelper.kt @@ -31,6 +31,7 @@ import org.opendc.compute.service.ComputeService import org.opendc.compute.service.scheduler.ComputeScheduler import org.opendc.compute.simulator.SimHost import org.opendc.compute.workload.topology.HostSpec +import org.opendc.simulator.compute.SimBareMetalMachine import org.opendc.simulator.compute.kernel.interference.VmInterferenceModel import org.opendc.simulator.compute.workload.SimTraceWorkload import org.opendc.simulator.flow.FlowEngine @@ -167,16 +168,17 @@ public class ComputeServiceHelper( * @return The [SimHost] that has been constructed by the runner. */ public fun registerHost(spec: HostSpec, optimize: Boolean = false): SimHost { + val machine = SimBareMetalMachine(engine, spec.model, spec.powerDriver) + val hypervisor = spec.hypervisor.create(engine, random) + val host = SimHost( spec.uid, spec.name, - spec.model, spec.meta, context, - engine, - spec.hypervisor, - random, - powerDriver = spec.powerDriver, + clock, + machine, + hypervisor, interferenceDomain = interferenceModel?.newDomain(), optimize = optimize ) diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/model/MachineModel.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/model/MachineModel.kt index 7e4d7191..22dcaef4 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/model/MachineModel.kt +++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/model/MachineModel.kt @@ -35,4 +35,20 @@ public data class MachineModel( public val memory: List<MemoryUnit>, public val net: List<NetworkAdapter> = emptyList(), public val storage: List<StorageDevice> = emptyList() -) +) { + /** + * Optimize the [MachineModel] by merging all resources of the same type into a single resource with the combined + * capacity. Such configurations can be simulated more efficiently by OpenDC. + */ + public fun optimize(): MachineModel { + val originalCpu = cpus[0] + val freq = cpus.sumOf { it.frequency } + val processingNode = originalCpu.node.copy(coreCount = 1) + val processingUnits = listOf(originalCpu.copy(frequency = freq, node = processingNode)) + + val memorySize = memory.sumOf { it.size } + val memoryUnits = listOf(MemoryUnit("Generic", "Generic", 3200.0, memorySize)) + + return MachineModel(processingUnits, memoryUnits) + } +} |
