diff options
| author | Fabian Mastenbroek <mail.fabianm@gmail.com> | 2022-09-23 12:49:32 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-09-23 12:49:32 +0200 |
| commit | 2d2a3854d355bd4b074ef651f291d34081e70d96 (patch) | |
| tree | e99c4bf7e5647341c1e269797f7f46099753436f /opendc-experiments/opendc-experiments-capelin | |
| parent | 8d1d091f093e6ac32dba1e6a4f74490b280fcc4b (diff) | |
| parent | 3d5eb562227dcad5a8a60f31b96e6d68f7774fb2 (diff) | |
merge: Do not require interference model during topology construction (#102)
This pull request refactors the existing workload interference model in order
to remove a dependency on it during the topology construction. With this change,
interference domains (e.g., a single host) can be constructed independently of the
interference profiles of virtual machines.
## Implementation Notes :hammer_and_pick:
* Move VM interference model into compute simulator
* Remove convergence listener parameter
* Remove FlowEngine from SimMachineContext
* Remove timestamp parameter from SimTrace
* Pass interference key via parameter
* Move interference logic into VmInterferenceMember
* Prevent boxing in interference algorithm
* Extract Random dependency from interference model
* Add separate error host state
* Simplify constructor of SimHost
* Make interference domain independent of profile
## External Dependencies :four_leaf_clover:
* N/A
## Breaking API Changes :warning:
* The interface of `VmInterferenceModel` is changed. Users do not need to
provide a seed for the model anymore.
* A `VmInterferenceModel` should be passed via the metadata parameter of
`startWorkload` to enable workload interference.
Diffstat (limited to 'opendc-experiments/opendc-experiments-capelin')
3 files changed, 35 insertions, 41 deletions
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..c09ce96a 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 @@ -55,7 +55,7 @@ class CapelinBenchmarks { fun setUp() { val loader = ComputeWorkloadLoader(File("src/test/resources/trace")) val source = trace("bitbrains-small") - vms = source.resolve(loader, Random(1L)).vms + vms = trace("bitbrains-small").resolve(loader, Random(1L)) topology = checkNotNull(object {}.javaClass.getResourceAsStream("/topology.txt")).use { clusterTopology(it) } } @@ -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, interference = true) } 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..dbb5ced3 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 @@ -22,7 +22,6 @@ package org.opendc.experiments.capelin -import org.opendc.compute.api.Server import org.opendc.compute.workload.ComputeServiceHelper import org.opendc.compute.workload.ComputeWorkloadLoader import org.opendc.compute.workload.createComputeScheduler @@ -68,18 +67,16 @@ public class CapelinRunner( grid5000(Duration.ofSeconds((operationalPhenomena.failureFrequency * 60).roundToLong())) else null - val (vms, interferenceModel) = scenario.workload.source.resolve(workloadLoader, seeder) + val vms = scenario.workload.source.resolve(workloadLoader, seeder) val runner = ComputeServiceHelper( coroutineContext, clock, computeScheduler, - failureModel, - interferenceModel?.withSeed(seed) + seed, ) val topology = clusterTopology(File(envPath, "${scenario.topology.name}.txt")) - val servers = mutableListOf<Server>() val partitions = scenario.partitions + ("seed" to seed.toString()) val partition = partitions.map { (k, v) -> "$k=$v" }.joinToString("/") val exporter = if (outputPath != null) { @@ -87,7 +84,6 @@ public class CapelinRunner( this, clock, runner.service, - servers, ParquetComputeMonitor( outputPath, partition, @@ -104,7 +100,7 @@ public class CapelinRunner( runner.apply(topology, optimize = true) // Run the workload trace - runner.run(vms, seeder.nextLong(), servers) + runner.run(vms, failureModel = failureModel, interference = operationalPhenomena.hasInterference) // 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 d7b7caad..eae3c993 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 @@ -26,7 +26,6 @@ import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertAll -import org.opendc.compute.api.Server import org.opendc.compute.service.scheduler.FilterScheduler import org.opendc.compute.service.scheduler.filters.ComputeFilter import org.opendc.compute.service.scheduler.filters.RamFilter @@ -81,20 +80,20 @@ 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() - - val servers = mutableListOf<Server>() - val reader = ComputeMetricReader(this, clock, runner.service, servers, monitor) + val reader = ComputeMetricReader(this, clock, runner.service, monitor) try { runner.apply(topology) - runner.run(workload, 0, servers) + runner.run(workload) val serviceMetrics = runner.service.getSchedulerStats() println( @@ -129,20 +128,20 @@ class CapelinIntegrationTest { */ @Test fun testSmall() = runBlockingSimulation { - val seed = 1 - val (workload, _) = createTestWorkload(0.25, seed) + 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>() - val reader = ComputeMetricReader(this, clock, runner.service, servers, monitor) + val reader = ComputeMetricReader(this, clock, runner.service, monitor) try { runner.apply(topology) - runner.run(workload, seed.toLong(), servers) + runner.run(workload) val serviceMetrics = runner.service.getSchedulerStats() println( @@ -173,22 +172,21 @@ class CapelinIntegrationTest { */ @Test fun testInterference() = runBlockingSimulation { - val seed = 0 - val (workload, interferenceModel) = createTestWorkload(1.0, seed) + val seed = 0L + val workload = createTestWorkload(1.0, seed) val simulator = ComputeServiceHelper( coroutineContext, clock, computeScheduler, - interferenceModel = interferenceModel?.withSeed(seed.toLong()) + seed ) val topology = createTopology("single") - val servers = mutableListOf<Server>() - val reader = ComputeMetricReader(this, clock, simulator.service, servers, monitor) + val reader = ComputeMetricReader(this, clock, simulator.service, monitor) try { simulator.apply(topology) - simulator.run(workload, seed.toLong(), servers) + simulator.run(workload, interference = true) val serviceMetrics = simulator.service.getSchedulerStats() println( @@ -209,7 +207,7 @@ class CapelinIntegrationTest { { assertEquals(6028050, this@CapelinIntegrationTest.monitor.idleTime) { "Idle time incorrect" } }, { assertEquals(14712749, this@CapelinIntegrationTest.monitor.activeTime) { "Active time incorrect" } }, { assertEquals(12532907, this@CapelinIntegrationTest.monitor.stealTime) { "Steal time incorrect" } }, - { assertEquals(467963, this@CapelinIntegrationTest.monitor.lostTime) { "Lost time incorrect" } } + { assertEquals(485510, this@CapelinIntegrationTest.monitor.lostTime) { "Lost time incorrect" } } ) } @@ -218,21 +216,20 @@ class CapelinIntegrationTest { */ @Test fun testFailures() = runBlockingSimulation { - val seed = 1 + val seed = 0L val simulator = ComputeServiceHelper( coroutineContext, clock, computeScheduler, - grid5000(Duration.ofDays(7)) + seed ) val topology = createTopology("single") - val (workload, _) = createTestWorkload(0.25, seed) - val servers = mutableListOf<Server>() - val reader = ComputeMetricReader(this, clock, simulator.service, servers, monitor) + val workload = createTestWorkload(0.25, seed) + val reader = ComputeMetricReader(this, clock, simulator.service, monitor) try { simulator.apply(topology) - simulator.run(workload, seed.toLong(), servers) + simulator.run(workload, failureModel = grid5000(Duration.ofDays(7))) val serviceMetrics = simulator.service.getSchedulerStats() println( @@ -250,20 +247,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): List<VirtualMachine> { val source = trace("bitbrains-small").sampleByLoad(fraction) - return source.resolve(workloadLoader, Random(seed.toLong())) + return source.resolve(workloadLoader, Random(seed)) } /** |
