summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimHost.kt3
-rw-r--r--opendc-compute/opendc-compute-simulator/src/test/kotlin/org/opendc/compute/simulator/SimHostTest.kt8
-rw-r--r--opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/ComputeServiceHelper.kt24
-rw-r--r--opendc-experiments/opendc-experiments-capelin/src/jmh/kotlin/org/opendc/experiments/capelin/CapelinBenchmarks.kt5
-rw-r--r--opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/CapelinRunner.kt5
-rw-r--r--opendc-experiments/opendc-experiments-capelin/src/test/kotlin/org/opendc/experiments/capelin/CapelinIntegrationTest.kt37
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/jmh/kotlin/org/opendc/simulator/compute/SimMachineBenchmarks.kt10
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimAbstractHypervisor.kt17
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimFairShareHypervisor.kt7
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimFairShareHypervisorProvider.kt4
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimHypervisorProvider.kt3
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimSpaceSharedHypervisor.kt8
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimSpaceSharedHypervisorProvider.kt4
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/interference/VmInterferenceMember.kt5
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/interference/VmInterferenceModel.kt43
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/SimFairShareHypervisorTest.kt13
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/SimSpaceSharedHypervisorTest.kt19
-rw-r--r--opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/OpenDCRunner.kt3
-rw-r--r--opendc-workflow/opendc-workflow-service/src/test/kotlin/org/opendc/workflow/service/WorkflowServiceTest.kt1
19 files changed, 130 insertions, 89 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 628f324b..ece3f752 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
@@ -62,6 +62,7 @@ public class SimHost(
context: CoroutineContext,
engine: FlowEngine,
hypervisorProvider: SimHypervisorProvider,
+ random: SplittableRandom,
scalingGovernor: ScalingGovernor = PerformanceScalingGovernor(),
powerDriver: PowerDriver = SimplePowerDriver(ConstantPowerModel(0.0)),
private val mapper: SimWorkloadMapper = SimMetaWorkloadMapper(),
@@ -92,7 +93,7 @@ public class SimHost(
* The hypervisor to run multiple workloads.
*/
private val hypervisor: SimHypervisor = hypervisorProvider
- .create(engine, scalingGovernor = scalingGovernor)
+ .create(engine, random, scalingGovernor = scalingGovernor)
/**
* The virtual machines running on the hypervisor.
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 5ba4a667..0b2285e5 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
@@ -67,6 +67,7 @@ internal class SimHostTest {
fun testOvercommitted() = runBlockingSimulation {
val duration = 5 * 60L
val engine = FlowEngine(coroutineContext, clock)
+ val random = SplittableRandom(1)
val host = SimHost(
uid = UUID.randomUUID(),
name = "test",
@@ -74,7 +75,8 @@ internal class SimHostTest {
meta = emptyMap(),
coroutineContext,
engine,
- SimFairShareHypervisorProvider()
+ SimFairShareHypervisorProvider(),
+ random,
)
val vmImageA = MockImage(
UUID.randomUUID(),
@@ -149,6 +151,7 @@ internal class SimHostTest {
fun testFailure() = runBlockingSimulation {
val duration = 5 * 60L
val engine = FlowEngine(coroutineContext, clock)
+ val random = SplittableRandom(1)
val host = SimHost(
uid = UUID.randomUUID(),
name = "test",
@@ -156,7 +159,8 @@ internal class SimHostTest {
meta = emptyMap(),
coroutineContext,
engine,
- SimFairShareHypervisorProvider()
+ SimFairShareHypervisorProvider(),
+ random
)
val image = MockImage(
UUID.randomUUID(),
diff --git a/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/ComputeServiceHelper.kt b/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/ComputeServiceHelper.kt
index fddb4890..879ef072 100644
--- a/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/ComputeServiceHelper.kt
+++ b/opendc-compute/opendc-compute-workload/src/main/kotlin/org/opendc/compute/workload/ComputeServiceHelper.kt
@@ -54,6 +54,7 @@ public class ComputeServiceHelper(
private val context: CoroutineContext,
private val clock: Clock,
scheduler: ComputeScheduler,
+ seed: Long,
private val failureModel: FailureModel? = null,
private val interferenceModel: VmInterferenceModel? = null,
schedulingQuantum: Duration = Duration.ofMinutes(5)
@@ -66,12 +67,17 @@ public class ComputeServiceHelper(
/**
* The [FlowEngine] to simulate the hosts.
*/
- private val _engine = FlowEngine(context, clock)
+ private val engine = FlowEngine(context, clock)
/**
* The hosts that belong to this class.
*/
- private val _hosts = mutableSetOf<SimHost>()
+ private val hosts = mutableSetOf<SimHost>()
+
+ /**
+ * The source of randomness.
+ */
+ private val random = SplittableRandom(seed)
init {
val service = createService(scheduler, schedulingQuantum)
@@ -82,18 +88,15 @@ public class ComputeServiceHelper(
* Run a simulation of the [ComputeService] by replaying the workload trace given by [trace].
*
* @param trace The trace to simulate.
- * @param seed The seed for the simulation.
* @param servers A list to which the created servers is added.
* @param submitImmediately A flag to indicate that the servers are scheduled immediately (so not at their start time).
*/
public suspend fun run(
trace: List<VirtualMachine>,
- seed: Long,
servers: MutableList<Server>? = null,
submitImmediately: Boolean = false
) {
- val random = Random(seed)
- val injector = failureModel?.createInjector(context, clock, service, random)
+ val injector = failureModel?.createInjector(context, clock, service, Random(random.nextLong()))
val client = service.newClient()
// Create new image for the virtual machine
@@ -170,14 +173,15 @@ public class ComputeServiceHelper(
spec.model,
spec.meta,
context,
- _engine,
+ engine,
spec.hypervisor,
+ random,
powerDriver = spec.powerDriver,
interferenceDomain = interferenceModel?.newDomain(),
optimize = optimize
)
- require(_hosts.add(host)) { "Host with uid ${spec.uid} already exists" }
+ require(hosts.add(host)) { "Host with uid ${spec.uid} already exists" }
service.addHost(host)
return host
@@ -186,11 +190,11 @@ public class ComputeServiceHelper(
override fun close() {
service.close()
- for (host in _hosts) {
+ for (host in hosts) {
host.close()
}
- _hosts.clear()
+ hosts.clear()
}
/**
diff --git a/opendc-experiments/opendc-experiments-capelin/src/jmh/kotlin/org/opendc/experiments/capelin/CapelinBenchmarks.kt b/opendc-experiments/opendc-experiments-capelin/src/jmh/kotlin/org/opendc/experiments/capelin/CapelinBenchmarks.kt
index fd2c26f0..074ffc3e 100644
--- a/opendc-experiments/opendc-experiments-capelin/src/jmh/kotlin/org/opendc/experiments/capelin/CapelinBenchmarks.kt
+++ b/opendc-experiments/opendc-experiments-capelin/src/jmh/kotlin/org/opendc/experiments/capelin/CapelinBenchmarks.kt
@@ -68,12 +68,13 @@ class CapelinBenchmarks {
val runner = ComputeServiceHelper(
coroutineContext,
clock,
- computeScheduler
+ computeScheduler,
+ seed = 0L,
)
try {
runner.apply(topology, isOptimized)
- runner.run(vms, 0)
+ runner.run(vms)
} finally {
runner.close()
}
diff --git a/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/CapelinRunner.kt b/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/CapelinRunner.kt
index cca5b6cf..2f417172 100644
--- a/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/CapelinRunner.kt
+++ b/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/CapelinRunner.kt
@@ -73,8 +73,9 @@ public class CapelinRunner(
coroutineContext,
clock,
computeScheduler,
+ seed,
failureModel,
- interferenceModel?.withSeed(seed)
+ interferenceModel?.takeIf { operationalPhenomena.hasInterference }
)
val topology = clusterTopology(File(envPath, "${scenario.topology.name}.txt"))
@@ -104,7 +105,7 @@ public class CapelinRunner(
runner.apply(topology, optimize = true)
// Run the workload trace
- runner.run(vms, seeder.nextLong(), servers)
+ runner.run(vms, servers)
// Stop the metric collection
exporter?.close()
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 368b0086..ff9faef7 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
@@ -81,11 +81,13 @@ class CapelinIntegrationTest {
*/
@Test
fun testLarge() = runBlockingSimulation {
- val (workload, _) = createTestWorkload(1.0)
+ val seed = 0L
+ val (workload, _) = createTestWorkload(1.0, seed)
val runner = ComputeServiceHelper(
coroutineContext,
clock,
- computeScheduler
+ computeScheduler,
+ seed,
)
val topology = createTopology()
@@ -94,7 +96,7 @@ class CapelinIntegrationTest {
try {
runner.apply(topology)
- runner.run(workload, 0, servers)
+ runner.run(workload, servers)
val serviceMetrics = runner.service.getSchedulerStats()
println(
@@ -129,12 +131,13 @@ class CapelinIntegrationTest {
*/
@Test
fun testSmall() = runBlockingSimulation {
- val seed = 1
+ val seed = 1L
val (workload, _) = createTestWorkload(0.25, seed)
val runner = ComputeServiceHelper(
coroutineContext,
clock,
- computeScheduler
+ computeScheduler,
+ seed,
)
val topology = createTopology("single")
val servers = mutableListOf<Server>()
@@ -142,7 +145,7 @@ class CapelinIntegrationTest {
try {
runner.apply(topology)
- runner.run(workload, seed.toLong(), servers)
+ runner.run(workload, servers)
val serviceMetrics = runner.service.getSchedulerStats()
println(
@@ -173,14 +176,15 @@ class CapelinIntegrationTest {
*/
@Test
fun testInterference() = runBlockingSimulation {
- val seed = 0
+ val seed = 0L
val (workload, interferenceModel) = createTestWorkload(1.0, seed)
val simulator = ComputeServiceHelper(
coroutineContext,
clock,
computeScheduler,
- interferenceModel = interferenceModel?.withSeed(seed.toLong())
+ seed,
+ interferenceModel = interferenceModel
)
val topology = createTopology("single")
val servers = mutableListOf<Server>()
@@ -188,7 +192,7 @@ class CapelinIntegrationTest {
try {
simulator.apply(topology)
- simulator.run(workload, seed.toLong(), servers)
+ simulator.run(workload, servers)
val serviceMetrics = simulator.service.getSchedulerStats()
println(
@@ -218,11 +222,12 @@ class CapelinIntegrationTest {
*/
@Test
fun testFailures() = runBlockingSimulation {
- val seed = 1
+ val seed = 0L
val simulator = ComputeServiceHelper(
coroutineContext,
clock,
computeScheduler,
+ seed,
grid5000(Duration.ofDays(7))
)
val topology = createTopology("single")
@@ -232,7 +237,7 @@ class CapelinIntegrationTest {
try {
simulator.apply(topology)
- simulator.run(workload, seed.toLong(), servers)
+ simulator.run(workload, servers)
val serviceMetrics = simulator.service.getSchedulerStats()
println(
@@ -250,20 +255,20 @@ class CapelinIntegrationTest {
// Note that these values have been verified beforehand
assertAll(
- { assertEquals(10867345, monitor.idleTime) { "Idle time incorrect" } },
- { assertEquals(9607095, monitor.activeTime) { "Active time incorrect" } },
+ { assertEquals(10982026, monitor.idleTime) { "Idle time incorrect" } },
+ { assertEquals(9740058, monitor.activeTime) { "Active time incorrect" } },
{ assertEquals(0, monitor.stealTime) { "Steal time incorrect" } },
{ assertEquals(0, monitor.lostTime) { "Lost time incorrect" } },
- { assertEquals(2559305056, monitor.uptime) { "Uptime incorrect" } }
+ { assertEquals(2590260605, monitor.uptime) { "Uptime incorrect" } },
)
}
/**
* Obtain the trace reader for the test.
*/
- private fun createTestWorkload(fraction: Double, seed: Int = 0): ComputeWorkload.Resolved {
+ private fun createTestWorkload(fraction: Double, seed: Long): ComputeWorkload.Resolved {
val source = trace("bitbrains-small").sampleByLoad(fraction)
- return source.resolve(workloadLoader, Random(seed.toLong()))
+ return source.resolve(workloadLoader, Random(seed))
}
/**
diff --git a/opendc-simulator/opendc-simulator-compute/src/jmh/kotlin/org/opendc/simulator/compute/SimMachineBenchmarks.kt b/opendc-simulator/opendc-simulator-compute/src/jmh/kotlin/org/opendc/simulator/compute/SimMachineBenchmarks.kt
index 02b48fa7..c3332d66 100644
--- a/opendc-simulator/opendc-simulator-compute/src/jmh/kotlin/org/opendc/simulator/compute/SimMachineBenchmarks.kt
+++ b/opendc-simulator/opendc-simulator-compute/src/jmh/kotlin/org/opendc/simulator/compute/SimMachineBenchmarks.kt
@@ -37,6 +37,7 @@ import org.opendc.simulator.compute.workload.SimTraceWorkload
import org.opendc.simulator.core.runBlockingSimulation
import org.opendc.simulator.flow.FlowEngine
import org.openjdk.jmh.annotations.*
+import java.util.SplittableRandom
import java.util.concurrent.ThreadLocalRandom
import java.util.concurrent.TimeUnit
@@ -85,7 +86,8 @@ class SimMachineBenchmarks {
val machine = SimBareMetalMachine(
engine, machineModel, SimplePowerDriver(ConstantPowerModel(0.0))
)
- val hypervisor = SimSpaceSharedHypervisor(engine, null)
+ val random = SplittableRandom(1)
+ val hypervisor = SimSpaceSharedHypervisor(engine, null, random)
launch { machine.runWorkload(hypervisor) }
@@ -107,7 +109,8 @@ class SimMachineBenchmarks {
val machine = SimBareMetalMachine(
engine, machineModel, SimplePowerDriver(ConstantPowerModel(0.0))
)
- val hypervisor = SimFairShareHypervisor(engine, null)
+ val random = SplittableRandom(1)
+ val hypervisor = SimFairShareHypervisor(engine, null, random)
launch { machine.runWorkload(hypervisor) }
@@ -129,7 +132,8 @@ class SimMachineBenchmarks {
val machine = SimBareMetalMachine(
engine, machineModel, SimplePowerDriver(ConstantPowerModel(0.0))
)
- val hypervisor = SimFairShareHypervisor(engine, null)
+ val random = SplittableRandom(1)
+ val hypervisor = SimFairShareHypervisor(engine, null, random)
launch { machine.runWorkload(hypervisor) }
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 98dab28f..2cabeece 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
@@ -31,6 +31,7 @@ import org.opendc.simulator.compute.model.ProcessingUnit
import org.opendc.simulator.compute.workload.SimWorkload
import org.opendc.simulator.flow.*
import org.opendc.simulator.flow.mux.FlowMultiplexer
+import java.util.SplittableRandom
import kotlin.math.roundToLong
/**
@@ -38,10 +39,12 @@ import kotlin.math.roundToLong
*
* @param engine The [FlowEngine] to drive the simulation.
* @param scalingGovernor The scaling governor to use for scaling the CPU frequency of the underlying hardware.
+ * @param random A randomness generator for the interference calculations.
*/
public abstract class SimAbstractHypervisor(
protected val engine: FlowEngine,
- private val scalingGovernor: ScalingGovernor?
+ private val scalingGovernor: ScalingGovernor?,
+ private val random: SplittableRandom
) : SimHypervisor, FlowConvergenceListener {
/**
* The machine on which the hypervisor runs.
@@ -142,8 +145,12 @@ public abstract class SimAbstractHypervisor(
if (delta > 0) {
_counters.record()
+ val mux = mux
+ val load = mux.rate / mux.capacity.coerceAtLeast(1.0)
+ val random = random
+
for (vm in _vms) {
- vm._counters.record()
+ vm._counters.record(random, load)
}
}
@@ -351,7 +358,7 @@ public abstract class SimAbstractHypervisor(
/**
* Record the CPU time of the hypervisor.
*/
- fun record() {
+ fun record(random: SplittableRandom, load: Double) {
val cpuTime = _cpuTime
val previous = _previous
@@ -383,9 +390,7 @@ public abstract class SimAbstractHypervisor(
// Compute the performance penalty due to flow interference
val key = key
if (key != null) {
- val mux = mux
- val load = mux.rate / mux.capacity.coerceAtLeast(1.0)
- val penalty = 1 - key.apply(load)
+ val penalty = 1 - key.apply(random, load)
val interference = (actualDelta * d * penalty).roundToLong()
if (interference > 0) {
diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimFairShareHypervisor.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimFairShareHypervisor.kt
index 66453835..4435a422 100644
--- a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimFairShareHypervisor.kt
+++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimFairShareHypervisor.kt
@@ -29,6 +29,7 @@ import org.opendc.simulator.compute.workload.SimWorkload
import org.opendc.simulator.flow.FlowEngine
import org.opendc.simulator.flow.mux.FlowMultiplexer
import org.opendc.simulator.flow.mux.MaxMinFlowMultiplexer
+import java.util.SplittableRandom
/**
* A [SimHypervisor] that distributes the computing requirements of multiple [SimWorkload]s on a single [SimMachine]
@@ -36,11 +37,13 @@ import org.opendc.simulator.flow.mux.MaxMinFlowMultiplexer
*
* @param engine The [FlowEngine] to manage the machine's resources.
* @param scalingGovernor The CPU frequency scaling governor to use for the hypervisor.
+ * @param random A randomness generator for the interference calculations.
*/
public class SimFairShareHypervisor(
engine: FlowEngine,
- scalingGovernor: ScalingGovernor?
-) : SimAbstractHypervisor(engine, scalingGovernor) {
+ scalingGovernor: ScalingGovernor?,
+ random: SplittableRandom
+) : SimAbstractHypervisor(engine, scalingGovernor, random) {
/**
* The multiplexer that distributes the computing capacity.
*/
diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimFairShareHypervisorProvider.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimFairShareHypervisorProvider.kt
index ad8177d3..c7008652 100644
--- a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimFairShareHypervisorProvider.kt
+++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimFairShareHypervisorProvider.kt
@@ -24,6 +24,7 @@ package org.opendc.simulator.compute.kernel
import org.opendc.simulator.compute.kernel.cpufreq.ScalingGovernor
import org.opendc.simulator.flow.FlowEngine
+import java.util.*
/**
* A [SimHypervisorProvider] for the [SimFairShareHypervisor] implementation.
@@ -33,6 +34,7 @@ public class SimFairShareHypervisorProvider : SimHypervisorProvider {
override fun create(
engine: FlowEngine,
+ random: SplittableRandom,
scalingGovernor: ScalingGovernor?,
- ): SimHypervisor = SimFairShareHypervisor(engine, scalingGovernor)
+ ): SimHypervisor = SimFairShareHypervisor(engine, scalingGovernor, random)
}
diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimHypervisorProvider.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimHypervisorProvider.kt
index 6ee523fd..020a2a60 100644
--- a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimHypervisorProvider.kt
+++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimHypervisorProvider.kt
@@ -24,6 +24,7 @@ package org.opendc.simulator.compute.kernel
import org.opendc.simulator.compute.kernel.cpufreq.ScalingGovernor
import org.opendc.simulator.flow.FlowEngine
+import java.util.SplittableRandom
/**
* A service provider interface for constructing a [SimHypervisor].
@@ -40,5 +41,5 @@ public interface SimHypervisorProvider {
/**
* Create a new [SimHypervisor] instance.
*/
- public fun create(engine: FlowEngine, scalingGovernor: ScalingGovernor? = null): SimHypervisor
+ public fun create(engine: FlowEngine, random: SplittableRandom, scalingGovernor: ScalingGovernor? = null): SimHypervisor
}
diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimSpaceSharedHypervisor.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimSpaceSharedHypervisor.kt
index 7976077c..51bf4ce5 100644
--- a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimSpaceSharedHypervisor.kt
+++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimSpaceSharedHypervisor.kt
@@ -27,14 +27,20 @@ import org.opendc.simulator.compute.model.MachineModel
import org.opendc.simulator.flow.FlowEngine
import org.opendc.simulator.flow.mux.FlowMultiplexer
import org.opendc.simulator.flow.mux.ForwardingFlowMultiplexer
+import java.util.SplittableRandom
/**
* A [SimHypervisor] that allocates its sub-resources exclusively for the virtual machine that it hosts.
+ *
+ * @param engine The [FlowEngine] to manage the machine's resources.
+ * @param scalingGovernor The CPU frequency scaling governor to use for the hypervisor.
+ * @param random A randomness generator for the interference calculations.
*/
public class SimSpaceSharedHypervisor(
engine: FlowEngine,
scalingGovernor: ScalingGovernor?,
-) : SimAbstractHypervisor(engine, scalingGovernor) {
+ random: SplittableRandom
+) : SimAbstractHypervisor(engine, scalingGovernor, random) {
override val mux: FlowMultiplexer = ForwardingFlowMultiplexer(engine, this)
override fun canFit(model: MachineModel): Boolean {
diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimSpaceSharedHypervisorProvider.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimSpaceSharedHypervisorProvider.kt
index f7456797..05c54528 100644
--- a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimSpaceSharedHypervisorProvider.kt
+++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimSpaceSharedHypervisorProvider.kt
@@ -24,6 +24,7 @@ package org.opendc.simulator.compute.kernel
import org.opendc.simulator.compute.kernel.cpufreq.ScalingGovernor
import org.opendc.simulator.flow.FlowEngine
+import java.util.*
/**
* A [SimHypervisorProvider] for the [SimSpaceSharedHypervisor] implementation.
@@ -33,6 +34,7 @@ public class SimSpaceSharedHypervisorProvider : SimHypervisorProvider {
override fun create(
engine: FlowEngine,
+ random: SplittableRandom,
scalingGovernor: ScalingGovernor?,
- ): SimHypervisor = SimSpaceSharedHypervisor(engine, scalingGovernor)
+ ): SimHypervisor = SimSpaceSharedHypervisor(engine, scalingGovernor, random)
}
diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/interference/VmInterferenceMember.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/interference/VmInterferenceMember.kt
index 2f3dd74b..04203c63 100644
--- a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/interference/VmInterferenceMember.kt
+++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/interference/VmInterferenceMember.kt
@@ -22,6 +22,8 @@
package org.opendc.simulator.compute.kernel.interference
+import java.util.*
+
/**
* A participant of an interference domain.
*/
@@ -39,9 +41,10 @@ public interface VmInterferenceMember {
/**
* Compute the performance score of the member in this interference domain.
*
+ * @param random The source of randomness to apply when computing the performance score.
* @param load The overall load on the interference domain.
* @return A score representing the performance score to be applied to the member, with 1
* meaning no influence, <1 means that performance degrades, and >1 means that performance improves.
*/
- public fun apply(load: Double): Double
+ public fun apply(random: SplittableRandom, load: Double): Double
}
diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/interference/VmInterferenceModel.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/interference/VmInterferenceModel.kt
index b9eee536..3ea869d4 100644
--- a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/interference/VmInterferenceModel.kt
+++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/interference/VmInterferenceModel.kt
@@ -32,7 +32,6 @@ import java.util.*
* @param members The members belonging to each group.
* @param membership The identifier of each key.
* @param size The number of groups.
- * @param seed The seed to use for randomly selecting the virtual machines that are affected.
*/
public class VmInterferenceModel private constructor(
private val idMapping: Map<String, Int>,
@@ -40,25 +39,12 @@ public class VmInterferenceModel private constructor(
private val membership: Array<IntArray>,
private val targets: DoubleArray,
private val scores: DoubleArray,
- private val size: Int,
- seed: Long,
+ private val size: Int
) {
/**
- * A [SplittableRandom] used for selecting the virtual machines that are affected.
- */
- private val random = SplittableRandom(seed)
-
- /**
* Construct a new [VmInterferenceDomain].
*/
- public fun newDomain(): VmInterferenceDomain = InterferenceDomainImpl(idMapping, members, membership, targets, scores, random)
-
- /**
- * Create a copy of this model with a different seed.
- */
- public fun withSeed(seed: Long): VmInterferenceModel {
- return VmInterferenceModel(idMapping, members, membership, targets, scores, size, seed)
- }
+ public fun newDomain(): VmInterferenceDomain = InterferenceDomainImpl(idMapping, members, membership, targets, scores)
public companion object {
/**
@@ -73,11 +59,6 @@ public class VmInterferenceModel private constructor(
*/
public class Builder internal constructor() {
/**
- * The initial capacity of the builder.
- */
- private val INITIAL_CAPACITY = 256
-
- /**
* The target load of each group.
*/
private var _targets = DoubleArray(INITIAL_CAPACITY) { Double.POSITIVE_INFINITY }
@@ -125,7 +106,7 @@ public class VmInterferenceModel private constructor(
/**
* Build the [VmInterferenceModel].
*/
- public fun build(seed: Long = 0): VmInterferenceModel {
+ public fun build(): VmInterferenceModel {
val size = size
val targets = _targets
val scores = _scores
@@ -176,8 +157,7 @@ public class VmInterferenceModel private constructor(
membership.map { it.value.toIntArray() }.toTypedArray(),
newTargets,
newScores,
- size,
- seed
+ size
)
}
@@ -191,6 +171,13 @@ public class VmInterferenceModel private constructor(
_targets = _targets.copyOf(newSize)
_scores = _scores.copyOf(newSize)
}
+
+ private companion object {
+ /**
+ * The initial capacity of the builder.
+ */
+ const val INITIAL_CAPACITY = 256
+ }
}
/**
@@ -202,7 +189,6 @@ public class VmInterferenceModel private constructor(
private val membership: Array<IntArray>,
private val targets: DoubleArray,
private val scores: DoubleArray,
- private val random: SplittableRandom
) : VmInterferenceDomain {
/**
* Keys registered with this domain.
@@ -221,7 +207,7 @@ public class VmInterferenceModel private constructor(
override fun getMember(id: String): VmInterferenceMember? {
val intId = idMapping[id] ?: return null
- return keys.computeIfAbsent(intId) { InterferenceMemberImpl(it, this, membership[it], members, targets, scores, random) }
+ return keys.computeIfAbsent(intId) { InterferenceMemberImpl(it, this, membership[it], members, targets, scores) }
}
override fun toString(): String = "VmInterferenceDomain"
@@ -307,8 +293,7 @@ public class VmInterferenceModel private constructor(
@JvmField val membership: IntArray,
private val members: Array<IntArray>,
private val targets: DoubleArray,
- private val scores: DoubleArray,
- private val random: SplittableRandom
+ private val scores: DoubleArray
) : VmInterferenceMember, Comparable<InterferenceMemberImpl> {
/**
* The active groups to which the key belongs.
@@ -333,7 +318,7 @@ public class VmInterferenceModel private constructor(
}
}
- override fun apply(load: Double): Double {
+ override fun apply(random: SplittableRandom, load: Double): Double {
val groupsSize = groupsSize
if (groupsSize == 0) {
diff --git a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/SimFairShareHypervisorTest.kt b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/SimFairShareHypervisorTest.kt
index 15d32002..23d832e8 100644
--- a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/SimFairShareHypervisorTest.kt
+++ b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/SimFairShareHypervisorTest.kt
@@ -43,6 +43,7 @@ import org.opendc.simulator.compute.workload.SimTraceFragment
import org.opendc.simulator.compute.workload.SimTraceWorkload
import org.opendc.simulator.core.runBlockingSimulation
import org.opendc.simulator.flow.FlowEngine
+import java.util.*
/**
* Test suite for the [SimHypervisor] class.
@@ -77,7 +78,8 @@ internal class SimFairShareHypervisorTest {
val platform = FlowEngine(coroutineContext, clock)
val machine = SimBareMetalMachine(platform, model, SimplePowerDriver(ConstantPowerModel(0.0)))
- val hypervisor = SimFairShareHypervisor(platform, PerformanceScalingGovernor())
+ val random = SplittableRandom(1)
+ val hypervisor = SimFairShareHypervisor(platform, PerformanceScalingGovernor(), random)
launch {
machine.runWorkload(hypervisor)
@@ -128,7 +130,8 @@ internal class SimFairShareHypervisorTest {
val machine = SimBareMetalMachine(
platform, model, SimplePowerDriver(ConstantPowerModel(0.0))
)
- val hypervisor = SimFairShareHypervisor(platform, null)
+ val random = SplittableRandom(1)
+ val hypervisor = SimFairShareHypervisor(platform, null, random)
launch {
machine.runWorkload(hypervisor)
@@ -167,7 +170,8 @@ internal class SimFairShareHypervisorTest {
val platform = FlowEngine(coroutineContext, clock)
val machine = SimBareMetalMachine(platform, model, SimplePowerDriver(ConstantPowerModel(0.0)))
- val hypervisor = SimFairShareHypervisor(platform, null)
+ val random = SplittableRandom(1)
+ val hypervisor = SimFairShareHypervisor(platform, null, random)
assertDoesNotThrow {
launch {
@@ -197,7 +201,8 @@ internal class SimFairShareHypervisorTest {
val machine = SimBareMetalMachine(
platform, model, SimplePowerDriver(ConstantPowerModel(0.0))
)
- val hypervisor = SimFairShareHypervisor(platform, null)
+ val random = SplittableRandom(1)
+ val hypervisor = SimFairShareHypervisor(platform, null, random)
val duration = 5 * 60L
val workloadA =
diff --git a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/SimSpaceSharedHypervisorTest.kt b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/SimSpaceSharedHypervisorTest.kt
index 0f533130..9471f548 100644
--- a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/SimSpaceSharedHypervisorTest.kt
+++ b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/SimSpaceSharedHypervisorTest.kt
@@ -40,6 +40,7 @@ import org.opendc.simulator.compute.runWorkload
import org.opendc.simulator.compute.workload.*
import org.opendc.simulator.core.runBlockingSimulation
import org.opendc.simulator.flow.FlowEngine
+import java.util.*
/**
* A test suite for the [SimSpaceSharedHypervisor].
@@ -75,7 +76,8 @@ internal class SimSpaceSharedHypervisorTest {
val engine = FlowEngine(coroutineContext, clock)
val machine = SimBareMetalMachine(engine, machineModel, SimplePowerDriver(ConstantPowerModel(0.0)))
- val hypervisor = SimSpaceSharedHypervisor(engine, null)
+ val random = SplittableRandom(1)
+ val hypervisor = SimSpaceSharedHypervisor(engine, null, random)
launch { machine.runWorkload(hypervisor) }
val vm = hypervisor.newMachine(machineModel)
@@ -97,7 +99,8 @@ internal class SimSpaceSharedHypervisorTest {
val workload = SimRuntimeWorkload(duration)
val engine = FlowEngine(coroutineContext, clock)
val machine = SimBareMetalMachine(engine, machineModel, SimplePowerDriver(ConstantPowerModel(0.0)))
- val hypervisor = SimSpaceSharedHypervisor(engine, null)
+ val random = SplittableRandom(1)
+ val hypervisor = SimSpaceSharedHypervisor(engine, null, random)
launch { machine.runWorkload(hypervisor) }
yield()
@@ -121,7 +124,8 @@ internal class SimSpaceSharedHypervisorTest {
val machine = SimBareMetalMachine(
engine, machineModel, SimplePowerDriver(ConstantPowerModel(0.0))
)
- val hypervisor = SimSpaceSharedHypervisor(engine, null)
+ val random = SplittableRandom(1)
+ val hypervisor = SimSpaceSharedHypervisor(engine, null, random)
launch { machine.runWorkload(hypervisor) }
yield()
@@ -142,7 +146,8 @@ internal class SimSpaceSharedHypervisorTest {
val machine = SimBareMetalMachine(
engine, machineModel, SimplePowerDriver(ConstantPowerModel(0.0))
)
- val hypervisor = SimSpaceSharedHypervisor(engine, null)
+ val random = SplittableRandom(1)
+ val hypervisor = SimSpaceSharedHypervisor(engine, null, random)
launch { machine.runWorkload(hypervisor) }
yield()
@@ -169,7 +174,8 @@ internal class SimSpaceSharedHypervisorTest {
fun testConcurrentWorkloadFails() = runBlockingSimulation {
val engine = FlowEngine(coroutineContext, clock)
val machine = SimBareMetalMachine(engine, machineModel, SimplePowerDriver(ConstantPowerModel(0.0)))
- val hypervisor = SimSpaceSharedHypervisor(engine, null)
+ val random = SplittableRandom(1)
+ val hypervisor = SimSpaceSharedHypervisor(engine, null, random)
launch { machine.runWorkload(hypervisor) }
yield()
@@ -193,7 +199,8 @@ internal class SimSpaceSharedHypervisorTest {
val machine = SimBareMetalMachine(
interpreter, machineModel, SimplePowerDriver(ConstantPowerModel(0.0))
)
- val hypervisor = SimSpaceSharedHypervisor(interpreter, null)
+ val random = SplittableRandom(1)
+ val hypervisor = SimSpaceSharedHypervisor(interpreter, null, random)
launch { machine.runWorkload(hypervisor) }
yield()
diff --git a/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/OpenDCRunner.kt b/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/OpenDCRunner.kt
index c958bdb2..d5dbed1c 100644
--- a/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/OpenDCRunner.kt
+++ b/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/OpenDCRunner.kt
@@ -220,6 +220,7 @@ public class OpenDCRunner(
coroutineContext,
clock,
computeScheduler,
+ seed = 0L,
failureModel,
interferenceModel.takeIf { phenomena.interference }
)
@@ -230,7 +231,7 @@ public class OpenDCRunner(
// Instantiate the topology onto the simulator
simulator.apply(topology)
// Run workload trace
- simulator.run(vms, seeder.nextLong(), servers)
+ simulator.run(vms, servers)
val serviceMetrics = simulator.service.getSchedulerStats()
logger.debug {
diff --git a/opendc-workflow/opendc-workflow-service/src/test/kotlin/org/opendc/workflow/service/WorkflowServiceTest.kt b/opendc-workflow/opendc-workflow-service/src/test/kotlin/org/opendc/workflow/service/WorkflowServiceTest.kt
index 73d1b23b..f6fa2134 100644
--- a/opendc-workflow/opendc-workflow-service/src/test/kotlin/org/opendc/workflow/service/WorkflowServiceTest.kt
+++ b/opendc-workflow/opendc-workflow-service/src/test/kotlin/org/opendc/workflow/service/WorkflowServiceTest.kt
@@ -73,6 +73,7 @@ internal class WorkflowServiceTest {
coroutineContext,
clock,
computeScheduler,
+ seed = 0,
schedulingQuantum = Duration.ofSeconds(1)
)