diff options
Diffstat (limited to 'opendc/opendc-compute/src')
5 files changed, 24 insertions, 12 deletions
diff --git a/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/FlopsHistoryFragment.kt b/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/FlopsHistoryFragment.kt index 320c09ff..92c0ab0c 100644 --- a/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/FlopsHistoryFragment.kt +++ b/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/FlopsHistoryFragment.kt @@ -1,3 +1,3 @@ package com.atlarge.opendc.compute.core.image -data class FlopsHistoryFragment(val tick: Long, val flops: Long, val duration: Long) +data class FlopsHistoryFragment(val tick: Long, val flops: Long, val duration: Long, val usage: Double) diff --git a/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/VmImage.kt b/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/VmImage.kt index 257b6149..4e8162ec 100644 --- a/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/VmImage.kt +++ b/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/VmImage.kt @@ -1,5 +1,6 @@ package com.atlarge.opendc.compute.core.image +import com.atlarge.odcsim.processContext import com.atlarge.opendc.compute.core.execution.ServerContext import com.atlarge.opendc.core.resource.TagContainer import kotlinx.coroutines.coroutineScope @@ -24,11 +25,10 @@ class VmImage( } else { val cores = min(this.cores, ctx.server.flavor.cpuCount) val req = fragment.flops / cores - coroutineScope { for (cpu in ctx.cpus.take(cores)) { - val usage = req / (fragment.duration * 1_000_000L).toDouble() - launch { cpu.run(req, usage, fragment.tick + fragment.duration) } + val usage = req / (fragment.usage * 1_000_000L) + launch { cpu.run(req, usage, processContext.clock.millis() + fragment.duration) } } } } diff --git a/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/driver/SimpleBareMetalDriver.kt b/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/driver/SimpleBareMetalDriver.kt index 202c30e9..b6d74cde 100644 --- a/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/driver/SimpleBareMetalDriver.kt +++ b/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/driver/SimpleBareMetalDriver.kt @@ -130,16 +130,19 @@ public class SimpleBareMetalDriver( private data class ProcessorContextImpl(override val info: ProcessingUnit) : ProcessorContext { override suspend fun run(burst: Long, maxUsage: Double, deadline: Long): Long { val start = processContext.clock.millis() - val usage = min(maxUsage, info.clockRate) + val usage = min(maxUsage, info.clockRate) * 1_000_000 // Usage from MHz to Hz try { - val duration = min(max(0, deadline - start), ceil(burst / usage).toLong()) + val duration = min( + max(0, deadline - start), // Determine duration between now and deadline + ceil(burst / usage * 1000).toLong() // Convert from seconds to milliseconds + ) delay(duration) } catch (_: CancellationException) { // On cancellation, we compute and return the remaining burst } val end = processContext.clock.millis() - val granted = ceil((end - start) * usage * 1_000_000).toLong() + val granted = ceil((end - start) / 1000.0 * usage).toLong() return max(0, burst - granted) } } diff --git a/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/driver/hypervisor/HypervisorVirtDriver.kt b/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/driver/hypervisor/HypervisorVirtDriver.kt index 65ec75a2..c0d5fe0f 100644 --- a/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/driver/hypervisor/HypervisorVirtDriver.kt +++ b/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/driver/hypervisor/HypervisorVirtDriver.kt @@ -61,6 +61,7 @@ class HypervisorVirtDriver( if (memoryAvailable - requiredMemory < 0) { throw InsufficientMemoryOnServerException() } + require(flavor.cpuCount <= hostContext.server.flavor.cpuCount) { "Machine does not fit" } val server = Server(UUID.randomUUID(), "<unnamed>", emptyMap(), flavor, image, ServerState.BUILD) memoryAvailable -= requiredMemory diff --git a/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/driver/hypervisor/VmSchedulerImpl.kt b/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/driver/hypervisor/VmSchedulerImpl.kt index dfed3d58..0b172c61 100644 --- a/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/driver/hypervisor/VmSchedulerImpl.kt +++ b/opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/driver/hypervisor/VmSchedulerImpl.kt @@ -55,8 +55,12 @@ public class VmSchedulerImpl( override fun createVirtualCpus(flavor: Flavor): List<ProcessorContext> { // TODO At the moment, the first N cores get filled the first. Distribute over all cores instead - return cpus.asSequence() + require(flavor.cpuCount <= cpus.size) { "Flavor cannot fit on machine" } + + return cpus + .asSequence() .take(flavor.cpuCount) + .sortedBy { it.vcpus.size } .map { VirtualProcessorContext(it) } .toList() } @@ -96,7 +100,7 @@ public class VmSchedulerImpl( vcpu.actualUsage = min(vcpu.requestedUsage, info.clockRate / vcpus.size) // The duration that we want to run is that of the shortest request from a vCPU - duration = min(duration, ceil(vcpu.requestedBurst / vcpu.actualUsage).toLong()) + duration = min(duration, ceil(vcpu.requestedBurst / (vcpu.actualUsage * 1_000_000L)).toLong()) deadline = min(deadline, vcpu.requestedDeadline) } @@ -104,16 +108,21 @@ public class VmSchedulerImpl( var usage: Double = 0.0 for (vcpu in vcpus) { - vcpu.actualBurst = (duration * vcpu.actualUsage).toLong() + vcpu.actualBurst = (duration * vcpu.actualUsage * 1_000_000L).toLong() burst += vcpu.actualBurst usage += vcpu.actualUsage } + // Ignore time slice if no work to request + if (burst <= 0L) { + return@launch + } + // We run the total burst on the host processor. Note that this call may be cancelled at any moment in // time, so not all of the burst may be executed. val remainder = run(burst, usage, deadline) val time = processContext.clock.millis() - var totalGrantedBurst: Long = 0 + val totalGrantedBurst: Long = burst - remainder // Compute for each vCPU the for (vcpu in vcpus) { @@ -121,7 +130,6 @@ public class VmSchedulerImpl( val fraction = vcpu.actualUsage / usage // Compute the burst time that the VM was actually granted val grantedBurst = max(0, vcpu.actualBurst - ceil(remainder * fraction).toLong()) - totalGrantedBurst += grantedBurst // Compute remaining burst time to be executed for the request vcpu.requestedBurst = max(0, vcpu.requestedBurst - grantedBurst) |
