From a7510e0708b6e5435f8440e588c762d6e6cd8a22 Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Fri, 2 Sep 2022 22:18:12 +0200 Subject: refactor(sim/compute): Remove timestamp parameter from SimTrace This change removes the timestamp parameter from `SimTrace`. Instead, it is now assumed that the trace is continuous and the end of a fragment starts a new fragment, in order to simplify replaying of the trace. --- .../org/opendc/compute/workload/ComputeWorkloadLoader.kt | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'opendc-compute/opendc-compute-workload/src/main') diff --git a/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/ComputeWorkloadLoader.kt b/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/ComputeWorkloadLoader.kt index 12c2325a..7ed04994 100644 --- a/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/ComputeWorkloadLoader.kt +++ b/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/ComputeWorkloadLoader.kt @@ -222,6 +222,11 @@ public class ComputeWorkloadLoader(private val baseDir: File) { */ private val builder = SimTrace.builder() + /** + * The deadline of the previous fragment. + */ + private var previousDeadline = Long.MIN_VALUE + /** * Add a fragment to the trace. * @@ -233,7 +238,14 @@ public class ComputeWorkloadLoader(private val baseDir: File) { fun add(timestamp: Long, deadline: Long, usage: Double, cores: Int) { val duration = max(0, deadline - timestamp) totalLoad += (usage * duration) / 1000.0 // avg MHz * duration = MFLOPs - builder.add(timestamp, deadline, usage, cores) + + if (timestamp != previousDeadline) { + // There is a gap between the previous and current fragment; fill the gap + builder.add(timestamp, 0.0, cores) + } + + builder.add(deadline, usage, cores) + previousDeadline = deadline } /** -- cgit v1.2.3 From 6171ab09f1df2ab3475a7b28ece383a9f87a77c5 Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Thu, 22 Sep 2022 10:28:37 +0200 Subject: refactor(sim/compute): Extract Random dependency from interference model This change moves the Random dependency outside the interference model, to allow the interference model to be completely immutable and passable between different simulations. --- .../compute/workload/ComputeServiceHelper.kt | 24 +++++++++++++--------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'opendc-compute/opendc-compute-workload/src/main') diff --git a/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/ComputeServiceHelper.kt b/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/ComputeServiceHelper.kt index fddb4890..879ef072 100644 --- a/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/ComputeServiceHelper.kt +++ b/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/ComputeServiceHelper.kt @@ -54,6 +54,7 @@ public class ComputeServiceHelper( private val context: CoroutineContext, private val clock: Clock, scheduler: ComputeScheduler, + seed: Long, private val failureModel: FailureModel? = null, private val interferenceModel: VmInterferenceModel? = null, schedulingQuantum: Duration = Duration.ofMinutes(5) @@ -66,12 +67,17 @@ public class ComputeServiceHelper( /** * The [FlowEngine] to simulate the hosts. */ - private val _engine = FlowEngine(context, clock) + private val engine = FlowEngine(context, clock) /** * The hosts that belong to this class. */ - private val _hosts = mutableSetOf() + private val hosts = mutableSetOf() + + /** + * The source of randomness. + */ + private val random = SplittableRandom(seed) init { val service = createService(scheduler, schedulingQuantum) @@ -82,18 +88,15 @@ public class ComputeServiceHelper( * Run a simulation of the [ComputeService] by replaying the workload trace given by [trace]. * * @param trace The trace to simulate. - * @param seed The seed for the simulation. * @param servers A list to which the created servers is added. * @param submitImmediately A flag to indicate that the servers are scheduled immediately (so not at their start time). */ public suspend fun run( trace: List, - seed: Long, servers: MutableList? = null, submitImmediately: Boolean = false ) { - val random = Random(seed) - val injector = failureModel?.createInjector(context, clock, service, random) + val injector = failureModel?.createInjector(context, clock, service, Random(random.nextLong())) val client = service.newClient() // Create new image for the virtual machine @@ -170,14 +173,15 @@ public class ComputeServiceHelper( spec.model, spec.meta, context, - _engine, + engine, spec.hypervisor, + random, powerDriver = spec.powerDriver, interferenceDomain = interferenceModel?.newDomain(), optimize = optimize ) - require(_hosts.add(host)) { "Host with uid ${spec.uid} already exists" } + require(hosts.add(host)) { "Host with uid ${spec.uid} already exists" } service.addHost(host) return host @@ -186,11 +190,11 @@ public class ComputeServiceHelper( override fun close() { service.close() - for (host in _hosts) { + for (host in hosts) { host.close() } - _hosts.clear() + hosts.clear() } /** -- cgit v1.2.3 From 8b6c15193281171bcb2e111f339ffb8da385332b Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Thu, 22 Sep 2022 11:12:01 +0200 Subject: refactor(compute): Simplify constructor of SimHost This change updates the constructor of SimHost to receive a `SimBareMetalMachine` and `SimHypervisor` directly instead of construction these objects itself. This ensures better testability and also simplifies the constructor of this class, especially when future changes to `SimBareMetalMachine` or `SimHypervisor` change their constructors. --- .../org/opendc/compute/workload/ComputeServiceHelper.kt | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'opendc-compute/opendc-compute-workload/src/main') diff --git a/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/ComputeServiceHelper.kt b/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/ComputeServiceHelper.kt index 879ef072..92652329 100644 --- a/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/ComputeServiceHelper.kt +++ b/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/ComputeServiceHelper.kt @@ -31,6 +31,7 @@ import org.opendc.compute.service.ComputeService import org.opendc.compute.service.scheduler.ComputeScheduler import org.opendc.compute.simulator.SimHost import org.opendc.compute.workload.topology.HostSpec +import org.opendc.simulator.compute.SimBareMetalMachine import org.opendc.simulator.compute.kernel.interference.VmInterferenceModel import org.opendc.simulator.compute.workload.SimTraceWorkload import org.opendc.simulator.flow.FlowEngine @@ -167,16 +168,17 @@ public class ComputeServiceHelper( * @return The [SimHost] that has been constructed by the runner. */ public fun registerHost(spec: HostSpec, optimize: Boolean = false): SimHost { + val machine = SimBareMetalMachine(engine, spec.model, spec.powerDriver) + val hypervisor = spec.hypervisor.create(engine, random) + val host = SimHost( spec.uid, spec.name, - spec.model, spec.meta, context, - engine, - spec.hypervisor, - random, - powerDriver = spec.powerDriver, + clock, + machine, + hypervisor, interferenceDomain = interferenceModel?.newDomain(), optimize = optimize ) -- cgit v1.2.3 From 17fa7619f1d7e96680e018d3f12f333fb75cdac1 Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Thu, 22 Sep 2022 14:45:12 +0200 Subject: refactor(sim/compute): Make interference domain independent of profile This change updates the virtual machine performance interference model so that the interference domain can be constructed independently of the interference profile. As a consequence, the construction of the topology now does not depend anymore on the interference profile. --- .../compute/workload/ComputeServiceHelper.kt | 25 +++++++++++++--------- .../org/opendc/compute/workload/ComputeWorkload.kt | 8 +------ .../compute/workload/ComputeWorkloadLoader.kt | 15 ++++++------- .../org/opendc/compute/workload/VirtualMachine.kt | 3 +++ .../workload/internal/CompositeComputeWorkload.kt | 12 +++++------ .../workload/internal/HpcSampledComputeWorkload.kt | 6 +++--- .../internal/LoadSampledComputeWorkload.kt | 6 +++--- .../workload/internal/TraceComputeWorkload.kt | 3 ++- 8 files changed, 40 insertions(+), 38 deletions(-) (limited to 'opendc-compute/opendc-compute-workload/src/main') diff --git a/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/ComputeServiceHelper.kt b/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/ComputeServiceHelper.kt index 92652329..ad132efe 100644 --- a/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/ComputeServiceHelper.kt +++ b/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/ComputeServiceHelper.kt @@ -32,7 +32,7 @@ import org.opendc.compute.service.scheduler.ComputeScheduler import org.opendc.compute.simulator.SimHost import org.opendc.compute.workload.topology.HostSpec import org.opendc.simulator.compute.SimBareMetalMachine -import org.opendc.simulator.compute.kernel.interference.VmInterferenceModel +import org.opendc.simulator.compute.kernel.interference.VmInterferenceDomain import org.opendc.simulator.compute.workload.SimTraceWorkload import org.opendc.simulator.flow.FlowEngine import java.time.Clock @@ -48,7 +48,6 @@ import kotlin.math.max * @param clock [Clock] instance tracking simulation time. * @param scheduler [ComputeScheduler] implementation to use for the service. * @param failureModel A failure model to use for injecting failures. - * @param interferenceModel The model to use for performance interference. * @param schedulingQuantum The scheduling quantum of the scheduler. */ public class ComputeServiceHelper( @@ -57,7 +56,6 @@ public class ComputeServiceHelper( scheduler: ComputeScheduler, seed: Long, private val failureModel: FailureModel? = null, - private val interferenceModel: VmInterferenceModel? = null, schedulingQuantum: Duration = Duration.ofMinutes(5) ) : AutoCloseable { /** @@ -91,11 +89,13 @@ public class ComputeServiceHelper( * @param trace The trace to simulate. * @param servers A list to which the created servers is added. * @param submitImmediately A flag to indicate that the servers are scheduled immediately (so not at their start time). + * @param interference A flag to indicate that VM interference needs to be enabled. */ public suspend fun run( trace: List, servers: MutableList? = null, - submitImmediately: Boolean = false + submitImmediately: Boolean = false, + interference: Boolean = false, ) { val injector = failureModel?.createInjector(context, clock, service, Random(random.nextLong())) val client = service.newClient() @@ -125,10 +125,16 @@ public class ComputeServiceHelper( delay(max(0, (start - offset) - now)) } - launch { - val workloadOffset = -offset + 300001 - val workload = SimTraceWorkload(entry.trace, workloadOffset) + val workloadOffset = -offset + 300001 + val workload = SimTraceWorkload(entry.trace, workloadOffset) + val meta = mutableMapOf("workload" to workload) + + val interferenceProfile = entry.interferenceProfile + if (interference && interferenceProfile != null) { + meta["interference-profile"] = interferenceProfile + } + launch { val server = client.newServer( entry.name, image, @@ -138,7 +144,7 @@ public class ComputeServiceHelper( entry.memCapacity, meta = if (entry.cpuCapacity > 0.0) mapOf("cpu-capacity" to entry.cpuCapacity) else emptyMap() ), - meta = mapOf("workload" to workload) + meta = meta ) servers?.add(server) @@ -169,7 +175,7 @@ public class ComputeServiceHelper( */ public fun registerHost(spec: HostSpec, optimize: Boolean = false): SimHost { val machine = SimBareMetalMachine(engine, spec.model, spec.powerDriver) - val hypervisor = spec.hypervisor.create(engine, random) + val hypervisor = spec.hypervisor.create(engine, random, interferenceDomain = VmInterferenceDomain()) val host = SimHost( spec.uid, @@ -179,7 +185,6 @@ public class ComputeServiceHelper( clock, machine, hypervisor, - interferenceDomain = interferenceModel?.newDomain(), optimize = optimize ) diff --git a/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/ComputeWorkload.kt b/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/ComputeWorkload.kt index aa0b5eaf..78002c2f 100644 --- a/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/ComputeWorkload.kt +++ b/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/ComputeWorkload.kt @@ -22,7 +22,6 @@ package org.opendc.compute.workload -import org.opendc.simulator.compute.kernel.interference.VmInterferenceModel import java.util.* /** @@ -32,10 +31,5 @@ public interface ComputeWorkload { /** * Resolve the workload into a list of [VirtualMachine]s to simulate. */ - public fun resolve(loader: ComputeWorkloadLoader, random: Random): Resolved - - /** - * A concrete instance of a workload. - */ - public data class Resolved(val vms: List, val interferenceModel: VmInterferenceModel?) + public fun resolve(loader: ComputeWorkloadLoader, random: Random): List } diff --git a/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/ComputeWorkloadLoader.kt b/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/ComputeWorkloadLoader.kt index 7ed04994..387a3ec2 100644 --- a/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/ComputeWorkloadLoader.kt +++ b/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/ComputeWorkloadLoader.kt @@ -48,7 +48,7 @@ public class ComputeWorkloadLoader(private val baseDir: File) { /** * The cache of workloads. */ - private val cache = ConcurrentHashMap>() + private val cache = ConcurrentHashMap>>() /** * Read the fragments into memory. @@ -87,7 +87,7 @@ public class ComputeWorkloadLoader(private val baseDir: File) { /** * Read the metadata into a workload. */ - private fun parseMeta(trace: Trace, fragments: Map): List { + private fun parseMeta(trace: Trace, fragments: Map, interferenceModel: VmInterferenceModel): List { val reader = checkNotNull(trace.getTable(TABLE_RESOURCES)).newReader() val idCol = reader.resolve(RESOURCE_ID) @@ -128,7 +128,8 @@ public class ComputeWorkloadLoader(private val baseDir: File) { totalLoad, submissionTime, endTime, - builder.build() + builder.build(), + interferenceModel.getProfile(id) ) ) } @@ -159,7 +160,6 @@ public class ComputeWorkloadLoader(private val baseDir: File) { val modelBuilder = VmInterferenceModel.builder() while (reader.nextRow()) { - @Suppress("UNCHECKED_CAST") val members = reader.getSet(membersCol, String::class.java)!! val target = reader.getDouble(targetCol) val score = reader.getDouble(scoreCol) @@ -177,7 +177,7 @@ public class ComputeWorkloadLoader(private val baseDir: File) { /** * Load the trace with the specified [name] and [format]. */ - public fun get(name: String, format: String): ComputeWorkload.Resolved { + public fun get(name: String, format: String): List { val ref = cache.compute(name) { key, oldVal -> val inst = oldVal?.get() if (inst == null) { @@ -188,11 +188,10 @@ public class ComputeWorkloadLoader(private val baseDir: File) { val trace = Trace.open(path, format) val fragments = parseFragments(trace) - val vms = parseMeta(trace, fragments) val interferenceModel = parseInterferenceModel(trace) - val instance = ComputeWorkload.Resolved(vms, interferenceModel) + val vms = parseMeta(trace, fragments, interferenceModel) - SoftReference(instance) + SoftReference(vms) } else { oldVal } diff --git a/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/VirtualMachine.kt b/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/VirtualMachine.kt index 88e80719..8560b537 100644 --- a/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/VirtualMachine.kt +++ b/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/VirtualMachine.kt @@ -22,6 +22,7 @@ package org.opendc.compute.workload +import org.opendc.simulator.compute.kernel.interference.VmInterferenceProfile import org.opendc.simulator.compute.workload.SimTrace import java.time.Instant import java.util.* @@ -37,6 +38,7 @@ import java.util.* * @param startTime The start time of the VM. * @param stopTime The stop time of the VM. * @param trace The trace that belong to this VM. + * @param interferenceProfile The interference profile of this virtual machine. */ public data class VirtualMachine( val uid: UUID, @@ -48,4 +50,5 @@ public data class VirtualMachine( val startTime: Instant, val stopTime: Instant, val trace: SimTrace, + val interferenceProfile: VmInterferenceProfile? ) diff --git a/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/internal/CompositeComputeWorkload.kt b/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/internal/CompositeComputeWorkload.kt index 1959c48d..9b2bec55 100644 --- a/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/internal/CompositeComputeWorkload.kt +++ b/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/internal/CompositeComputeWorkload.kt @@ -37,17 +37,17 @@ internal class CompositeComputeWorkload(val sources: Map { val traces = sources.map { (source, fraction) -> fraction to source.resolve(loader, random) } - val totalLoad = traces.sumOf { (_, w) -> w.vms.sumOf { it.totalLoad } } + val totalLoad = traces.sumOf { (_, vms) -> vms.sumOf { it.totalLoad } } val res = mutableListOf() - for ((fraction, w) in traces) { + for ((fraction, vms) in traces) { var currentLoad = 0.0 - for (entry in w.vms) { + for (entry in vms) { val entryLoad = entry.totalLoad if ((currentLoad + entryLoad) / totalLoad > fraction) { break @@ -58,9 +58,9 @@ internal class CompositeComputeWorkload(val sources: Map w.vms.size } + val vmCount = traces.sumOf { (_, vms) -> vms.size } logger.info { "Sampled $vmCount VMs into subset of ${res.size} VMs" } - return ComputeWorkload.Resolved(res, null) + return res } } diff --git a/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/internal/HpcSampledComputeWorkload.kt b/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/internal/HpcSampledComputeWorkload.kt index 84a77f0f..52f4c672 100644 --- a/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/internal/HpcSampledComputeWorkload.kt +++ b/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/internal/HpcSampledComputeWorkload.kt @@ -45,8 +45,8 @@ internal class HpcSampledComputeWorkload(val source: ComputeWorkload, val fracti */ private val pattern = Regex("^(ComputeNode|cn).*") - override fun resolve(loader: ComputeWorkloadLoader, random: Random): ComputeWorkload.Resolved { - val (vms, interferenceModel) = source.resolve(loader, random) + override fun resolve(loader: ComputeWorkloadLoader, random: Random): List { + val vms = source.resolve(loader, random) val (hpc, nonHpc) = vms.partition { entry -> val name = entry.name @@ -130,7 +130,7 @@ internal class HpcSampledComputeWorkload(val source: ComputeWorkload, val fracti logger.debug { "Total sampled load: ${hpcLoad + nonHpcLoad}" } logger.info { "Sampled ${vms.size} VMs (fraction $fraction) into subset of ${res.size} VMs" } - return ComputeWorkload.Resolved(res, interferenceModel) + return res } /** diff --git a/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/internal/LoadSampledComputeWorkload.kt b/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/internal/LoadSampledComputeWorkload.kt index bc13560c..ef6de729 100644 --- a/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/internal/LoadSampledComputeWorkload.kt +++ b/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/internal/LoadSampledComputeWorkload.kt @@ -37,8 +37,8 @@ internal class LoadSampledComputeWorkload(val source: ComputeWorkload, val fract */ private val logger = KotlinLogging.logger {} - override fun resolve(loader: ComputeWorkloadLoader, random: Random): ComputeWorkload.Resolved { - val (vms, interferenceModel) = source.resolve(loader, random) + override fun resolve(loader: ComputeWorkloadLoader, random: Random): List { + val vms = source.resolve(loader, random) val res = mutableListOf() val totalLoad = vms.sumOf { it.totalLoad } @@ -56,6 +56,6 @@ internal class LoadSampledComputeWorkload(val source: ComputeWorkload, val fract logger.info { "Sampled ${vms.size} VMs (fraction $fraction) into subset of ${res.size} VMs" } - return ComputeWorkload.Resolved(res, interferenceModel) + return res } } diff --git a/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/internal/TraceComputeWorkload.kt b/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/internal/TraceComputeWorkload.kt index dc9abaef..c20cb8f3 100644 --- a/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/internal/TraceComputeWorkload.kt +++ b/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/internal/TraceComputeWorkload.kt @@ -24,13 +24,14 @@ package org.opendc.compute.workload.internal import org.opendc.compute.workload.ComputeWorkload import org.opendc.compute.workload.ComputeWorkloadLoader +import org.opendc.compute.workload.VirtualMachine import java.util.* /** * A [ComputeWorkload] from a trace. */ internal class TraceComputeWorkload(val name: String, val format: String) : ComputeWorkload { - override fun resolve(loader: ComputeWorkloadLoader, random: Random): ComputeWorkload.Resolved { + override fun resolve(loader: ComputeWorkloadLoader, random: Random): List { return loader.get(name, format) } } -- cgit v1.2.3 From 92787292269783701cb7f1082f0262e7e2851df9 Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Thu, 22 Sep 2022 22:28:44 +0200 Subject: refactor(sim/compute): Simplify SimHypervisor class This change simplifies the SimHypervisor class into a single implementation. Previously, it was implemented as an abstract class with multiple implementations for each multiplexer type. We now pass the multiplexer type as parameter to the SimHypervisor constructor. --- .../kotlin/org/opendc/compute/workload/ComputeServiceHelper.kt | 4 ++-- .../main/kotlin/org/opendc/compute/workload/topology/HostSpec.kt | 7 +++---- 2 files changed, 5 insertions(+), 6 deletions(-) (limited to 'opendc-compute/opendc-compute-workload/src/main') diff --git a/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/ComputeServiceHelper.kt b/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/ComputeServiceHelper.kt index ad132efe..3be0217c 100644 --- a/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/ComputeServiceHelper.kt +++ b/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/ComputeServiceHelper.kt @@ -32,7 +32,7 @@ import org.opendc.compute.service.scheduler.ComputeScheduler import org.opendc.compute.simulator.SimHost import org.opendc.compute.workload.topology.HostSpec import org.opendc.simulator.compute.SimBareMetalMachine -import org.opendc.simulator.compute.kernel.interference.VmInterferenceDomain +import org.opendc.simulator.compute.kernel.SimHypervisor import org.opendc.simulator.compute.workload.SimTraceWorkload import org.opendc.simulator.flow.FlowEngine import java.time.Clock @@ -175,7 +175,7 @@ public class ComputeServiceHelper( */ public fun registerHost(spec: HostSpec, optimize: Boolean = false): SimHost { val machine = SimBareMetalMachine(engine, spec.model, spec.powerDriver) - val hypervisor = spec.hypervisor.create(engine, random, interferenceDomain = VmInterferenceDomain()) + val hypervisor = SimHypervisor(engine, spec.multiplexerFactory, random) val host = SimHost( spec.uid, diff --git a/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/topology/HostSpec.kt b/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/topology/HostSpec.kt index f3dc1e9e..87530f5a 100644 --- a/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/topology/HostSpec.kt +++ b/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/topology/HostSpec.kt @@ -22,10 +22,9 @@ package org.opendc.compute.workload.topology -import org.opendc.simulator.compute.kernel.SimFairShareHypervisorProvider -import org.opendc.simulator.compute.kernel.SimHypervisorProvider import org.opendc.simulator.compute.model.MachineModel import org.opendc.simulator.compute.power.PowerDriver +import org.opendc.simulator.flow.mux.FlowMultiplexerFactory import java.util.* /** @@ -36,7 +35,7 @@ import java.util.* * @param meta The metadata of the host. * @param model The physical model of the machine. * @param powerDriver The [PowerDriver] to model the power consumption of the machine. - * @param hypervisor The hypervisor implementation to use. + * @param multiplexerFactory The [FlowMultiplexerFactory] that is used to multiplex the virtual machines over the host. */ public data class HostSpec( val uid: UUID, @@ -44,5 +43,5 @@ public data class HostSpec( val meta: Map, val model: MachineModel, val powerDriver: PowerDriver, - val hypervisor: SimHypervisorProvider = SimFairShareHypervisorProvider() + val multiplexerFactory: FlowMultiplexerFactory = FlowMultiplexerFactory.maxMinMultiplexer() ) -- cgit v1.2.3 From d97356cf696dedb6c26fc42d9d7c44a977264dcd Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Thu, 22 Sep 2022 22:39:33 +0200 Subject: refactor(compute): Pass failure model during workload evaluation This change updates the `ComputeServiceHelper` class to provide the failure model via a parameter to the `run` method instead of constructor parameter. This separates the construction of the topology from the simulation of the workload. --- .../main/kotlin/org/opendc/compute/workload/ComputeServiceHelper.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'opendc-compute/opendc-compute-workload/src/main') diff --git a/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/ComputeServiceHelper.kt b/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/ComputeServiceHelper.kt index 3be0217c..4c07b785 100644 --- a/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/ComputeServiceHelper.kt +++ b/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/ComputeServiceHelper.kt @@ -47,7 +47,6 @@ import kotlin.math.max * @param context [CoroutineContext] to run the simulation in. * @param clock [Clock] instance tracking simulation time. * @param scheduler [ComputeScheduler] implementation to use for the service. - * @param failureModel A failure model to use for injecting failures. * @param schedulingQuantum The scheduling quantum of the scheduler. */ public class ComputeServiceHelper( @@ -55,7 +54,6 @@ public class ComputeServiceHelper( private val clock: Clock, scheduler: ComputeScheduler, seed: Long, - private val failureModel: FailureModel? = null, schedulingQuantum: Duration = Duration.ofMinutes(5) ) : AutoCloseable { /** @@ -89,12 +87,14 @@ public class ComputeServiceHelper( * @param trace The trace to simulate. * @param servers A list to which the created servers is added. * @param submitImmediately A flag to indicate that the servers are scheduled immediately (so not at their start time). + * @param failureModel A failure model to use for injecting failures. * @param interference A flag to indicate that VM interference needs to be enabled. */ public suspend fun run( trace: List, servers: MutableList? = null, submitImmediately: Boolean = false, + failureModel: FailureModel? = null, interference: Boolean = false, ) { val injector = failureModel?.createInjector(context, clock, service, Random(random.nextLong())) -- cgit v1.2.3 From 3d5eb562227dcad5a8a60f31b96e6d68f7774fb2 Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Fri, 23 Sep 2022 12:27:09 +0200 Subject: refactor(compute): Provide access to instances in compute service This change updates the interface of `ComputeService` to provide access to the instances (servers) that have been registered with the compute service. This allows metric collectors to query the metrics of the servers that are currently running. --- .../org/opendc/compute/workload/ComputeServiceHelper.kt | 13 ++----------- .../compute/workload/telemetry/ComputeMetricReader.kt | 9 ++++++--- 2 files changed, 8 insertions(+), 14 deletions(-) (limited to 'opendc-compute/opendc-compute-workload/src/main') diff --git a/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/ComputeServiceHelper.kt b/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/ComputeServiceHelper.kt index 4c07b785..f6744123 100644 --- a/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/ComputeServiceHelper.kt +++ b/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/ComputeServiceHelper.kt @@ -26,7 +26,6 @@ import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.delay import kotlinx.coroutines.launch import kotlinx.coroutines.yield -import org.opendc.compute.api.Server import org.opendc.compute.service.ComputeService import org.opendc.compute.service.scheduler.ComputeScheduler import org.opendc.compute.simulator.SimHost @@ -59,7 +58,7 @@ public class ComputeServiceHelper( /** * The [ComputeService] that has been configured by the manager. */ - public val service: ComputeService + public val service: ComputeService = ComputeService(context, clock, scheduler, schedulingQuantum) /** * The [FlowEngine] to simulate the hosts. @@ -76,29 +75,23 @@ public class ComputeServiceHelper( */ private val random = SplittableRandom(seed) - init { - val service = createService(scheduler, schedulingQuantum) - this.service = service - } - /** * Run a simulation of the [ComputeService] by replaying the workload trace given by [trace]. * * @param trace The trace to simulate. - * @param servers A list to which the created servers is added. * @param submitImmediately A flag to indicate that the servers are scheduled immediately (so not at their start time). * @param failureModel A failure model to use for injecting failures. * @param interference A flag to indicate that VM interference needs to be enabled. */ public suspend fun run( trace: List, - servers: MutableList? = null, submitImmediately: Boolean = false, failureModel: FailureModel? = null, interference: Boolean = false, ) { val injector = failureModel?.createInjector(context, clock, service, Random(random.nextLong())) val client = service.newClient() + val clock = clock // Create new image for the virtual machine val image = client.newImage("vm-image") @@ -147,8 +140,6 @@ public class ComputeServiceHelper( meta = meta ) - servers?.add(server) - // Wait for the server reach its end time val endTime = entry.stopTime.toEpochMilli() delay(endTime + workloadOffset - clock.millis() + 5 * 60 * 1000) diff --git a/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/telemetry/ComputeMetricReader.kt b/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/telemetry/ComputeMetricReader.kt index 45bd9ab1..a0ec4bd6 100644 --- a/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/telemetry/ComputeMetricReader.kt +++ b/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/telemetry/ComputeMetricReader.kt @@ -42,7 +42,6 @@ import java.time.Instant * @param scope The [CoroutineScope] to run the reader in. * @param clock The virtual clock. * @param service The [ComputeService] to monitor. - * @param servers The [Server]s to monitor. * @param monitor The monitor to export the metrics to. * @param exportInterval The export interval. */ @@ -50,7 +49,6 @@ public class ComputeMetricReader( scope: CoroutineScope, clock: Clock, private val service: ComputeService, - private val servers: List, private val monitor: ComputeMonitor, private val exportInterval: Duration = Duration.ofMinutes(5) ) : AutoCloseable { @@ -76,6 +74,11 @@ public class ComputeMetricReader( */ private val job = scope.launch { val intervalMs = exportInterval.toMillis() + val service = service + val monitor = monitor + val hostTableReaders = hostTableReaders + val serverTableReaders = serverTableReaders + val serviceTableReader = serviceTableReader try { while (isActive) { @@ -91,7 +94,7 @@ public class ComputeMetricReader( reader.reset() } - for (server in servers) { + for (server in service.servers) { val reader = serverTableReaders.computeIfAbsent(server) { ServerTableReaderImpl(service, it) } reader.record(now) monitor.record(reader) -- cgit v1.2.3