From 2dc44c7283200f4689cc1be15115a8b1cd37d456 Mon Sep 17 00:00:00 2001 From: Dante Niewenhuis Date: Mon, 29 Apr 2024 12:48:20 +0200 Subject: [PATCH] Fixed several cpu related bugs, changed input topology (#226) --- .../service/scheduler/filters/VCpuFilter.kt | 10 +- .../org/opendc/compute/simulator/SimHost.kt | 2 +- .../compute/topology/TopologyFactories.kt | 19 +- .../compute/topology/specs/JSONSpecs.kt | 4 +- .../base/ScenarioIntegrationTest.kt | 22 +- .../src/test/resources/env/multi.json | 36 +-- .../src/test/resources/env/single.json | 12 +- site/docs/documentation/Input/Topology.md | 12 +- .../documentation/Input/TopologySchema.md | 300 +++++++++--------- 9 files changed, 196 insertions(+), 221 deletions(-) diff --git a/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/scheduler/filters/VCpuFilter.kt b/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/scheduler/filters/VCpuFilter.kt index 451ea4b6d..cefb3f7ad 100644 --- a/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/scheduler/filters/VCpuFilter.kt +++ b/opendc-compute/opendc-compute-service/src/main/kotlin/org/opendc/compute/service/scheduler/filters/VCpuFilter.kt @@ -36,15 +36,15 @@ public class VCpuFilter(private val allocationRatio: Double) : HostFilter { server: Server, ): Boolean { val requested = server.flavor.coreCount - val total = host.host.model.coreCount - val limit = total * allocationRatio + val totalCores = host.host.model.coreCount + val limit = totalCores * allocationRatio // Do not allow an instance to overcommit against itself, only against other instances - if (requested > total) { + if (requested > totalCores) { return false } - val free = limit - host.provisionedCores - return free >= requested + val availableCores = limit - host.provisionedCores + return availableCores >= requested } } 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 bfd21a3cb..84799123f 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 @@ -146,7 +146,7 @@ public class SimHost( override fun canFit(server: Server): Boolean { val sufficientMemory = model.memoryCapacity >= server.flavor.memorySize - val enoughCpus = model.cpuCount >= server.flavor.coreCount + val enoughCpus = model.coreCount >= server.flavor.coreCount val canFit = hypervisor.canFit(server.flavor.toMachineModel()) return sufficientMemory && enoughCpus && canFit 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 f8c7afbd4..549086d42 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 @@ -24,7 +24,6 @@ package org.opendc.compute.topology -import org.opendc.compute.topology.specs.CPUJSONSpec import org.opendc.compute.topology.specs.ClusterJSONSpec import org.opendc.compute.topology.specs.HostJSONSpec import org.opendc.compute.topology.specs.HostSpec @@ -104,14 +103,14 @@ private fun ClusterJSONSpec.toHostSpecs(random: RandomGenerator): List * Helper method to convert a [HostJSONSpec] into a [HostSpec]s. */ private var hostId = 0 +private var globalCoreId = 0 private fun HostJSONSpec.toHostSpecs( clusterId: Int, random: RandomGenerator, ): HostSpec { - val unknownProcessingNode = ProcessingNode("unknown", "unknown", "unknown", cpus.sumOf { it.coreCount }) - - val units = cpus.flatMap { cpu -> List(cpu.count) { cpu.toProcessingUnits(unknownProcessingNode) }.flatten() } + val unknownProcessingNode = ProcessingNode("unknown", "unknown", "unknown", cpu.coreCount) + val units = List(cpu.count) { ProcessingUnit(unknownProcessingNode, globalCoreId++, cpu.coreSpeed) } val unknownMemoryUnit = MemoryUnit(memory.vendor, memory.modelName, memory.memorySpeed, memory.memorySize) val machineModel = @@ -134,15 +133,3 @@ private fun HostJSONSpec.toHostSpecs( return hostSpec } - -/** - * Helper method to convert a [CPUJSONSpec] into a list of [ProcessingUnit]s. - */ -private var globalCoreId = 0 - -private fun CPUJSONSpec.toProcessingUnits(unknownProcessingNode: ProcessingNode): List { - val units = List(coreCount) { ProcessingUnit(unknownProcessingNode, globalCoreId++, coreSpeed) } - return units - -// return listOf(ProcessingUnit(unknownProcessingNode, globalCoreId++, coreSpeed)) -} diff --git a/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/specs/JSONSpecs.kt b/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/specs/JSONSpecs.kt index 8f73f524d..2bfed5029 100644 --- a/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/specs/JSONSpecs.kt +++ b/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/specs/JSONSpecs.kt @@ -54,7 +54,7 @@ public data class ClusterJSONSpec( * Definition of a compute host modeled in the simulation. * * @param name The name of the host. - * @param cpus List of the different CPUs available in this cluster + * @param cpu The CPU available in this cluster * @param memory The amount of RAM memory available in Byte * @param powerModel The power model used to determine the power draw of a host * @param count The power model used to determine the power draw of a host @@ -62,7 +62,7 @@ public data class ClusterJSONSpec( @Serializable public data class HostJSONSpec( val name: String = "Host", - val cpus: List, + val cpu: CPUJSONSpec, val memory: MemoryJSONSpec, val powerModel: PowerModelJSONSpec = PowerModelJSONSpec("linear", 350.0, 400.0, 200.0), val count: Int = 1, 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 0ab305ee9..96e62e800 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 @@ -121,12 +121,12 @@ class ScenarioIntegrationTest { { assertEquals(0, monitor.serversActive, "All VMs should finish after a run") }, { assertEquals(0, monitor.attemptsFailure, "No VM should be unscheduled") }, { assertEquals(0, monitor.serversPending, "No VM should not be in the queue") }, - { assertEquals(223379991650, monitor.idleTime) { "Incorrect idle time" } }, - { assertEquals(66977091124, monitor.activeTime) { "Incorrect active time" } }, - { assertEquals(3160267873, monitor.stealTime) { "Incorrect steal time" } }, + { assertEquals(36256553309, monitor.idleTime) { "Incorrect idle time" } }, + { assertEquals(10404414534, monitor.activeTime) { "Incorrect active time" } }, + { assertEquals(54402726811, monitor.stealTime) { "Incorrect steal time" } }, { assertEquals(0, monitor.lostTime) { "Incorrect lost time" } }, - { assertEquals(2.0774585843587227E7, monitor.powerDraw, 1E4) { "Incorrect power draw" } }, - { assertEquals(6.232122296636381E9, monitor.energyUsage, 1E4) { "Incorrect energy usage" } }, + { assertEquals(3.804398939214319E7, monitor.powerDraw, 1E4) { "Incorrect power draw" } }, + { assertEquals(1.141307641744099E10, monitor.energyUsage, 1E4) { "Incorrect energy usage" } }, ) } @@ -163,12 +163,12 @@ class ScenarioIntegrationTest { // Note that these values have been verified beforehand assertAll( - { assertEquals(10996730092, monitor.idleTime) { "Idle time incorrect" } }, - { assertEquals(9741285381, monitor.activeTime) { "Active time incorrect" } }, - { assertEquals(152, monitor.stealTime) { "Steal time incorrect" } }, + { assertEquals(873236440, monitor.idleTime) { "Idle time incorrect" } }, + { assertEquals(1719015528, monitor.activeTime) { "Active time incorrect" } }, + { assertEquals(8022269916, monitor.stealTime) { "Steal time incorrect" } }, { assertEquals(0, monitor.lostTime) { "Lost time incorrect" } }, - { assertEquals(2539987.394500494, monitor.powerDraw, 1E4) { "Incorrect power draw" } }, - { assertEquals(7.619825262052509E8, monitor.energyUsage, 1E4) { "Incorrect energy usage" } }, + { assertEquals(2874229.394500494, monitor.powerDraw, 1E4) { "Incorrect power draw" } }, + { assertEquals(8.622534568334692E8, monitor.energyUsage, 1E4) { "Incorrect energy usage" } }, ) } @@ -213,8 +213,8 @@ class ScenarioIntegrationTest { /** * Test a small simulation setup with failures. + * FIXME: Currently failures do not work. reactivate this test when Failures are implemented again */ - @Test fun testFailures() = runSimulation { val seed = 0L diff --git a/opendc-experiments/opendc-experiments-base/src/test/resources/env/multi.json b/opendc-experiments/opendc-experiments-base/src/test/resources/env/multi.json index d23dbfe36..c3a060cc4 100644 --- a/opendc-experiments/opendc-experiments-base/src/test/resources/env/multi.json +++ b/opendc-experiments/opendc-experiments-base/src/test/resources/env/multi.json @@ -7,13 +7,11 @@ [ { "name": "H01", - "cpus": - [ - { - "coreCount": 32, - "coreSpeed": 3200 - } - ], + "cpu": + { + "coreCount": 32, + "coreSpeed": 3200 + }, "memory": { "memorySize": 256000 } @@ -27,13 +25,11 @@ { "name": "H02", "count": 6, - "cpus": - [ - { - "coreCount": 8, - "coreSpeed": 2930 - } - ], + "cpu": + { + "coreCount": 8, + "coreSpeed": 2930 + }, "memory": { "memorySize": 64000 } @@ -47,13 +43,11 @@ { "name": "H03", "count": 2, - "cpus": - [ - { - "coreCount": 16, - "coreSpeed": 3200 - } - ], + "cpu": + { + "coreCount": 16, + "coreSpeed": 3200 + }, "memory": { "memorySize": 128000 } diff --git a/opendc-experiments/opendc-experiments-base/src/test/resources/env/single.json b/opendc-experiments/opendc-experiments-base/src/test/resources/env/single.json index 2d68b234d..f69b21be0 100644 --- a/opendc-experiments/opendc-experiments-base/src/test/resources/env/single.json +++ b/opendc-experiments/opendc-experiments-base/src/test/resources/env/single.json @@ -7,13 +7,11 @@ [ { "name": "H01", - "cpus": - [ - { - "coreCount": 8, - "coreSpeed": 3200 - } - ], + "cpu": + { + "coreCount": 8, + "coreSpeed": 3200 + }, "memory": { "memorySize": 128000 } diff --git a/site/docs/documentation/Input/Topology.md b/site/docs/documentation/Input/Topology.md index 8a57a1836..23286c099 100644 --- a/site/docs/documentation/Input/Topology.md +++ b/site/docs/documentation/Input/Topology.md @@ -17,12 +17,12 @@ In the following section, we describe the different components of the schema. ### Host -| variable | type | required? | default | description | -|-------------|-----------------------------|-----------|---------|--------------------------------------------------------------------------------| -| name | string | no | Host | The name of the host. This is only important for debugging and post-processing | -| count | integer | no | 1 | The amount of hosts of this type are in the cluster | -| cpus | List[[CPU](#cpu)] | yes | N/A | A list of the hosts in a cluster. | -| memory | [Memory](#memory) | yes | N/A | The memory used by the host | +| variable | type | required? | default | description | +|------------|-----------------------|-----------|---------|--------------------------------------------------------------------------------| +| name | string | no | Host | The name of the host. This is only important for debugging and post-processing | +| count | integer | no | 1 | The amount of hosts of this type are in the cluster | +| cpu | [CPU](#cpu) | yes | N/A | The CPUs in the host | +| memory | [Memory](#memory) | yes | N/A | The memory used by the host | | power model | [Power Model](#power-model) | yes | N/A | The power model used to determine the power draw of the host | ### CPU diff --git a/site/docs/documentation/Input/TopologySchema.md b/site/docs/documentation/Input/TopologySchema.md index d8d3aa48d..9c4e0c400 100644 --- a/site/docs/documentation/Input/TopologySchema.md +++ b/site/docs/documentation/Input/TopologySchema.md @@ -3,162 +3,158 @@ A topology file can be validated using a JSON schema validator, such as https:// ```json { - "$schema": "OpenDC/Topology", - "$defs": { - "cpu": { - "description": "definition of a cpu", - "type": "object", - "properties": { - "vendor": { - "type": "string", - "default": "unknown" - }, - "modelName": { - "type": "string", - "default": "unknown" - }, - "arch": { - "type": "string", - "default": "unknown" - }, - "coreCount": { - "type": "integer" - }, - "coreSpeed": { - "description": "The core speed of the cpu in Mhz", - "type": "number" - }, - "count": { - "description": "The amount CPUs of this type present in the cluster", - "type": "integer" - } - }, - "required": [ - "coreCount", - "coreSpeed" - ] - }, - "memory": { - "type": "object", - "properties": { - "vendor": { - "type": "string", - "default": "unknown" - }, - "modelName": { - "type": "string", - "default": "unknown" - }, - "arch": { - "type": "string", - "default": "unknown" - }, - "memorySize": { - "description": "The amount of the memory in B", - "type": "integer" - }, - "memorySpeed": { - "description": "The speed of the memory in Mhz. Note: currently, this does nothing", - "type": "number", - "default": -1 - } - }, - "required": [ - "memorySize" - ] - }, - "powerModel": { - "type": "object", - "properties": { - "modelType": { - "description": "The type of model used to determine power draw", - "type": "string" - }, - "power": { - "description": "The constant power draw when using the 'constant' power model type in Watt", - "type": "number", - "default": 400 - }, - "maxPower": { - "description": "The power draw of a host when idle in Watt", - "type": "number" - }, - "idlePower": { - "description": "The power draw of a host when using max capacity in Watt", - "type": "number" - } - }, - "required": [ - "modelType", - "maxPower", - "idlePower" - ] - }, - "host": { - "type": "object", - "properties": { - "name": { - "type": "string", - "default": "Host" - }, - "count": { - "description": "The amount hosts of this type present in the cluster", - "type": "integer", - "default": 1 - }, - "cpus": { - "type": "array", - "items": { - "$ref": "#/$defs/cpu" - }, - "minItems": 1 + "$schema": "OpenDC/Topology", + "$defs": { + "cpu": { + "description": "definition of a cpu", + "type": "object", + "properties": { + "vendor": { + "type": "string", + "default": "unknown" + }, + "modelName": { + "type": "string", + "default": "unknown" + }, + "arch": { + "type": "string", + "default": "unknown" + }, + "coreCount": { + "type": "integer" + }, + "coreSpeed": { + "description": "The core speed of the cpu in Mhz", + "type": "number" + }, + "count": { + "description": "The amount CPUs of this type present in the cluster", + "type": "integer" + } + }, + "required": [ + "coreCount", + "coreSpeed" + ] }, "memory": { - "$ref": "#/$defs/memory" + "type": "object", + "properties": { + "vendor": { + "type": "string", + "default": "unknown" + }, + "modelName": { + "type": "string", + "default": "unknown" + }, + "arch": { + "type": "string", + "default": "unknown" + }, + "memorySize": { + "description": "The amount of the memory in B", + "type": "integer" + }, + "memorySpeed": { + "description": "The speed of the memory in Mhz. Note: currently, this does nothing", + "type": "number", + "default": -1 + } + }, + "required": [ + "memorySize" + ] + }, + "powerModel": { + "type": "object", + "properties": { + "modelType": { + "description": "The type of model used to determine power draw", + "type": "string" + }, + "power": { + "description": "The constant power draw when using the 'constant' power model type in Watt", + "type": "number", + "default": 400 + }, + "maxPower": { + "description": "The power draw of a host when idle in Watt", + "type": "number" + }, + "idlePower": { + "description": "The power draw of a host when using max capacity in Watt", + "type": "number" + } + }, + "required": [ + "modelType", + "maxPower", + "idlePower" + ] + }, + "host": { + "type": "object", + "properties": { + "name": { + "type": "string", + "default": "Host" + }, + "count": { + "description": "The amount hosts of this type present in the cluster", + "type": "integer", + "default": 1 + }, + "cpu": { + "$ref": "#/$defs/cpu" + }, + "memory": { + "$ref": "#/$defs/memory" + } + }, + "required": [ + "cpu", + "memory" + ] + }, + "cluster": { + "type": "object", + "properties": { + "name": { + "type": "string", + "default": "Cluster" + }, + "count": { + "description": "The amount clusters of this type present in the Data center", + "type": "integer", + "default": 1 + }, + "hosts": { + "type": "array", + "items": { + "$ref": "#/$defs/host" + }, + "minItems": 1 + } + }, + "required": [ + "hosts" + ] } - }, - "required": [ - "cpus", - "memory" - ] }, - "cluster": { - "type": "object", - "properties": { - "name": { - "type": "string", - "default": "Cluster" - }, - "count": { - "description": "The amount clusters of this type present in the Data center", - "type": "integer", - "default": 1 - }, - "hosts": { - "type": "array", - "items": { - "$ref": "#/$defs/host" - }, - "minItems": 1 + "properties": { + "clusters": { + "description": "Clusters present in the data center", + "type": "array", + "items": { + "$ref": "#/$defs/cluster" + }, + "minItems": 1 } - }, - "required": [ - "hosts" - ] - } - }, - "properties": { - "clusters": { - "description": "Clusters present in the data center", - "type": "array", - "items": { - "$ref": "#/$defs/cluster" - }, - "minItems": 1 - } - }, - "required": [ - "clusters" - ] + }, + "required": [ + "clusters" + ] } ```