diff options
| author | Fabian Mastenbroek <mail.fabianm@gmail.com> | 2020-10-04 17:17:23 +0200 |
|---|---|---|
| committer | Fabian Mastenbroek <mail.fabianm@gmail.com> | 2020-10-04 17:23:34 +0200 |
| commit | 47f803afc14a50c467d2f5f7ff406824428223f7 (patch) | |
| tree | afb4109773039d908578bafd2f80edf70ef21e63 /simulator/opendc-compute | |
| parent | 136c1b9ddc7bd9331d3552d681e9190fc6198271 (diff) | |
Reimplement performance interference in opendc-simulator-compute
This change reimplements the performance interference model originally
implemented for the SimpleVirtDriver class, for SimHypervisor.
Diffstat (limited to 'simulator/opendc-compute')
2 files changed, 20 insertions, 135 deletions
diff --git a/simulator/opendc-compute/src/main/kotlin/org/opendc/compute/core/workload/PerformanceInterferenceModel.kt b/simulator/opendc-compute/src/main/kotlin/org/opendc/compute/core/workload/PerformanceInterferenceModel.kt deleted file mode 100644 index 51f62197..00000000 --- a/simulator/opendc-compute/src/main/kotlin/org/opendc/compute/core/workload/PerformanceInterferenceModel.kt +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (c) 2020 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.compute.core.workload - -import java.util.* -import kotlin.random.Random - -/** - * Meta-data key for the [PerformanceInterferenceModel] of an image. - */ -public const val IMAGE_PERF_INTERFERENCE_MODEL: String = "image:performance-interference" - -/** - * Performance Interference Model describing the variability incurred by different sets of workloads if colocated. - * - * @param items The [PerformanceInterferenceModelItem]s that make up this model. - */ -public class PerformanceInterferenceModel( - public val items: SortedSet<PerformanceInterferenceModelItem>, - private val random: Random = Random(0) -) { - private var intersectingItems: List<PerformanceInterferenceModelItem> = emptyList() - private val colocatedWorkloads = TreeMap<String, Int>() - - /** - * Indicate that a VM has started. - */ - public fun onStart(name: String) { - colocatedWorkloads.merge(name, 1, Int::plus) - intersectingItems = items.filter { item -> doesMatch(item) } - } - - /** - * Indicate that a VM has stopped. - */ - public fun onStop(name: String) { - colocatedWorkloads.computeIfPresent(name) { _, v -> (v - 1).takeUnless { it == 0 } } - intersectingItems = items.filter { item -> doesMatch(item) } - } - - /** - * Compute the performance interference based on the current server load. - */ - public fun apply(currentServerLoad: Double): Double { - if (intersectingItems.isEmpty()) { - return 1.0 - } - val score = intersectingItems - .firstOrNull { it.minServerLoad <= currentServerLoad } - - // Apply performance penalty to (on average) only one of the VMs - return if (score != null && random.nextInt(score.workloadNames.size) == 0) { - score.performanceScore - } else { - 1.0 - } - } - - private fun doesMatch(item: PerformanceInterferenceModelItem): Boolean { - var count = 0 - for ( - name in item.workloadNames.subSet( - colocatedWorkloads.firstKey(), - colocatedWorkloads.lastKey() + "\u0000" - ) - ) { - count += colocatedWorkloads.getOrDefault(name, 0) - if (count > 1) - return true - } - return false - } -} - -/** - * Model describing how a specific set of workloads causes performance variability for each workload. - * - * @param workloadNames The names of the workloads that together cause performance variability for each workload in the set. - * @param minServerLoad The minimum total server load at which this interference is activated and noticeable. - * @param performanceScore The performance score that should be applied to each workload's performance. 1 means no - * influence, <1 means that performance degrades, and >1 means that performance improves. - */ -public data class PerformanceInterferenceModelItem( - public val workloadNames: SortedSet<String>, - public val minServerLoad: Double, - public val performanceScore: Double -) : Comparable<PerformanceInterferenceModelItem> { - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (javaClass != other?.javaClass) return false - - other as PerformanceInterferenceModelItem - - if (workloadNames != other.workloadNames) return false - - return true - } - - override fun hashCode(): Int = workloadNames.hashCode() - - override fun compareTo(other: PerformanceInterferenceModelItem): Int { - var cmp = performanceScore.compareTo(other.performanceScore) - if (cmp != 0) { - return cmp - } - - cmp = minServerLoad.compareTo(other.minServerLoad) - if (cmp != 0) { - return cmp - } - - return hashCode().compareTo(other.hashCode()) - } -} diff --git a/simulator/opendc-compute/src/main/kotlin/org/opendc/compute/virt/driver/SimVirtDriver.kt b/simulator/opendc-compute/src/main/kotlin/org/opendc/compute/virt/driver/SimVirtDriver.kt index 6e0df93f..357ad714 100644 --- a/simulator/opendc-compute/src/main/kotlin/org/opendc/compute/virt/driver/SimVirtDriver.kt +++ b/simulator/opendc-compute/src/main/kotlin/org/opendc/compute/virt/driver/SimVirtDriver.kt @@ -35,6 +35,8 @@ import org.opendc.core.services.ServiceRegistry import org.opendc.simulator.compute.SimExecutionContext import org.opendc.simulator.compute.SimHypervisor import org.opendc.simulator.compute.SimMachine +import org.opendc.simulator.compute.interference.IMAGE_PERF_INTERFERENCE_MODEL +import org.opendc.simulator.compute.interference.PerformanceInterferenceModel import org.opendc.simulator.compute.workload.SimWorkload import org.opendc.utils.flow.EventFlow import java.time.Clock @@ -124,15 +126,31 @@ public class SimVirtDriver( events ) availableMemory -= requiredMemory - vms.add(VirtualMachine(server, events, hypervisor.createMachine(ctx.machine))) + val vm = VirtualMachine(server, events, hypervisor.createMachine(ctx.machine)) + vms.add(vm) + vmStarted(vm) eventFlow.emit(HypervisorEvent.VmsUpdated(this, vms.size, availableMemory)) return server } + private fun vmStarted(vm: VirtualMachine) { + vms.forEach { it -> + vm.performanceInterferenceModel?.onStart(it.server.image.name) + } + } + + private fun vmStopped(vm: VirtualMachine) { + vms.forEach { it -> + vm.performanceInterferenceModel?.onStop(it.server.image.name) + } + } + /** * A virtual machine instance that the driver manages. */ private inner class VirtualMachine(server: Server, val events: EventFlow<ServerEvent>, machine: SimMachine) { + val performanceInterferenceModel: PerformanceInterferenceModel? = server.image.tags[IMAGE_PERF_INTERFERENCE_MODEL] as? PerformanceInterferenceModel? + val job = coroutineScope.launch { val workload = object : SimWorkload { override suspend fun run(ctx: SimExecutionContext) { @@ -176,6 +194,7 @@ public class SimVirtDriver( server = server.copy(state = serverState) availableMemory += server.flavor.memorySize vms.remove(this) + vmStopped(this) eventFlow.emit(HypervisorEvent.VmsUpdated(this@SimVirtDriver, vms.size, availableMemory)) events.close() } |
