summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimHost.kt1
-rw-r--r--opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/internal/Guest.kt1
-rw-r--r--opendc-compute/opendc-compute-simulator/src/test/kotlin/org/opendc/compute/simulator/SimHostTest.kt4
-rw-r--r--opendc-experiments/opendc-experiments-capelin/src/test/kotlin/org/opendc/experiments/capelin/CapelinIntegrationTest.kt10
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimAbstractHypervisor.kt21
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimHypervisorCounters.kt5
-rw-r--r--opendc-simulator/opendc-simulator-flow/src/main/kotlin/org/opendc/simulator/flow/mux/FlowMultiplexer.kt10
-rw-r--r--opendc-simulator/opendc-simulator-flow/src/main/kotlin/org/opendc/simulator/flow/mux/ForwardingFlowMultiplexer.kt4
-rw-r--r--opendc-simulator/opendc-simulator-flow/src/main/kotlin/org/opendc/simulator/flow/mux/MaxMinFlowMultiplexer.kt42
9 files changed, 76 insertions, 22 deletions
diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimHost.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimHost.kt
index 43f33f27..4eb6392e 100644
--- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimHost.kt
+++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimHost.kt
@@ -418,6 +418,7 @@ public class SimHost(
*/
private fun collectCpuTime(result: ObservableLongMeasurement) {
val counters = hypervisor.counters
+ counters.flush()
result.record(counters.cpuActiveTime / 1000L, _activeState)
result.record(counters.cpuIdleTime / 1000L, _idleState)
diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/internal/Guest.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/internal/Guest.kt
index f49c2824..bb378ee3 100644
--- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/internal/Guest.kt
+++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/internal/Guest.kt
@@ -272,6 +272,7 @@ internal class Guest(
*/
fun collectCpuTime(result: ObservableLongMeasurement) {
val counters = machine.counters
+ counters.flush()
result.record(counters.cpuActiveTime / 1000, _activeState)
result.record(counters.cpuIdleTime / 1000, _idleState)
diff --git a/opendc-compute/opendc-compute-simulator/src/test/kotlin/org/opendc/compute/simulator/SimHostTest.kt b/opendc-compute/opendc-compute-simulator/src/test/kotlin/org/opendc/compute/simulator/SimHostTest.kt
index dd13b60c..f0325023 100644
--- a/opendc-compute/opendc-compute-simulator/src/test/kotlin/org/opendc/compute/simulator/SimHostTest.kt
+++ b/opendc-compute/opendc-compute-simulator/src/test/kotlin/org/opendc/compute/simulator/SimHostTest.kt
@@ -173,7 +173,7 @@ internal class SimHostTest {
assertAll(
{ assertEquals(658, activeTime, "Active time does not match") },
- { assertEquals(1741, idleTime, "Idle time does not match") },
+ { assertEquals(2341, idleTime, "Idle time does not match") },
{ assertEquals(637, stealTime, "Steal time does not match") },
{ assertEquals(1500001, clock.millis()) }
)
@@ -278,7 +278,7 @@ internal class SimHostTest {
meterProvider.close()
assertAll(
- { assertEquals(1175, idleTime, "Idle time does not match") },
+ { assertEquals(1775, idleTime, "Idle time does not match") },
{ assertEquals(624, activeTime, "Active time does not match") },
{ assertEquals(900001, uptime, "Uptime does not match") },
{ assertEquals(300000, downtime, "Downtime does not match") },
diff --git a/opendc-experiments/opendc-experiments-capelin/src/test/kotlin/org/opendc/experiments/capelin/CapelinIntegrationTest.kt b/opendc-experiments/opendc-experiments-capelin/src/test/kotlin/org/opendc/experiments/capelin/CapelinIntegrationTest.kt
index aefd8304..891fc8be 100644
--- a/opendc-experiments/opendc-experiments-capelin/src/test/kotlin/org/opendc/experiments/capelin/CapelinIntegrationTest.kt
+++ b/opendc-experiments/opendc-experiments-capelin/src/test/kotlin/org/opendc/experiments/capelin/CapelinIntegrationTest.kt
@@ -117,7 +117,7 @@ class CapelinIntegrationTest {
{ assertEquals(0, serviceMetrics.serversActive, "All VMs should finish after a run") },
{ assertEquals(0, serviceMetrics.attemptsFailure, "No VM should be unscheduled") },
{ assertEquals(0, serviceMetrics.serversPending, "No VM should not be in the queue") },
- { assertEquals(223388307, this@CapelinIntegrationTest.exporter.idleTime) { "Incorrect idle time" } },
+ { assertEquals(223393683, this@CapelinIntegrationTest.exporter.idleTime) { "Incorrect idle time" } },
{ assertEquals(66977508, this@CapelinIntegrationTest.exporter.activeTime) { "Incorrect active time" } },
{ assertEquals(3160381, this@CapelinIntegrationTest.exporter.stealTime) { "Incorrect steal time" } },
{ assertEquals(0, this@CapelinIntegrationTest.exporter.lostTime) { "Incorrect lost time" } },
@@ -166,7 +166,7 @@ class CapelinIntegrationTest {
// Note that these values have been verified beforehand
assertAll(
- { assertEquals(10999208, this@CapelinIntegrationTest.exporter.idleTime) { "Idle time incorrect" } },
+ { assertEquals(10999592, this@CapelinIntegrationTest.exporter.idleTime) { "Idle time incorrect" } },
{ assertEquals(9741207, this@CapelinIntegrationTest.exporter.activeTime) { "Active time incorrect" } },
{ assertEquals(0, this@CapelinIntegrationTest.exporter.stealTime) { "Steal time incorrect" } },
{ assertEquals(0, this@CapelinIntegrationTest.exporter.lostTime) { "Lost time incorrect" } },
@@ -218,10 +218,10 @@ class CapelinIntegrationTest {
// Note that these values have been verified beforehand
assertAll(
- { assertEquals(6027666, this@CapelinIntegrationTest.exporter.idleTime) { "Idle time incorrect" } },
+ { assertEquals(6028050, this@CapelinIntegrationTest.exporter.idleTime) { "Idle time incorrect" } },
{ assertEquals(14712749, this@CapelinIntegrationTest.exporter.activeTime) { "Active time incorrect" } },
{ assertEquals(12532907, this@CapelinIntegrationTest.exporter.stealTime) { "Steal time incorrect" } },
- { assertEquals(468522, this@CapelinIntegrationTest.exporter.lostTime) { "Lost time incorrect" } }
+ { assertEquals(467963, this@CapelinIntegrationTest.exporter.lostTime) { "Lost time incorrect" } }
)
}
@@ -263,7 +263,7 @@ class CapelinIntegrationTest {
// Note that these values have been verified beforehand
assertAll(
- { assertEquals(10866961, exporter.idleTime) { "Idle time incorrect" } },
+ { assertEquals(10867345, exporter.idleTime) { "Idle time incorrect" } },
{ assertEquals(9607095, exporter.activeTime) { "Active time incorrect" } },
{ assertEquals(0, exporter.stealTime) { "Steal time incorrect" } },
{ assertEquals(0, exporter.lostTime) { "Lost time incorrect" } },
diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimAbstractHypervisor.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimAbstractHypervisor.kt
index 07465126..b7f70749 100644
--- a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimAbstractHypervisor.kt
+++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimAbstractHypervisor.kt
@@ -137,7 +137,9 @@ public abstract class SimAbstractHypervisor(
/* FlowConvergenceListener */
override fun onConverge(now: Long, delta: Long) {
- _counters.record()
+ if (delta > 0) {
+ _counters.record()
+ }
val load = cpuDemand / cpuCapacity
for (governor in governors) {
@@ -274,6 +276,10 @@ public abstract class SimAbstractHypervisor(
fun close() {
switch.removeInput(source)
}
+
+ fun flush() {
+ switch.flushCounters(source)
+ }
}
/**
@@ -337,6 +343,11 @@ public abstract class SimAbstractHypervisor(
cpuTime[2] += ((demandDelta - actualDelta) * d).roundToLong()
cpuTime[3] += (interferenceDelta * d).roundToLong()
}
+
+ override fun flush() {
+ hv.mux.flushCounters()
+ record()
+ }
}
/**
@@ -348,10 +359,16 @@ public abstract class SimAbstractHypervisor(
override val cpuActiveTime: Long
get() = (cpus.sumOf { it.counters.actual } * d).roundToLong()
override val cpuIdleTime: Long
- get() = (cpus.sumOf { it.counters.actual + it.counters.remaining } * d).roundToLong()
+ get() = (cpus.sumOf { it.counters.remaining } * d).roundToLong()
override val cpuStealTime: Long
get() = (cpus.sumOf { it.counters.demand - it.counters.actual } * d).roundToLong()
override val cpuLostTime: Long
get() = (cpus.sumOf { it.counters.interference } * d).roundToLong()
+
+ override fun flush() {
+ for (cpu in cpus) {
+ cpu.flush()
+ }
+ }
}
}
diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimHypervisorCounters.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimHypervisorCounters.kt
index 030d9c5f..63fee507 100644
--- a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimHypervisorCounters.kt
+++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimHypervisorCounters.kt
@@ -45,4 +45,9 @@ public interface SimHypervisorCounters {
* The amount of CPU time (in milliseconds) that was lost due to interference between virtual machines.
*/
public val cpuLostTime: Long
+
+ /**
+ * Flush the counter values.
+ */
+ public fun flush()
}
diff --git a/opendc-simulator/opendc-simulator-flow/src/main/kotlin/org/opendc/simulator/flow/mux/FlowMultiplexer.kt b/opendc-simulator/opendc-simulator-flow/src/main/kotlin/org/opendc/simulator/flow/mux/FlowMultiplexer.kt
index a7877546..5f198944 100644
--- a/opendc-simulator/opendc-simulator-flow/src/main/kotlin/org/opendc/simulator/flow/mux/FlowMultiplexer.kt
+++ b/opendc-simulator/opendc-simulator-flow/src/main/kotlin/org/opendc/simulator/flow/mux/FlowMultiplexer.kt
@@ -105,4 +105,14 @@ public interface FlowMultiplexer {
* Clear the outputs of the multiplexer.
*/
public fun clearOutputs()
+
+ /**
+ * Flush the counters of the multiplexer.
+ */
+ public fun flushCounters()
+
+ /**
+ * Flush the counters of the specified [input].
+ */
+ public fun flushCounters(input: FlowConsumer)
}
diff --git a/opendc-simulator/opendc-simulator-flow/src/main/kotlin/org/opendc/simulator/flow/mux/ForwardingFlowMultiplexer.kt b/opendc-simulator/opendc-simulator-flow/src/main/kotlin/org/opendc/simulator/flow/mux/ForwardingFlowMultiplexer.kt
index eff111b8..7fe0c1b7 100644
--- a/opendc-simulator/opendc-simulator-flow/src/main/kotlin/org/opendc/simulator/flow/mux/ForwardingFlowMultiplexer.kt
+++ b/opendc-simulator/opendc-simulator-flow/src/main/kotlin/org/opendc/simulator/flow/mux/ForwardingFlowMultiplexer.kt
@@ -135,6 +135,10 @@ public class ForwardingFlowMultiplexer(
clearInputs()
}
+ override fun flushCounters() {}
+
+ override fun flushCounters(input: FlowConsumer) {}
+
private var _lastConverge = Long.MAX_VALUE
override fun onConverge(now: Long, delta: Long) {
diff --git a/opendc-simulator/opendc-simulator-flow/src/main/kotlin/org/opendc/simulator/flow/mux/MaxMinFlowMultiplexer.kt b/opendc-simulator/opendc-simulator-flow/src/main/kotlin/org/opendc/simulator/flow/mux/MaxMinFlowMultiplexer.kt
index 3d26efda..7ee4d326 100644
--- a/opendc-simulator/opendc-simulator-flow/src/main/kotlin/org/opendc/simulator/flow/mux/MaxMinFlowMultiplexer.kt
+++ b/opendc-simulator/opendc-simulator-flow/src/main/kotlin/org/opendc/simulator/flow/mux/MaxMinFlowMultiplexer.kt
@@ -141,6 +141,14 @@ public class MaxMinFlowMultiplexer(
clearInputs()
}
+ override fun flushCounters() {
+ scheduler.updateCounters(engine.clock.millis())
+ }
+
+ override fun flushCounters(input: FlowConsumer) {
+ (input as Input).doUpdateCounters(engine.clock.millis())
+ }
+
/**
* Helper class containing the scheduler state.
*/
@@ -189,7 +197,6 @@ public class MaxMinFlowMultiplexer(
* Flag to indicate that the scheduler is active.
*/
private var _schedulerActive = false
- private var _lastSchedulerCycle = Long.MAX_VALUE
/**
* The last convergence timestamp and the input.
@@ -324,14 +331,9 @@ public class MaxMinFlowMultiplexer(
* Synchronously run the scheduler of the multiplexer.
*/
fun runScheduler(now: Long): Long {
- val lastSchedulerCycle = _lastSchedulerCycle
- _lastSchedulerCycle = now
-
- val delta = max(0, now - lastSchedulerCycle)
-
return try {
_schedulerActive = true
- doRunScheduler(now, delta)
+ doRunScheduler(now)
} finally {
_schedulerActive = false
}
@@ -384,14 +386,14 @@ public class MaxMinFlowMultiplexer(
*
* @return The deadline after which a new scheduling cycle should start.
*/
- private fun doRunScheduler(now: Long, delta: Long): Long {
+ private fun doRunScheduler(now: Long): Long {
val activeInputs = _activeInputs
val activeOutputs = _activeOutputs
var inputArray = _inputArray
var inputSize = _inputArray.size
// Update the counters of the scheduler
- updateCounters(delta)
+ updateCounters(now)
// If there is no work yet, mark the inputs as idle.
if (inputSize == 0) {
@@ -475,14 +477,19 @@ public class MaxMinFlowMultiplexer(
* The previous capacity of the multiplexer.
*/
private var _previousCapacity = 0.0
+ private var _previousUpdate = Long.MIN_VALUE
/**
* Update the counters of the scheduler.
*/
- private fun updateCounters(delta: Long) {
+ fun updateCounters(now: Long) {
val previousCapacity = _previousCapacity
_previousCapacity = capacity
+ val previousUpdate = _previousUpdate
+ _previousUpdate = now
+
+ val delta = (now - previousUpdate).coerceAtLeast(0)
if (delta <= 0) {
return
}
@@ -643,7 +650,7 @@ public class MaxMinFlowMultiplexer(
delta: Long,
rate: Double
) {
- doUpdateCounters(delta)
+ doUpdateCounters(now)
val allowed = min(rate, capacity)
limit = rate
@@ -654,7 +661,7 @@ public class MaxMinFlowMultiplexer(
}
override fun onFinish(ctx: FlowConsumerContext, now: Long, delta: Long, cause: Throwable?) {
- doUpdateCounters(delta)
+ doUpdateCounters(now)
limit = 0.0
actualRate = 0.0
@@ -673,9 +680,18 @@ public class MaxMinFlowMultiplexer(
override fun compareTo(other: Input): Int = allowedRate.compareTo(other.allowedRate)
/**
+ * The timestamp that the counters where last updated.
+ */
+ private var _lastUpdate = Long.MIN_VALUE
+
+ /**
* Helper method to update the flow counters of the multiplexer.
*/
- private fun doUpdateCounters(delta: Long) {
+ fun doUpdateCounters(now: Long) {
+ val lastUpdate = _lastUpdate
+ _lastUpdate = now
+
+ val delta = (now - lastUpdate).coerceAtLeast(0)
if (delta <= 0L) {
return
}