summaryrefslogtreecommitdiff
path: root/opendc-experiments/opendc-experiments-capelin/src
diff options
context:
space:
mode:
Diffstat (limited to 'opendc-experiments/opendc-experiments-capelin/src')
-rw-r--r--opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/ExperimentHelpers.kt7
-rw-r--r--opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/Portfolio.kt11
-rw-r--r--opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/trace/ParquetTraceReader.kt8
-rw-r--r--opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/trace/PerformanceInterferenceReader.kt65
-rw-r--r--opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/trace/VmPlacementReader.kt6
-rw-r--r--opendc-experiments/opendc-experiments-capelin/src/test/kotlin/org/opendc/experiments/capelin/CapelinIntegrationTest.kt2
-rw-r--r--opendc-experiments/opendc-experiments-capelin/src/test/kotlin/org/opendc/experiments/capelin/trace/PerformanceInterferenceReaderTest.kt47
-rw-r--r--opendc-experiments/opendc-experiments-capelin/src/test/resources/perf-interference.json22
8 files changed, 157 insertions, 11 deletions
diff --git a/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/ExperimentHelpers.kt b/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/ExperimentHelpers.kt
index 06251dd3..9548253d 100644
--- a/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/ExperimentHelpers.kt
+++ b/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/ExperimentHelpers.kt
@@ -44,6 +44,8 @@ import org.opendc.experiments.capelin.monitor.ExperimentMonitor
import org.opendc.format.environment.EnvironmentReader
import org.opendc.format.trace.TraceReader
import org.opendc.simulator.compute.kernel.SimFairShareHypervisorProvider
+import org.opendc.simulator.compute.kernel.interference.VmInterferenceModel
+import org.opendc.simulator.compute.power.SimplePowerDriver
import org.opendc.simulator.compute.workload.SimTraceWorkload
import org.opendc.simulator.compute.workload.SimWorkload
import org.opendc.simulator.failures.CorrelatedFaultInjector
@@ -123,6 +125,7 @@ suspend fun withComputeService(
meterProvider: MeterProvider,
environmentReader: EnvironmentReader,
scheduler: ComputeScheduler,
+ interferenceModel: VmInterferenceModel? = null,
block: suspend CoroutineScope.(ComputeService) -> Unit
): Unit = coroutineScope {
val interpreter = SimResourceInterpreter(coroutineContext, clock)
@@ -138,7 +141,8 @@ suspend fun withComputeService(
interpreter,
meterProvider.get("opendc-compute-simulator"),
SimFairShareHypervisorProvider(),
- def.powerModel
+ powerDriver = SimplePowerDriver(def.powerModel),
+ interferenceDomain = interferenceModel?.newDomain()
)
}
@@ -161,7 +165,6 @@ suspend fun withComputeService(
/**
* Attach the specified monitor to the VM provisioner.
*/
-@OptIn(ExperimentalCoroutinesApi::class)
suspend fun withMonitor(
monitor: ExperimentMonitor,
clock: Clock,
diff --git a/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/Portfolio.kt b/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/Portfolio.kt
index 460da303..cbb5bfd9 100644
--- a/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/Portfolio.kt
+++ b/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/Portfolio.kt
@@ -39,11 +39,14 @@ import org.opendc.experiments.capelin.model.Topology
import org.opendc.experiments.capelin.model.Workload
import org.opendc.experiments.capelin.monitor.ParquetExperimentMonitor
import org.opendc.experiments.capelin.trace.ParquetTraceReader
+import org.opendc.experiments.capelin.trace.PerformanceInterferenceReader
import org.opendc.experiments.capelin.trace.RawParquetTraceReader
import org.opendc.harness.dsl.Experiment
import org.opendc.harness.dsl.anyOf
+import org.opendc.simulator.compute.kernel.interference.VmInterferenceModel
import org.opendc.simulator.core.runBlockingSimulation
import java.io.File
+import java.io.FileInputStream
import java.util.*
import java.util.concurrent.ConcurrentHashMap
@@ -119,6 +122,12 @@ abstract class Portfolio(name: String) : Experiment(name) {
}
}
+ val performanceInterferenceModel = if (operationalPhenomena.hasInterference)
+ PerformanceInterferenceReader(FileInputStream(config.getString("interference-model")))
+ .use { VmInterferenceModel(it.read(), Random(seeder.nextLong())) }
+ else
+ null
+
val trace = ParquetTraceReader(rawReaders, workload, seeder.nextInt())
val monitor = ParquetExperimentMonitor(
@@ -127,7 +136,7 @@ abstract class Portfolio(name: String) : Experiment(name) {
4096
)
- withComputeService(clock, meterProvider, environment, allocationPolicy) { scheduler ->
+ withComputeService(clock, meterProvider, environment, allocationPolicy, performanceInterferenceModel) { scheduler ->
val failureDomain = if (operationalPhenomena.failureFrequency > 0) {
logger.debug("ENABLING failures")
createFailureDomain(
diff --git a/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/trace/ParquetTraceReader.kt b/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/trace/ParquetTraceReader.kt
index 2ebe65ea..5ad75565 100644
--- a/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/trace/ParquetTraceReader.kt
+++ b/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/trace/ParquetTraceReader.kt
@@ -31,11 +31,11 @@ import org.opendc.simulator.compute.workload.SimWorkload
/**
* A [TraceReader] for the internal VM workload trace format.
*
- * @param rawReaders The raw trace readers to use..
- * @param workload The workload to use.
- * @param seed The seed to use for workload sampling.
+ * @param rawReaders The internal raw trace readers to use.
+ * @param workload The workload to read.
+ * @param seed The seed to use for sampling.
*/
-class ParquetTraceReader(
+public class ParquetTraceReader(
rawReaders: List<RawParquetTraceReader>,
workload: Workload,
seed: Int
diff --git a/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/trace/PerformanceInterferenceReader.kt b/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/trace/PerformanceInterferenceReader.kt
new file mode 100644
index 00000000..a19f5699
--- /dev/null
+++ b/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/trace/PerformanceInterferenceReader.kt
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2021 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.experiments.capelin.trace
+
+import com.fasterxml.jackson.annotation.JsonProperty
+import com.fasterxml.jackson.databind.ObjectMapper
+import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
+import com.fasterxml.jackson.module.kotlin.readValue
+import org.opendc.simulator.compute.kernel.interference.VmInterferenceGroup
+import java.io.InputStream
+
+/**
+ * A parser for the JSON performance interference setup files used for the TPDS article on Capelin.
+ *
+ * @param input The input stream to read from.
+ * @param mapper The Jackson object mapper to use.
+ */
+class PerformanceInterferenceReader(
+ private val input: InputStream,
+ private val mapper: ObjectMapper = jacksonObjectMapper()
+) : AutoCloseable {
+ init {
+ mapper.addMixIn(VmInterferenceGroup::class.java, GroupMixin::class.java)
+ }
+
+ /**
+ * Read the performance interface model from the input.
+ */
+ fun read(): List<VmInterferenceGroup> {
+ return mapper.readValue(input)
+ }
+
+ override fun close() {
+ input.close()
+ }
+
+ private data class GroupMixin(
+ @JsonProperty("minServerLoad")
+ val targetLoad: Double,
+ @JsonProperty("performanceScore")
+ val score: Double,
+ @JsonProperty("vms")
+ val members: Set<String>,
+ )
+}
diff --git a/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/trace/VmPlacementReader.kt b/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/trace/VmPlacementReader.kt
index fb641f1b..7a1683f0 100644
--- a/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/trace/VmPlacementReader.kt
+++ b/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/trace/VmPlacementReader.kt
@@ -28,7 +28,7 @@ import com.fasterxml.jackson.module.kotlin.readValue
import java.io.InputStream
/**
- * A parser for the JSON VM placement data files used for the SC20 paper.
+ * A parser for the JSON VM placement data files used for the TPDS article on Capelin.
*
* @param input The input stream to read from.
* @param mapper The Jackson object mapper to use.
@@ -38,9 +38,9 @@ public class VmPlacementReader(
private val mapper: ObjectMapper = jacksonObjectMapper()
) : AutoCloseable {
/**
- * Read the VM placements.
+ * Read the VM placements from the input.
*/
- fun read(): Map<String, String> {
+ public fun read(): Map<String, String> {
return mapper.readValue<Map<String, String>>(input)
.mapKeys { "vm__workload__${it.key}.txt" }
.mapValues { it.value.split("/")[1] } // Clusters have format XX0 / X00
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 beaa798f..08e04ddf 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
@@ -172,7 +172,7 @@ class CapelinIntegrationTest {
* Obtain the environment reader for the test.
*/
private fun createTestEnvironmentReader(name: String = "topology"): EnvironmentReader {
- val stream = object {}.javaClass.getResourceAsStream("/env/$name.txt")
+ val stream = checkNotNull(object {}.javaClass.getResourceAsStream("/env/$name.txt"))
return ClusterEnvironmentReader(stream)
}
diff --git a/opendc-experiments/opendc-experiments-capelin/src/test/kotlin/org/opendc/experiments/capelin/trace/PerformanceInterferenceReaderTest.kt b/opendc-experiments/opendc-experiments-capelin/src/test/kotlin/org/opendc/experiments/capelin/trace/PerformanceInterferenceReaderTest.kt
new file mode 100644
index 00000000..9b1513dc
--- /dev/null
+++ b/opendc-experiments/opendc-experiments-capelin/src/test/kotlin/org/opendc/experiments/capelin/trace/PerformanceInterferenceReaderTest.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2021 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.experiments.capelin.trace
+
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.assertAll
+
+/**
+ * Test suite for the [PerformanceInterferenceReader] class.
+ */
+class PerformanceInterferenceReaderTest {
+ @Test
+ fun testSmoke() {
+ val input = checkNotNull(PerformanceInterferenceReader::class.java.getResourceAsStream("/perf-interference.json"))
+ val reader = PerformanceInterferenceReader(input)
+
+ val result = reader.use { reader.read() }
+
+ assertAll(
+ { assertEquals(2, result.size) },
+ { assertEquals(setOf("vm_a", "vm_c", "vm_x", "vm_y"), result[0].members) },
+ { assertEquals(0.0, result[0].targetLoad, 0.001) },
+ { assertEquals(0.8830158730158756, result[0].score, 0.001) }
+ )
+ }
+}
diff --git a/opendc-experiments/opendc-experiments-capelin/src/test/resources/perf-interference.json b/opendc-experiments/opendc-experiments-capelin/src/test/resources/perf-interference.json
new file mode 100644
index 00000000..1be5852b
--- /dev/null
+++ b/opendc-experiments/opendc-experiments-capelin/src/test/resources/perf-interference.json
@@ -0,0 +1,22 @@
+[
+ {
+ "vms": [
+ "vm_a",
+ "vm_c",
+ "vm_x",
+ "vm_y"
+ ],
+ "minServerLoad": 0.0,
+ "performanceScore": 0.8830158730158756
+ },
+ {
+ "vms": [
+ "vm_a",
+ "vm_b",
+ "vm_c",
+ "vm_d"
+ ],
+ "minServerLoad": 0.0,
+ "performanceScore": 0.7133055555552751
+ }
+]