summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/FlopsHistoryFragment.kt2
-rw-r--r--opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/core/image/VmImage.kt6
-rw-r--r--opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/driver/SimpleBareMetalDriver.kt9
-rw-r--r--opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/driver/hypervisor/HypervisorVirtDriver.kt1
-rw-r--r--opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/virt/driver/hypervisor/VmSchedulerImpl.kt18
-rw-r--r--opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/Sc20HypervisorMonitor.kt16
-rw-r--r--opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/TestExperiment.kt2
-rw-r--r--opendc/opendc-experiments-sc20/src/main/resources/env/setup-small.json21
-rw-r--r--opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/trace/vm/VmTraceReader.kt11
9 files changed, 63 insertions, 23 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)
diff --git a/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/Sc20HypervisorMonitor.kt b/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/Sc20HypervisorMonitor.kt
index fc0c2686..e095d300 100644
--- a/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/Sc20HypervisorMonitor.kt
+++ b/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/Sc20HypervisorMonitor.kt
@@ -2,13 +2,15 @@ package com.atlarge.opendc.experiments.sc20
import com.atlarge.opendc.compute.core.Server
import com.atlarge.opendc.compute.virt.monitor.HypervisorMonitor
-import java.io.File
+import java.io.BufferedWriter
+import java.io.Closeable
+import java.io.FileWriter
-class Sc20HypervisorMonitor : HypervisorMonitor {
- private val outputFile = File("sc20-experiment-results.csv")
+class Sc20HypervisorMonitor : HypervisorMonitor, Closeable {
+ private val outputFile = BufferedWriter(FileWriter("sc20-experiment-results.csv"))
init {
- outputFile.writeText("time,requestedBurst,grantedBurst,numberOfDeployedImages,server\n")
+ outputFile.write("time,requestedBurst,grantedBurst,numberOfDeployedImages,server\n")
}
override fun onSliceFinish(
@@ -18,6 +20,10 @@ class Sc20HypervisorMonitor : HypervisorMonitor {
numberOfDeployedImages: Int,
hostServer: Server
) {
- outputFile.appendText("$time,$requestedBurst,$grantedBurst,$numberOfDeployedImages,$numberOfDeployedImages,${hostServer.uid}\n")
+ outputFile.write("$time,$requestedBurst,$grantedBurst,$numberOfDeployedImages,$numberOfDeployedImages,${hostServer.uid}\n")
+ }
+
+ override fun close() {
+ outputFile.close()
}
}
diff --git a/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/TestExperiment.kt b/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/TestExperiment.kt
index 439412ba..3882feb7 100644
--- a/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/TestExperiment.kt
+++ b/opendc/opendc-experiments-sc20/src/main/kotlin/com/atlarge/opendc/experiments/sc20/TestExperiment.kt
@@ -49,7 +49,7 @@ fun main(args: Array<String>) {
return
}
- val environment = Sc20EnvironmentReader(object {}.javaClass.getResourceAsStream("/env/setup-test.json"))
+ val environment = Sc20EnvironmentReader(object {}.javaClass.getResourceAsStream("/env/setup-small.json"))
.use { it.read() }
val token = Channel<Boolean>()
diff --git a/opendc/opendc-experiments-sc20/src/main/resources/env/setup-small.json b/opendc/opendc-experiments-sc20/src/main/resources/env/setup-small.json
new file mode 100644
index 00000000..80b24dba
--- /dev/null
+++ b/opendc/opendc-experiments-sc20/src/main/resources/env/setup-small.json
@@ -0,0 +1,21 @@
+{
+ "name": "Experimental Setup 2",
+ "rooms": [
+ {
+ "type": "SERVER",
+ "objects": [
+ {
+ "type": "RACK",
+ "machines": [
+ {"cpus": [1], "memories": [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]},
+ {"cpus": [1], "memories": [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]},
+ {"cpus": [1], "memories": [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]},
+ {"cpus": [1], "memories": [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]},
+ {"cpus": [1], "memories": [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]},
+ {"cpus": [1], "memories": [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]}
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/trace/vm/VmTraceReader.kt b/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/trace/vm/VmTraceReader.kt
index c3db9d33..2e881a6c 100644
--- a/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/trace/vm/VmTraceReader.kt
+++ b/opendc/opendc-format/src/main/kotlin/com/atlarge/opendc/format/trace/vm/VmTraceReader.kt
@@ -89,23 +89,24 @@ class VmTraceReader(traceDirectory: File) : TraceReader<VmWorkload> {
vmId = vmFile.nameWithoutExtension.trim().toLong()
val timestamp = values[timestampCol].trim().toLong() - 5 * 60
cores = values[coreCol].trim().toInt()
- val cpuUsage = values[cpuUsageCol].trim().toDouble()
+ val cpuUsage = values[cpuUsageCol].trim().toDouble() // MHz
requiredMemory = (values[provisionedMemoryCol].trim().toDouble() / 1000).toLong()
- val flops: Long = (cpuUsage * cores * 1_000_000L * 5 * 60).toLong()
+ val flops: Long = (cpuUsage * 1_000_000L * 5 * 60 * cores).toLong()
if (flopsHistory.isEmpty()) {
- flopsHistory.add(FlopsHistoryFragment(timestamp, flops, traceInterval))
+ flopsHistory.add(FlopsHistoryFragment(timestamp, flops, traceInterval, cpuUsage))
} else {
if (flopsHistory.last().flops != flops) {
- flopsHistory.add(FlopsHistoryFragment(timestamp, flops, traceInterval))
+ flopsHistory.add(FlopsHistoryFragment(timestamp, flops, traceInterval, cpuUsage))
} else {
val oldFragment = flopsHistory.removeAt(flopsHistory.size - 1)
flopsHistory.add(
FlopsHistoryFragment(
oldFragment.tick,
oldFragment.flops + flops,
- oldFragment.duration + traceInterval
+ oldFragment.duration + traceInterval,
+ cpuUsage
)
)
}