From 48ddc082ea301f54717a8ab7c54023f73220e4eb Mon Sep 17 00:00:00 2001 From: Dante Niewenhuis Date: Thu, 2 Oct 2025 15:32:32 +0200 Subject: Improved FilterScheduler using a constantly sorting array (#374) Updated FilterScheduler.kt for performance using a constantly sorted Array --- .../compute/simulator/service/ComputeService.java | 23 +++- .../opendc/compute/simulator/service/HostView.java | 6 + .../simulator/scheduler/ComputeScheduler.kt | 6 + .../simulator/scheduler/ComputeSchedulers.kt | 19 ++- .../compute/simulator/scheduler/FilterScheduler.kt | 83 ++++++++---- .../simulator/scheduler/MemorizingScheduler.kt | 4 + .../simulator/scheduler/SortedHostViewList.kt | 143 +++++++++++++++++++++ .../simulator/scheduler/filters/HostFilter.kt | 4 + .../simulator/scheduler/filters/RamFilter.kt | 14 +- .../simulator/scheduler/filters/VCpuFilter.kt | 17 ++- .../scheduler/timeshift/MemorizingTimeshift.kt | 4 + .../scheduler/timeshift/TimeshiftScheduler.kt | 4 + 12 files changed, 293 insertions(+), 34 deletions(-) create mode 100644 opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/scheduler/SortedHostViewList.kt (limited to 'opendc-compute/opendc-compute-simulator/src/main') diff --git a/opendc-compute/opendc-compute-simulator/src/main/java/org/opendc/compute/simulator/service/ComputeService.java b/opendc-compute/opendc-compute-simulator/src/main/java/org/opendc/compute/simulator/service/ComputeService.java index 3f6ef73b..f1e747b3 100644 --- a/opendc-compute/opendc-compute-simulator/src/main/java/org/opendc/compute/simulator/service/ComputeService.java +++ b/opendc-compute/opendc-compute-simulator/src/main/java/org/opendc/compute/simulator/service/ComputeService.java @@ -151,8 +151,10 @@ public final class ComputeService implements AutoCloseable, CarbonReceiver { if (hv != null) { if (newState == HostState.UP) { availableHosts.add(hv); + restartHosts(hv); } else { availableHosts.remove(hv); + failHosts(hv); } } @@ -184,6 +186,7 @@ public final class ComputeService implements AutoCloseable, CarbonReceiver { final ServiceFlavor flavor = task.getFlavor(); if (hv != null) { hv.provisionedCpuCores -= flavor.getCpuCoreCount(); + hv.availableCpuCores += flavor.getCpuCoreCount(); hv.instanceCount--; hv.availableMemory += flavor.getMemorySize(); hv.provisionedGpuCores -= flavor.getGpuCoreCount(); @@ -193,9 +196,7 @@ public final class ComputeService implements AutoCloseable, CarbonReceiver { host.delete(task); - if (host.isEmpty()) { - setHostEmpty(host); - } + updateHost(host); if (newState == TaskState.COMPLETED) { tasksCompleted++; @@ -298,10 +299,18 @@ public final class ComputeService implements AutoCloseable, CarbonReceiver { host.addListener(hostListener); } - public void setHostEmpty(SimHost host) { + public void updateHost(SimHost host) { HostView hv = hostToView.get(host); - this.scheduler.setHostEmpty(hv); + this.scheduler.updateHost(hv); + } + + public void failHosts(HostView hv) { + this.scheduler.failHost(hv); + } + + public void restartHosts(HostView hv) { + this.scheduler.restartHost(hv); } public void addPowerSource(SimPowerSource simPowerSource) { @@ -519,6 +528,7 @@ public final class ComputeService implements AutoCloseable, CarbonReceiver { for (Iterator iterator = taskQueue.iterator(); iterator.hasNext(); iterator = taskQueue.iterator()) { + final SchedulingResult result = scheduler.select(iterator); if (result.getResultType() == SchedulingResultType.EMPTY) { break; @@ -570,10 +580,13 @@ public final class ComputeService implements AutoCloseable, CarbonReceiver { hv.instanceCount++; hv.provisionedCpuCores += flavor.getCpuCoreCount(); + hv.availableCpuCores -= flavor.getCpuCoreCount(); hv.availableMemory -= flavor.getMemorySize(); hv.provisionedGpuCores += flavor.getGpuCoreCount(); activeTasks.put(task, host); + + updateHost(host); } catch (Exception cause) { LOGGER.error("Failed to deploy VM", cause); scheduler.removeTask(task, hv); diff --git a/opendc-compute/opendc-compute-simulator/src/main/java/org/opendc/compute/simulator/service/HostView.java b/opendc-compute/opendc-compute-simulator/src/main/java/org/opendc/compute/simulator/service/HostView.java index c07f58c7..ba4dbf64 100644 --- a/opendc-compute/opendc-compute-simulator/src/main/java/org/opendc/compute/simulator/service/HostView.java +++ b/opendc-compute/opendc-compute-simulator/src/main/java/org/opendc/compute/simulator/service/HostView.java @@ -32,6 +32,7 @@ public class HostView { int instanceCount; long availableMemory; int provisionedCpuCores; + int availableCpuCores; int provisionedGpuCores; /** @@ -58,6 +59,7 @@ public class HostView { public HostView(SimHost host) { this.host = host; this.availableMemory = host.getModel().memoryCapacity(); + this.availableCpuCores = host.getModel().coreCount(); } /** @@ -88,6 +90,10 @@ public class HostView { return provisionedCpuCores; } + public int getAvailableCpuCores() { + return availableCpuCores; + } + public int getProvisionedGpuCores() { return provisionedGpuCores; } diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/scheduler/ComputeScheduler.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/scheduler/ComputeScheduler.kt index 65037817..f951c3fa 100644 --- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/scheduler/ComputeScheduler.kt +++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/scheduler/ComputeScheduler.kt @@ -39,6 +39,12 @@ public interface ComputeScheduler { */ public fun removeHost(host: HostView) + public fun failHost(host: HostView) {} + + public fun restartHost(host: HostView) {} + + public fun updateHost(host: HostView) + public fun setHostEmpty(hostView: HostView) /** diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/scheduler/ComputeSchedulers.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/scheduler/ComputeSchedulers.kt index 79af6f62..01804a70 100644 --- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/scheduler/ComputeSchedulers.kt +++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/scheduler/ComputeSchedulers.kt @@ -59,8 +59,9 @@ public fun createPrefabComputeScheduler( name: String, seeder: RandomGenerator, clock: InstantSource, + numHosts: Int = 1000, ): ComputeScheduler { - return createPrefabComputeScheduler(ComputeSchedulerEnum.valueOf(name.uppercase()), seeder, clock) + return createPrefabComputeScheduler(ComputeSchedulerEnum.valueOf(name.uppercase()), seeder, clock, numHosts) } /** @@ -70,50 +71,59 @@ public fun createPrefabComputeScheduler( name: ComputeSchedulerEnum, seeder: RandomGenerator, clock: InstantSource, + numHosts: Int = 1000, ): ComputeScheduler { val cpuAllocationRatio = 1.0 - val ramAllocationRatio = 1.5 + val ramAllocationRatio = 1.0 val gpuAllocationRatio = 1.0 return when (name) { ComputeSchedulerEnum.Mem -> FilterScheduler( - filters = listOf(ComputeFilter(), VCpuFilter(cpuAllocationRatio), RamFilter(ramAllocationRatio)), + filters = listOf(VCpuFilter(cpuAllocationRatio), RamFilter(ramAllocationRatio)), weighers = listOf(RamWeigher(multiplier = 1.0)), + numHosts = numHosts, ) ComputeSchedulerEnum.MemInv -> FilterScheduler( filters = listOf(ComputeFilter(), VCpuFilter(cpuAllocationRatio), RamFilter(ramAllocationRatio)), weighers = listOf(RamWeigher(multiplier = -1.0)), + numHosts = numHosts, ) ComputeSchedulerEnum.CoreMem -> FilterScheduler( filters = listOf(ComputeFilter(), VCpuFilter(cpuAllocationRatio), RamFilter(ramAllocationRatio)), weighers = listOf(CoreRamWeigher(multiplier = 1.0)), + numHosts = numHosts, ) ComputeSchedulerEnum.CoreMemInv -> FilterScheduler( filters = listOf(ComputeFilter(), VCpuFilter(cpuAllocationRatio), RamFilter(ramAllocationRatio)), weighers = listOf(CoreRamWeigher(multiplier = -1.0)), + numHosts = numHosts, ) ComputeSchedulerEnum.ActiveServers -> FilterScheduler( filters = listOf(ComputeFilter(), VCpuFilter(cpuAllocationRatio), RamFilter(ramAllocationRatio)), weighers = listOf(InstanceCountWeigher(multiplier = -1.0)), + numHosts = numHosts, ) ComputeSchedulerEnum.ActiveServersInv -> FilterScheduler( filters = listOf(ComputeFilter(), VCpuFilter(cpuAllocationRatio), RamFilter(ramAllocationRatio)), weighers = listOf(InstanceCountWeigher(multiplier = 1.0)), + numHosts = numHosts, ) ComputeSchedulerEnum.ProvisionedCores -> FilterScheduler( filters = listOf(ComputeFilter(), VCpuFilter(cpuAllocationRatio), RamFilter(ramAllocationRatio)), weighers = listOf(VCpuWeigher(cpuAllocationRatio, multiplier = 1.0)), + numHosts = numHosts, ) ComputeSchedulerEnum.ProvisionedCoresInv -> FilterScheduler( filters = listOf(ComputeFilter(), VCpuFilter(cpuAllocationRatio), RamFilter(ramAllocationRatio)), weighers = listOf(VCpuWeigher(cpuAllocationRatio, multiplier = -1.0)), + numHosts = numHosts, ) ComputeSchedulerEnum.Random -> FilterScheduler( @@ -121,6 +131,7 @@ public fun createPrefabComputeScheduler( weighers = emptyList(), subsetSize = Int.MAX_VALUE, random = SplittableRandom(seeder.nextLong()), + numHosts = numHosts, ) ComputeSchedulerEnum.TaskNumMemorizing -> MemorizingScheduler( @@ -144,6 +155,7 @@ public fun createPrefabComputeScheduler( RamFilter(ramAllocationRatio), ), weighers = listOf(VCpuWeigher(cpuAllocationRatio, multiplier = 1.0), VGpuWeigher(gpuAllocationRatio, multiplier = 1.0)), + numHosts = numHosts, ) ComputeSchedulerEnum.ProvisionedCpuGpuCoresInv -> FilterScheduler( @@ -159,6 +171,7 @@ public fun createPrefabComputeScheduler( VCpuWeigher(cpuAllocationRatio, multiplier = -1.0), VGpuWeigher(gpuAllocationRatio, multiplier = -1.0), ), + numHosts = numHosts, ) ComputeSchedulerEnum.GpuTaskMemorizing -> MemorizingScheduler( diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/scheduler/FilterScheduler.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/scheduler/FilterScheduler.kt index fb7eadfb..3dab71b0 100644 --- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/scheduler/FilterScheduler.kt +++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/scheduler/FilterScheduler.kt @@ -46,13 +46,18 @@ public class FilterScheduler( private val weighers: List, private val subsetSize: Int = 1, private val random: RandomGenerator = SplittableRandom(0), + numHosts: Int = 1000, ) : ComputeScheduler { /** * The pool of hosts available to the scheduler. */ + private val failedHosts = mutableListOf() // List of Hosts that are currently not available private val emptyHostMap = mutableMapOf>() - private val usedHosts = mutableListOf() + + private val weights = DoubleArray(numHosts) + + private val usedHosts = SortedHostViewList(numHosts, filters) init { require(subsetSize >= 1) { "Subset size must be one or greater" } @@ -68,10 +73,39 @@ public class FilterScheduler( } } + // Remove host from the Available hosts list override fun removeHost(hostView: HostView) { val hostType = hostView.host.getType() - emptyHostMap[hostType]?.remove(hostView) + // remove from emptyHosts if present + val removed = emptyHostMap[hostType]?.remove(hostView) + if (removed != null && removed) { + return + } + + // If the hosts was being used, remove it from there + usedHosts.remove(hostView) + } + + // Remove a failed host from available hosts, and add it to the failed hosts. + override fun failHost(hostView: HostView) { + removeHost(hostView) + failedHosts.add(hostView) + } + + override fun restartHost(hostView: HostView) { + val removed = failedHosts.remove(hostView) + if (removed) { + addHost(hostView) + } + } + + override fun updateHost(hostView: HostView) { + if (hostView.host.isEmpty()) { + setHostEmpty(hostView) + } else { + usedHosts.updateHost(hostView) + } } override fun setHostEmpty(hostView: HostView) { @@ -98,20 +132,29 @@ public class FilterScheduler( } } - val availableHosts = usedHosts.toMutableList() + val task = req.task + + val fittingHosts = usedHosts.getFittingHosts(task) + for (emptyHosts in emptyHostMap.values) { if (!emptyHosts.isEmpty()) { - availableHosts += emptyHosts.first() + val host = emptyHosts.first() + if (filters.all { filter -> filter.test(host, req.task) }) { + fittingHosts.add(host) + } } } - val task = req.task - val filteredHosts = availableHosts.filter { host -> filters.all { filter -> filter.test(host, task) } } + if (fittingHosts.isEmpty()) { + return SchedulingResult(SchedulingResultType.FAILURE, null, req) + } + + var maxWeight = Double.MIN_VALUE + var maxIndex = 0 - val subset = + val hostView = if (weighers.isNotEmpty()) { - val results = weighers.map { it.getWeights(filteredHosts, task) } - val weights = DoubleArray(filteredHosts.size) + val results = weighers.map { it.getWeights(fittingHosts, task) } for (result in results) { val min = result.min @@ -126,32 +169,26 @@ public class FilterScheduler( val factor = multiplier / range for ((i, weight) in result.weights.withIndex()) { - weights[i] += factor * (weight - min) + this.weights[i] += factor * (weight - min) + if (this.weights[i] > maxWeight) { + maxIndex = i + maxWeight = weight + } } } - weights.indices - .asSequence() - .sortedByDescending { weights[it] } - .map { filteredHosts[it] } - .take(subsetSize) - .toList() + fittingHosts[maxIndex] } else { - filteredHosts + fittingHosts.first() } - if (subset.isEmpty()) { - return SchedulingResult(SchedulingResultType.FAILURE, null, req) - } - iter.remove() - val hostView = subset.first() val hostType = hostView.host.getType() if (hostView.host.isEmpty()) { emptyHostMap[hostType]?.remove(hostView) - usedHosts.add(hostView) + usedHosts.addSorted(hostView) } return SchedulingResult(SchedulingResultType.SUCCESS, hostView, req) diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/scheduler/MemorizingScheduler.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/scheduler/MemorizingScheduler.kt index 9f21c71f..3efc686d 100644 --- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/scheduler/MemorizingScheduler.kt +++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/scheduler/MemorizingScheduler.kt @@ -73,6 +73,10 @@ public class MemorizingScheduler( numHosts-- } + override fun updateHost(hostView: HostView) { + // No-op + } + override fun setHostEmpty(hostView: HostView) { // No-op } diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/scheduler/SortedHostViewList.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/scheduler/SortedHostViewList.kt new file mode 100644 index 00000000..d2718726 --- /dev/null +++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/scheduler/SortedHostViewList.kt @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2025 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.simulator.scheduler + +import org.opendc.compute.simulator.scheduler.filters.HostFilter +import org.opendc.compute.simulator.service.HostView +import org.opendc.compute.simulator.service.ServiceTask + +public class SortedHostViewList( + public val capacity: Int, + public val filters: List, +) { + private var firstFilter: HostFilter + private var otherFilters: List = listOf() + + private var noFilters = false + + public val hosts: ArrayList = ArrayList(capacity) + + public var cmp: Comparator + + init { + cmp = compareBy { filters[0].score(it) as Comparable<*>? } + for (i in 1 until filters.size) { + cmp = cmp.thenBy { filters[i].score(it) as Comparable<*>? } + } + + if (filters.isNotEmpty()) { + firstFilter = filters[0] + } else { + noFilters = true + firstFilter = + object : HostFilter { + override fun test( + host: HostView, + task: ServiceTask, + ): Boolean { + return true + } + + override fun score(host: HostView): Double { + return 0.0 + } + } + } + + if (filters.size > 1) { + otherFilters = filters.subList(1, filters.size) + } + } + + public fun addSorted(hostView: HostView) { + if (noFilters) { + hosts.add(hostView) + return + } + + val index = hosts.binarySearch(hostView, cmp) + val insertIndex = if (index < 0) -index - 1 else index + hosts.add(insertIndex, hostView) + } + + public fun updateHost(hostView: HostView) { + // TODO: See if we can improve this by using binary search to find the index + hosts.remove(hostView) + + // TODO: See if we can move this instead of removing and adding + addSorted(hostView) + } + + public fun findIndex(task: ServiceTask): Int { + // lower_bound on firstFilter.score + var lowIndex = 0 + var highIndex = this.hosts.size + while (lowIndex < highIndex) { + val mid = (lowIndex + highIndex) ushr 1 + if (this.firstFilter.test(this.hosts[mid], task)) highIndex = mid else lowIndex = mid + 1 + } + + if (lowIndex == 0) { + return if (this.hosts.isNotEmpty() && this.firstFilter.test(this.hosts[0], task)) 0 else -1 + } + + return lowIndex + } + + public fun remove(hostView: HostView) { + hosts.remove(hostView) + } + + public fun getFittingHosts(task: ServiceTask): MutableList { + if (filters.isEmpty()) { + return hosts + } + + val index = findIndex(task) + + if (index < 0) return mutableListOf() + + var subset = hosts.subList(index, hosts.size).toMutableList() + + if (otherFilters.isEmpty()) { + return subset + } + + subset = subset.filter { host -> otherFilters.all { it.test(host, task) } }.toMutableList() + + return subset + } + + public fun isSorted(): Boolean { + return hosts.isSorted(cmp) + } + + private fun List.isSorted(comparator: Comparator): Boolean { + for (i in 0 until size - 1) { + if (comparator.compare(this[i], this[i + 1]) > 0) { + return false + } + } + return true + } +} diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/scheduler/filters/HostFilter.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/scheduler/filters/HostFilter.kt index bb9c1cbf..536ad8ff 100644 --- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/scheduler/filters/HostFilter.kt +++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/scheduler/filters/HostFilter.kt @@ -37,4 +37,8 @@ public fun interface HostFilter { host: HostView, task: ServiceTask, ): Boolean + + public fun score(host: HostView): Number = 0.0 + + public fun requiredScore(task: ServiceTask): Number = 0.0 } diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/scheduler/filters/RamFilter.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/scheduler/filters/RamFilter.kt index 0b570d52..fcc5e49c 100644 --- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/scheduler/filters/RamFilter.kt +++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/scheduler/filters/RamFilter.kt @@ -30,11 +30,15 @@ import org.opendc.compute.simulator.service.ServiceTask * * @param allocationRatio Virtual RAM to physical RAM allocation ratio. */ -public class RamFilter(private val allocationRatio: Double) : HostFilter { +public class RamFilter(private val allocationRatio: Double = 1.0) : HostFilter { + private val isSimple = allocationRatio == 1.0 + override fun test( host: HostView, task: ServiceTask, ): Boolean { + if (isSimple) return host.availableMemory >= task.flavor.memorySize + val requestedMemory = task.flavor.memorySize val availableMemory = host.availableMemory val memoryCapacity = host.host.getModel().memoryCapacity @@ -52,4 +56,12 @@ public class RamFilter(private val allocationRatio: Double) : HostFilter { val result = usable >= requestedMemory return result } + + override fun score(host: HostView): Double { + return if (isSimple) { + return host.availableMemory.toDouble() + } else { + host.host.getModel().memoryCapacity * allocationRatio + } + } } diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/scheduler/filters/VCpuFilter.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/scheduler/filters/VCpuFilter.kt index 89739658..a017c623 100644 --- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/scheduler/filters/VCpuFilter.kt +++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/scheduler/filters/VCpuFilter.kt @@ -30,21 +30,34 @@ import org.opendc.compute.simulator.service.ServiceTask * * @param allocationRatio Virtual CPU to physical CPU allocation ratio. */ -public class VCpuFilter(private val allocationRatio: Double) : HostFilter { +public class VCpuFilter(private val allocationRatio: Double = 1.0) : HostFilter { + private val isSimple = allocationRatio == 1.0 + override fun test( host: HostView, task: ServiceTask, ): Boolean { + if (isSimple) return host.availableCpuCores >= task.flavor.cpuCoreCount + val requested = task.flavor.cpuCoreCount val totalCores = host.host.getModel().coreCount - val limit = totalCores * allocationRatio // Do not allow an instance to overcommit against itself, only against other instances if (requested > totalCores) { return false } + val limit = totalCores * allocationRatio + val availableCores = limit - host.provisionedCpuCores return availableCores >= requested } + + override fun score(host: HostView): Double { + return if (isSimple) { + host.availableCpuCores.toDouble() + } else { + host.host.getModel().coreCount * allocationRatio + } + } } diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/scheduler/timeshift/MemorizingTimeshift.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/scheduler/timeshift/MemorizingTimeshift.kt index 6361f7d1..e0488e30 100644 --- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/scheduler/timeshift/MemorizingTimeshift.kt +++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/scheduler/timeshift/MemorizingTimeshift.kt @@ -88,6 +88,10 @@ public class MemorizingTimeshift( numHosts-- } + override fun updateHost(hostView: HostView) { + // No-op + } + override fun setHostEmpty(hostView: HostView) { // No-op } diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/scheduler/timeshift/TimeshiftScheduler.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/scheduler/timeshift/TimeshiftScheduler.kt index ff8be34b..58b8904b 100644 --- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/scheduler/timeshift/TimeshiftScheduler.kt +++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/scheduler/timeshift/TimeshiftScheduler.kt @@ -73,6 +73,10 @@ public class TimeshiftScheduler( hosts.remove(host) } + override fun updateHost(hostView: HostView) { + // No-op + } + override fun setHostEmpty(hostView: HostView) { // No-op } -- cgit v1.2.3