diff --git a/opendc-compute/opendc-compute-service/src/main/java/org/opendc/compute/service/driver/HostModel.java b/opendc-compute/opendc-compute-service/src/main/java/org/opendc/compute/service/driver/HostModel.java index 2d45817bf..87464fe14 100644 --- a/opendc-compute/opendc-compute-service/src/main/java/org/opendc/compute/service/driver/HostModel.java +++ b/opendc-compute/opendc-compute-service/src/main/java/org/opendc/compute/service/driver/HostModel.java @@ -26,7 +26,7 @@ * Record describing the static machine properties of the host. * * @param cpuCapacity The total CPU capacity of the host in MHz. - * @param cpuCount The number of logical processing cores available for this host. + * @param coreCount The number of logical processing cores available for this host. * @param memoryCapacity The amount of memory available for this host in MB. */ -public record HostModel(double cpuCapacity, int cpuCount, int coreCount, long memoryCapacity) {} +public record HostModel(double cpuCapacity, int coreCount, long memoryCapacity) {} diff --git a/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/scheduler/filters/VCpuCapacityFilter.kt b/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/scheduler/filters/VCpuCapacityFilter.kt index f87658cd0..5af7ccf0a 100644 --- a/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/scheduler/filters/VCpuCapacityFilter.kt +++ b/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/scheduler/filters/VCpuCapacityFilter.kt @@ -36,7 +36,7 @@ public class VCpuCapacityFilter : HostFilter { ): Boolean { val requiredCapacity = task.flavor.meta["cpu-capacity"] as? Double val hostModel = host.host.model - val availableCapacity = hostModel.cpuCapacity / hostModel.cpuCount + val availableCapacity = hostModel.cpuCapacity return requiredCapacity == null || availableCapacity >= (requiredCapacity / task.flavor.coreCount) } diff --git a/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/scheduler/weights/CoreRamWeigher.kt b/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/scheduler/weights/CoreRamWeigher.kt index d84f5e682..6e320bf48 100644 --- a/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/scheduler/weights/CoreRamWeigher.kt +++ b/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/scheduler/weights/CoreRamWeigher.kt @@ -37,7 +37,7 @@ public class CoreRamWeigher(override val multiplier: Double = 1.0) : HostWeigher host: HostView, task: Task, ): Double { - return host.availableMemory.toDouble() / host.host.model.cpuCount + return host.availableMemory.toDouble() } override fun toString(): String = "CoreRamWeigher" diff --git a/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/scheduler/weights/VCpuCapacityWeigher.kt b/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/scheduler/weights/VCpuCapacityWeigher.kt index 6d1482ff7..5f99cab3c 100644 --- a/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/scheduler/weights/VCpuCapacityWeigher.kt +++ b/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/scheduler/weights/VCpuCapacityWeigher.kt @@ -35,7 +35,7 @@ public class VCpuCapacityWeigher(override val multiplier: Double = 1.0) : HostWe ): Double { val model = host.host.model val requiredCapacity = task.flavor.meta["cpu-capacity"] as? Double ?: 0.0 - return model.cpuCapacity / model.cpuCount - requiredCapacity / task.flavor.coreCount + return model.cpuCapacity - requiredCapacity / task.flavor.coreCount } override fun toString(): String = "VCpuWeigher" diff --git a/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/scheduler/weights/VCpuWeigher.kt b/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/scheduler/weights/VCpuWeigher.kt index dfc30b546..0c3d9c217 100644 --- a/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/scheduler/weights/VCpuWeigher.kt +++ b/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/scheduler/weights/VCpuWeigher.kt @@ -39,7 +39,7 @@ public class VCpuWeigher(private val allocationRatio: Double, override val multi host: HostView, task: Task, ): Double { - return host.host.model.cpuCount * allocationRatio - host.provisionedCores + return allocationRatio - host.provisionedCores } override fun toString(): String = "VCpuWeigher" diff --git a/opendc-compute/opendc-compute-service/src/test/kotlin/org/opendc/compute/service/ComputeServiceTest.kt b/opendc-compute/opendc-compute-service/src/test/kotlin/org/opendc/compute/service/ComputeServiceTest.kt index fa5b775e0..eb686faf8 100644 --- a/opendc-compute/opendc-compute-service/src/test/kotlin/org/opendc/compute/service/ComputeServiceTest.kt +++ b/opendc-compute/opendc-compute-service/src/test/kotlin/org/opendc/compute/service/ComputeServiceTest.kt @@ -136,7 +136,7 @@ internal class ComputeServiceTest { scope.runSimulation { val host = mockk(relaxUnitFun = true) - every { host.model } returns HostModel(4 * 2600.0, 1, 4, 2048) + every { host.model } returns HostModel(4 * 2600.0, 4, 2048) every { host.state } returns HostState.UP assertEquals(emptySet(), service.hosts) @@ -157,7 +157,7 @@ internal class ComputeServiceTest { scope.runSimulation { val host = mockk(relaxUnitFun = true) - every { host.model } returns HostModel(4 * 2600.0, 1, 4, 2048) + every { host.model } returns HostModel(4 * 2600.0, 4, 2048) every { host.state } returns HostState.DOWN assertEquals(emptySet(), service.hosts) @@ -230,7 +230,7 @@ internal class ComputeServiceTest { scope.runSimulation { val host = mockk(relaxUnitFun = true) - every { host.model } returns HostModel(4 * 2600.0, 1, 4, 2048) + every { host.model } returns HostModel(4 * 2600.0, 4, 2048) every { host.state } returns HostState.UP every { host.canFit(any()) } returns false @@ -256,7 +256,7 @@ internal class ComputeServiceTest { val listeners = mutableListOf() every { host.uid } returns UUID.randomUUID() - every { host.model } returns HostModel(4 * 2600.0, 1, 4, 2048) + every { host.model } returns HostModel(4 * 2600.0, 4, 2048) every { host.state } returns HostState.DOWN every { host.addListener(any()) } answers { listeners.add(it.invocation.args[0] as HostListener) } every { host.canFit(any()) } returns false @@ -288,7 +288,7 @@ internal class ComputeServiceTest { val listeners = mutableListOf() every { host.uid } returns UUID.randomUUID() - every { host.model } returns HostModel(4 * 2600.0, 1, 4, 2048) + every { host.model } returns HostModel(4 * 2600.0, 4, 2048) every { host.state } returns HostState.UP every { host.addListener(any()) } answers { listeners.add(it.invocation.args[0] as HostListener) } every { host.canFit(any()) } returns false @@ -320,7 +320,7 @@ internal class ComputeServiceTest { val listeners = mutableListOf() every { host.uid } returns UUID.randomUUID() - every { host.model } returns HostModel(4 * 2600.0, 1, 4, 2048) + every { host.model } returns HostModel(4 * 2600.0, 4, 2048) every { host.state } returns HostState.UP every { host.canFit(any()) } returns true every { host.addListener(any()) } answers { listeners.add(it.invocation.args[0] as HostListener) } @@ -364,7 +364,7 @@ internal class ComputeServiceTest { val listeners = mutableListOf() every { host.uid } returns UUID.randomUUID() - every { host.model } returns HostModel(4 * 2600.0, 1, 4, 2048) + every { host.model } returns HostModel(4 * 2600.0, 4, 2048) every { host.state } returns HostState.UP every { host.canFit(any()) } returns true every { host.addListener(any()) } answers { listeners.add(it.invocation.args[0] as HostListener) } diff --git a/opendc-compute/opendc-compute-service/src/test/kotlin/org/opendc/compute/service/scheduler/FilterSchedulerTest.kt b/opendc-compute/opendc-compute-service/src/test/kotlin/org/opendc/compute/service/scheduler/FilterSchedulerTest.kt index 2478bf821..add10f8fa 100644 --- a/opendc-compute/opendc-compute-service/src/test/kotlin/org/opendc/compute/service/scheduler/FilterSchedulerTest.kt +++ b/opendc-compute/opendc-compute-service/src/test/kotlin/org/opendc/compute/service/scheduler/FilterSchedulerTest.kt @@ -193,12 +193,12 @@ internal class FilterSchedulerTest { val hostA = mockk() every { hostA.host.state } returns HostState.UP - every { hostA.host.model } returns HostModel(4 * 2600.0, 1, 4, 2048) + every { hostA.host.model } returns HostModel(4 * 2600.0, 4, 2048) every { hostA.availableMemory } returns 512 val hostB = mockk() every { hostB.host.state } returns HostState.UP - every { hostB.host.model } returns HostModel(4 * 2600.0, 1, 4, 2048) + every { hostB.host.model } returns HostModel(4 * 2600.0, 4, 2048) every { hostB.availableMemory } returns 2048 scheduler.addHost(hostA) @@ -221,7 +221,7 @@ internal class FilterSchedulerTest { val host = mockk() every { host.host.state } returns HostState.UP - every { host.host.model } returns HostModel(4 * 2600.0, 1, 4, 2048) + every { host.host.model } returns HostModel(4 * 2600.0, 4, 2048) every { host.availableMemory } returns 2048 scheduler.addHost(host) @@ -243,12 +243,12 @@ internal class FilterSchedulerTest { val hostA = mockk() every { hostA.host.state } returns HostState.UP - every { hostA.host.model } returns HostModel(4 * 2600.0, 1, 4, 2048) + every { hostA.host.model } returns HostModel(4 * 2600.0, 4, 2048) every { hostA.provisionedCores } returns 3 val hostB = mockk() every { hostB.host.state } returns HostState.UP - every { hostB.host.model } returns HostModel(4 * 2600.0, 1, 4, 2048) + every { hostB.host.model } returns HostModel(4 * 2600.0, 4, 2048) every { hostB.provisionedCores } returns 0 scheduler.addHost(hostA) @@ -271,7 +271,7 @@ internal class FilterSchedulerTest { val host = mockk() every { host.host.state } returns HostState.UP - every { host.host.model } returns HostModel(4 * 2600.0, 1, 4, 2048) + every { host.host.model } returns HostModel(4 * 2600.0, 4, 2048) every { host.provisionedCores } returns 0 scheduler.addHost(host) @@ -294,13 +294,13 @@ internal class FilterSchedulerTest { val hostA = mockk() every { hostA.host.state } returns HostState.UP - every { hostA.host.model } returns HostModel(8 * 2600.0, 1, 8, 2048) + every { hostA.host.model } returns HostModel(8 * 2600.0, 8, 2048) every { hostA.availableMemory } returns 512 scheduler.addHost(hostA) val hostB = mockk() every { hostB.host.state } returns HostState.UP - every { hostB.host.model } returns HostModel(4 * 3200.0, 1, 4, 2048) + every { hostB.host.model } returns HostModel(4 * 3200.0, 4, 2048) every { hostB.availableMemory } returns 512 scheduler.addHost(hostB) @@ -323,12 +323,12 @@ internal class FilterSchedulerTest { val hostA = mockk() every { hostA.host.state } returns HostState.UP - every { hostA.host.model } returns HostModel(4 * 2600.0, 1, 4, 2048) + every { hostA.host.model } returns HostModel(4 * 2600.0, 4, 2048) every { hostA.instanceCount } returns 2 val hostB = mockk() every { hostB.host.state } returns HostState.UP - every { hostB.host.model } returns HostModel(4 * 2600.0, 1, 4, 2048) + every { hostB.host.model } returns HostModel(4 * 2600.0, 4, 2048) every { hostB.instanceCount } returns 0 scheduler.addHost(hostA) @@ -356,13 +356,13 @@ internal class FilterSchedulerTest { val hostA = mockk() every { hostA.host.state } returns HostState.UP - every { hostA.host.model } returns HostModel(4 * 2600.0, 1, 4, 2048) + every { hostA.host.model } returns HostModel(4 * 2600.0, 4, 2048) every { hostA.host.instances } returns emptySet() every { hostA.provisionedCores } returns 3 val hostB = mockk() every { hostB.host.state } returns HostState.UP - every { hostB.host.model } returns HostModel(4 * 2600.0, 1, 4, 2048) + every { hostB.host.model } returns HostModel(4 * 2600.0, 4, 2048) every { hostB.host.instances } returns setOf(taskA) every { hostB.provisionedCores } returns 0 @@ -396,13 +396,13 @@ internal class FilterSchedulerTest { val hostA = mockk() every { hostA.host.state } returns HostState.UP - every { hostA.host.model } returns HostModel(4 * 2600.0, 1, 4, 2048) + every { hostA.host.model } returns HostModel(4 * 2600.0, 4, 2048) every { hostA.host.instances } returns setOf(taskA) every { hostA.provisionedCores } returns 3 val hostB = mockk() every { hostB.host.state } returns HostState.UP - every { hostB.host.model } returns HostModel(4 * 2600.0, 1, 4, 2048) + every { hostB.host.model } returns HostModel(4 * 2600.0, 4, 2048) every { hostB.host.instances } returns emptySet() every { hostB.provisionedCores } returns 0 @@ -431,12 +431,12 @@ internal class FilterSchedulerTest { val hostA = mockk() every { hostA.host.state } returns HostState.UP - every { hostA.host.model } returns HostModel(4 * 2600.0, 1, 4, 2048) + every { hostA.host.model } returns HostModel(4 * 2600.0, 4, 2048) every { hostA.availableMemory } returns 1024 val hostB = mockk() every { hostB.host.state } returns HostState.UP - every { hostB.host.model } returns HostModel(4 * 2600.0, 1, 4, 2048) + every { hostB.host.model } returns HostModel(4 * 2600.0, 4, 2048) every { hostB.availableMemory } returns 512 scheduler.addHost(hostA) @@ -460,12 +460,12 @@ internal class FilterSchedulerTest { val hostA = mockk() every { hostA.host.state } returns HostState.UP - every { hostA.host.model } returns HostModel(12 * 2600.0, 1, 12, 2048) + every { hostA.host.model } returns HostModel(12 * 2600.0, 12, 2048) every { hostA.availableMemory } returns 1024 val hostB = mockk() every { hostB.host.state } returns HostState.UP - every { hostB.host.model } returns HostModel(4 * 2600.0, 1, 4, 2048) + every { hostB.host.model } returns HostModel(4 * 2600.0, 4, 2048) every { hostB.availableMemory } returns 512 scheduler.addHost(hostA) @@ -488,12 +488,12 @@ internal class FilterSchedulerTest { val hostA = mockk() every { hostA.host.state } returns HostState.UP - every { hostA.host.model } returns HostModel(4 * 2600.0, 1, 4, 2048) + every { hostA.host.model } returns HostModel(4 * 2600.0, 4, 2048) every { hostA.provisionedCores } returns 2 val hostB = mockk() every { hostB.host.state } returns HostState.UP - every { hostB.host.model } returns HostModel(4 * 2600.0, 1, 4, 2048) + every { hostB.host.model } returns HostModel(4 * 2600.0, 4, 2048) every { hostB.provisionedCores } returns 0 scheduler.addHost(hostA) @@ -516,12 +516,12 @@ internal class FilterSchedulerTest { val hostA = mockk() every { hostA.host.state } returns HostState.UP - every { hostA.host.model } returns HostModel(4 * 2600.0, 1, 4, 2048) + every { hostA.host.model } returns HostModel(4 * 2600.0, 4, 2048) every { hostA.instanceCount } returns 2 val hostB = mockk() every { hostB.host.state } returns HostState.UP - every { hostB.host.model } returns HostModel(4 * 2600.0, 1, 4, 2048) + every { hostB.host.model } returns HostModel(4 * 2600.0, 4, 2048) every { hostB.instanceCount } returns 0 scheduler.addHost(hostA) 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 ac0a8043a..e681403ce 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 @@ -41,8 +41,6 @@ import org.opendc.simulator.compute.SimMachineContext import org.opendc.simulator.compute.kernel.SimHypervisor 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.workload.SimWorkload import org.opendc.simulator.compute.workload.SimWorkloads import java.time.Duration @@ -96,10 +94,9 @@ public class SimHost( private val model: HostModel = HostModel( - machine.model.cpus.sumOf { it.frequency }, - machine.model.cpus.size, - machine.model.cpus.sumOf { it.node.coreCount }, - machine.model.memory.sumOf { it.size }, + machine.model.cpu.totalCapacity, + machine.model.cpu.coreCount, + machine.model.memory.size, ) /** @@ -349,22 +346,14 @@ public class SimHost( * Convert flavor to machine model. */ private fun Flavor.toMachineModel(): MachineModel { - val originalCpu = machine.model.cpus[0] - val originalNode = originalCpu.node - val cpuCapacity = (this.meta["cpu-capacity"] as? Double ?: Double.MAX_VALUE).coerceAtMost(originalCpu.frequency) - val processingNode = ProcessingNode(originalNode.vendor, originalNode.modelName, originalNode.architecture, coreCount) - val processingUnits = (0 until coreCount).map { ProcessingUnit(processingNode, it, cpuCapacity) } - val memoryUnits = listOf(MemoryUnit("Generic", "Generic", 3200.0, memorySize)) - - val model = MachineModel(processingUnits, memoryUnits) - return if (optimize) model.optimize() else model + return MachineModel(machine.model.cpu, MemoryUnit("Generic", "Generic", 3200.0, memorySize)) } private var localLastReport = clock.millis() private var localUptime = 0L private var localDowntime = 0L private var localBootTime: Instant? = null - private val localCpuLimit = machine.model.cpus.sumOf { it.frequency * it.node.coreCount } + private val localCpuLimit = machine.model.cpu.totalCapacity /** * Helper function to track the uptime of a machine. diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/internal/DefaultWorkloadMapper.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/internal/DefaultWorkloadMapper.kt index ea8f51d0c..412da37fd 100644 --- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/internal/DefaultWorkloadMapper.kt +++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/internal/DefaultWorkloadMapper.kt @@ -39,8 +39,8 @@ internal object DefaultWorkloadMapper : SimWorkloadMapper { override fun createWorkload(task: Task): SimWorkload { val workload = delegate.createWorkload(task) - // FIXME: look at connecting this to frontend. Probably not needed since the duration is so small - val bootWorkload = SimWorkloads.runtime(Duration.ofMillis(1), 0.8, 0L, 0L) + // FIXME: look at connecting this to frontend. This does currently not work correctly + val bootWorkload = SimWorkloads.runtime(Duration.ofMillis(0), 1.0, 0L, 0L) return SimWorkloads.chain(bootWorkload, workload) } } diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/internal/Guest.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/internal/Guest.kt index 1925233f4..cf6c146a7 100644 --- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/internal/Guest.kt +++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/internal/Guest.kt @@ -31,7 +31,6 @@ import org.opendc.compute.simulator.SimHost import org.opendc.compute.simulator.SimWorkloadMapper import org.opendc.simulator.compute.SimMachineContext import org.opendc.simulator.compute.kernel.SimHypervisor -import org.opendc.simulator.compute.kernel.SimVirtualMachine import org.opendc.simulator.compute.workload.SimWorkload import java.time.Duration import java.time.Instant @@ -47,7 +46,7 @@ internal class Guest( private val mapper: SimWorkloadMapper, private val listener: GuestListener, val task: Task, - val machine: SimVirtualMachine, + val machine: SimHypervisor.SimVirtualMachine, ) { /** * The state of the [Guest]. @@ -225,7 +224,7 @@ internal class Guest( private var localDowntime = 0L private var localLastReport = clock.millis() private var localBootTime: Instant? = null - private val localCpuLimit = machine.model.cpus.sumOf { it.frequency } + private val localCpuLimit = machine.model.cpu.totalCapacity /** * Helper function to track the uptime and downtime of the guest. 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 77cd22911..b5bc66a94 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 @@ -38,10 +38,9 @@ import org.opendc.compute.service.driver.Host import org.opendc.compute.service.driver.HostListener import org.opendc.simulator.compute.SimBareMetalMachine import org.opendc.simulator.compute.kernel.SimHypervisor +import org.opendc.simulator.compute.model.Cpu 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.workload.SimTrace import org.opendc.simulator.compute.workload.SimTraceFragment import org.opendc.simulator.flow2.FlowEngine @@ -60,14 +59,18 @@ internal class SimHostTest { @BeforeEach fun setUp() { - val cpuNode = ProcessingNode("Intel", "Xeon", "amd64", 2) - machineModel = MachineModel( - // cpus - List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 3200.0) }, + Cpu( + 0, + 2, + 3200.0, + "Intel", + "Xeon", + "amd64", + ), // memory - List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) }, + MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000 * 4), ) } @@ -102,11 +105,11 @@ internal class SimHostTest { mapOf( "workload" to SimTrace.ofFragments( - SimTraceFragment(0, duration * 1000, 2 * 28.0, 2), - SimTraceFragment(duration * 1000, duration * 1000, 2 * 3500.0, 2), + SimTraceFragment(0, duration * 1000, 0.0, 2), + SimTraceFragment(duration * 1000, duration * 1000, 3200.0, 2), SimTraceFragment(duration * 2000, duration * 1000, 0.0, 2), - SimTraceFragment(duration * 3000, duration * 1000, 2 * 183.0, 2), - ).createWorkload(1), + SimTraceFragment(duration * 3000, duration * 1000, 6500.0, 2), + ).createWorkload(0), ), ) @@ -134,16 +137,16 @@ internal class SimHostTest { } // Ensure last cycle is collected - delay(1000L * duration) +// delay(1000L * duration) host.close() val cpuStats = host.getCpuStats() assertAll( - { assertEquals(347908, cpuStats.activeTime, "Active time does not match") }, - { assertEquals(2652092, cpuStats.idleTime, "Idle time does not match") }, - { assertEquals(1, cpuStats.stealTime, "Steal time does not match") }, - { assertEquals(1500000, timeSource.millis()) }, + { assertEquals(450000, cpuStats.activeTime, "Active time does not match") }, + { assertEquals(750000, cpuStats.idleTime, "Idle time does not match") }, + { assertEquals(4688, cpuStats.stealTime, "Steal time does not match") }, + { assertEquals(1200000, timeSource.millis()) }, ) } @@ -178,11 +181,11 @@ internal class SimHostTest { mapOf( "workload" to SimTrace.ofFragments( - SimTraceFragment(0, duration * 1000, 2 * 28.0, 2), - SimTraceFragment(duration * 1000, duration * 1000, 2 * 3500.0, 2), + SimTraceFragment(0, duration * 1000, 0.0, 2), + SimTraceFragment(duration * 1000, duration * 1000, 3200.0, 2), SimTraceFragment(duration * 2000, duration * 1000, 0.0, 2), - SimTraceFragment(duration * 3000, duration * 1000, 2 * 183.0, 2), - ).createWorkload(1), + SimTraceFragment(duration * 3000, duration * 1000, 6500.0, 2), + ).createWorkload(0), ), ) val vmImageB = @@ -193,11 +196,11 @@ internal class SimHostTest { mapOf( "workload" to SimTrace.ofFragments( - SimTraceFragment(0, duration * 1000, 2 * 28.0, 2), - SimTraceFragment(duration * 1000, duration * 1000, 2 * 3100.0, 2), + SimTraceFragment(0, duration * 1000, 0.0, 2), + SimTraceFragment(duration * 1000, duration * 1000, 3200.0, 2), SimTraceFragment(duration * 2000, duration * 1000, 0.0, 2), - SimTraceFragment(duration * 3000, duration * 1000, 2 * 73.0, 2), - ).createWorkload(1), + SimTraceFragment(duration * 3000, duration * 1000, 6500.0, 2), + ).createWorkload(0), ), ) @@ -237,9 +240,9 @@ internal class SimHostTest { val cpuStats = host.getCpuStats() assertAll( - { assertEquals(629252, cpuStats.activeTime, "Active time does not match") }, - { assertEquals(2370748, cpuStats.idleTime, "Idle time does not match") }, - { assertEquals(18754, cpuStats.stealTime, "Steal time does not match") }, + { assertEquals(600000, cpuStats.activeTime, "Active time does not match") }, + { assertEquals(900000, cpuStats.idleTime, "Idle time does not match") }, + { assertEquals(309375, cpuStats.stealTime, "Steal time does not match") }, { assertEquals(1500000, timeSource.millis()) }, ) } @@ -274,11 +277,11 @@ internal class SimHostTest { mapOf( "workload" to SimTrace.ofFragments( - SimTraceFragment(0, duration * 1000, 2 * 28.0, 2), - SimTraceFragment(duration * 1000L, duration * 1000, 2 * 3500.0, 2), - SimTraceFragment(duration * 2000L, duration * 1000, 0.0, 2), - SimTraceFragment(duration * 3000L, duration * 1000, 2 * 183.0, 2), - ).createWorkload(1), + SimTraceFragment(0, duration * 1000, 0.0, 2), + SimTraceFragment(duration * 1000, duration * 1000, 3200.0, 2), + SimTraceFragment(duration * 2000, duration * 1000, 0.0, 2), + SimTraceFragment(duration * 3000, duration * 1000, 6500.0, 2), + ).createWorkload(0), ), ) val flavor = MockFlavor(2, 0) @@ -318,8 +321,8 @@ internal class SimHostTest { val guestSysStats = host.getSystemStats(server) assertAll( - { assertEquals(2062046, cpuStats.idleTime, "Idle time does not match") }, - { assertEquals(347954, cpuStats.activeTime, "Active time does not match") }, + { assertEquals(755000, cpuStats.idleTime, "Idle time does not match") }, + { assertEquals(450000, cpuStats.activeTime, "Active time does not match") }, { assertEquals(1205000, sysStats.uptime.toMillis(), "Uptime does not match") }, { assertEquals(300000, sysStats.downtime.toMillis(), "Downtime does not match") }, { assertEquals(1205000, guestSysStats.uptime.toMillis(), "Guest uptime does not match") }, diff --git a/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/ComputeMetricReader.kt b/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/ComputeMetricReader.kt index a98a1a6dd..56cda31c7 100644 --- a/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/ComputeMetricReader.kt +++ b/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/ComputeMetricReader.kt @@ -258,7 +258,8 @@ public class ComputeMetricReader( private val _host = host - override val host: HostInfo = HostInfo(host.uid.toString(), host.name, "x86", host.model.cpuCount, host.model.memoryCapacity) + override val host: HostInfo = + HostInfo(host.uid.toString(), host.name, "x86", host.model.coreCount, host.model.cpuCapacity, host.model.memoryCapacity) override val timestamp: Instant get() = _timestamp @@ -539,7 +540,15 @@ public class ComputeMetricReader( val newHost = service.lookupHost(task) if (newHost != null && newHost.uid != _host?.uid) { _host = newHost - host = HostInfo(newHost.uid.toString(), newHost.name, "x86", newHost.model.cpuCount, newHost.model.memoryCapacity) + host = + HostInfo( + newHost.uid.toString(), + newHost.name, + "x86", + newHost.model.coreCount, + newHost.model.cpuCapacity, + newHost.model.memoryCapacity, + ) } val cpuStats = _host?.getCpuStats(task) diff --git a/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/export/parquet/DfltHostExportColumns.kt b/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/export/parquet/DfltHostExportColumns.kt index 68b5a6645..261c5462e 100644 --- a/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/export/parquet/DfltHostExportColumns.kt +++ b/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/export/parquet/DfltHostExportColumns.kt @@ -76,8 +76,8 @@ public object DfltHostExportColumns { public val CPU_COUNT: ExportColumn = ExportColumn( - field = Types.required(INT32).named("cpu_count"), - ) { it.host.cpuCount } + field = Types.required(INT32).named("core_count"), + ) { it.host.coreCount } public val MEM_CAPACITY: ExportColumn = ExportColumn( diff --git a/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/table/HostInfo.kt b/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/table/HostInfo.kt index 58b7853d5..62b7ef0d7 100644 --- a/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/table/HostInfo.kt +++ b/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/table/HostInfo.kt @@ -25,4 +25,11 @@ package org.opendc.compute.telemetry.table /** * Information about a host exposed to the telemetry service. */ -public data class HostInfo(val id: String, val name: String, val arch: String, val cpuCount: Int, val memCapacity: Long) +public data class HostInfo( + val id: String, + val name: String, + val arch: String, + val coreCount: Int, + val coreSpeed: Double, + val memCapacity: Long, +) diff --git a/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/TopologyFactories.kt b/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/TopologyFactories.kt index d4d4bfe37..e0fba34f0 100644 --- a/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/TopologyFactories.kt +++ b/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/TopologyFactories.kt @@ -29,10 +29,9 @@ import org.opendc.compute.topology.specs.HostJSONSpec import org.opendc.compute.topology.specs.HostSpec import org.opendc.compute.topology.specs.TopologySpec import org.opendc.simulator.compute.SimPsuFactories +import org.opendc.simulator.compute.model.Cpu 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.getPowerModel import java.io.File import java.io.InputStream @@ -119,14 +118,20 @@ private fun HostJSONSpec.toHostSpecs( clusterId: Int, random: RandomGenerator, ): HostSpec { - val unknownProcessingNode = ProcessingNode("unknown", "unknown", "unknown", cpu.coreCount) - val units = List(cpu.count) { ProcessingUnit(unknownProcessingNode, globalCoreId++, cpu.coreSpeed.toMHz()) } + val units = + List(cpu.count) { + Cpu( + globalCoreId++, + cpu.coreCount, + cpu.coreSpeed.toMHz(), + ) + } val unknownMemoryUnit = MemoryUnit(memory.vendor, memory.modelName, memory.memorySpeed.toMHz(), memory.memorySize.toMiB().toLong()) val machineModel = MachineModel( units, - listOf(unknownMemoryUnit), + unknownMemoryUnit, ) val powerModel = diff --git a/opendc-experiments/opendc-experiments-base/src/test/kotlin/org/opendc/experiments/base/ScenarioIntegrationTest.kt b/opendc-experiments/opendc-experiments-base/src/test/kotlin/org/opendc/experiments/base/ScenarioIntegrationTest.kt index c6ae51804..08eddca07 100644 --- a/opendc-experiments/opendc-experiments-base/src/test/kotlin/org/opendc/experiments/base/ScenarioIntegrationTest.kt +++ b/opendc-experiments/opendc-experiments-base/src/test/kotlin/org/opendc/experiments/base/ScenarioIntegrationTest.kt @@ -120,12 +120,12 @@ class ScenarioIntegrationTest { { assertEquals(0, monitor.tasksActive, "All VMs should finish after a run") }, { assertEquals(0, monitor.attemptsFailure, "No VM should be unscheduled") }, { assertEquals(0, monitor.tasksPending, "No VM should not be in the queue") }, - { assertEquals(43101695530, monitor.idleTime) { "Incorrect idle time" } }, - { assertEquals(3489503997, monitor.activeTime) { "Incorrect active time" } }, - { assertEquals(142, monitor.stealTime) { "Incorrect steal time" } }, + { assertEquals(43101769345, monitor.idleTime) { "Incorrect idle time" } }, + { assertEquals(3489430672, monitor.activeTime) { "Incorrect active time" } }, + { assertEquals(0, monitor.stealTime) { "Incorrect steal time" } }, { assertEquals(0, monitor.lostTime) { "Incorrect lost time" } }, { assertEquals(3.3388920269258898E7, monitor.powerDraw, 1E4) { "Incorrect power draw" } }, - { assertEquals(1.0016142948422823E10, monitor.energyUsage, 1E4) { "Incorrect energy usage" } }, + { assertEquals(1.0016127451211525E10, monitor.energyUsage, 1E4) { "Incorrect energy usage" } }, ) } @@ -162,9 +162,9 @@ class ScenarioIntegrationTest { // Note that these values have been verified beforehand assertAll( - { assertEquals(1373412033, monitor.idleTime) { "Idle time incorrect" } }, - { assertEquals(1217675912, monitor.activeTime) { "Active time incorrect" } }, - { assertEquals(19, monitor.stealTime) { "Steal time incorrect" } }, + { assertEquals(1373419781, monitor.idleTime) { "Idle time incorrect" } }, + { assertEquals(1217668222, monitor.activeTime) { "Active time incorrect" } }, + { assertEquals(0, monitor.stealTime) { "Steal time incorrect" } }, { assertEquals(0, monitor.lostTime) { "Lost time incorrect" } }, { assertEquals(2539987.394500494, monitor.powerDraw, 1E4) { "Incorrect power draw" } }, { assertEquals(7.617527900379665E8, monitor.energyUsage, 1E4) { "Incorrect energy usage" } }, diff --git a/opendc-experiments/opendc-experiments-faas/src/test/kotlin/org/opendc/experiments/faas/FaaSExperiment.kt b/opendc-experiments/opendc-experiments-faas/src/test/kotlin/org/opendc/experiments/faas/FaaSExperiment.kt index 346059a89..49d7d4899 100644 --- a/opendc-experiments/opendc-experiments-faas/src/test/kotlin/org/opendc/experiments/faas/FaaSExperiment.kt +++ b/opendc-experiments/opendc-experiments-faas/src/test/kotlin/org/opendc/experiments/faas/FaaSExperiment.kt @@ -30,10 +30,9 @@ import org.opendc.faas.service.FaaSService import org.opendc.faas.service.autoscaler.FunctionTerminationPolicyFixed import org.opendc.faas.service.router.RandomRoutingPolicy import org.opendc.faas.simulator.delay.ColdStartModel +import org.opendc.simulator.compute.model.Cpu 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.kotlin.runSimulation import java.io.File import java.time.Duration @@ -80,13 +79,11 @@ class FaaSExperiment { * Construct the machine model to test with. */ private fun createMachineModel(): MachineModel { - val cpuNode = ProcessingNode("Intel", "Xeon", "amd64", 2) - return MachineModel( // cpus - List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 1000.0) }, + Cpu(0, 2, 1000.0, "Intel", "Xeon", "amd64"), // memory - List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) }, + MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000 * 4), ) } } diff --git a/opendc-experiments/opendc-experiments-tf20/src/main/kotlin/org/opendc/experiments/tf20/core/SimTFDevice.kt b/opendc-experiments/opendc-experiments-tf20/src/main/kotlin/org/opendc/experiments/tf20/core/SimTFDevice.kt index 1a99cedf4..11e010ec0 100644 --- a/opendc-experiments/opendc-experiments-tf20/src/main/kotlin/org/opendc/experiments/tf20/core/SimTFDevice.kt +++ b/opendc-experiments/opendc-experiments-tf20/src/main/kotlin/org/opendc/experiments/tf20/core/SimTFDevice.kt @@ -29,9 +29,9 @@ import org.opendc.simulator.compute.SimBareMetalMachine import org.opendc.simulator.compute.SimMachine import org.opendc.simulator.compute.SimMachineContext import org.opendc.simulator.compute.SimPsuFactories +import org.opendc.simulator.compute.model.Cpu import org.opendc.simulator.compute.model.MachineModel import org.opendc.simulator.compute.model.MemoryUnit -import org.opendc.simulator.compute.model.ProcessingUnit import org.opendc.simulator.compute.power.CpuPowerModel import org.opendc.simulator.compute.workload.SimWorkload import org.opendc.simulator.flow2.FlowEngine @@ -52,7 +52,7 @@ public class SimTFDevice( override val uid: UUID, override val isGpu: Boolean, dispatcher: Dispatcher, - pu: ProcessingUnit, + pu: Cpu, private val memory: MemoryUnit, powerModel: CpuPowerModel, ) : TFDevice { @@ -62,7 +62,7 @@ public class SimTFDevice( private val machine = SimBareMetalMachine.create( FlowEngine.create(dispatcher).newGraph(), - MachineModel(listOf(pu), listOf(memory)), + MachineModel(pu, memory), SimPsuFactories.simple(powerModel), ) @@ -108,7 +108,7 @@ public class SimTFDevice( output = stage.getOutlet("out") lastPull = ctx.graph.engine.clock.millis() - ctx.graph.connect(output, ctx.cpus[0].input) + ctx.graph.connect(output, ctx.cpu.input) } override fun onStop(ctx: SimMachineContext) { diff --git a/opendc-experiments/opendc-experiments-tf20/src/main/kotlin/org/opendc/experiments/tf20/util/MLEnvironmentReader.kt b/opendc-experiments/opendc-experiments-tf20/src/main/kotlin/org/opendc/experiments/tf20/util/MLEnvironmentReader.kt index 077bcc047..34b4bc7ba 100644 --- a/opendc-experiments/opendc-experiments-tf20/src/main/kotlin/org/opendc/experiments/tf20/util/MLEnvironmentReader.kt +++ b/opendc-experiments/opendc-experiments-tf20/src/main/kotlin/org/opendc/experiments/tf20/util/MLEnvironmentReader.kt @@ -25,10 +25,9 @@ package org.opendc.experiments.tf20.util import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper import com.fasterxml.jackson.module.kotlin.readValue +import org.opendc.simulator.compute.model.Cpu 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.CpuPowerModels import java.io.InputStream import java.util.UUID @@ -54,36 +53,50 @@ public class MLEnvironmentReader { var maxPower = 350.0 var minPower = 200.0 val cores = - machine.cpus.flatMap { id -> + machine.cpus.map { id -> when (id) { 1 -> { // ref: https://www.guru3d.com/articles-pages/nvidia-geforce-gtx-titan-x-review,8.html#:~:text=GeForce%20GTX%20Titan%20X%20%2D%20On,power%20supply%20unit%20as%20minimum. - maxPower = 334.0 - minPower = 90.0 - val node = ProcessingNode("NVidia", "TITAN X", "Pascal", 4992) - List(node.coreCount) { ProcessingUnit(node, it, 824.0) } + Cpu( + 0, + 4992, + 824.0, + "NVidia", + "TITAN X", + "Pascal", + ) } 2 -> { // ref: https://www.microway.com/hpc-tech-tips/nvidia-tesla-p100-pci-e-16gb-gpu-accelerator-pascal-gp100-close/ - maxPower = 250.0 - minPower = 125.0 - val node = ProcessingNode("NVIDIA", "Tesla P100", "Pascal", 3584) - List(node.coreCount) { ProcessingUnit(node, it, 1190.0) } + Cpu( + 0, + 3584, + 1190.0, + "NVIDIA", + "Tesla P100", + "Pascal", + ) } 3 -> { // ref: https://www.anandtech.com/show/10923/openpower-saga-tyans-1u-power8-gt75/7 - minPower = 84.0 - maxPower = 135.0 - val node = ProcessingNode("Intel", "E5-2690v3 Haswell24", "amd64", 24) - isGpuFlag = false - List(node.coreCount) { ProcessingUnit(node, it, 3498.0) } + Cpu( + 0, + 24, + 3498.0, + "Intel", + "E5-2690v3 Haswell24", + "amd64", + ) } 4 -> { - minPower = 130.0 - maxPower = 190.0 - val node = ProcessingNode("IBM", "POWER8", "RISC", 10) - isGpuFlag = false - List(node.coreCount) { ProcessingUnit(node, it, 143000.0) } // 28600.0 3690 + Cpu( + 0, + 10, + 143000.0, + "IBM", + "POWER8", + "RISC", + ) } else -> throw IllegalArgumentException("The cpu id $id is not recognized") } @@ -103,7 +116,7 @@ public class MLEnvironmentReader { UUID(0, counter.toLong()), "node-${counter++}", mapOf("gpu" to isGpuFlag), - MachineModel(cores, memories), + MachineModel(cores, memories[0]), CpuPowerModels.linear(maxPower, minPower), ) } diff --git a/opendc-experiments/opendc-experiments-tf20/src/test/kotlin/org/opendc/experiments/tf20/TensorFlowTest.kt b/opendc-experiments/opendc-experiments-tf20/src/test/kotlin/org/opendc/experiments/tf20/TensorFlowTest.kt index 28a77c2e3..447827e97 100644 --- a/opendc-experiments/opendc-experiments-tf20/src/test/kotlin/org/opendc/experiments/tf20/TensorFlowTest.kt +++ b/opendc-experiments/opendc-experiments-tf20/src/test/kotlin/org/opendc/experiments/tf20/TensorFlowTest.kt @@ -49,8 +49,8 @@ class TensorFlowTest { def.uid, def.meta["gpu"] as Boolean, dispatcher, - def.model.cpus[0], - def.model.memory[0], + def.model.cpu, + def.model.memory, CpuPowerModels.linear(250.0, 60.0), ) val strategy = OneDeviceStrategy(device) @@ -84,8 +84,8 @@ class TensorFlowTest { def.uid, def.meta["gpu"] as Boolean, dispatcher, - def.model.cpus[0], - def.model.memory[0], + def.model.cpu, + def.model.memory, CpuPowerModels.linear(250.0, 60.0), ) val strategy = OneDeviceStrategy(device) @@ -119,8 +119,8 @@ class TensorFlowTest { def.uid, def.meta["gpu"] as Boolean, dispatcher, - def.model.cpus[0], - def.model.memory[0], + def.model.cpu, + def.model.memory, CpuPowerModels.linear(250.0, 60.0), ) @@ -129,8 +129,8 @@ class TensorFlowTest { UUID.randomUUID(), def.meta["gpu"] as Boolean, dispatcher, - def.model.cpus[0], - def.model.memory[0], + def.model.cpu, + def.model.memory, CpuPowerModels.linear(250.0, 60.0), ) diff --git a/opendc-experiments/opendc-experiments-tf20/src/test/kotlin/org/opendc/experiments/tf20/core/SimTFDeviceTest.kt b/opendc-experiments/opendc-experiments-tf20/src/test/kotlin/org/opendc/experiments/tf20/core/SimTFDeviceTest.kt index 764738684..e0c4599ae 100644 --- a/opendc-experiments/opendc-experiments-tf20/src/test/kotlin/org/opendc/experiments/tf20/core/SimTFDeviceTest.kt +++ b/opendc-experiments/opendc-experiments-tf20/src/test/kotlin/org/opendc/experiments/tf20/core/SimTFDeviceTest.kt @@ -27,9 +27,8 @@ import kotlinx.coroutines.launch import org.junit.jupiter.api.Assertions.assertAll import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test +import org.opendc.simulator.compute.model.Cpu 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.CpuPowerModels import org.opendc.simulator.kotlin.runSimulation import java.util.UUID @@ -41,8 +40,7 @@ internal class SimTFDeviceTest { @Test fun testSmoke() = runSimulation { - val puNode = ProcessingNode("NVIDIA", "Tesla V100", "unknown", 1) - val pu = ProcessingUnit(puNode, 0, 960 * 1230.0) + val pu = Cpu(0, 1, 960 * 1230.0, "NVIDIA", "Tesla V100", "unknown") val memory = MemoryUnit("NVIDIA", "Tesla V100", 877.0, 32_000) val device = diff --git a/opendc-faas/opendc-faas-simulator/src/test/kotlin/org/opendc/faas/simulator/SimFaaSServiceTest.kt b/opendc-faas/opendc-faas-simulator/src/test/kotlin/org/opendc/faas/simulator/SimFaaSServiceTest.kt index f68860e36..2d6d4ac89 100644 --- a/opendc-faas/opendc-faas-simulator/src/test/kotlin/org/opendc/faas/simulator/SimFaaSServiceTest.kt +++ b/opendc-faas/opendc-faas-simulator/src/test/kotlin/org/opendc/faas/simulator/SimFaaSServiceTest.kt @@ -36,10 +36,9 @@ import org.opendc.faas.service.router.RandomRoutingPolicy import org.opendc.faas.simulator.delay.ColdStartModel import org.opendc.faas.simulator.delay.StochasticDelayInjector import org.opendc.faas.simulator.workload.SimFaaSWorkload +import org.opendc.simulator.compute.model.Cpu 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.workload.SimWorkload import org.opendc.simulator.compute.workload.SimWorkloads import org.opendc.simulator.kotlin.runSimulation @@ -54,12 +53,17 @@ internal class SimFaaSServiceTest { @BeforeEach fun setUp() { - val cpuNode = ProcessingNode("Intel", "Xeon", "amd64", 2) - machineModel = MachineModel( - List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 1000.0) }, - List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) }, + Cpu( + 0, + 2, + 1000.0, + "Intel", + "Xeon", + "amd64", + ), + MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000 * 4), ) } diff --git a/opendc-simulator/opendc-simulator-compute/src/jmh/kotlin/org/opendc/simulator/compute/SimMachineBenchmarks.kt b/opendc-simulator/opendc-simulator-compute/src/jmh/kotlin/org/opendc/simulator/compute/SimMachineBenchmarks.kt index 3707b6019..5975f9440 100644 --- a/opendc-simulator/opendc-simulator-compute/src/jmh/kotlin/org/opendc/simulator/compute/SimMachineBenchmarks.kt +++ b/opendc-simulator/opendc-simulator-compute/src/jmh/kotlin/org/opendc/simulator/compute/SimMachineBenchmarks.kt @@ -25,10 +25,10 @@ package org.opendc.simulator.compute import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.launch import org.opendc.simulator.compute.kernel.SimHypervisor +import org.opendc.simulator.compute.model.Cpu 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.workload.SimTrace import org.opendc.simulator.flow2.FlowEngine import org.opendc.simulator.flow2.mux.FlowMultiplexerFactory @@ -59,7 +59,13 @@ class SimMachineBenchmarks { machineModel = MachineModel( // cpus - List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 1000.0) }, + List(cpuNode.coreCount) { + Cpu( + cpuNode, + it, + 1000.0, + ) + }, // memory List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) }, ) diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimAbstractMachine.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimAbstractMachine.java index af56f2485..3a9e35c17 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimAbstractMachine.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimAbstractMachine.java @@ -23,7 +23,6 @@ package org.opendc.simulator.compute; import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.function.Consumer; import org.opendc.simulator.compute.device.SimNetworkAdapter; @@ -43,7 +42,7 @@ public abstract class SimAbstractMachine implements SimMachine { private final MachineModel model; - private Context activeContext; + private SimAbstractMachineContext activeContext; /** * Construct a {@link SimAbstractMachine} instance. @@ -66,40 +65,40 @@ public final SimMachineContext startWorkload( throw new IllegalStateException("A machine cannot run multiple workloads concurrently"); } - final Context ctx = createContext(workload, new HashMap<>(meta), completion); + final SimAbstractMachineContext ctx = createContext(workload, new HashMap<>(meta), completion); ctx.start(); return ctx; } @Override public final void cancel() { - final Context context = activeContext; + final SimAbstractMachineContext context = activeContext; if (context != null) { context.shutdown(); } } /** - * Construct a new {@link Context} instance representing the active execution. + * Construct a new {@link SimAbstractMachineContext} instance representing the active execution. * * @param workload The workload to start on the machine. * @param meta The metadata to pass to the workload. * @param completion A block that is invoked when the workload completes carrying an exception if thrown by the workload. */ - protected abstract Context createContext( + protected abstract SimAbstractMachineContext createContext( SimWorkload workload, Map meta, Consumer completion); /** - * Return the active {@link Context} instance (if any). + * Return the active {@link SimAbstractMachineContext} instance (if any). */ - protected Context getActiveContext() { + protected SimAbstractMachineContext getActiveContext() { return activeContext; } /** * The execution context in which the workload runs. */ - public abstract static class Context implements SimMachineContext { + public abstract static class SimAbstractMachineContext implements SimMachineContext { private final SimAbstractMachine machine; private final SimWorkload workload; private final Map meta; @@ -108,14 +107,14 @@ public abstract static class Context implements SimMachineContext { private SimWorkload snapshot; /** - * Construct a new {@link Context} instance. + * Construct a new {@link SimAbstractMachineContext} instance. * * @param machine The {@link SimAbstractMachine} to which the context belongs. * @param workload The {@link SimWorkload} to which the context belongs. * @param meta The metadata passed to the context. * @param completion A block that is invoked when the workload completes carrying an exception if thrown by the workload. */ - public Context( + public SimAbstractMachineContext( SimAbstractMachine machine, SimWorkload workload, Map meta, @@ -145,10 +144,8 @@ public SimWorkload getSnapshot(long now) { public void reset() { final FlowGraph graph = getMemory().getInput().getGraph(); - for (SimProcessingUnit cpu : getCpus()) { - final Inlet inlet = cpu.getInput(); - graph.disconnect(inlet); - } + final Inlet inlet = getCpu().getInput(); + graph.disconnect(inlet); graph.disconnect(getMemory().getInput()); @@ -225,16 +222,12 @@ public String toString() { */ public static final class Memory implements SimMemory { private final SimpleFlowSink sink; - private final List models; + private final MemoryUnit memoryUnit; - public Memory(FlowGraph graph, List models) { - long memorySize = 0; - for (MemoryUnit mem : models) { - memorySize += mem.getSize(); - } + public Memory(FlowGraph graph, MemoryUnit memoryUnit) { - this.sink = new SimpleFlowSink(graph, (float) memorySize); - this.models = models; + this.memoryUnit = memoryUnit; + this.sink = new SimpleFlowSink(graph, (float) memoryUnit.getSize()); } @Override @@ -243,8 +236,8 @@ public double getCapacity() { } @Override - public List getModels() { - return models; + public MemoryUnit getMemoryUnit() { + return memoryUnit; } @Override diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimBareMetalMachine.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimBareMetalMachine.java index 11356eb28..6acc605ef 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimBareMetalMachine.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimBareMetalMachine.java @@ -28,8 +28,8 @@ import java.util.Map; import java.util.function.Consumer; import org.opendc.simulator.compute.device.SimPeripheral; +import org.opendc.simulator.compute.model.Cpu; import org.opendc.simulator.compute.model.MachineModel; -import org.opendc.simulator.compute.model.ProcessingUnit; import org.opendc.simulator.compute.workload.SimWorkload; import org.opendc.simulator.flow2.FlowGraph; import org.opendc.simulator.flow2.InPort; @@ -56,7 +56,7 @@ public final class SimBareMetalMachine extends SimAbstractMachine { /** * The resources of this machine. */ - private final List cpus; + private final SimCpu cpu; private final Memory memory; private final List net; @@ -75,13 +75,7 @@ private SimBareMetalMachine(FlowGraph graph, MachineModel model, SimPsuFactory p this.graph = graph; this.psu = psuFactory.newPsu(this, graph); - int cpuIndex = 0; - final ArrayList cpus = new ArrayList<>(); - this.cpus = cpus; - for (ProcessingUnit cpu : model.getCpus()) { - cpus.add(new Cpu(psu, cpu, cpuIndex++)); - } - + this.cpu = new SimCpu(psu, model.getCpu(), 0); this.memory = new Memory(graph, model.getMemory()); int netIndex = 0; @@ -139,76 +133,58 @@ public List getPeripherals() { * Return the CPU capacity of the machine in MHz. */ public double getCpuCapacity() { - final Context context = (Context) getActiveContext(); + final SimAbstractMachineContext context = (SimAbstractMachineContext) getActiveContext(); if (context == null) { return 0.0; } - float capacity = 0.f; - - for (SimProcessingUnit cpu : context.cpus) { - capacity += cpu.getFrequency(); - } - - return capacity; + return cpu.getFrequency(); } /** * The CPU demand of the machine in MHz. */ public double getCpuDemand() { - final Context context = (Context) getActiveContext(); + final SimAbstractMachineContext context = (SimAbstractMachineContext) getActiveContext(); if (context == null) { return 0.0; } - float demand = 0.f; - - for (SimProcessingUnit cpu : context.cpus) { - demand += cpu.getDemand(); - } - - return demand; + return cpu.getDemand(); } /** * The CPU usage of the machine in MHz. */ public double getCpuUsage() { - final Context context = (Context) getActiveContext(); + final SimAbstractMachineContext context = (SimAbstractMachineContext) getActiveContext(); if (context == null) { return 0.0; } - float rate = 0.f; - - for (SimProcessingUnit cpu : context.cpus) { - rate += cpu.getSpeed(); - } - - return rate; + return cpu.getSpeed(); } @Override - protected SimAbstractMachine.Context createContext( + protected SimAbstractMachine.SimAbstractMachineContext createContext( SimWorkload workload, Map meta, Consumer completion) { - return new Context(this, workload, meta, completion); + return new SimAbstractMachineContext(this, workload, meta, completion); } /** * The execution context for a {@link SimBareMetalMachine}. */ - private static final class Context extends SimAbstractMachine.Context { + private static final class SimAbstractMachineContext extends SimAbstractMachine.SimAbstractMachineContext { private final FlowGraph graph; - private final List cpus; + private final SimCpu cpu; private final Memory memory; private final List net; private final List disk; - private Context( + private SimAbstractMachineContext( SimBareMetalMachine machine, SimWorkload workload, Map meta, @@ -216,7 +192,7 @@ private Context( super(machine, workload, meta, completion); this.graph = machine.graph; - this.cpus = machine.cpus; + this.cpu = machine.cpu; this.memory = machine.memory; this.net = machine.net; this.disk = machine.disk; @@ -228,8 +204,8 @@ public FlowGraph getGraph() { } @Override - public List getCpus() { - return cpus; + public SimCpu getCpu() { + return cpu; } @Override @@ -251,17 +227,17 @@ public List getStorageInterfaces() { /** * A {@link SimProcessingUnit} of a bare-metal machine. */ - private static final class Cpu implements SimProcessingUnit { + private static final class SimCpu implements SimProcessingUnit { private final SimPsu psu; - private final ProcessingUnit model; + private final Cpu cpuModel; private final InPort port; - private Cpu(SimPsu psu, ProcessingUnit model, int id) { + private SimCpu(SimPsu psu, Cpu cpuModel, int id) { this.psu = psu; - this.model = model; - this.port = psu.getCpuPower(id, model); + this.cpuModel = cpuModel; + this.port = psu.getCpuPower(id, cpuModel); - this.port.pull((float) model.getFrequency()); + this.port.pull((float) cpuModel.getTotalCapacity()); } @Override @@ -272,7 +248,7 @@ public double getFrequency() { @Override public void setFrequency(double frequency) { // Clamp the capacity of the CPU between [0.0, maxFreq] - frequency = Math.max(0, Math.min(model.getFrequency(), frequency)); + frequency = Math.max(0, Math.min(cpuModel.getTotalCapacity(), frequency)); psu.setCpuFrequency(port, frequency); } @@ -287,8 +263,8 @@ public double getSpeed() { } @Override - public ProcessingUnit getModel() { - return model; + public org.opendc.simulator.compute.model.Cpu getCpuModel() { + return cpuModel; } @Override @@ -298,7 +274,7 @@ public Inlet getInput() { @Override public String toString() { - return "SimBareMetalMachine.Cpu[model=" + model + "]"; + return "SimBareMetalMachine.Cpu[model=" + cpuModel + "]"; } } } diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimMachineContext.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimMachineContext.java index 7f98dee5b..887967fb4 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimMachineContext.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimMachineContext.java @@ -51,7 +51,7 @@ public interface SimMachineContext { /** * Return the CPUs available on the machine. */ - List getCpus(); + SimProcessingUnit getCpu(); /** * Return the memory interface of the machine. diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimMemory.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimMemory.java index 4fcc64ab2..85027f284 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimMemory.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimMemory.java @@ -22,7 +22,6 @@ package org.opendc.simulator.compute; -import java.util.List; import org.opendc.simulator.compute.model.MemoryUnit; import org.opendc.simulator.flow2.sink.FlowSink; @@ -38,5 +37,5 @@ public interface SimMemory extends FlowSink { /** * Return the models representing the static information of the memory units supporting this interface. */ - List getModels(); + MemoryUnit getMemoryUnit(); } diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimProcessingUnit.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimProcessingUnit.java index 3dbd3656a..213c3d4f6 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimProcessingUnit.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimProcessingUnit.java @@ -22,7 +22,7 @@ package org.opendc.simulator.compute; -import org.opendc.simulator.compute.model.ProcessingUnit; +import org.opendc.simulator.compute.model.Cpu; import org.opendc.simulator.flow2.sink.FlowSink; /** @@ -58,5 +58,5 @@ public interface SimProcessingUnit extends FlowSink { /** * The model representing the static properties of the processing unit. */ - ProcessingUnit getModel(); + Cpu getCpuModel(); } diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsu.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsu.java index 68dae4bfe..e77186041 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsu.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsu.java @@ -22,7 +22,7 @@ package org.opendc.simulator.compute; -import org.opendc.simulator.compute.model.ProcessingUnit; +import org.opendc.simulator.compute.model.Cpu; import org.opendc.simulator.flow2.InPort; import org.opendc.simulator.power.SimPowerInlet; @@ -57,7 +57,7 @@ public abstract class SimPsu extends SimPowerInlet { * @param id The unique identifier of the CPU for this machine. * @param model The details of the processing unit. */ - abstract InPort getCpuPower(int id, ProcessingUnit model); + abstract InPort getCpuPower(int id, Cpu model); /** * This method is invoked when the CPU frequency is changed for the specified port. diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsuFactories.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsuFactories.java index 5b1184292..273276162 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsuFactories.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsuFactories.java @@ -24,7 +24,7 @@ import java.time.InstantSource; import org.jetbrains.annotations.NotNull; -import org.opendc.simulator.compute.model.ProcessingUnit; +import org.opendc.simulator.compute.model.Cpu; import org.opendc.simulator.compute.power.CpuPowerModel; import org.opendc.simulator.flow2.FlowGraph; import org.opendc.simulator.flow2.FlowStage; @@ -92,7 +92,7 @@ public double getEnergyUsage() { } @Override - InPort getCpuPower(int id, ProcessingUnit model) { + InPort getCpuPower(int id, Cpu model) { final InPort port = stage.getInlet("cpu" + id); port.setMask(true); return port; @@ -165,8 +165,8 @@ public double getEnergyUsage() { } @Override - InPort getCpuPower(int id, ProcessingUnit model) { - targetFreq += model.getFrequency(); + InPort getCpuPower(int id, Cpu model) { + targetFreq += model.getTotalCapacity(); final InPort port = stage.getInlet("cpu" + id); port.setHandler(handler); diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/kernel/SimHypervisor.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/kernel/SimHypervisor.java index aced54a7f..42750b0fc 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/kernel/SimHypervisor.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/kernel/SimHypervisor.java @@ -29,7 +29,6 @@ import java.util.Map; import java.util.SplittableRandom; import java.util.function.Consumer; -import java.util.stream.Collectors; import org.opendc.simulator.compute.SimAbstractMachine; import org.opendc.simulator.compute.SimMachine; import org.opendc.simulator.compute.SimMachineContext; @@ -44,8 +43,8 @@ import org.opendc.simulator.compute.kernel.interference.VmInterferenceDomain; import org.opendc.simulator.compute.kernel.interference.VmInterferenceMember; import org.opendc.simulator.compute.kernel.interference.VmInterferenceProfile; +import org.opendc.simulator.compute.model.Cpu; import org.opendc.simulator.compute.model.MachineModel; -import org.opendc.simulator.compute.model.ProcessingUnit; import org.opendc.simulator.compute.workload.SimWorkload; import org.opendc.simulator.flow2.FlowGraph; import org.opendc.simulator.flow2.FlowStage; @@ -68,8 +67,8 @@ public final class SimHypervisor implements SimWorkload { private final ScalingGovernorFactory scalingGovernorFactory; private final VmInterferenceDomain interferenceDomain; - private Context activeContext; - private final ArrayList vms = new ArrayList<>(); + private SimHyperVisorContext activeContext; + private final ArrayList vms = new ArrayList<>(); private final HvCounters counters = new HvCounters(); @Override @@ -156,7 +155,7 @@ public SimVirtualMachine newMachine(MachineModel model) { throw new IllegalArgumentException("Machine does not fit"); } - VirtualMachine vm = new VirtualMachine(model); + SimVirtualMachine vm = new SimVirtualMachine(model); vms.add(vm); return vm; } @@ -169,7 +168,7 @@ public SimVirtualMachine newMachine(MachineModel model) { public void removeMachine(SimVirtualMachine machine) { if (vms.remove(machine)) { // This cast must always succeed, since `_vms` only contains `VirtualMachine` types. - ((VirtualMachine) machine).close(); + ((SimVirtualMachine) machine).close(); } } @@ -177,7 +176,7 @@ public void removeMachine(SimVirtualMachine machine) { * Return the CPU capacity of the hypervisor in MHz. */ public double getCpuCapacity() { - final Context context = activeContext; + final SimHyperVisorContext context = activeContext; if (context == null) { return 0.0; @@ -190,7 +189,7 @@ public double getCpuCapacity() { * The CPU demand of the hypervisor in MHz. */ public double getCpuDemand() { - final Context context = activeContext; + final SimHyperVisorContext context = activeContext; if (context == null) { return 0.0; @@ -203,7 +202,7 @@ public double getCpuDemand() { * The CPU usage of the hypervisor in MHz. */ public double getCpuUsage() { - final Context context = activeContext; + final SimHyperVisorContext context = activeContext; if (context == null) { return 0.0; @@ -217,26 +216,26 @@ public double getCpuUsage() { * moment. */ public boolean canFit(MachineModel model) { - final Context context = activeContext; + final SimHyperVisorContext context = activeContext; if (context == null) { return false; } final FlowMultiplexer multiplexer = context.multiplexer; - return (multiplexer.getMaxInputs() - multiplexer.getInputCount()) - >= model.getCpus().size(); + return (multiplexer.getMaxInputs() - multiplexer.getInputCount()) >= 1; } @Override public void onStart(SimMachineContext ctx) { - final Context context = new Context(ctx, muxFactory, scalingGovernorFactory, counters); + final SimHyperVisorContext context = + new SimHyperVisorContext(ctx, muxFactory, scalingGovernorFactory, counters); context.start(); activeContext = context; } @Override public void onStop(SimMachineContext ctx) { - final Context context = activeContext; + final SimHyperVisorContext context = activeContext; if (context != null) { activeContext = null; context.stop(); @@ -276,11 +275,11 @@ public double getCheckpointIntervalScaling() { /** * The context which carries the state when the hypervisor is running on a machine. */ - private static final class Context implements FlowStageLogic { + private static final class SimHyperVisorContext implements FlowStageLogic { private final SimMachineContext ctx; private final FlowMultiplexer multiplexer; private final FlowStage stage; - private final List scalingGovernors; + private final ScalingGovernor scalingGovernor; private final InstantSource clock; private final HvCounters counters; @@ -290,7 +289,7 @@ private static final class Context implements FlowStageLogic { private float previousRate; private float previousCapacity; - private Context( + private SimHyperVisorContext( SimMachineContext ctx, FlowMultiplexerFactory muxFactory, ScalingGovernorFactory scalingGovernorFactory, @@ -306,20 +305,15 @@ private Context( this.lastCounterUpdate = clock.millis(); + final SimProcessingUnit cpu = ctx.getCpu(); + if (scalingGovernorFactory != null) { - this.scalingGovernors = ctx.getCpus().stream() - .map(cpu -> scalingGovernorFactory.newGovernor(new ScalingPolicyImpl(cpu))) - .collect(Collectors.toList()); + this.scalingGovernor = scalingGovernorFactory.newGovernor(new ScalingPolicyImpl(cpu)); } else { - this.scalingGovernors = Collections.emptyList(); + this.scalingGovernor = null; } - float cpuCapacity = 0.f; - final List cpus = ctx.getCpus(); - for (SimProcessingUnit cpu : cpus) { - cpuCapacity += cpu.getFrequency(); - } - this.d = cpus.size() / cpuCapacity; + this.d = 1 / cpu.getFrequency(); } /** @@ -329,12 +323,10 @@ void start() { final FlowGraph graph = ctx.getGraph(); final FlowMultiplexer multiplexer = this.multiplexer; - for (SimProcessingUnit cpu : ctx.getCpus()) { - graph.connect(multiplexer.newOutput(), cpu.getInput()); - } + graph.connect(multiplexer.newOutput(), ctx.getCpu().getInput()); - for (ScalingGovernor governor : scalingGovernors) { - governor.onStart(); + if (this.scalingGovernor != null) { + this.scalingGovernor.onStart(); } } @@ -392,7 +384,7 @@ public long onUpdate(FlowStage ctx, long now) { updateCounters(now); final FlowMultiplexer multiplexer = this.multiplexer; - final List scalingGovernors = this.scalingGovernors; + final ScalingGovernor scalingGovernors = this.scalingGovernor; float demand = multiplexer.getDemand(); float rate = multiplexer.getRate(); @@ -404,10 +396,8 @@ public long onUpdate(FlowStage ctx, long now) { double load = rate / Math.min(1.0, capacity); - if (!scalingGovernors.isEmpty()) { - for (ScalingGovernor governor : scalingGovernors) { - governor.onLimit(load); - } + if (scalingGovernor != null) { + scalingGovernor.onLimit(load); } return Long.MAX_VALUE; @@ -446,27 +436,25 @@ public double getMin() { @Override public double getMax() { - return cpu.getModel().getFrequency(); + return cpu.getCpuModel().getTotalCapacity(); } } /** * A virtual machine running on the hypervisor. */ - private class VirtualMachine extends SimAbstractMachine implements SimVirtualMachine { + public class SimVirtualMachine extends SimAbstractMachine { private boolean isClosed; private final VmCounters counters = new VmCounters(this); - private VirtualMachine(MachineModel model) { + private SimVirtualMachine(MachineModel model) { super(model); } - @Override public SimHypervisorCounters getCounters() { return counters; } - @Override public double getCpuDemand() { final VmContext context = (VmContext) getActiveContext(); @@ -477,7 +465,6 @@ public double getCpuDemand() { return context.previousDemand; } - @Override public double getCpuUsage() { final VmContext context = (VmContext) getActiveContext(); @@ -488,7 +475,6 @@ public double getCpuUsage() { return context.usage; } - @Override public double getCpuCapacity() { final VmContext context = (VmContext) getActiveContext(); @@ -505,13 +491,13 @@ public List getPeripherals() { } @Override - protected Context createContext( + protected SimAbstractMachineContext createContext( SimWorkload workload, Map meta, Consumer completion) { if (isClosed) { throw new IllegalStateException("Virtual machine does not exist anymore"); } - final SimHypervisor.Context context = activeContext; + final SimHyperVisorContext context = activeContext; if (context == null) { throw new IllegalStateException("Hypervisor is inactive"); } @@ -529,7 +515,7 @@ protected Context createContext( } @Override - public Context getActiveContext() { + public SimAbstractMachineContext getActiveContext() { return super.getActiveContext(); } @@ -544,10 +530,11 @@ void close() { } /** - * A {@link SimAbstractMachine.Context} for a virtual machine instance. + * A {@link SimAbstractMachine.SimAbstractMachineContext} for a virtual machine instance. */ - private static final class VmContext extends SimAbstractMachine.Context implements FlowStageLogic { - private final Context context; + private static final class VmContext extends SimAbstractMachine.SimAbstractMachineContext + implements FlowStageLogic { + private final SimHyperVisorContext simHyperVisorContext; private final SplittableRandom random; private final VmCounters vmCounters; private final HvCounters hvCounters; @@ -556,7 +543,7 @@ private static final class VmContext extends SimAbstractMachine.Context implemen private final FlowMultiplexer multiplexer; private final InstantSource clock; - private final List cpus; + private final VCpu cpu; private final SimAbstractMachine.Memory memory; private final List net; private final List disk; @@ -574,8 +561,8 @@ private static final class VmContext extends SimAbstractMachine.Context implemen private float previousCapacity; private VmContext( - Context context, - VirtualMachine machine, + SimHyperVisorContext simHyperVisorContext, + SimVirtualMachine machine, SplittableRandom random, VmInterferenceDomain interferenceDomain, VmCounters vmCounters, @@ -585,11 +572,11 @@ private VmContext( Consumer completion) { super(machine, workload, meta, completion); - this.context = context; + this.simHyperVisorContext = simHyperVisorContext; this.random = random; this.vmCounters = vmCounters; this.hvCounters = hvCounters; - this.clock = context.clock; + this.clock = simHyperVisorContext.clock; final VmInterferenceProfile interferenceProfile = (VmInterferenceProfile) meta.get("interference-profile"); VmInterferenceMember interferenceMember = null; @@ -599,45 +586,36 @@ private VmContext( } this.interferenceMember = interferenceMember; - final FlowGraph graph = context.ctx.getGraph(); + final FlowGraph graph = simHyperVisorContext.ctx.getGraph(); final FlowStage stage = graph.newStage(this); this.stage = stage; this.lastUpdate = clock.millis(); this.lastCounterUpdate = clock.millis(); - final FlowMultiplexer multiplexer = context.multiplexer; + final FlowMultiplexer multiplexer = simHyperVisorContext.multiplexer; this.multiplexer = multiplexer; final MachineModel model = machine.getModel(); - final List cpuModels = model.getCpus(); - final Inlet[] muxInlets = new Inlet[cpuModels.size()]; - final ArrayList cpus = new ArrayList<>(); + final Cpu cpuModel = model.getCpu(); + final Inlet[] muxInlets = new Inlet[1]; this.muxInlets = muxInlets; - this.cpus = cpus; - - float capacity = 0.f; - for (int i = 0; i < cpuModels.size(); i++) { - final Inlet muxInlet = multiplexer.newInput(); - muxInlets[i] = muxInlet; + final Inlet muxInlet = multiplexer.newInput(); + muxInlets[0] = muxInlet; - final InPort input = stage.getInlet("cpu" + i); - final OutPort output = stage.getOutlet("mux" + i); + final InPort input = stage.getInlet("cpu"); + final OutPort output = stage.getOutlet("mux"); - final Handler handler = new Handler(this, input, output); - input.setHandler(handler); - output.setHandler(handler); + final Handler handler = new Handler(this, input, output); + input.setHandler(handler); + output.setHandler(handler); - final ProcessingUnit cpuModel = cpuModels.get(i); - capacity += cpuModel.getFrequency(); + this.cpu = new VCpu(cpuModel, input); - final VCpu cpu = new VCpu(cpuModel, input); - cpus.add(cpu); + graph.connect(output, muxInlet); - graph.connect(output, muxInlet); - } - this.d = cpuModels.size() / capacity; + this.d = 1 / cpuModel.getTotalCapacity(); this.memory = new SimAbstractMachine.Memory(graph, model.getMemory()); @@ -664,7 +642,7 @@ private VmContext( void updateCounters(long now) { long lastUpdate = this.lastCounterUpdate; this.lastCounterUpdate = now; - long delta = now - lastUpdate; + long delta = now - lastUpdate; // time between updates if (delta > 0) { final VmCounters counters = this.vmCounters; @@ -673,7 +651,7 @@ void updateCounters(long now) { float rate = this.usage; float capacity = this.previousCapacity; - final double factor = this.d * delta; + final double factor = this.d * delta; // time between divided by total capacity final double active = rate * factor; counters.cpuActiveTime += Math.round(active); @@ -695,8 +673,8 @@ public FlowGraph getGraph() { } @Override - public List getCpus() { - return cpus; + public SimProcessingUnit getCpu() { + return cpu; } @Override @@ -746,7 +724,7 @@ public long onUpdate(FlowStage ctx, long now) { } // Invalidate the FlowStage of the hypervisor to update its counters (via onUpdate) - context.invalidate(); + simHyperVisorContext.invalidate(); return Long.MAX_VALUE; } @@ -776,14 +754,14 @@ protected void doCancel() { * A {@link SimProcessingUnit} of a virtual machine. */ private static final class VCpu implements SimProcessingUnit { - private final ProcessingUnit model; + private final Cpu model; private final InPort input; - private VCpu(ProcessingUnit model, InPort input) { + private VCpu(Cpu model, InPort input) { this.model = model; this.input = input; - input.pull((float) model.getFrequency()); + input.pull((float) model.getTotalCapacity()); } @Override @@ -807,7 +785,7 @@ public double getSpeed() { } @Override - public ProcessingUnit getModel() { + public Cpu getCpuModel() { return model; } @@ -901,7 +879,7 @@ public long getCpuLostTime() { @Override public void sync() { - final Context context = activeContext; + final SimHyperVisorContext context = activeContext; if (context != null) { context.updateCounters(); @@ -913,13 +891,13 @@ public void sync() { * Implementation of {@link SimHypervisorCounters} for the virtual machine. */ private static class VmCounters implements SimHypervisorCounters { - private final VirtualMachine vm; + private final SimVirtualMachine vm; private long cpuActiveTime; private long cpuIdleTime; private long cpuStealTime; private long cpuLostTime; - private VmCounters(VirtualMachine vm) { + private VmCounters(SimVirtualMachine vm) { this.vm = vm; } diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/kernel/SimVirtualMachine.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/kernel/SimVirtualMachine.java deleted file mode 100644 index fdf5e47f2..000000000 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/kernel/SimVirtualMachine.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2022 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.kernel; - -import org.opendc.simulator.compute.SimMachine; - -/** - * A virtual {@link SimMachine} running on top of another {@link SimMachine}. - */ -public interface SimVirtualMachine extends SimMachine { - /** - * Return the performance counters associated with the virtual machine. - */ - SimHypervisorCounters getCounters(); - - /** - * Return the CPU usage of the VM in MHz. - */ - double getCpuUsage(); - - /** - * Return the CPU usage of the VM in MHz. - */ - double getCpuDemand(); - - /** - * Return the CPU capacity of the VM in MHz. - */ - double getCpuCapacity(); -} diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/model/Cpu.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/model/Cpu.java new file mode 100644 index 000000000..c319ae1ac --- /dev/null +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/model/Cpu.java @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2022 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.model; + +import java.util.Objects; + +/** + * A single logical compute unit of processor node, either virtual or physical. + */ +public final class Cpu { + private final int id; + private final int coreCount; + private final double coreSpeed; + private final double totalCapacity; + + private final String vendor; + private final String modelName; + private final String arch; + + /** + * Construct a {@link Cpu} instance. + * + * @param id The identifier of the CPU core within the processing node. + * @param coreCount The number of cores present in the CPU + * @param coreSpeed The speed of a single core + * @param vendor The vendor of the CPU + * @param modelName The name of the CPU + * @param arch The architecture of the CPU + */ + public Cpu(int id, int coreCount, double coreSpeed, String vendor, String modelName, String arch) { + this.id = id; + this.coreCount = coreCount; + this.coreSpeed = coreSpeed; + this.totalCapacity = coreSpeed * coreCount; + this.vendor = vendor; + this.modelName = modelName; + this.arch = arch; + } + + public Cpu(int id, int coreCount, double coreSpeed) { + this(id, coreCount, coreSpeed, "unkown", "unkown", "unkown"); + } + + /** + * Return the identifier of the CPU core within the processing node. + */ + public int getId() { + return id; + } + + /** + * Return the number of logical CPUs in the processor node. + */ + public int getCoreCount() { + return coreCount; + } + + /** + * Return the clock rate of a single core of the CPU MHz. + */ + public double getCoreSpeed() { + return coreSpeed; + } + + /** + * Return the clock rate of the CPU in MHz. + */ + public double getTotalCapacity() { + return totalCapacity; + } + + /** + * Return the vendor of the storage device. + */ + public String getVendor() { + return vendor; + } + + /** + * Return the model name of the device. + */ + public String getModelName() { + return modelName; + } + + /** + * Return the micro-architecture of the processor node. + */ + public String getArchitecture() { + return arch; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Cpu that = (Cpu) o; + return id == that.id + && Double.compare(that.totalCapacity, totalCapacity) == 0 + && Double.compare(that.coreSpeed, coreSpeed) == 0 + && Objects.equals(vendor, that.vendor) + && Objects.equals(modelName, that.modelName) + && Objects.equals(arch, that.arch); + } + + @Override + public int hashCode() { + return Objects.hash(id, coreCount, coreSpeed, totalCapacity, vendor, modelName, arch); + } + + @Override + public String toString() { + return "ProcessingUnit[" + "id= " + id + ", coreCount= " + coreCount + ", coreSpeed= " + coreSpeed + + ", frequency= " + totalCapacity + ", vendor= " + vendor + ", modelName= " + modelName + ", arch= " + + arch + "]"; + } +} diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/model/MachineModel.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/model/MachineModel.java index 2c625fce9..e4019dacb 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/model/MachineModel.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/model/MachineModel.java @@ -31,29 +31,23 @@ * A description of the physical or virtual machine on which a bootable image runs. */ public final class MachineModel { - private final List cpus; - private final List memory; + private final Cpu cpu; + private final MemoryUnit memory; private final List net; private final List storage; /** * Construct a {@link MachineModel} instance. * - * @param cpus The list of processing units available to the image. + * @param cpu The cpu available to the image. * @param memory The list of memory units available to the image. * @param net A list of network adapters available to the machine. * @param storage A list of storage devices available to the machine. */ - public MachineModel( - Iterable cpus, - Iterable memory, - Iterable net, - Iterable storage) { - this.cpus = new ArrayList<>(); - cpus.forEach(this.cpus::add); + public MachineModel(Cpu cpu, MemoryUnit memory, Iterable net, Iterable storage) { + this.cpu = cpu; - this.memory = new ArrayList<>(); - memory.forEach(this.memory::add); + this.memory = memory; this.net = new ArrayList<>(); net.forEach(this.net::add); @@ -62,54 +56,50 @@ public MachineModel( storage.forEach(this.storage::add); } + public MachineModel(Cpu cpu, MemoryUnit memory) { + this(cpu, memory, Collections.emptyList(), Collections.emptyList()); + } + /** * Construct a {@link MachineModel} instance. + * A list of the same cpus, are automatically converted to a single CPU with the number of cores of + * all cpus in the list combined. * * @param cpus The list of processing units available to the image. * @param memory The list of memory units available to the image. */ - public MachineModel(Iterable cpus, Iterable memory) { - this(cpus, memory, Collections.emptyList(), Collections.emptyList()); + public MachineModel( + List cpus, MemoryUnit memory, Iterable net, Iterable storage) { + + this( + new Cpu( + cpus.get(0).getId(), + cpus.get(0).getCoreCount() * cpus.size(), + cpus.get(0).getCoreSpeed(), + cpus.get(0).getVendor(), + cpus.get(0).getModelName(), + cpus.get(0).getArchitecture()), + memory, + net, + storage); } - /** - * 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 MachineModel optimize() { - ProcessingUnit originalCpu = cpus.get(0); - - double freq = 0.0; - for (ProcessingUnit cpu : cpus) { - freq += cpu.getFrequency(); - } - - ProcessingNode originalNode = originalCpu.getNode(); - ProcessingNode processingNode = new ProcessingNode( - originalNode.getVendor(), originalNode.getModelName(), originalNode.getArchitecture(), 1); - ProcessingUnit processingUnit = new ProcessingUnit(processingNode, originalCpu.getId(), freq); - - long memorySize = 0; - for (MemoryUnit mem : memory) { - memorySize += mem.getSize(); - } - MemoryUnit memoryUnit = new MemoryUnit("Generic", "Generic", 3200.0, memorySize); - - return new MachineModel(List.of(processingUnit), List.of(memoryUnit)); + public MachineModel(List cpus, MemoryUnit memory) { + this(cpus, memory, Collections.emptyList(), Collections.emptyList()); } /** * Return the processing units of this machine. */ - public List getCpus() { - return Collections.unmodifiableList(cpus); + public Cpu getCpu() { + return this.cpu; } /** * Return the memory units of this machine. */ - public List getMemory() { - return Collections.unmodifiableList(memory); + public MemoryUnit getMemory() { + return memory; } /** @@ -131,7 +121,7 @@ public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; MachineModel that = (MachineModel) o; - return cpus.equals(that.cpus) + return cpu.equals(that.cpu) && memory.equals(that.memory) && net.equals(that.net) && storage.equals(that.storage); @@ -139,11 +129,11 @@ public boolean equals(Object o) { @Override public int hashCode() { - return Objects.hash(cpus, memory, net, storage); + return Objects.hash(cpu, memory, net, storage); } @Override public String toString() { - return "MachineModel[cpus=" + cpus + ",memory=" + memory + ",net=" + net + ",storage=" + storage + "]"; + return "MachineModel[cpus=" + cpu + ",memory=" + memory + ",net=" + net + ",storage=" + storage + "]"; } } diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/model/ProcessingUnit.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/model/ProcessingUnit.java deleted file mode 100644 index 0bead16a7..000000000 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/model/ProcessingUnit.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2022 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.model; - -import java.util.Objects; - -/** - * A single logical compute unit of processor node, either virtual or physical. - */ -public final class ProcessingUnit { - private final ProcessingNode node; - private final int id; - private final double frequency; - - /** - * Construct a {@link ProcessingUnit} instance. - * - * @param node The processing node containing the CPU core. - * @param id The identifier of the CPU core within the processing node. - * @param frequency The clock rate of the CPU in MHz. - */ - public ProcessingUnit(ProcessingNode node, int id, double frequency) { - this.node = node; - this.id = id; - this.frequency = frequency * node.getCoreCount(); - } - - /** - * Return the processing node containing the CPU core. - */ - public ProcessingNode getNode() { - return node; - } - - /** - * Return the identifier of the CPU core within the processing node. - */ - public int getId() { - return id; - } - - /** - * Return the clock rate of the CPU in MHz. - */ - public double getFrequency() { - return frequency; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - ProcessingUnit that = (ProcessingUnit) o; - return id == that.id && Double.compare(that.frequency, frequency) == 0 && Objects.equals(node, that.node); - } - - @Override - public int hashCode() { - return Objects.hash(node, id, frequency); - } - - @Override - public String toString() { - return "ProcessingUnit[node=" + node + ",id=" + id + ",frequency=" + frequency + "]"; - } -} diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimChainWorkload.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimChainWorkload.java index edf201a7c..1dcb3674b 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimChainWorkload.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimChainWorkload.java @@ -41,7 +41,7 @@ final class SimChainWorkload implements SimWorkload { private final SimWorkload[] workloads; private int activeWorkloadIndex; - private Context activeContext; + private SimChainWorkloadContext activeContext; private long checkpointInterval = 0; private long checkpointDuration = 0; @@ -108,7 +108,7 @@ public void onStart(SimMachineContext ctx) { return; } - final Context context = new Context(ctx); + final SimChainWorkloadContext context = new SimChainWorkloadContext(ctx); activeContext = context; if (checkpointInterval > 0) { @@ -128,7 +128,7 @@ public void onStop(SimMachineContext ctx) { return; } - final Context context = activeContext; + final SimChainWorkloadContext context = activeContext; activeContext = null; if (this.checkpointModel != null) { @@ -174,7 +174,7 @@ private class CheckPointModel implements FlowStageLogic { private Boolean firstCheckPoint = true; CheckPointModel( - Context context, + SimChainWorkloadContext context, SimChainWorkload workload, long checkpointInterval, long checkpointDuration, @@ -228,11 +228,11 @@ public void stop() { /** * A {@link SimMachineContext} that intercepts the shutdown calls. */ - private class Context implements SimMachineContext { + private class SimChainWorkloadContext implements SimMachineContext { private final SimMachineContext ctx; private SimWorkload snapshot; - private Context(SimMachineContext ctx) { + private SimChainWorkloadContext(SimMachineContext ctx) { this.ctx = ctx; } @@ -247,8 +247,8 @@ public Map getMeta() { } @Override - public List getCpus() { - return ctx.getCpus(); + public SimProcessingUnit getCpu() { + return ctx.getCpu(); } @Override diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimFlopsWorkload.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimFlopsWorkload.java index 06fcb2bc3..5311fa380 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimFlopsWorkload.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimFlopsWorkload.java @@ -22,7 +22,6 @@ package org.opendc.simulator.compute.workload; -import java.util.List; import org.opendc.simulator.compute.SimMachineContext; import org.opendc.simulator.compute.SimProcessingUnit; import org.opendc.simulator.flow2.FlowGraph; @@ -92,17 +91,14 @@ public void onStart(SimMachineContext ctx) { final FlowStage stage = graph.newStage(this); this.stage = stage; - final List cpus = ctx.getCpus(); - final OutPort[] outputs = new OutPort[cpus.size()]; + final SimProcessingUnit cpu = ctx.getCpu(); + final OutPort[] outputs = new OutPort[1]; this.outputs = outputs; - for (int i = 0; i < cpus.size(); i++) { - final SimProcessingUnit cpu = cpus.get(i); - final OutPort output = stage.getOutlet("cpu" + i); + final OutPort output = stage.getOutlet("cpu"); - graph.connect(output, cpu.getInput()); - outputs[i] = output; - } + graph.connect(output, cpu.getInput()); + outputs[0] = output; this.remainingAmount = flops; this.lastUpdate = graph.getEngine().getClock().millis(); diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimRuntimeWorkload.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimRuntimeWorkload.java index 64b1a10ba..be4cc2f56 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimRuntimeWorkload.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimRuntimeWorkload.java @@ -22,7 +22,6 @@ package org.opendc.simulator.compute.workload; -import java.util.List; import org.opendc.simulator.compute.SimMachineContext; import org.opendc.simulator.compute.SimProcessingUnit; import org.opendc.simulator.flow2.FlowGraph; @@ -122,17 +121,14 @@ public void onStart(SimMachineContext ctx) { final FlowStage stage = graph.newStage(this); this.stage = stage; - final List cpus = ctx.getCpus(); - final OutPort[] outputs = new OutPort[cpus.size()]; + final OutPort[] outputs = new OutPort[1]; this.outputs = outputs; - for (int i = 0; i < cpus.size(); i++) { - final SimProcessingUnit cpu = cpus.get(i); - final OutPort output = stage.getOutlet("cpu" + i); + final SimProcessingUnit cpu = ctx.getCpu(); + final OutPort output = stage.getOutlet("cpu"); - graph.connect(output, cpu.getInput()); - outputs[i] = output; - } + graph.connect(output, cpu.getInput()); + outputs[0] = output; this.remainingDuration = duration; this.lastUpdate = graph.getEngine().getClock().millis(); diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimTrace.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimTrace.java index 384907b25..b8445a9c3 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimTrace.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/workload/SimTrace.java @@ -210,11 +210,7 @@ public void setOffset(long now) { @Override public void onStart(SimMachineContext ctx) { final WorkloadStageLogic logic; - if (ctx.getCpus().size() == 1) { - logic = new SingleWorkloadLogic(ctx, offset, fragments.iterator()); - } else { - logic = new MultiWorkloadLogic(ctx, offset, fragments.iterator()); - } + logic = new SingleWorkloadLogic(ctx, offset, fragments.iterator()); this.logic = logic; } @@ -325,11 +321,9 @@ private SingleWorkloadLogic(SimMachineContext ctx, long offset, Iterator cpus = ctx.getCpus(); - stage = graph.newStage(this); - final SimProcessingUnit cpu = cpus.get(0); + final SimProcessingUnit cpu = ctx.getCpu(); final OutPort output = stage.getOutlet("cpu"); this.output = output; @@ -416,149 +410,4 @@ private long doStop(FlowStage ctx) { return Long.MAX_VALUE; } } - - /** - * Implementation of {@link FlowStageLogic} for multiple CPUs. - */ - private static class MultiWorkloadLogic implements WorkloadStageLogic { - private final FlowStage stage; - private final OutPort[] outputs; - private int index = 0; - - private final int coreCount; - - private Iterator fragments; - private SimTraceFragment currentFragment; - private long startOffFragment; - - private final SimMachineContext ctx; - - private MultiWorkloadLogic(SimMachineContext ctx, long offset, Iterator fragments) { - this.ctx = ctx; - this.fragments = fragments; - - final FlowGraph graph = ctx.getGraph(); - final List cpus = ctx.getCpus(); - - stage = graph.newStage(this); - this.coreCount = cpus.size(); - - final OutPort[] outputs = new OutPort[cpus.size()]; - this.outputs = outputs; - - for (int i = 0; i < cpus.size(); i++) { - final SimProcessingUnit cpu = cpus.get(i); - final OutPort output = stage.getOutlet("cpu" + i); - - graph.connect(output, cpu.getInput()); - outputs[i] = output; - } - - this.currentFragment = this.fragments.next(); - - int cores = Math.min(this.coreCount, currentFragment.coreCount()); - float usage = (float) currentFragment.cpuUsage() / cores; - - // Push the usage to all active cores - for (int i = 0; i < cores; i++) { - outputs[i].push(usage); - } - - // Push a usage of 0 to all non-active cores - for (int i = cores; i < outputs.length; i++) { - outputs[i].push(0.f); - } - - this.startOffFragment = offset; - } - - public long getPassedTime(long now) { - return now - this.startOffFragment; - } - - @Override - public void updateFragments(Iterator newFragments, long offset) { - this.fragments = newFragments; - - // Start the first Fragment - this.currentFragment = this.fragments.next(); - int cores = Math.min(this.coreCount, currentFragment.coreCount()); - float usage = (float) currentFragment.cpuUsage() / cores; - - // Push the usage to all active cores - for (int i = 0; i < cores; i++) { - outputs[i].push(usage); - } - - // Push a usage of 0 to all non-active cores - for (int i = cores; i < outputs.length; i++) { - outputs[i].push(0.f); - } - this.startOffFragment = offset; - } - - @Override - public long onUpdate(FlowStage ctx, long now) { - long passedTime = now - this.startOffFragment; - long duration = this.currentFragment.duration(); - - // The current Fragment has not yet been finished, continue - if (passedTime < duration) { - return now + (duration - passedTime); - } - - // Loop through fragments until the passed time is filled. - // We need a while loop to account for skipping of fragments. - while (passedTime >= duration) { - - // Stop running - if (!this.fragments.hasNext()) { - final SimMachineContext machineContext = this.ctx; - if (machineContext != null) { - machineContext.shutdown(); - } - ctx.close(); - return Long.MAX_VALUE; - } - - passedTime = passedTime - duration; - - // get next Fragment - this.index++; - currentFragment = this.fragments.next(); - duration = currentFragment.duration(); - } - - // start the new fragment - this.startOffFragment = now - passedTime; - - int cores = Math.min(this.coreCount, currentFragment.coreCount()); - float usage = (float) currentFragment.cpuUsage() / cores; - - final OutPort[] outputs = this.outputs; - - // Push the usage to all active cores - for (int i = 0; i < cores; i++) { - outputs[i].push(usage); - } - - // Push a usage of 0 to all non-active cores - for (int i = cores; i < outputs.length; i++) { - outputs[i].push(0.f); - } - - // Return the time when the current fragment will complete - return now + (duration - passedTime); - } - - @Override - public FlowStage getStage() { - return stage; - } - - @Override - public int getIndex() { - return index; - } - } } 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 da8bb5d27..be6d289cc 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 @@ -35,11 +35,10 @@ import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows import org.opendc.simulator.compute.device.SimNetworkAdapter +import org.opendc.simulator.compute.model.Cpu import org.opendc.simulator.compute.model.MachineModel import org.opendc.simulator.compute.model.MemoryUnit 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.CpuPowerModels import org.opendc.simulator.compute.workload.SimTrace @@ -60,12 +59,17 @@ class SimMachineTest { @BeforeEach fun setUp() { - val cpuNode = ProcessingNode("Intel", "Xeon", "amd64", 2) - machineModel = MachineModel( - List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 1000.0) }, - List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) }, + Cpu( + 0, + 2, + 1000.0, + "Intel", + "Xeon", + "amd64", + ), + MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000 * 4), listOf(NetworkAdapter("Mellanox", "ConnectX-5", 25000.0)), listOf(StorageDevice("Samsung", "EVO", 1000.0, 250.0, 250.0)), ) @@ -121,11 +125,17 @@ class SimMachineTest { val engine = FlowEngine.create(dispatcher) val graph = engine.newGraph() - val cpuNode = machineModel.cpus[0].node + val cpuNode = machineModel.cpu val machineModel = MachineModel( - List(cpuNode.coreCount * 2) { ProcessingUnit(cpuNode, it % 2, 1000.0) }, - List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) }, + List(cpuNode.coreCount * 2) { + Cpu( + it, + cpuNode.coreCount, + 1000.0, + ) + }, + MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000 * 4), ) val machine = SimBareMetalMachine.create( @@ -179,10 +189,10 @@ class SimMachineTest { machine.runWorkload( object : SimWorkload { override fun onStart(ctx: SimMachineContext) { - val cpu = ctx.cpus[0] + val cpu = ctx.cpu - cpu.frequency = (cpu.model.frequency + 1000.0) - assertEquals(cpu.model.frequency, cpu.frequency) + cpu.frequency = (cpu.cpuModel.totalCapacity + 1000.0) + assertEquals(cpu.cpuModel.totalCapacity, cpu.frequency) cpu.frequency = -1.0 assertEquals(0.0, cpu.frequency) 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 bef226997..6cebc46fa 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 @@ -33,10 +33,9 @@ import org.junit.jupiter.api.assertDoesNotThrow import org.opendc.simulator.compute.SimBareMetalMachine import org.opendc.simulator.compute.kernel.cpufreq.ScalingGovernors import org.opendc.simulator.compute.kernel.interference.VmInterferenceModel +import org.opendc.simulator.compute.model.Cpu 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.runWorkload import org.opendc.simulator.compute.workload.SimTrace import org.opendc.simulator.compute.workload.SimTraceFragment @@ -53,13 +52,18 @@ internal class SimFairShareHypervisorTest { @BeforeEach fun setUp() { - val cpuNode = ProcessingNode("Intel", "Xeon", "amd64", 1) model = MachineModel( - // cpus - List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 3200.0) }, + Cpu( + 0, + 1, + 3200.0, + "Intel", + "Xeon", + "amd64", + ), // memory - List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) }, + MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000 * 4), ) } @@ -167,13 +171,18 @@ internal class SimFairShareHypervisorTest { @Test fun testMultipleCPUs() = runSimulation { - val cpuNode = ProcessingNode("Intel", "Xeon", "amd64", 2) val model = MachineModel( - // cpus - List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 3200.0) }, + Cpu( + 0, + 2, + 3200.0, + "Intel", + "Xeon", + "amd64", + ), // memory - List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) }, + MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000 * 4), ) val engine = FlowEngine.create(dispatcher) @@ -197,13 +206,18 @@ internal class SimFairShareHypervisorTest { @Test fun testInterference() = runSimulation { - val cpuNode = ProcessingNode("Intel", "Xeon", "amd64", 2) val model = MachineModel( - // cpus - List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 3200.0) }, + Cpu( + 0, + 2, + 3200.0, + "Intel", + "Xeon", + "amd64", + ), // memory - List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) }, + MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000 * 4), ) val interferenceModel = 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 b762acea6..b4ae372cb 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 @@ -33,10 +33,9 @@ import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows import org.opendc.simulator.compute.SimBareMetalMachine +import org.opendc.simulator.compute.model.Cpu 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.runWorkload import org.opendc.simulator.compute.workload.SimTrace import org.opendc.simulator.compute.workload.SimTraceFragment @@ -54,13 +53,18 @@ internal class SimSpaceSharedHypervisorTest { @BeforeEach fun setUp() { - val cpuNode = ProcessingNode("Intel", "Xeon", "amd64", 1) machineModel = MachineModel( - // cpus - List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 3200.0) }, + Cpu( + 0, + 1, + 3200.0, + "Intel", + "Xeon", + "amd64", + ), // memory - List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) }, + MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000 * 4), ) } diff --git a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/workload/SimChainWorkloadTest.kt b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/workload/SimChainWorkloadTest.kt index 33de77518..582635fc9 100644 --- a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/workload/SimChainWorkloadTest.kt +++ b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/workload/SimChainWorkloadTest.kt @@ -33,10 +33,9 @@ import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows import org.opendc.simulator.compute.SimBareMetalMachine import org.opendc.simulator.compute.SimMachineContext +import org.opendc.simulator.compute.model.Cpu 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.runWorkload import org.opendc.simulator.flow2.FlowEngine import org.opendc.simulator.kotlin.runSimulation @@ -49,14 +48,18 @@ class SimChainWorkloadTest { @BeforeEach fun setUp() { - val cpuNode = ProcessingNode("Intel", "Xeon", "amd64", 2) - machineModel = MachineModel( - // cpus - List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 1000.0) }, + Cpu( + 0, + 2, + 1000.0, + "Intel", + "Xeon", + "amd64", + ), // memory - List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) }, + MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000 * 4), ) } 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 e40d4f8b3..a53f6c656 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 @@ -27,10 +27,9 @@ import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.opendc.simulator.compute.SimBareMetalMachine +import org.opendc.simulator.compute.model.Cpu 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.runWorkload import org.opendc.simulator.flow2.FlowEngine import org.opendc.simulator.kotlin.runSimulation @@ -43,14 +42,18 @@ class SimTraceWorkloadTest { @BeforeEach fun setUp() { - val cpuNode = ProcessingNode("Intel", "Xeon", "amd64", 2) - machineModel = MachineModel( - // cpus - List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 1000.0) }, + Cpu( + 0, + 2, + 1000.0, + "Intel", + "Xeon", + "amd64", + ), // memory - List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) }, + MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000 * 4), ) } diff --git a/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/OpenDCRunner.kt b/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/OpenDCRunner.kt index 18af0d1a8..af9d55290 100644 --- a/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/OpenDCRunner.kt +++ b/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/OpenDCRunner.kt @@ -37,10 +37,9 @@ import org.opendc.compute.workload.sampleByLoad import org.opendc.compute.workload.trace import org.opendc.experiments.base.runner.replay import org.opendc.simulator.compute.SimPsuFactories +import org.opendc.simulator.compute.model.Cpu 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.CpuPowerModels import org.opendc.simulator.kotlin.runSimulation import org.opendc.web.proto.runner.Job @@ -325,15 +324,10 @@ public class OpenDCRunner( val position = machine.position val processors = - machine.cpus.flatMap { cpu -> - val cores = cpu.numberOfCores - val speed = cpu.clockRateMhz - // TODO: Remove hard coding of vendor - val node = ProcessingNode("Intel", "amd64", cpu.name, cores) - List(cores) { coreId -> - ProcessingUnit(node, coreId, speed) - } + machine.cpus.map { cpu -> + Cpu(0, cpu.numberOfCores, cpu.clockRateMhz, "Intel", "amd64", cpu.name) } + val memoryUnits = machine.memory.map { memory -> MemoryUnit( @@ -352,7 +346,7 @@ public class OpenDCRunner( UUID(random.nextLong(), random.nextLong()), "node-$clusterId-$position", mapOf("cluster" to clusterId), - MachineModel(processors, memoryUnits), + MachineModel(processors, memoryUnits[0]), SimPsuFactories.simple(powerModel), ) diff --git a/site/docs/advanced-guides/toolchain.md b/site/docs/advanced-guides/toolchain.md index a1735767c..1673d9742 100644 --- a/site/docs/advanced-guides/toolchain.md +++ b/site/docs/advanced-guides/toolchain.md @@ -41,7 +41,7 @@ Open the project once it's ready fetching the codebase, and let it set up with t that this is a Gradle codebase). You will now be prompted in a dialogue to enable auto-import for Gradle, which we suggest you do. Wait for any progress -bars in the lower bar to disappear and then look for the Gradle context menu on the right-hand side. In it, go +bars in the lower bar to disappear and then look for the Gradle simHyperVisorContext menu on the right-hand side. In it, go to `opendc > Tasks > verification > test`. This will build the codebase and run checks to verify that tests pass. If you get a `BUILD SUCCESSFUL` message, you're ready to go to the [next section](architecture)! diff --git a/site/docs/getting-started/0-installation.md b/site/docs/getting-started/0-installation.md index e0e944ccc..e9f539a8a 100644 --- a/site/docs/getting-started/0-installation.md +++ b/site/docs/getting-started/0-installation.md @@ -40,7 +40,7 @@ __ ____ __ _____ ___ __ ____ ______ 2022-09-12 10:30:22,282 INFO [org.ope.web.run.run.OpenDCRunnerRecorder] (main) Starting OpenDC Runner in background (polling every PT30S) 2022-09-12 10:30:22,347 INFO [io.quarkus] (main) opendc-web-server 2.1-rc1 on JVM (powered by Quarkus 2.11.1.Final) started in 1.366s. Listening on: http://0.0.0.0:8080 2022-09-12 10:30:22,348 INFO [io.quarkus] (main) Profile prod activated. -2022-09-12 10:30:22,348 INFO [io.quarkus] (main) Installed features: [agroal, cdi, flyway, hibernate-orm, hibernate-validator, jdbc-h2, jdbc-postgresql, kotlin, narayana-jta, opendc-runner, opendc-ui, resteasy, resteasy-jackson, security, smallrye-context-propagation, smallrye-openapi, swagger-ui, vertx] +2022-09-12 10:30:22,348 INFO [io.quarkus] (main) Installed features: [agroal, cdi, flyway, hibernate-orm, hibernate-validator, jdbc-h2, jdbc-postgresql, kotlin, narayana-jta, opendc-runner, opendc-ui, resteasy, resteasy-jackson, security, smallrye-simHyperVisorContext-propagation, smallrye-openapi, swagger-ui, vertx] ``` This will launch the built-in single-user OpenDC server on port 8080. Visit [http://localhost:8080](http://localhost:8080) to access the bundled web UI. diff --git a/site/docs/getting-started/1-design.mdx b/site/docs/getting-started/1-design.mdx index 144fbf987..e8ab2c58e 100644 --- a/site/docs/getting-started/1-design.mdx +++ b/site/docs/getting-started/1-design.mdx @@ -83,7 +83,7 @@ build rooms. Let’s take a moment to familiarize ourselves with the interface. If you dismiss the sidebar on your left, you have controls for zooming in and out. Next to the zooming buttons, you also have a ‘Screenshot’ button, in case you want to record the state of the canvas and export it to an image file. On the -right side of the screen, you have the context menu. This menu changes depending on your zoom level. +right side of the screen, you have the simHyperVisorContext menu. This menu changes depending on your zoom level. As there are currently no rooms, we are in ‘Building’ mode, and our only option is to ‘Construct a new room’. Click on that button to build a first datacenter room - once you’ve clicked on it, every tile of the canvas that you click on @@ -106,7 +106,7 @@ Create at least a single room, with help of the above instructions. Once you’ve placed the tiles, you can give the room a name, if you want to. To do this, click on the room you want to edit. You’ll notice the application going into ‘Room’ mode, allowing you to manipulate the topology of the datacenter at -a more fine-grained level. In the context menu, change the room name, and click on the ‘Save’ button. You can exit +a more fine-grained level. In the simHyperVisorContext menu, change the room name, and click on the ‘Save’ button. You can exit ‘Room’ mode by clicking on any of the darkened areas outside of the selected room. This will bring you back to ‘Building’ mode. @@ -131,7 +131,7 @@ Add a couple of servers to the rack. ::: To add actual servers to the empty racks, we’ll need to go one level deeper in the topological hierarchy of the -datacenter. Clicking on a rack lets you do just that. Once you’ve clicked on it, you’ll notice the context menu now +datacenter. Clicking on a rack lets you do just that. Once you’ve clicked on it, you’ll notice the simHyperVisorContext menu now displaying slots. In each slot fits exactly one server unit. To add such a server unit, click on the ‘Add machine’ button of that slot. Just like in ‘Room’ mode, you can exit ‘Rack’ mode by clicking on any of the darkened tiles around the currently @@ -148,7 +148,7 @@ Populate the machines with CPU and memory resources. ::: -To do this, click on any machine you want to edit. Notice the context menu changing, with tabs to add different kinds of +To do this, click on any machine you want to edit. Notice the simHyperVisorContext menu changing, with tabs to add different kinds of units to your machine. Have a look around as to what can be added. Once you are satisfied with the datacenter design, we will experiment with the design in the next chapter. diff --git a/site/docs/getting-started/2-experiment.mdx b/site/docs/getting-started/2-experiment.mdx index e25dffc9a..14970ea60 100644 --- a/site/docs/getting-started/2-experiment.mdx +++ b/site/docs/getting-started/2-experiment.mdx @@ -31,7 +31,7 @@ The baseline for comparison in a portfolio is the **base scenario**. It represen or, when planning infrastructure from scratch, it consists of very simple base workloads and topologies. The other scenarios in a portfolio, called the **candidate scenarios**, represent changes to the configuration that might be of interest to the datacenter designer. Dividing scenarios into these two categories ensures that any -comparative insights provided by OpenDC are meaningful within the context of the current architecture. +comparative insights provided by OpenDC are meaningful within the simHyperVisorContext of the current architecture. To create a new scenario, open a portfolio in the OpenDC web interface and click on ‘+ New Scenario’ in the top right corner of the scenario table. This opens a modal with the following options (as shown in [Figure 1](#explore)):