summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFabian Mastenbroek <mail.fabianm@gmail.com>2020-05-20 02:19:45 +0200
committerFabian Mastenbroek <mail.fabianm@gmail.com>2020-05-20 02:19:45 +0200
commitcbf8c3d0463c7ace0c659235fcc4234c6c71a2c0 (patch)
treeff802a1fbe13b5d3a2dea7995dccff23eac6f021
parent3b3ebd47f433fbf49b4cf476029bb168ca621aac (diff)
bug: Fix CPU usage calculation
-rw-r--r--opendc/opendc-compute/src/main/kotlin/com/atlarge/opendc/compute/metal/driver/SimpleBareMetalDriver.kt30
1 files changed, 19 insertions, 11 deletions
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 30981e6e..45dcae23 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
@@ -53,7 +53,6 @@ import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.InternalCoroutinesApi
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.intrinsics.startCoroutineCancellable
import kotlinx.coroutines.launch
import kotlinx.coroutines.selects.SelectClause0
@@ -118,9 +117,6 @@ public class SimpleBareMetalDriver(
@OptIn(FlowPreview::class)
override val usage: Flow<Double> = usageState
- // Debounce changes for 1 ms to prevent emitting two values during the same instant (e.g. slices finishes and
- // new slice starts).
- .debounce(1)
override val powerDraw: Flow<Double> = powerModel(this)
@@ -259,6 +255,11 @@ public class SimpleBareMetalDriver(
setNode(nodeState.value.copy(state = newNodeState, server = server))
}
+ /**
+ * A disposable to prevent resetting the usage state for subsequent calls to onRun.
+ */
+ private var usageFlush: DisposableHandle? = null
+
@OptIn(InternalCoroutinesApi::class)
override fun onRun(
batch: Sequence<ServerContext.Slice>,
@@ -270,6 +271,10 @@ public class SimpleBareMetalDriver(
return object : SelectClause0 {
@InternalCoroutinesApi
override fun <R> registerSelectClause0(select: SelectInstance<R>, block: suspend () -> R) {
+ // Do not reset the usage state: we will set it ourselves
+ usageFlush?.dispose()
+ usageFlush = null
+
val context = select.completion.context
val clock = context[SimulationContext]!!.clock
val delay = context[ContinuationInterceptor] as Delay
@@ -326,15 +331,21 @@ public class SimpleBareMetalDriver(
schedule(queue.next())
// A DisposableHandle to flush the work in case the call is cancelled
- val flush = DisposableHandle {
+ val disposable = DisposableHandle {
val end = clock.millis()
val duration = end - start
currentWork?.stop(duration)
currentDisposable?.dispose()
+
+ // Schedule reset the usage of the machine since the call is returning
+ usageFlush = delay.invokeOnTimeout(1, Runnable {
+ usageState.value = 0.0
+ usageFlush = null
+ })
}
- select.disposeOnSelect(flush)
+ select.disposeOnSelect(disposable)
} else if (select.trySelect()) {
// No work has been given: select immediately
block.startCoroutineCancellable(select.completion)
@@ -385,7 +396,7 @@ public class SimpleBareMetalDriver(
val usage = min(slice.limit[i], cpu.frequency)
val cpuDuration = ceil(slice.burst[i] / usage * 1000).toLong() // Convert from seconds to milliseconds
- totalUsage += usage
+ totalUsage += usage / cpu.frequency
if (cpuDuration != 0L) { // We only wait for processor cores with a non-zero burst
minExit = min(minExit, cpuDuration)
@@ -404,7 +415,7 @@ public class SimpleBareMetalDriver(
* Indicate that the work on the slice has started.
*/
public fun start() {
- usageState.value = totalUsage
+ usageState.value = totalUsage / cpus.size
}
/**
@@ -427,9 +438,6 @@ public class SimpleBareMetalDriver(
}
}
- // Reset the usage of the machine since the slice has finished
- usageState.value = 0.0
-
return hasFinished
}
}