diff options
| author | Dante Niewenhuis <d.niewenhuis@hotmail.com> | 2024-03-19 20:26:04 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-03-19 20:26:04 +0100 |
| commit | dff30fa60809c018101052f395b09cf17cb83ccb (patch) | |
| tree | 2c5f67b9424547061aaa0c6b6b85af9a125ec263 /opendc-experiments/opendc-experiments-greenifier/src/main/kotlin | |
| parent | 960b3d8a13c67ac4b7f479d5764b0b618fc9ea09 (diff) | |
Scenario and Portfolio update (#209)
* Initial commit
* Implemented a new systems of defining and running scenarios / portfolios. Scenarios and Portfolios can now be defined using JSON files similar to topologies. This allows user to define experiments without changing any KotLin code.
* Ran spotlessApply
Diffstat (limited to 'opendc-experiments/opendc-experiments-greenifier/src/main/kotlin')
3 files changed, 0 insertions, 325 deletions
diff --git a/opendc-experiments/opendc-experiments-greenifier/src/main/kotlin/org/opendc/experiments/greenifier/GreenifierCli.kt b/opendc-experiments/opendc-experiments-greenifier/src/main/kotlin/org/opendc/experiments/greenifier/GreenifierCli.kt deleted file mode 100644 index 93557500..00000000 --- a/opendc-experiments/opendc-experiments-greenifier/src/main/kotlin/org/opendc/experiments/greenifier/GreenifierCli.kt +++ /dev/null @@ -1,158 +0,0 @@ -/* - * 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("GreenifierCli") - -package org.opendc.experiments.greenifier - -import com.github.ajalt.clikt.core.CliktCommand -import com.github.ajalt.clikt.parameters.arguments.argument -import com.github.ajalt.clikt.parameters.arguments.default -import com.github.ajalt.clikt.parameters.options.associate -import com.github.ajalt.clikt.parameters.options.default -import com.github.ajalt.clikt.parameters.options.defaultLazy -import com.github.ajalt.clikt.parameters.options.flag -import com.github.ajalt.clikt.parameters.options.option -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.base.portfolio.model.Scenario -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 = GreenifierCommand().main(args) - -/** - * Represents the command for the Greenifier experiments. - */ -internal class GreenifierCommand : CliktCommand(name = "greenifier") { - /** - * 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( - "greenifier" to { GreenifierPortfolio() }, - ) - .default({ GreenifierPortfolio() }) - - /** - * 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 = GreenifierRunner(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: GreenifierRunner, - 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-greenifier/src/main/kotlin/org/opendc/experiments/greenifier/GreenifierPortfolio.kt b/opendc-experiments/opendc-experiments-greenifier/src/main/kotlin/org/opendc/experiments/greenifier/GreenifierPortfolio.kt deleted file mode 100644 index f7452be2..00000000 --- a/opendc-experiments/opendc-experiments-greenifier/src/main/kotlin/org/opendc/experiments/greenifier/GreenifierPortfolio.kt +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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.greenifier - -import org.opendc.compute.workload.sampleByLoad -import org.opendc.compute.workload.trace -import org.opendc.experiments.base.portfolio.Portfolio -import org.opendc.experiments.base.portfolio.model.OperationalPhenomena -import org.opendc.experiments.base.portfolio.model.Scenario -import org.opendc.experiments.base.portfolio.model.Topology -import org.opendc.experiments.base.portfolio.model.Workload - -/** - * A [Portfolio] that explores the difference between horizontal and vertical scaling. - */ -public class GreenifierPortfolio : Portfolio { - private val topologies = - listOf( - Topology("single.json"), - Topology("multi.json"), - ) - - private val workloads = - listOf( - Workload("bitbrains-small", trace("trace").sampleByLoad(1.0)), - ) - private val operationalPhenomena = OperationalPhenomena(0.0, false) - private val allocationPolicy = "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-greenifier/src/main/kotlin/org/opendc/experiments/greenifier/GreenifierRunner.kt b/opendc-experiments/opendc-experiments-greenifier/src/main/kotlin/org/opendc/experiments/greenifier/GreenifierRunner.kt deleted file mode 100644 index bd855aac..00000000 --- a/opendc-experiments/opendc-experiments-greenifier/src/main/kotlin/org/opendc/experiments/greenifier/GreenifierRunner.kt +++ /dev/null @@ -1,105 +0,0 @@ -/* - * 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.greenifier - -import org.opendc.compute.service.ComputeService -import org.opendc.compute.service.scheduler.createComputeScheduler -import org.opendc.compute.simulator.failure.grid5000 -import org.opendc.compute.simulator.provisioner.Provisioner -import org.opendc.compute.simulator.provisioner.registerComputeMonitor -import org.opendc.compute.simulator.provisioner.setupComputeService -import org.opendc.compute.simulator.provisioner.setupHosts -import org.opendc.compute.telemetry.export.parquet.ParquetComputeMonitor -import org.opendc.compute.topology.clusterTopology -import org.opendc.compute.workload.ComputeWorkloadLoader -import org.opendc.experiments.base.portfolio.model.Scenario -import org.opendc.experiments.base.runner.replay -import org.opendc.simulator.kotlin.runSimulation -import java.io.File -import java.time.Duration -import java.util.Random -import kotlin.math.roundToLong - -/** - * Helper class for running the Greenifier 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 GreenifierRunner( - 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, - ) = runSimulation { - val serviceDomain = "compute.opendc.org" - val topology = clusterTopology(File(envPath, scenario.topology.name)) - - Provisioner(dispatcher, seed).use { provisioner -> - provisioner.runSteps( - setupComputeService(serviceDomain, { createComputeScheduler(scenario.allocationPolicy, Random(it.seeder.nextLong())) }), - setupHosts(serviceDomain, topology, optimize = true), - ) - - if (outputPath != null) { - val partitions = scenario.partitions + ("seed" to seed.toString()) - val partition = partitions.map { (k, v) -> "$k=$v" }.joinToString("/") - - provisioner.runStep( - registerComputeMonitor( - serviceDomain, - ParquetComputeMonitor( - outputPath, - partition, - bufferSize = 4096, - ), - ), - ) - } - - val service = provisioner.registry.resolve(serviceDomain, ComputeService::class.java)!! - val vms = scenario.workload.source.resolve(workloadLoader, Random(seed)) - val operationalPhenomena = scenario.operationalPhenomena - val failureModel = - if (operationalPhenomena.failureFrequency > 0) { - grid5000(Duration.ofSeconds((operationalPhenomena.failureFrequency * 60).roundToLong())) - } else { - null - } - - service.replay(timeSource, vms, seed, failureModel = failureModel, interference = operationalPhenomena.hasInterference) - } - } -} |
