summaryrefslogtreecommitdiff
path: root/opendc-experiments
diff options
context:
space:
mode:
Diffstat (limited to 'opendc-experiments')
-rw-r--r--opendc-experiments/opendc-experiments-capelin/LICENSE.txt21
-rw-r--r--opendc-experiments/opendc-experiments-capelin/README.md9
-rw-r--r--opendc-experiments/opendc-experiments-capelin/build.gradle.kts48
-rw-r--r--opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/CapelinCli.kt152
-rw-r--r--opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/CapelinRunner.kt115
-rw-r--r--opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/Portfolio.kt140
-rw-r--r--opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/ReplayPortfolio.kt51
-rw-r--r--opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/model/Scenario.kt (renamed from opendc-experiments/opendc-experiments-serverless20/build.gradle.kts)34
-rw-r--r--opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/portfolio/CompositeWorkloadPortfolio.kt (renamed from opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/CompositeWorkloadPortfolio.kt)35
-rw-r--r--opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/portfolio/HorVerPortfolio.kt (renamed from opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/HorVerPortfolio.kt)40
-rw-r--r--opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/portfolio/MoreHpcPortfolio.kt (renamed from opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/MoreHpcPortfolio.kt)46
-rw-r--r--opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/portfolio/MoreVelocityPortfolio.kt (renamed from opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/MoreVelocityPortfolio.kt)39
-rw-r--r--opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/portfolio/OperationalPhenomenaPortfolio.kt (renamed from opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/OperationalPhenomenaPortfolio.kt)42
-rw-r--r--opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/portfolio/Portfolio.kt (renamed from opendc-experiments/opendc-experiments-serverless20/src/main/kotlin/org/opendc/experiments/serverless/trace/FunctionTrace.kt)13
-rw-r--r--opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/portfolio/TestPortfolio.kt (renamed from opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/TestPortfolio.kt)27
-rw-r--r--opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/util/VmPlacementReader.kt47
-rw-r--r--opendc-experiments/opendc-experiments-capelin/src/main/resources/application.conf6
-rw-r--r--opendc-experiments/opendc-experiments-capelin/src/main/resources/log4j2.xml8
-rw-r--r--opendc-experiments/opendc-experiments-serverless20/README.md7
-rw-r--r--opendc-experiments/opendc-experiments-serverless20/src/main/kotlin/org/opendc/experiments/serverless/ServerlessExperiment.kt132
-rw-r--r--opendc-experiments/opendc-experiments-serverless20/src/main/kotlin/org/opendc/experiments/serverless/trace/FunctionSample.kt44
-rw-r--r--opendc-experiments/opendc-experiments-serverless20/src/main/kotlin/org/opendc/experiments/serverless/trace/FunctionTraceWorkload.kt37
-rw-r--r--opendc-experiments/opendc-experiments-serverless20/src/main/kotlin/org/opendc/experiments/serverless/trace/ServerlessTraceReader.kt107
-rw-r--r--opendc-experiments/opendc-experiments-serverless20/src/main/resources/application.conf8
-rw-r--r--opendc-experiments/opendc-experiments-tf20/build.gradle.kts5
-rw-r--r--opendc-experiments/opendc-experiments-tf20/src/main/kotlin/org/opendc/experiments/tf20/Models.kt4
-rw-r--r--opendc-experiments/opendc-experiments-tf20/src/main/kotlin/org/opendc/experiments/tf20/core/SimTFDevice.kt3
-rw-r--r--opendc-experiments/opendc-experiments-tf20/src/test/kotlin/org/opendc/experiments/tf20/TensorFlowTest.kt (renamed from opendc-experiments/opendc-experiments-tf20/src/main/kotlin/org/opendc/experiments/tf20/TensorFlowExperiment.kt)65
-rw-r--r--opendc-experiments/opendc-experiments-tf20/src/test/kotlin/org/opendc/experiments/tf20/core/SimTFDeviceTest.kt2
29 files changed, 554 insertions, 733 deletions
diff --git a/opendc-experiments/opendc-experiments-capelin/LICENSE.txt b/opendc-experiments/opendc-experiments-capelin/LICENSE.txt
new file mode 100644
index 00000000..3931600a
--- /dev/null
+++ b/opendc-experiments/opendc-experiments-capelin/LICENSE.txt
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Georgios Andreadis, Fabian Mastenbroek
+
+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.
diff --git a/opendc-experiments/opendc-experiments-capelin/README.md b/opendc-experiments/opendc-experiments-capelin/README.md
new file mode 100644
index 00000000..d86fe81d
--- /dev/null
+++ b/opendc-experiments/opendc-experiments-capelin/README.md
@@ -0,0 +1,9 @@
+# Capelin
+Data-Driven Compute Capacity Procurement for Cloud Datacenters Using Portfolios of Scenarios.
+
+See the [publication](https://arxiv.org/abs/2103.02060) and
+[thesis](https://repository.tudelft.nl/islandora/object/uuid:d6d50861-86a3-4dd3-a13f-42d84db7af66?collection=education) for information.
+
+## License
+
+OpenDC and Capelin are distributed under the MIT license. See [LICENSE-OpenDC.txt](/LICENSE.txt) and [LICENSE.txt](LICENSE.txt).
diff --git a/opendc-experiments/opendc-experiments-capelin/build.gradle.kts b/opendc-experiments/opendc-experiments-capelin/build.gradle.kts
index 39cf101d..8320179a 100644
--- a/opendc-experiments/opendc-experiments-capelin/build.gradle.kts
+++ b/opendc-experiments/opendc-experiments-capelin/build.gradle.kts
@@ -24,28 +24,62 @@ description = "Experiments for the Capelin work"
/* Build configuration */
plugins {
- `experiment-conventions`
+ `kotlin-conventions`
`testing-conventions`
`jacoco-conventions`
`benchmark-conventions`
+ distribution
}
dependencies {
- api(projects.opendcHarness.opendcHarnessApi)
api(projects.opendcCompute.opendcComputeWorkload)
implementation(projects.opendcSimulator.opendcSimulatorCore)
implementation(projects.opendcSimulator.opendcSimulatorCompute)
implementation(projects.opendcCompute.opendcComputeSimulator)
- implementation(libs.config)
+ implementation(libs.clikt)
+ implementation(libs.progressbar)
implementation(libs.kotlin.logging)
- implementation(libs.jackson.databind)
- implementation(libs.jackson.module.kotlin)
implementation(libs.jackson.dataformat.csv)
- implementation(kotlin("reflect"))
runtimeOnly(projects.opendcTrace.opendcTraceOpendc)
+ runtimeOnly(libs.log4j.slf4j)
+}
+
+val createCapelinApp by tasks.creating(CreateStartScripts::class) {
+ dependsOn(tasks.jar)
+
+ applicationName = "capelin"
+ mainClass.set("org.opendc.experiments.capelin.CapelinCli")
+ classpath = tasks.jar.get().outputs.files + configurations["runtimeClasspath"]
+ outputDir = project.buildDir.resolve("scripts")
+}
+
+/* Create custom Capelin distribution */
+distributions {
+ main {
+ distributionBaseName.set("capelin")
+
+ contents {
+ from("README.md")
+ from("LICENSE.txt")
+ from("../../LICENSE.txt") {
+ rename { "LICENSE-OpenDC.txt" }
+ }
+
+ into("bin") {
+ from(createCapelinApp)
+ }
+
+ into("lib") {
+ from(tasks.jar)
+ from(configurations["runtimeClasspath"])
+ }
- testImplementation(libs.log4j.slf4j)
+ into("input") {
+ from("input")
+ }
+ }
+ }
}
diff --git a/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/CapelinCli.kt b/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/CapelinCli.kt
new file mode 100644
index 00000000..875ae0dc
--- /dev/null
+++ b/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/CapelinCli.kt
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2022 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.
+ */
+
+@file:JvmName("CapelinCli")
+package org.opendc.experiments.capelin
+
+import com.github.ajalt.clikt.core.CliktCommand
+import com.github.ajalt.clikt.parameters.arguments.argument
+import com.github.ajalt.clikt.parameters.options.*
+import com.github.ajalt.clikt.parameters.types.choice
+import com.github.ajalt.clikt.parameters.types.file
+import com.github.ajalt.clikt.parameters.types.int
+import com.github.ajalt.clikt.parameters.types.long
+import me.tongfei.progressbar.ProgressBarBuilder
+import me.tongfei.progressbar.ProgressBarStyle
+import org.opendc.experiments.capelin.model.Scenario
+import org.opendc.experiments.capelin.portfolio.*
+import java.io.File
+import java.util.concurrent.ForkJoinPool
+import java.util.stream.LongStream
+
+/**
+ * Main entrypoint of the application.
+ */
+fun main(args: Array<String>): Unit = CapelinCommand().main(args)
+
+/**
+ * Represents the command for the Capelin experiments.
+ */
+internal class CapelinCommand : CliktCommand(name = "capelin") {
+ /**
+ * The path to the environment directory.
+ */
+ private val envPath by option("--env-path", help = "path to environment directory")
+ .file(canBeDir = true, canBeFile = false)
+ .defaultLazy { File("input/environments") }
+
+ /**
+ * The path to the trace directory.
+ */
+ private val tracePath by option("--trace-path", help = "path to trace directory")
+ .file(canBeDir = true, canBeFile = false)
+ .defaultLazy { File("input/traces") }
+
+ /**
+ * The path to the experiment output.
+ */
+ private val outputPath by option("-O", "--output", help = "path to experiment output")
+ .file(canBeDir = true, canBeFile = false)
+ .defaultLazy { File("output") }
+
+ /**
+ * Disable writing output.
+ */
+ private val disableOutput by option("--disable-output", help = "disable output").flag()
+
+ /**
+ * The number of threads to use for parallelism.
+ */
+ private val parallelism by option("-p", "--parallelism", help = "number of worker threads")
+ .int()
+ .default(Runtime.getRuntime().availableProcessors() - 1)
+
+ /**
+ * The number of repeats.
+ */
+ private val repeats by option("-r", "--repeats", help = "number of repeats")
+ .int()
+ .default(128)
+
+ /**
+ * The seed for seeding the random instances.
+ */
+ private val seed by option("-s", "--seed", help = "initial seed for randomness")
+ .long()
+ .default(0)
+
+ /**
+ * The portfolio to replay.
+ */
+ private val portfolio by argument(help = "portfolio to replay")
+ .choice(
+ "test" to { TestPortfolio() },
+ "composite-workload" to { CompositeWorkloadPortfolio() },
+ "hor-ver" to { HorVerPortfolio() },
+ "more-hpc" to { MoreHpcPortfolio() },
+ "more-velocity" to { MoreVelocityPortfolio() },
+ "op-phen" to { OperationalPhenomenaPortfolio() },
+ )
+
+ /**
+ * The base partitions to use for the invocation
+ */
+ private val basePartitions: Map<String, String> by option("-P", "--base-partitions").associate()
+
+ override fun run() {
+ val runner = CapelinRunner(envPath, tracePath, outputPath.takeUnless { disableOutput })
+ val scenarios = portfolio().scenarios.toList()
+
+ val pool = ForkJoinPool(parallelism)
+
+ echo("Detected ${scenarios.size} scenarios [$repeats replications]")
+
+ for (scenario in scenarios) {
+ runScenario(runner, pool, scenario)
+ }
+
+ pool.shutdown()
+ }
+
+ /**
+ * Run a single scenario.
+ */
+ private fun runScenario(runner: CapelinRunner, pool: ForkJoinPool, scenario: Scenario) {
+ val pb = ProgressBarBuilder()
+ .setInitialMax(repeats.toLong())
+ .setStyle(ProgressBarStyle.ASCII)
+ .setTaskName("Simulating...")
+ .build()
+
+ pool.submit {
+ LongStream.range(0, repeats.toLong())
+ .parallel()
+ .forEach { repeat ->
+ val augmentedScenario = scenario.copy(partitions = basePartitions + scenario.partitions)
+ runner.runScenario(augmentedScenario, seed + repeat)
+ pb.step()
+ }
+
+ pb.close()
+ }.join()
+ }
+}
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
new file mode 100644
index 00000000..cca5b6cf
--- /dev/null
+++ b/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/CapelinRunner.kt
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2022 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
+
+import org.opendc.compute.api.Server
+import org.opendc.compute.workload.ComputeServiceHelper
+import org.opendc.compute.workload.ComputeWorkloadLoader
+import org.opendc.compute.workload.createComputeScheduler
+import org.opendc.compute.workload.export.parquet.ParquetComputeMonitor
+import org.opendc.compute.workload.grid5000
+import org.opendc.compute.workload.telemetry.ComputeMetricReader
+import org.opendc.compute.workload.topology.apply
+import org.opendc.experiments.capelin.model.Scenario
+import org.opendc.experiments.capelin.topology.clusterTopology
+import org.opendc.simulator.core.runBlockingSimulation
+import java.io.File
+import java.time.Duration
+import java.util.*
+import kotlin.math.roundToLong
+
+/**
+ * Helper class for running the Capelin experiments.
+ *
+ * @param envPath The path to the directory containing the environments.
+ * @param tracePath The path to the directory containing the traces.
+ * @param outputPath The path to the directory where the output should be written (or `null` if no output should be generated).
+ */
+public class CapelinRunner(
+ private val envPath: File,
+ tracePath: File,
+ private val outputPath: File?
+) {
+ /**
+ * The [ComputeWorkloadLoader] to use for loading the traces.
+ */
+ private val workloadLoader = ComputeWorkloadLoader(tracePath)
+
+ /**
+ * Run a single [scenario] with the specified seed.
+ */
+ fun runScenario(scenario: Scenario, seed: Long) = runBlockingSimulation {
+ val seeder = Random(seed)
+
+ val operationalPhenomena = scenario.operationalPhenomena
+ val computeScheduler = createComputeScheduler(scenario.allocationPolicy, seeder)
+ val failureModel =
+ if (operationalPhenomena.failureFrequency > 0)
+ grid5000(Duration.ofSeconds((operationalPhenomena.failureFrequency * 60).roundToLong()))
+ else
+ null
+ val (vms, interferenceModel) = scenario.workload.source.resolve(workloadLoader, seeder)
+ val runner = ComputeServiceHelper(
+ coroutineContext,
+ clock,
+ computeScheduler,
+ failureModel,
+ interferenceModel?.withSeed(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) {
+ ComputeMetricReader(
+ this,
+ clock,
+ runner.service,
+ servers,
+ ParquetComputeMonitor(
+ outputPath,
+ partition,
+ bufferSize = 4096
+ ),
+ exportInterval = Duration.ofMinutes(5)
+ )
+ } else {
+ null
+ }
+
+ try {
+ // Instantiate the desired topology
+ runner.apply(topology, optimize = true)
+
+ // Run the workload trace
+ runner.run(vms, seeder.nextLong(), servers)
+
+ // Stop the metric collection
+ exporter?.close()
+ } finally {
+ runner.close()
+ }
+ }
+}
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
deleted file mode 100644
index 0de8aa7b..00000000
--- a/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/Portfolio.kt
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * 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
-
-import com.typesafe.config.ConfigFactory
-import kotlinx.coroutines.*
-import org.opendc.compute.api.Server
-import org.opendc.compute.workload.ComputeServiceHelper
-import org.opendc.compute.workload.ComputeWorkloadLoader
-import org.opendc.compute.workload.createComputeScheduler
-import org.opendc.compute.workload.export.parquet.ParquetComputeMonitor
-import org.opendc.compute.workload.grid5000
-import org.opendc.compute.workload.telemetry.ComputeMetricReader
-import org.opendc.compute.workload.topology.apply
-import org.opendc.experiments.capelin.model.OperationalPhenomena
-import org.opendc.experiments.capelin.model.Topology
-import org.opendc.experiments.capelin.model.Workload
-import org.opendc.experiments.capelin.topology.clusterTopology
-import org.opendc.harness.dsl.Experiment
-import org.opendc.harness.dsl.anyOf
-import org.opendc.simulator.core.runBlockingSimulation
-import java.io.File
-import java.time.Duration
-import java.util.*
-import kotlin.math.roundToLong
-
-/**
- * A portfolio represents a collection of scenarios are tested for the work.
- *
- * @param name The name of the portfolio.
- */
-abstract class Portfolio(name: String) : Experiment(name) {
- /**
- * The configuration to use.
- */
- private val config = ConfigFactory.load().getConfig("opendc.experiments.capelin")
-
- /**
- * The path to the original VM placements file.
- */
- private val vmPlacements by anyOf(emptyMap<String, String>())
-
- /**
- * The topology to test.
- */
- abstract val topology: Topology
-
- /**
- * The workload to test.
- */
- abstract val workload: Workload
-
- /**
- * The operational phenomenas to consider.
- */
- abstract val operationalPhenomena: OperationalPhenomena
-
- /**
- * The allocation policies to consider.
- */
- abstract val allocationPolicy: String
-
- /**
- * A helper class to load workload traces.
- */
- private val workloadLoader = ComputeWorkloadLoader(File(config.getString("trace-path")))
-
- /**
- * Perform a single trial for this portfolio.
- */
- override fun doRun(repeat: Int): Unit = runBlockingSimulation {
- val seeder = Random(repeat.toLong())
-
- val computeScheduler = createComputeScheduler(allocationPolicy, seeder, vmPlacements)
- val failureModel =
- if (operationalPhenomena.failureFrequency > 0)
- grid5000(Duration.ofSeconds((operationalPhenomena.failureFrequency * 60).roundToLong()))
- else
- null
- val (vms, interferenceModel) = workload.source.resolve(workloadLoader, seeder)
- val runner = ComputeServiceHelper(
- coroutineContext,
- clock,
- computeScheduler,
- failureModel,
- interferenceModel?.withSeed(repeat.toLong())
- )
-
- val topology = clusterTopology(File(config.getString("env-path"), "${topology.name}.txt"))
- val servers = mutableListOf<Server>()
- val exporter = ComputeMetricReader(
- this,
- clock,
- runner.service,
- servers,
- ParquetComputeMonitor(
- File(config.getString("output-path")),
- "portfolio_id=$name/scenario_id=$id/run_id=$repeat",
- bufferSize = 4096
- ),
- exportInterval = Duration.ofMinutes(5)
- )
-
- try {
- // Instantiate the desired topology
- runner.apply(topology)
-
- coroutineScope {
- // Run the workload trace
- runner.run(vms, seeder.nextLong(), servers)
-
- // Stop the metric collection
- exporter.close()
- }
- } finally {
- runner.close()
- exporter.close()
- }
- }
-}
diff --git a/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/ReplayPortfolio.kt b/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/ReplayPortfolio.kt
deleted file mode 100644
index 17ec48d4..00000000
--- a/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/ReplayPortfolio.kt
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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
-
-import org.opendc.compute.workload.trace
-import org.opendc.experiments.capelin.model.OperationalPhenomena
-import org.opendc.experiments.capelin.model.Topology
-import org.opendc.experiments.capelin.model.Workload
-import org.opendc.harness.dsl.anyOf
-
-/**
- * A [Portfolio] that compares the original VM placements against our policies.
- */
-public class ReplayPortfolio : Portfolio("replay") {
- override val topology: Topology by anyOf(
- Topology("base")
- )
-
- override val workload: Workload by anyOf(
- Workload("solvinity", trace("solvinity"))
- )
-
- override val operationalPhenomena: OperationalPhenomena by anyOf(
- OperationalPhenomena(failureFrequency = 0.0, hasInterference = false)
- )
-
- override val allocationPolicy: String by anyOf(
- "replay",
- "active-servers"
- )
-}
diff --git a/opendc-experiments/opendc-experiments-serverless20/build.gradle.kts b/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/model/Scenario.kt
index a6391986..2218a46b 100644
--- a/opendc-experiments/opendc-experiments-serverless20/build.gradle.kts
+++ b/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/model/Scenario.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 AtLarge Research
+ * Copyright (c) 2022 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
@@ -20,19 +20,21 @@
* SOFTWARE.
*/
-description = "Experiments for OpenDC Serverless"
+package org.opendc.experiments.capelin.model
-/* Build configuration */
-plugins {
- `experiment-conventions`
- `testing-conventions`
-}
-
-dependencies {
- api(projects.opendcHarness.opendcHarnessApi)
- implementation(projects.opendcSimulator.opendcSimulatorCore)
- implementation(projects.opendcFaas.opendcFaasService)
- implementation(projects.opendcFaas.opendcFaasSimulator)
- implementation(libs.kotlin.logging)
- implementation(libs.config)
-}
+/**
+ * A single scenario of a portfolio.
+ *
+ * @property topology The topology to test.
+ * @property workload The workload to test.
+ * @property operationalPhenomena The [OperationalPhenomena] to model.
+ * @property allocationPolicy The allocation policy of the scheduler.
+ * @property partitions The partition of the scenario.
+ */
+public data class Scenario(
+ val topology: Topology,
+ val workload: Workload,
+ val operationalPhenomena: OperationalPhenomena,
+ val allocationPolicy: String,
+ val partitions: Map<String, String> = emptyMap()
+)
diff --git a/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/CompositeWorkloadPortfolio.kt b/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/portfolio/CompositeWorkloadPortfolio.kt
index 31e8f961..68eb15b3 100644
--- a/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/CompositeWorkloadPortfolio.kt
+++ b/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/portfolio/CompositeWorkloadPortfolio.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 AtLarge Research
+ * Copyright (c) 2022 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
@@ -20,29 +20,26 @@
* SOFTWARE.
*/
-package org.opendc.experiments.capelin
+package org.opendc.experiments.capelin.portfolio
import org.opendc.compute.workload.composite
import org.opendc.compute.workload.trace
import org.opendc.experiments.capelin.model.OperationalPhenomena
+import org.opendc.experiments.capelin.model.Scenario
import org.opendc.experiments.capelin.model.Topology
import org.opendc.experiments.capelin.model.Workload
-import org.opendc.harness.dsl.anyOf
/**
* A [Portfolio] that explores the effect of a composite workload.
*/
-public class CompositeWorkloadPortfolio : Portfolio("composite-workload") {
- private val totalSampleLoad = 1.3301733005049648E12
-
- override val topology: Topology by anyOf(
+public class CompositeWorkloadPortfolio : Portfolio {
+ private val topologies = listOf(
Topology("base"),
Topology("exp-vol-hor-hom"),
Topology("exp-vol-ver-hom"),
Topology("exp-vel-ver-hom")
)
-
- override val workload: Workload by anyOf(
+ private val workloads = listOf(
Workload(
"all-azure",
composite(trace("solvinity-short") to 0.0, trace("azure") to 1.0)
@@ -64,12 +61,18 @@ public class CompositeWorkloadPortfolio : Portfolio("composite-workload") {
composite(trace("solvinity-short") to 1.0, trace("azure") to 0.0)
)
)
+ private val operationalPhenomena = OperationalPhenomena(failureFrequency = 24.0 * 7, hasInterference = false)
+ private val allocationPolicy = "active-servers"
- override val operationalPhenomena: OperationalPhenomena by anyOf(
- OperationalPhenomena(failureFrequency = 24.0 * 7, hasInterference = false)
- )
-
- override val allocationPolicy: String by anyOf(
- "active-servers"
- )
+ override val scenarios: Iterable<Scenario> = topologies.flatMap { topology ->
+ workloads.map { workload ->
+ Scenario(
+ topology,
+ workload,
+ operationalPhenomena,
+ allocationPolicy,
+ mapOf("topology" to topology.name, "workload" to workload.name)
+ )
+ }
+ }
}
diff --git a/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/HorVerPortfolio.kt b/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/portfolio/HorVerPortfolio.kt
index cd093e6c..0d7f3072 100644
--- a/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/HorVerPortfolio.kt
+++ b/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/portfolio/HorVerPortfolio.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 AtLarge Research
+ * Copyright (c) 2022 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
@@ -20,20 +20,20 @@
* SOFTWARE.
*/
-package org.opendc.experiments.capelin
+package org.opendc.experiments.capelin.portfolio
import org.opendc.compute.workload.sampleByLoad
import org.opendc.compute.workload.trace
import org.opendc.experiments.capelin.model.OperationalPhenomena
+import org.opendc.experiments.capelin.model.Scenario
import org.opendc.experiments.capelin.model.Topology
import org.opendc.experiments.capelin.model.Workload
-import org.opendc.harness.dsl.anyOf
/**
* A [Portfolio] that explores the difference between horizontal and vertical scaling.
*/
-public class HorVerPortfolio : Portfolio("horizontal_vs_vertical") {
- override val topology: Topology by anyOf(
+public class HorVerPortfolio : Portfolio {
+ private val topologies = listOf(
Topology("base"),
Topology("rep-vol-hor-hom"),
Topology("rep-vol-hor-het"),
@@ -45,18 +45,24 @@ public class HorVerPortfolio : Portfolio("horizontal_vs_vertical") {
Topology("exp-vol-ver-het")
)
- override val workload: Workload by anyOf(
- Workload("solvinity", trace("solvinity").sampleByLoad(0.1)),
- Workload("solvinity", trace("solvinity").sampleByLoad(0.25)),
- Workload("solvinity", trace("solvinity").sampleByLoad(0.5)),
- Workload("solvinity", trace("solvinity").sampleByLoad(1.0))
+ private val workloads = listOf(
+ Workload("solvinity-10%", trace("solvinity").sampleByLoad(0.1)),
+ Workload("solvinity-25%", trace("solvinity").sampleByLoad(0.25)),
+ Workload("solvinity-50%", trace("solvinity").sampleByLoad(0.5)),
+ Workload("solvinity-100%", trace("solvinity").sampleByLoad(1.0))
)
+ private val operationalPhenomena = OperationalPhenomena(failureFrequency = 24.0 * 7, hasInterference = true)
+ private val allocationPolicy = "active-servers"
- override val operationalPhenomena: OperationalPhenomena by anyOf(
- OperationalPhenomena(failureFrequency = 24.0 * 7, hasInterference = true)
- )
-
- override val allocationPolicy: String by anyOf(
- "active-servers"
- )
+ override val scenarios: Iterable<Scenario> = topologies.flatMap { topology ->
+ workloads.map { workload ->
+ Scenario(
+ topology,
+ workload,
+ operationalPhenomena,
+ allocationPolicy,
+ mapOf("topology" to topology.name, "workload" to workload.name)
+ )
+ }
+ }
}
diff --git a/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/MoreHpcPortfolio.kt b/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/portfolio/MoreHpcPortfolio.kt
index 73e59a58..6afffc09 100644
--- a/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/MoreHpcPortfolio.kt
+++ b/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/portfolio/MoreHpcPortfolio.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 AtLarge Research
+ * Copyright (c) 2022 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
@@ -20,42 +20,48 @@
* SOFTWARE.
*/
-package org.opendc.experiments.capelin
+package org.opendc.experiments.capelin.portfolio
import org.opendc.compute.workload.sampleByHpc
import org.opendc.compute.workload.sampleByHpcLoad
import org.opendc.compute.workload.trace
import org.opendc.experiments.capelin.model.OperationalPhenomena
+import org.opendc.experiments.capelin.model.Scenario
import org.opendc.experiments.capelin.model.Topology
import org.opendc.experiments.capelin.model.Workload
-import org.opendc.harness.dsl.anyOf
/**
* A [Portfolio] to explore the effect of HPC workloads.
*/
-public class MoreHpcPortfolio : Portfolio("more_hpc") {
- override val topology: Topology by anyOf(
+public class MoreHpcPortfolio : Portfolio {
+ private val topologies = listOf(
Topology("base"),
Topology("exp-vol-hor-hom"),
Topology("exp-vol-ver-hom"),
Topology("exp-vel-ver-hom")
)
-
- override val workload: Workload by anyOf(
- Workload("solvinity", trace("solvinity").sampleByHpc(0.0)),
- Workload("solvinity", trace("solvinity").sampleByHpc(0.25)),
- Workload("solvinity", trace("solvinity").sampleByHpc(0.5)),
- Workload("solvinity", trace("solvinity").sampleByHpc(1.0)),
- Workload("solvinity", trace("solvinity").sampleByHpcLoad(0.25)),
- Workload("solvinity", trace("solvinity").sampleByHpcLoad(0.5)),
- Workload("solvinity", trace("solvinity").sampleByHpcLoad(1.0))
+ private val workloads = listOf(
+ Workload("hpc-0%", trace("solvinity").sampleByHpc(0.0)),
+ Workload("hpc-25%", trace("solvinity").sampleByHpc(0.25)),
+ Workload("hpc-50%", trace("solvinity").sampleByHpc(0.5)),
+ Workload("hpc-100%", trace("solvinity").sampleByHpc(1.0)),
+ Workload("hpc-load-25%", trace("solvinity").sampleByHpcLoad(0.25)),
+ Workload("hpc-load-50%", trace("solvinity").sampleByHpcLoad(0.5)),
+ Workload("hpc-load-100%", trace("solvinity").sampleByHpcLoad(1.0))
)
- override val operationalPhenomena: OperationalPhenomena by anyOf(
- OperationalPhenomena(failureFrequency = 24.0 * 7, hasInterference = true)
- )
+ private val operationalPhenomena = OperationalPhenomena(failureFrequency = 24.0 * 7, hasInterference = true)
+ private val allocationPolicy: String = "active-servers"
- override val allocationPolicy: String by anyOf(
- "active-servers"
- )
+ override val scenarios: Iterable<Scenario> = topologies.flatMap { topology ->
+ workloads.map { workload ->
+ Scenario(
+ topology,
+ workload,
+ operationalPhenomena,
+ allocationPolicy,
+ mapOf("topology" to topology.name, "workload" to workload.name)
+ )
+ }
+ }
}
diff --git a/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/MoreVelocityPortfolio.kt b/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/portfolio/MoreVelocityPortfolio.kt
index 9d5717bb..92bf80b3 100644
--- a/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/MoreVelocityPortfolio.kt
+++ b/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/portfolio/MoreVelocityPortfolio.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 AtLarge Research
+ * Copyright (c) 2022 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
@@ -20,20 +20,20 @@
* SOFTWARE.
*/
-package org.opendc.experiments.capelin
+package org.opendc.experiments.capelin.portfolio
import org.opendc.compute.workload.sampleByLoad
import org.opendc.compute.workload.trace
import org.opendc.experiments.capelin.model.OperationalPhenomena
+import org.opendc.experiments.capelin.model.Scenario
import org.opendc.experiments.capelin.model.Topology
import org.opendc.experiments.capelin.model.Workload
-import org.opendc.harness.dsl.anyOf
/**
* A [Portfolio] that explores the effect of adding more velocity to a cluster (e.g., faster machines).
*/
-public class MoreVelocityPortfolio : Portfolio("more_velocity") {
- override val topology: Topology by anyOf(
+public class MoreVelocityPortfolio : Portfolio {
+ private val topologies = listOf(
Topology("base"),
Topology("rep-vel-ver-hom"),
Topology("rep-vel-ver-het"),
@@ -41,18 +41,25 @@ public class MoreVelocityPortfolio : Portfolio("more_velocity") {
Topology("exp-vel-ver-het")
)
- override val workload: Workload by anyOf(
- Workload("solvinity", trace("solvinity").sampleByLoad(0.1)),
- Workload("solvinity", trace("solvinity").sampleByLoad(0.25)),
- Workload("solvinity", trace("solvinity").sampleByLoad(0.5)),
- Workload("solvinity", trace("solvinity").sampleByLoad(1.0))
+ private val workloads = listOf(
+ Workload("solvinity-10%", trace("solvinity").sampleByLoad(0.1)),
+ Workload("solvinity-25%", trace("solvinity").sampleByLoad(0.25)),
+ Workload("solvinity-50%", trace("solvinity").sampleByLoad(0.5)),
+ Workload("solvinity-100%", trace("solvinity").sampleByLoad(1.0))
)
- override val operationalPhenomena: OperationalPhenomena by anyOf(
- OperationalPhenomena(failureFrequency = 24.0 * 7, hasInterference = true)
- )
+ private val operationalPhenomena = OperationalPhenomena(failureFrequency = 24.0 * 7, hasInterference = true)
+ private val allocationPolicy = "active-servers"
- override val allocationPolicy: String by anyOf(
- "active-servers"
- )
+ override val scenarios: Iterable<Scenario> = topologies.flatMap { topology ->
+ workloads.map { workload ->
+ Scenario(
+ topology,
+ workload,
+ operationalPhenomena,
+ allocationPolicy,
+ mapOf("topology" to topology.name, "workload" to workload.name)
+ )
+ }
+ }
}
diff --git a/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/OperationalPhenomenaPortfolio.kt b/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/portfolio/OperationalPhenomenaPortfolio.kt
index 7ab586b3..f9a9d681 100644
--- a/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/OperationalPhenomenaPortfolio.kt
+++ b/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/portfolio/OperationalPhenomenaPortfolio.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 AtLarge Research
+ * Copyright (c) 2022 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
@@ -20,38 +20,35 @@
* SOFTWARE.
*/
-package org.opendc.experiments.capelin
+package org.opendc.experiments.capelin.portfolio
import org.opendc.compute.workload.sampleByLoad
import org.opendc.compute.workload.trace
import org.opendc.experiments.capelin.model.OperationalPhenomena
+import org.opendc.experiments.capelin.model.Scenario
import org.opendc.experiments.capelin.model.Topology
import org.opendc.experiments.capelin.model.Workload
-import org.opendc.harness.dsl.anyOf
/**
* A [Portfolio] that explores the effect of operational phenomena on metrics.
*/
-public class OperationalPhenomenaPortfolio : Portfolio("operational_phenomena") {
- override val topology: Topology by anyOf(
- Topology("base")
+public class OperationalPhenomenaPortfolio : Portfolio {
+ private val topology = Topology("base")
+ private val workloads = listOf(
+ Workload("solvinity-10%", trace("solvinity").sampleByLoad(0.1)),
+ Workload("solvinity-25%", trace("solvinity").sampleByLoad(0.25)),
+ Workload("solvinity-50%", trace("solvinity").sampleByLoad(0.5)),
+ Workload("solvinity-100%", trace("solvinity").sampleByLoad(1.0))
)
- override val workload: Workload by anyOf(
- Workload("solvinity", trace("solvinity").sampleByLoad(0.1)),
- Workload("solvinity", trace("solvinity").sampleByLoad(0.25)),
- Workload("solvinity", trace("solvinity").sampleByLoad(0.5)),
- Workload("solvinity", trace("solvinity").sampleByLoad(1.0))
- )
-
- override val operationalPhenomena: OperationalPhenomena by anyOf(
+ private val phenomenas = listOf(
OperationalPhenomena(failureFrequency = 24.0 * 7, hasInterference = true),
OperationalPhenomena(failureFrequency = 0.0, hasInterference = true),
OperationalPhenomena(failureFrequency = 24.0 * 7, hasInterference = false),
OperationalPhenomena(failureFrequency = 0.0, hasInterference = false)
)
- override val allocationPolicy: String by anyOf(
+ private val allocationPolicies = listOf(
"mem",
"mem-inv",
"core-mem",
@@ -60,4 +57,19 @@ public class OperationalPhenomenaPortfolio : Portfolio("operational_phenomena")
"active-servers-inv",
"random"
)
+
+ override val scenarios: Iterable<Scenario> =
+ workloads.flatMap { workload ->
+ phenomenas.flatMapIndexed { index, operationalPhenomena ->
+ allocationPolicies.map { allocationPolicy ->
+ Scenario(
+ topology,
+ workload,
+ operationalPhenomena,
+ allocationPolicy,
+ mapOf("workload" to workload.name, "scheduler" to allocationPolicy, "phenomena" to index.toString())
+ )
+ }
+ }
+ }
}
diff --git a/opendc-experiments/opendc-experiments-serverless20/src/main/kotlin/org/opendc/experiments/serverless/trace/FunctionTrace.kt b/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/portfolio/Portfolio.kt
index 4fea6b96..abf37a5f 100644
--- a/opendc-experiments/opendc-experiments-serverless20/src/main/kotlin/org/opendc/experiments/serverless/trace/FunctionTrace.kt
+++ b/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/portfolio/Portfolio.kt
@@ -20,9 +20,16 @@
* SOFTWARE.
*/
-package org.opendc.experiments.serverless.trace
+package org.opendc.experiments.capelin.portfolio
+
+import org.opendc.experiments.capelin.model.Scenario
/**
- * A trace for a single function
+ * A portfolio represents a collection of scenarios are tested for the work.
*/
-public data class FunctionTrace(val id: String, val maxMemory: Int, val samples: List<FunctionSample>)
+public interface Portfolio {
+ /**
+ * The scenarios that belong to this portfolio.
+ */
+ val scenarios: Iterable<Scenario>
+}
diff --git a/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/TestPortfolio.kt b/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/portfolio/TestPortfolio.kt
index 98eb989d..944e9f43 100644
--- a/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/TestPortfolio.kt
+++ b/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/portfolio/TestPortfolio.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 AtLarge Research
+ * Copyright (c) 2022 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
@@ -20,29 +20,24 @@
* SOFTWARE.
*/
-package org.opendc.experiments.capelin
+package org.opendc.experiments.capelin.portfolio
import org.opendc.compute.workload.trace
import org.opendc.experiments.capelin.model.OperationalPhenomena
+import org.opendc.experiments.capelin.model.Scenario
import org.opendc.experiments.capelin.model.Topology
import org.opendc.experiments.capelin.model.Workload
-import org.opendc.harness.dsl.anyOf
/**
* A [Portfolio] to perform a simple test run.
*/
-public class TestPortfolio : Portfolio("test") {
- override val topology: Topology by anyOf(
- Topology("base")
+public class TestPortfolio : Portfolio {
+ override val scenarios: Iterable<Scenario> = listOf(
+ Scenario(
+ Topology("base"),
+ Workload("solvinity", trace("solvinity")),
+ OperationalPhenomena(failureFrequency = 24.0 * 7, hasInterference = true),
+ "active-servers"
+ )
)
-
- override val workload: Workload by anyOf(
- Workload("solvinity", trace("solvinity"))
- )
-
- override val operationalPhenomena: OperationalPhenomena by anyOf(
- OperationalPhenomena(failureFrequency = 24.0 * 7, hasInterference = true)
- )
-
- override val allocationPolicy: String by anyOf("active-servers")
}
diff --git a/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/util/VmPlacementReader.kt b/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/util/VmPlacementReader.kt
deleted file mode 100644
index 67de2777..00000000
--- a/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/util/VmPlacementReader.kt
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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.util
-
-import com.fasterxml.jackson.databind.ObjectMapper
-import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
-import com.fasterxml.jackson.module.kotlin.readValue
-import java.io.InputStream
-
-/**
- * A parser for the JSON VM placement data files used for the TPDS article on Capelin.
- */
-class VmPlacementReader {
- /**
- * The [ObjectMapper] to parse the placement.
- */
- private val mapper = jacksonObjectMapper()
-
- /**
- * Read the VM placements from the input.
- */
- fun read(input: InputStream): 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/main/resources/application.conf b/opendc-experiments/opendc-experiments-capelin/src/main/resources/application.conf
deleted file mode 100644
index f0e0f2d3..00000000
--- a/opendc-experiments/opendc-experiments-capelin/src/main/resources/application.conf
+++ /dev/null
@@ -1,6 +0,0 @@
-# Default configuration for the Capelin experiments
-opendc.experiments.capelin {
- env-path = input/environments/
- trace-path = input/traces/
- output-path = output
-}
diff --git a/opendc-experiments/opendc-experiments-capelin/src/main/resources/log4j2.xml b/opendc-experiments/opendc-experiments-capelin/src/main/resources/log4j2.xml
index d46b50c3..e479f2ca 100644
--- a/opendc-experiments/opendc-experiments-capelin/src/main/resources/log4j2.xml
+++ b/opendc-experiments/opendc-experiments-capelin/src/main/resources/log4j2.xml
@@ -30,13 +30,7 @@
</Console>
</Appenders>
<Loggers>
- <Logger name="org.opendc" level="debug" additivity="false">
- <AppenderRef ref="Console"/>
- </Logger>
- <Logger name="org.opendc.experiments.capelin" level="info" additivity="false">
- <AppenderRef ref="Console"/>
- </Logger>
- <Logger name="org.opendc.experiments.vm.trace" level="debug" additivity="false">
+ <Logger name="org.opendc" level="warn" additivity="false">
<AppenderRef ref="Console"/>
</Logger>
<Logger name="org.apache.hadoop" level="warn" additivity="false">
diff --git a/opendc-experiments/opendc-experiments-serverless20/README.md b/opendc-experiments/opendc-experiments-serverless20/README.md
deleted file mode 100644
index 40855ad0..00000000
--- a/opendc-experiments/opendc-experiments-serverless20/README.md
+++ /dev/null
@@ -1,7 +0,0 @@
-OpenDC Serverless
-=================
-
-This module contains a reproduction of the experiments of Soufiane Jounaid's BSc Computer Science thesis:
-OpenDC Serverless: Design, Implementation and Evaluation of a FaaS Platform Simulator [1]
-
-[1] https://drive.google.com/file/d/12hox3PwagpD0jNFA57tO4r2HqvOonkY3/view?usp=sharing
diff --git a/opendc-experiments/opendc-experiments-serverless20/src/main/kotlin/org/opendc/experiments/serverless/ServerlessExperiment.kt b/opendc-experiments/opendc-experiments-serverless20/src/main/kotlin/org/opendc/experiments/serverless/ServerlessExperiment.kt
deleted file mode 100644
index 1c357f67..00000000
--- a/opendc-experiments/opendc-experiments-serverless20/src/main/kotlin/org/opendc/experiments/serverless/ServerlessExperiment.kt
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * 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.serverless
-
-import com.typesafe.config.ConfigFactory
-import kotlinx.coroutines.coroutineScope
-import kotlinx.coroutines.delay
-import kotlinx.coroutines.launch
-import mu.KotlinLogging
-import org.opendc.experiments.serverless.trace.FunctionTraceWorkload
-import org.opendc.experiments.serverless.trace.ServerlessTraceReader
-import org.opendc.faas.service.FaaSService
-import org.opendc.faas.service.autoscaler.FunctionTerminationPolicyFixed
-import org.opendc.faas.service.router.RandomRoutingPolicy
-import org.opendc.faas.simulator.SimFunctionDeployer
-import org.opendc.faas.simulator.delay.ColdStartModel
-import org.opendc.faas.simulator.delay.StochasticDelayInjector
-import org.opendc.harness.dsl.Experiment
-import org.opendc.harness.dsl.anyOf
-import org.opendc.simulator.compute.model.MachineModel
-import org.opendc.simulator.compute.model.MemoryUnit
-import org.opendc.simulator.compute.model.ProcessingNode
-import org.opendc.simulator.compute.model.ProcessingUnit
-import org.opendc.simulator.core.runBlockingSimulation
-import java.io.File
-import java.time.Duration
-import java.util.*
-import kotlin.math.max
-
-/**
- * A reproduction of the experiments of Soufiane Jounaid's BSc Computer Science thesis:
- * OpenDC Serverless: Design, Implementation and Evaluation of a FaaS Platform Simulator.
- */
-public class ServerlessExperiment : Experiment("Serverless") {
- /**
- * The logger for this portfolio instance.
- */
- private val logger = KotlinLogging.logger {}
-
- /**
- * The configuration to use.
- */
- private val config = ConfigFactory.load().getConfig("opendc.experiments.serverless20")
-
- /**
- * The routing policy to test.
- */
- private val routingPolicy by anyOf(RandomRoutingPolicy())
-
- /**
- * The cold start models to test.
- */
- private val coldStartModel by anyOf(ColdStartModel.LAMBDA, ColdStartModel.AZURE, ColdStartModel.GOOGLE)
-
- override fun doRun(repeat: Int): Unit = runBlockingSimulation {
- val trace = ServerlessTraceReader().parse(File(config.getString("trace-path")))
- val traceById = trace.associateBy { it.id }
- val delayInjector = StochasticDelayInjector(coldStartModel, Random())
- val deployer = SimFunctionDeployer(clock, this, createMachineModel(), delayInjector) { FunctionTraceWorkload(traceById.getValue(it.name)) }
- val service =
- FaaSService(
- coroutineContext,
- clock,
- deployer,
- routingPolicy,
- FunctionTerminationPolicyFixed(coroutineContext, clock, timeout = Duration.ofMinutes(10))
- )
- val client = service.newClient()
-
- coroutineScope {
- for (entry in trace) {
- launch {
- val function = client.newFunction(entry.id, entry.maxMemory.toLong())
- var offset = Long.MIN_VALUE
-
- for (sample in entry.samples) {
- if (sample.invocations == 0) {
- continue
- }
-
- if (offset < 0) {
- offset = sample.timestamp - clock.millis()
- }
-
- delay(max(0, (sample.timestamp - offset) - clock.millis()))
-
- logger.info { "Invoking function ${entry.id} ${sample.invocations} times [${sample.timestamp}]" }
-
- repeat(sample.invocations) {
- function.invoke()
- }
- }
- }
- }
- }
-
- client.close()
- service.close()
- }
-
- /**
- * Construct the machine model to test with.
- */
- private fun createMachineModel(): MachineModel {
- val cpuNode = ProcessingNode("Intel", "Xeon", "amd64", 2)
-
- return MachineModel(
- cpus = List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 1000.0) },
- memory = List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) }
- )
- }
-}
diff --git a/opendc-experiments/opendc-experiments-serverless20/src/main/kotlin/org/opendc/experiments/serverless/trace/FunctionSample.kt b/opendc-experiments/opendc-experiments-serverless20/src/main/kotlin/org/opendc/experiments/serverless/trace/FunctionSample.kt
deleted file mode 100644
index 492f44b9..00000000
--- a/opendc-experiments/opendc-experiments-serverless20/src/main/kotlin/org/opendc/experiments/serverless/trace/FunctionSample.kt
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * 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.serverless.trace
-
-/**
- * A sample of a single function.
- *
- * @param timestamp The timestamp of the function.
- * @param duration The average execution time of the function.
- * @param invocations The number of invocations.
- * @param provisionedCpu The provisioned CPU for this function in MHz.
- * @param provisionedMem The amount of memory provisioned for this function in MB.
- * @param cpuUsage The actual CPU usage in MHz.
- * @param memUsage The actual memory usage in MB.
- */
-public data class FunctionSample(
- val timestamp: Long,
- val duration: Long,
- val invocations: Int,
- val provisionedCpu: Int,
- val provisionedMem: Int,
- val cpuUsage: Double,
- val memUsage: Double
-)
diff --git a/opendc-experiments/opendc-experiments-serverless20/src/main/kotlin/org/opendc/experiments/serverless/trace/FunctionTraceWorkload.kt b/opendc-experiments/opendc-experiments-serverless20/src/main/kotlin/org/opendc/experiments/serverless/trace/FunctionTraceWorkload.kt
deleted file mode 100644
index bbe130e3..00000000
--- a/opendc-experiments/opendc-experiments-serverless20/src/main/kotlin/org/opendc/experiments/serverless/trace/FunctionTraceWorkload.kt
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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.serverless.trace
-
-import org.opendc.faas.simulator.workload.SimFaaSWorkload
-import org.opendc.simulator.compute.workload.SimTrace
-import org.opendc.simulator.compute.workload.SimTraceFragment
-import org.opendc.simulator.compute.workload.SimTraceWorkload
-import org.opendc.simulator.compute.workload.SimWorkload
-
-/**
- * A [SimFaaSWorkload] for a [FunctionTrace].
- */
-class FunctionTraceWorkload(trace: FunctionTrace) :
- SimFaaSWorkload, SimWorkload by SimTraceWorkload(SimTrace.ofFragments(trace.samples.map { SimTraceFragment(it.timestamp, it.duration, it.cpuUsage, 1) })) {
- override suspend fun invoke() {}
-}
diff --git a/opendc-experiments/opendc-experiments-serverless20/src/main/kotlin/org/opendc/experiments/serverless/trace/ServerlessTraceReader.kt b/opendc-experiments/opendc-experiments-serverless20/src/main/kotlin/org/opendc/experiments/serverless/trace/ServerlessTraceReader.kt
deleted file mode 100644
index 6dc35c59..00000000
--- a/opendc-experiments/opendc-experiments-serverless20/src/main/kotlin/org/opendc/experiments/serverless/trace/ServerlessTraceReader.kt
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * 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.serverless.trace
-
-import mu.KotlinLogging
-import java.io.File
-import kotlin.math.max
-
-/**
- * A trace reader for the serverless workload trace used in the OpenDC Serverless thesis.
- */
-public class ServerlessTraceReader {
- /**
- * The logger for this portfolio instance.
- */
- private val logger = KotlinLogging.logger {}
-
- /**
- * Parse the traces at the specified [path].
- */
- public fun parse(path: File): List<FunctionTrace> {
- return if (path.isFile) {
- listOf(parseSingle(path))
- } else {
- path.walk()
- .filterNot { it.isDirectory }
- .map { file ->
- logger.info { "Parsing $file" }
- parseSingle(file)
- }
- .toList()
- }
- }
-
- /**
- * Parse a single trace.
- */
- private fun parseSingle(path: File): FunctionTrace {
- val samples = mutableListOf<FunctionSample>()
- val id = path.nameWithoutExtension
- var idx = 0
-
- var timestampCol = 0
- var invocationsCol = 0
- var execTimeCol = 0
- var provCpuCol = 0
- var provMemCol = 0
- var cpuUsageCol = 0
- var memoryUsageCol = 0
- var maxMemory = 0
-
- path.forEachLine { line ->
- if (line.startsWith("#") && line.isNotBlank()) {
- return@forEachLine
- }
-
- val values = line.split(",")
-
- /* Header parsing */
- if (idx++ == 0) {
- val header = values.mapIndexed { col, name -> Pair(name.trim(), col) }.toMap()
- timestampCol = header["Timestamp [ms]"]!!
- invocationsCol = header["Invocations"]!!
- execTimeCol = header["Avg Exec time per Invocation"]!!
- provCpuCol = header["Provisioned CPU [Mhz]"]!!
- provMemCol = header["Provisioned Memory [mb]"]!!
- cpuUsageCol = header["Avg cpu usage per Invocation [Mhz]"]!!
- memoryUsageCol = header["Avg mem usage per Invocation [mb]"]!!
- return@forEachLine
- }
-
- val timestamp = values[timestampCol].trim().toLong()
- val invocations = values[invocationsCol].trim().toInt()
- val execTime = values[execTimeCol].trim().toLong()
- val provisionedCpu = values[provCpuCol].trim().toInt()
- val provisionedMemory = values[provMemCol].trim().toInt()
- val cpuUsage = values[cpuUsageCol].trim().toDouble()
- val memoryUsage = values[memoryUsageCol].trim().toDouble()
-
- maxMemory = max(maxMemory, provisionedMemory)
-
- samples.add(FunctionSample(timestamp, execTime, invocations, provisionedCpu, provisionedMemory, cpuUsage, memoryUsage))
- }
-
- return FunctionTrace(id, maxMemory, samples)
- }
-}
diff --git a/opendc-experiments/opendc-experiments-serverless20/src/main/resources/application.conf b/opendc-experiments/opendc-experiments-serverless20/src/main/resources/application.conf
deleted file mode 100644
index a065c5d6..00000000
--- a/opendc-experiments/opendc-experiments-serverless20/src/main/resources/application.conf
+++ /dev/null
@@ -1,8 +0,0 @@
-# Default configuration for the serverless experiments
-opendc.experiments.serverless20 {
- # Path to the directory containing the serverless trace
- trace-path = input/traces/serverless
-
- # Path to the output directory to write the results to
- output-path = output
-}
diff --git a/opendc-experiments/opendc-experiments-tf20/build.gradle.kts b/opendc-experiments/opendc-experiments-tf20/build.gradle.kts
index f61c8fef..7b3b084f 100644
--- a/opendc-experiments/opendc-experiments-tf20/build.gradle.kts
+++ b/opendc-experiments/opendc-experiments-tf20/build.gradle.kts
@@ -20,16 +20,15 @@
* SOFTWARE.
*/
-description = "Experiments with the OpenDC TensorFlow model"
+description = "TensorFlow application model in OpenDC"
/* Build configuration */
plugins {
- `experiment-conventions`
+ `kotlin-conventions`
`testing-conventions`
}
dependencies {
- api(projects.opendcHarness.opendcHarnessApi)
implementation(projects.opendcSimulator.opendcSimulatorCore)
implementation(projects.opendcSimulator.opendcSimulatorCompute)
implementation(projects.opendcCommon)
diff --git a/opendc-experiments/opendc-experiments-tf20/src/main/kotlin/org/opendc/experiments/tf20/Models.kt b/opendc-experiments/opendc-experiments-tf20/src/main/kotlin/org/opendc/experiments/tf20/Models.kt
index 9ef5b621..be166bd5 100644
--- a/opendc-experiments/opendc-experiments-tf20/src/main/kotlin/org/opendc/experiments/tf20/Models.kt
+++ b/opendc-experiments/opendc-experiments-tf20/src/main/kotlin/org/opendc/experiments/tf20/Models.kt
@@ -20,8 +20,10 @@
* SOFTWARE.
*/
-package org.opendc.experiments.tf20.keras
+package org.opendc.experiments.tf20
+import org.opendc.experiments.tf20.keras.Sequential
+import org.opendc.experiments.tf20.keras.TrainableModel
import org.opendc.experiments.tf20.keras.activations.Activation
import org.opendc.experiments.tf20.keras.layer.conv.Conv2D
import org.opendc.experiments.tf20.keras.layer.conv.ConvPadding
diff --git a/opendc-experiments/opendc-experiments-tf20/src/main/kotlin/org/opendc/experiments/tf20/core/SimTFDevice.kt b/opendc-experiments/opendc-experiments-tf20/src/main/kotlin/org/opendc/experiments/tf20/core/SimTFDevice.kt
index d2105196..90350142 100644
--- a/opendc-experiments/opendc-experiments-tf20/src/main/kotlin/org/opendc/experiments/tf20/core/SimTFDevice.kt
+++ b/opendc-experiments/opendc-experiments-tf20/src/main/kotlin/org/opendc/experiments/tf20/core/SimTFDevice.kt
@@ -39,6 +39,7 @@ import java.util.*
import kotlin.coroutines.Continuation
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.resume
+import kotlin.math.ceil
import kotlin.math.roundToLong
/**
@@ -137,7 +138,7 @@ public class SimTFDevice(
if (activeWork.consume(consumedWork)) {
this.activeWork = null
} else {
- val duration = (activeWork.flops / conn.capacity * 1000).roundToLong()
+ val duration = ceil(activeWork.flops / conn.capacity * 1000).toLong()
conn.push(conn.capacity)
return duration
}
diff --git a/opendc-experiments/opendc-experiments-tf20/src/main/kotlin/org/opendc/experiments/tf20/TensorFlowExperiment.kt b/opendc-experiments/opendc-experiments-tf20/src/test/kotlin/org/opendc/experiments/tf20/TensorFlowTest.kt
index 19236029..7d72b48d 100644
--- a/opendc-experiments/opendc-experiments-tf20/src/main/kotlin/org/opendc/experiments/tf20/TensorFlowExperiment.kt
+++ b/opendc-experiments/opendc-experiments-tf20/src/test/kotlin/org/opendc/experiments/tf20/TensorFlowTest.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 AtLarge Research
+ * Copyright (c) 2022 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
@@ -22,43 +22,76 @@
package org.opendc.experiments.tf20
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.assertAll
import org.opendc.experiments.tf20.core.SimTFDevice
-import org.opendc.experiments.tf20.distribute.*
-import org.opendc.experiments.tf20.keras.AlexNet
+import org.opendc.experiments.tf20.distribute.OneDeviceStrategy
import org.opendc.experiments.tf20.util.MLEnvironmentReader
-import org.opendc.harness.dsl.Experiment
-import org.opendc.harness.dsl.anyOf
import org.opendc.simulator.compute.power.LinearPowerModel
import org.opendc.simulator.core.runBlockingSimulation
/**
- * Experiments with the TensorFlow simulation model.
+ * Integration test suite for the TensorFlow application model in OpenDC.
*/
-public class TensorFlowExperiment : Experiment(name = "tf20") {
+class TensorFlowTest {
/**
- * The environment file to use.
+ * Smoke test that tests the capabilities of the TensorFlow application model in OpenDC.
*/
- private val environmentFile by anyOf("/kth.json")
+ @Test
+ fun testSmokeAlexNet() = runBlockingSimulation {
+ val envInput = checkNotNull(TensorFlowTest::class.java.getResourceAsStream("/kth.json"))
+ val def = MLEnvironmentReader().readEnvironment(envInput).first()
+
+ val device = SimTFDevice(
+ def.uid, def.meta["gpu"] as Boolean, coroutineContext, clock, def.model.cpus[0], def.model.memory[0],
+ LinearPowerModel(250.0, 60.0)
+ )
+ val strategy = OneDeviceStrategy(device)
+ val batchSize = 32
+ val model = AlexNet(batchSize.toLong())
+ model.use {
+ it.compile(strategy)
+
+ it.fit(epochs = 9088 / batchSize, batchSize = batchSize)
+ }
+
+ device.close()
+
+ val stats = device.getDeviceStats()
+ assertAll(
+ { assertEquals(3309694252, clock.millis()) },
+ { assertEquals(8.2520933087E8, stats.energyUsage) }
+ )
+ }
/**
- * The batch size used.
+ * Smoke test that tests the capabilities of the TensorFlow application model in OpenDC.
*/
- private val batchSize by anyOf(16, 32, 64, 128)
-
- override fun doRun(repeat: Int): Unit = runBlockingSimulation {
- val envInput = checkNotNull(TensorFlowExperiment::class.java.getResourceAsStream(environmentFile))
+ @Test
+ fun testSmokeVGG() = runBlockingSimulation {
+ val envInput = checkNotNull(TensorFlowTest::class.java.getResourceAsStream("/kth.json"))
val def = MLEnvironmentReader().readEnvironment(envInput).first()
+
val device = SimTFDevice(
def.uid, def.meta["gpu"] as Boolean, coroutineContext, clock, def.model.cpus[0], def.model.memory[0],
LinearPowerModel(250.0, 60.0)
)
val strategy = OneDeviceStrategy(device)
-
- val model = AlexNet(batchSize.toLong())
+ val batchSize = 128
+ val model = VGG16(batchSize.toLong())
model.use {
it.compile(strategy)
it.fit(epochs = 9088 / batchSize, batchSize = batchSize)
}
+
+ device.close()
+
+ val stats = device.getDeviceStats()
+ assertAll(
+ { assertEquals(176230322904, clock.millis()) },
+ { assertEquals(4.296544914744E10, stats.energyUsage) }
+ )
}
}
diff --git a/opendc-experiments/opendc-experiments-tf20/src/test/kotlin/org/opendc/experiments/tf20/core/SimTFDeviceTest.kt b/opendc-experiments/opendc-experiments-tf20/src/test/kotlin/org/opendc/experiments/tf20/core/SimTFDeviceTest.kt
index fd18a3a7..21d30250 100644
--- a/opendc-experiments/opendc-experiments-tf20/src/test/kotlin/org/opendc/experiments/tf20/core/SimTFDeviceTest.kt
+++ b/opendc-experiments/opendc-experiments-tf20/src/test/kotlin/org/opendc/experiments/tf20/core/SimTFDeviceTest.kt
@@ -63,6 +63,8 @@ internal class SimTFDeviceTest {
launch { device.compute(2e6) }
}
+ device.close()
+
val stats = device.getDeviceStats()
assertAll(