diff options
| author | Dante Niewenhuis <d.niewenhuis@hotmail.com> | 2024-08-29 10:05:46 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-08-29 10:05:46 +0200 |
| commit | fa6e850b11bf09947c4afc03f4af18f488436bbd (patch) | |
| tree | ca90573548e58cd14335479ef0efdb7957cc37fd | |
| parent | 3363df4c72a064e590ca98f8e01832cfa4e15a3f (diff) | |
Renamed Scenario to Experiment. A Scenario is now defined as a single setup. An experiment is a set of Scenarios. (#247)
8 files changed, 128 insertions, 78 deletions
diff --git a/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/runner/ScenarioCli.kt b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/runner/ExperimentCli.kt index abf9ad46..28ebe45c 100644 --- a/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/runner/ScenarioCli.kt +++ b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/runner/ExperimentCli.kt @@ -20,7 +20,7 @@ * SOFTWARE. */ -@file:JvmName("ScenarioCli") +@file:JvmName("ExperimentCli") package org.opendc.experiments.base.runner @@ -30,24 +30,24 @@ import com.github.ajalt.clikt.parameters.options.defaultLazy import com.github.ajalt.clikt.parameters.options.option import com.github.ajalt.clikt.parameters.types.file import com.github.ajalt.clikt.parameters.types.int -import org.opendc.experiments.base.scenario.getScenarios +import org.opendc.experiments.base.scenario.getExperiment import java.io.File /** * Main entrypoint of the application. */ -public fun main(args: Array<String>): Unit = ScenarioCommand().main(args) +public fun main(args: Array<String>): Unit = ExperimentCommand().main(args) /** * Represents the command for the Scenario experiments. */ -internal class ScenarioCommand : CliktCommand(name = "scenario") { +internal class ExperimentCommand : CliktCommand(name = "experiment") { /** * The path to the environment directory. */ - private val scenarioPath by option("--scenario-path", help = "path to scenario file") + private val scenarioPath by option("--experiment-path", help = "path to experiment file") .file(canBeDir = false, canBeFile = true) - .defaultLazy { File("resources/scenario.json") } + .defaultLazy { File("resources/experiment.json") } /** * The number of threads to use for parallelism. @@ -57,9 +57,7 @@ internal class ScenarioCommand : CliktCommand(name = "scenario") { .default(Runtime.getRuntime().availableProcessors() - 1) override fun run() { - val scenarios = getScenarios(scenarioPath) - runScenarios(scenarios, parallelism) - - // TODO: implement outputResults(scenario) // this will take the results, from a folder, and output them visually + val experiment = getExperiment(scenarioPath) + runExperiment(experiment, parallelism) } } diff --git a/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/runner/ExperimentRunner.kt b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/runner/ExperimentRunner.kt new file mode 100644 index 00000000..076cfb9f --- /dev/null +++ b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/runner/ExperimentRunner.kt @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2024 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.base.runner + +import org.opendc.experiments.base.scenario.Scenario +import java.util.concurrent.ForkJoinPool + +/** + * Run scenario when no pool is available for parallel execution + * + * @param experiment The scenarios to run + * @param parallelism The number of scenarios that can be run in parallel + */ +public fun runExperiment( + experiment: List<Scenario>, + parallelism: Int, +) { + val ansiReset = "\u001B[0m" + val ansiGreen = "\u001B[32m" + val ansiBlue = "\u001B[34m" + + setupOutputFolderStructure(experiment[0].outputFolder) + + for (scenario in experiment) { + val pool = ForkJoinPool(parallelism) + println( + "\n\n$ansiGreen================================================================================$ansiReset", + ) + println("$ansiBlue Running scenario: ${scenario.name} $ansiReset") + println("$ansiGreen================================================================================$ansiReset") + runScenario( + scenario, + pool, + ) + } +} diff --git a/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/runner/ScenarioRunner.kt b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/runner/ScenarioRunner.kt index abd359ff..5462b406 100644 --- a/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/runner/ScenarioRunner.kt +++ b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/runner/ScenarioRunner.kt @@ -45,36 +45,6 @@ import java.util.concurrent.ForkJoinPool import java.util.stream.LongStream /** - * Run scenario when no pool is available for parallel execution - * - * @param scenarios The scenarios to run - * @param parallelism The number of scenarios that can be run in parallel - */ -public fun runScenarios( - scenarios: List<Scenario>, - parallelism: Int, -) { - val ansiReset = "\u001B[0m" - val ansiGreen = "\u001B[32m" - val ansiBlue = "\u001B[34m" - - setupOutputFolderStructure(scenarios[0].outputFolder) - - for (scenario in scenarios) { - val pool = ForkJoinPool(parallelism) - println( - "\n\n$ansiGreen================================================================================$ansiReset", - ) - println("$ansiBlue Running scenario: ${scenario.name} $ansiReset") - println("$ansiGreen================================================================================$ansiReset") - runScenario( - scenario, - pool, - ) - } -} - -/** * Run scenario when a pool is available for parallel execution * The scenario is run multiple times based on the user input * @@ -180,7 +150,7 @@ public fun clearOutputFolder(outputFolderPath: String) { * Utility function to create the output folder structure for the simulation results. * @param folderPath The path to the output folder */ -private fun setupOutputFolderStructure(folderPath: String) { +public fun setupOutputFolderStructure(folderPath: String) { val trackrPath = "$folderPath/trackr.json" val simulationAnalysisPath = "$folderPath/simulation-analysis/" val energyAnalysisPath = "$simulationAnalysisPath/power_draw/" diff --git a/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/scenario/ScenarioFactories.kt b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/scenario/ExperimentFactories.kt index fb43f102..b364ffe6 100644 --- a/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/scenario/ScenarioFactories.kt +++ b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/scenario/ExperimentFactories.kt @@ -22,12 +22,12 @@ package org.opendc.experiments.base.scenario +import org.opendc.experiments.base.scenario.specs.ExperimentSpec import org.opendc.experiments.base.scenario.specs.ScenarioSpec -import org.opendc.experiments.base.scenario.specs.ScenariosSpec import java.io.File -private val scenarioReader = ScenarioReader() -private val scenarioWriter = ScenarioWriter() +private val experimentReader = ExperimentReader() +private val experimentWriter = ExperimentWriter() /** * Returns a list of Scenarios from a given file path (input). @@ -35,8 +35,8 @@ private val scenarioWriter = ScenarioWriter() * @param filePath The path to the file containing the scenario specifications. * @return A list of Scenarios. */ -public fun getScenarios(filePath: String): List<Scenario> { - return getScenarios(File(filePath)) +public fun getExperiment(filePath: String): List<Scenario> { + return getExperiment(File(filePath)) } /** @@ -45,19 +45,19 @@ public fun getScenarios(filePath: String): List<Scenario> { * @param file The file containing the scenario specifications. * @return A list of Scenarios. */ -public fun getScenarios(file: File): List<Scenario> { - return getScenarios(scenarioReader.read(file)) +public fun getExperiment(file: File): List<Scenario> { + return getExperiment(experimentReader.read(file)) } /** * Returns a list of Scenarios from a given ScenarioSpec by generating all possible combinations of * workloads, allocation policies, failure models, and export models within a topology. * - * @param scenariosSpec The ScenarioSpec containing the scenario specifications. + * @param experimentSpec The ScenarioSpec containing the scenario specifications. * @return A list of Scenarios. */ -public fun getScenarios(scenariosSpec: ScenariosSpec): List<Scenario> { - val outputFolder = scenariosSpec.outputFolder + "/" + scenariosSpec.name +public fun getExperiment(experimentSpec: ExperimentSpec): List<Scenario> { + val outputFolder = experimentSpec.outputFolder + "/" + experimentSpec.name File(outputFolder).mkdirs() val trackrPath = "$outputFolder/trackr.json" @@ -65,7 +65,7 @@ public fun getScenarios(scenariosSpec: ScenariosSpec): List<Scenario> { val scenarios = mutableListOf<Scenario>() - val cartesianInput = scenariosSpec.getCartesian() + val cartesianInput = experimentSpec.getCartesian() for ((scenarioID, scenarioSpec) in cartesianInput.withIndex()) { val scenario = @@ -80,8 +80,8 @@ public fun getScenarios(scenariosSpec: ScenariosSpec): List<Scenario> { exportModelSpec = scenarioSpec.exportModel, outputFolder = outputFolder, name = scenarioID.toString(), - runs = scenariosSpec.runs, - initialSeed = scenariosSpec.initialSeed, + runs = experimentSpec.runs, + initialSeed = experimentSpec.initialSeed, computeExportConfig = scenarioSpec.computeExportConfig, ) trackScenario(scenarioSpec, outputFolder) @@ -105,7 +105,7 @@ public fun trackScenario( outputFolder: String, ) { val trackrPath = "$outputFolder/trackr.json" - scenarioWriter.write( + experimentWriter.write( scenarioSpec, File(trackrPath), ) diff --git a/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/scenario/ScenarioReader.kt b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/scenario/ExperimentReader.kt index 1fba71d1..00b57602 100644 --- a/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/scenario/ScenarioReader.kt +++ b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/scenario/ExperimentReader.kt @@ -26,29 +26,29 @@ import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.json.Json import kotlinx.serialization.json.decodeFromStream import org.opendc.compute.telemetry.export.parquet.ComputeExportConfig -import org.opendc.experiments.base.scenario.specs.ScenariosSpec +import org.opendc.experiments.base.scenario.specs.ExperimentSpec import java.io.File import java.io.InputStream import java.nio.file.Path import kotlin.io.path.inputStream -public class ScenarioReader { +public class ExperimentReader { // private val jsonReader = Json { serializersModule = failureModule } private val jsonReader = Json - public fun read(file: File): ScenariosSpec = read(file.inputStream()) + public fun read(file: File): ExperimentSpec = read(file.inputStream()) - public fun read(path: Path): ScenariosSpec = read(path.inputStream()) + public fun read(path: Path): ExperimentSpec = read(path.inputStream()) /** * Read the specified [input]. */ @OptIn(ExperimentalSerializationApi::class) - public fun read(input: InputStream): ScenariosSpec { + public fun read(input: InputStream): ExperimentSpec { // Loads the default parquet output fields, // so that they can be deserialized ComputeExportConfig.loadDfltColumns() - return jsonReader.decodeFromStream<ScenariosSpec>(input) + return jsonReader.decodeFromStream<ExperimentSpec>(input) } } diff --git a/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/scenario/ScenarioWriter.kt b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/scenario/ExperimentWriter.kt index a582d140..6afe6031 100644 --- a/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/scenario/ScenarioWriter.kt +++ b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/scenario/ExperimentWriter.kt @@ -32,7 +32,7 @@ import java.io.File * @param jsonText The JSON text to write to the file, which is constantly updated during the writing process. * @param json The JSON object used to encode the scenario specification. */ -public class ScenarioWriter { +public class ExperimentWriter { private var jsonText = "[" private val json = Json { prettyPrint = true } diff --git a/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/scenario/specs/ScenariosSpec.kt b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/scenario/specs/ExperimentSpec.kt index cb4491b6..db26849e 100644 --- a/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/scenario/specs/ScenariosSpec.kt +++ b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/scenario/specs/ExperimentSpec.kt @@ -28,21 +28,6 @@ import org.opendc.common.logger.logger import org.opendc.compute.telemetry.export.parquet.ComputeExportConfig import java.util.UUID -@Serializable -public data class ScenarioSpec( - var id: Int = -1, - var name: String = "", - val outputFolder: String = "output", - val computeExportConfig: ComputeExportConfig, - val topology: ScenarioTopologySpec, - val workload: WorkloadSpec, - val allocationPolicy: AllocationPolicySpec = AllocationPolicySpec(), - val exportModel: ExportModelSpec = ExportModelSpec(), - val failureModel: FailureModelSpec? = null, - val checkpointModel: CheckpointModelSpec? = null, - val carbonTracePath: String? = null, -) - /** * specification describing a scenario * @@ -58,7 +43,7 @@ public data class ScenarioSpec( * be included in the output files. */ @Serializable -public data class ScenariosSpec( +public data class ExperimentSpec( var id: Int = -1, var name: String = "", val outputFolder: String = "output", diff --git a/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/scenario/specs/ScenarioSpec.kt b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/scenario/specs/ScenarioSpec.kt new file mode 100644 index 00000000..41e9a885 --- /dev/null +++ b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/scenario/specs/ScenarioSpec.kt @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2024 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.base.scenario.specs + +import kotlinx.serialization.Serializable +import org.opendc.compute.telemetry.export.parquet.ComputeExportConfig + +@Serializable +public data class ScenarioSpec( + var id: Int = -1, + var name: String = "", + val outputFolder: String = "output", + val computeExportConfig: ComputeExportConfig, + val topology: ScenarioTopologySpec, + val workload: WorkloadSpec, + val allocationPolicy: AllocationPolicySpec = AllocationPolicySpec(), + val exportModel: ExportModelSpec = ExportModelSpec(), + val failureModel: FailureModelSpec? = null, + val checkpointModel: CheckpointModelSpec? = null, + val carbonTracePath: String? = null, +) |
