diff options
| author | Radu Nicolae <rnicolae04@gmail.com> | 2025-06-16 18:01:07 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-06-16 18:01:07 +0200 |
| commit | 0df3d9ced743ac3385dd710c7133a6cf369b051c (patch) | |
| tree | eff5d6d67c275643e229731ba08c5fe7dc4ccd0a /opendc-experiments/opendc-experiments-m3sa/src/main/kotlin/org | |
| parent | c7e303ad1b5217e2ff24cee9538ac841d6149706 (diff) | |
integrated M3SA, updated with tests and CpuPowerModels
Diffstat (limited to 'opendc-experiments/opendc-experiments-m3sa/src/main/kotlin/org')
| -rw-r--r-- | opendc-experiments/opendc-experiments-m3sa/src/main/kotlin/org/opendc/experiments/m3sa/M3SAAnalyzer.kt (renamed from opendc-experiments/opendc-experiments-m3sa/src/main/kotlin/org/opendc/experiments/m3sa/M3saAnalyzer.kt) | 48 | ||||
| -rw-r--r-- | opendc-experiments/opendc-experiments-m3sa/src/main/kotlin/org/opendc/experiments/m3sa/runner/M3SACli.kt | 80 | ||||
| -rw-r--r-- | opendc-experiments/opendc-experiments-m3sa/src/main/kotlin/org/opendc/experiments/m3sa/runner/M3SARunner.kt | 33 |
3 files changed, 117 insertions, 44 deletions
diff --git a/opendc-experiments/opendc-experiments-m3sa/src/main/kotlin/org/opendc/experiments/m3sa/M3saAnalyzer.kt b/opendc-experiments/opendc-experiments-m3sa/src/main/kotlin/org/opendc/experiments/m3sa/M3SAAnalyzer.kt index 545ed656..5cc7cb78 100644 --- a/opendc-experiments/opendc-experiments-m3sa/src/main/kotlin/org/opendc/experiments/m3sa/M3saAnalyzer.kt +++ b/opendc-experiments/opendc-experiments-m3sa/src/main/kotlin/org/opendc/experiments/m3sa/M3SAAnalyzer.kt @@ -20,38 +20,56 @@ * SOFTWARE. */ -package org.opendc.experiments.m3sa - -import kotlin.io.path.Path +import java.nio.file.Files +import java.nio.file.Paths /** * This constant variable should be changed depending on the root folder that is being run. * PATH_TO_PYTHON_MAIN should point to the main python file, ran when the analysis starts. */ -public val ANALYSIS_SCRIPTS_DIRECTORY: String = "./opendc-experiments/opendc-experiments-m3sa/src/main/python" -public val ABSOLUTE_SCRIPT_PATH: String = - Path("$ANALYSIS_SCRIPTS_DIRECTORY/main.py").toAbsolutePath().normalize().toString() -public val SCRIPT_LANGUAGE: String = Path("$ANALYSIS_SCRIPTS_DIRECTORY/venv/bin/python3").toAbsolutePath().normalize().toString() - public fun m3saAnalyze( outputFolderPath: String, m3saSetupPath: String, + m3saExecPath: String, ) { + // script to run + val scriptPath = + Paths.get(m3saExecPath, "main.py") + .toAbsolutePath() + .normalize() + .toString() + + // look for venv python; if missing, use system python3 + val venvPython = + Paths.get(m3saExecPath, "venv", "bin", "python3") + .toAbsolutePath() + .normalize() + val pythonBin = + if (Files.isRegularFile(venvPython) && Files.isExecutable(venvPython)) { + venvPython.toString() + } else { + "python3" // fallback + } + val process = ProcessBuilder( - SCRIPT_LANGUAGE, - ABSOLUTE_SCRIPT_PATH, - outputFolderPath, + pythonBin, + scriptPath, m3saSetupPath, - ).directory(Path(ANALYSIS_SCRIPTS_DIRECTORY).toFile()) + "$outputFolderPath/raw-output", + "-o", + outputFolderPath, + ) + .redirectErrorStream(true) .start() val exitCode = process.waitFor() + val output = process.inputStream.bufferedReader().readText() if (exitCode == 0) { - println("[M3SA says] M3SA operation(s) completed successfully.") + println("[M3SA says] Success:\n$output") } else { - val errors = process.errorStream.bufferedReader().readText() - println("[M3SA says] Exit code $exitCode; Error(s): $errors") + println("[M3SA says] Exit code $exitCode; Output:\n$output") + throw RuntimeException("M3SA analysis failed with exit code $exitCode") } } diff --git a/opendc-experiments/opendc-experiments-m3sa/src/main/kotlin/org/opendc/experiments/m3sa/runner/M3SACli.kt b/opendc-experiments/opendc-experiments-m3sa/src/main/kotlin/org/opendc/experiments/m3sa/runner/M3SACli.kt index 4fe58d88..51919722 100644 --- a/opendc-experiments/opendc-experiments-m3sa/src/main/kotlin/org/opendc/experiments/m3sa/runner/M3SACli.kt +++ b/opendc-experiments/opendc-experiments-m3sa/src/main/kotlin/org/opendc/experiments/m3sa/runner/M3SACli.kt @@ -30,9 +30,8 @@ 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 m3saAnalyze import org.opendc.experiments.base.experiment.getExperiment -import org.opendc.experiments.base.runner.runExperiment -import org.opendc.experiments.m3sa.m3saAnalyze import org.opendc.experiments.m3sa.scenario.getOutputFolder import java.io.File @@ -52,35 +51,62 @@ internal class M3SACommand : CliktCommand(name = "experiment") { .file(canBeDir = false, canBeFile = true) .defaultLazy { File("resources/experiment.json") } - /** - * 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) - private val m3saPath by option("-m", "--m3sa-setup-path", help = "path to m3sa setup file") .file(canBeDir = false, canBeFile = true) - .defaultLazy { File("") } + + private val m3saExec by option("-e", "--m3sa-exec-path", help = "path to m3sa executable") + .file(canBeDir = true, canBeFile = false) + .defaultLazy { File("opendc-experiments/opendc-experiments-m3sa/src/main/python/") } + + private val inputIterations by option("-i", "--iterations", help = "number of iterations to run") + .int() + .default(1) override fun run() { - println("The provided m3saPath is $m3saPath") - - val experiment = getExperiment(scenarioPath) - runExperiment(experiment, parallelism) - - if (m3saPath.toString().isNotEmpty()) { - m3saAnalyze( - outputFolderPath = getOutputFolder(scenarioPath), - m3saSetupPath = m3saPath.toString(), - ) - } else { - println( - "\n" + - "===================================================\n" + - "|M3SA path is not provided. Skipping M3SA analysis.|\n" + - "===================================================", - ) + val file = File("analysis.txt") + if (!file.exists()) { + file.createNewFile() } + + var iterations = inputIterations + var currentIteration = 1 + + while (iterations > 0) { + val startTime = System.currentTimeMillis() + val experiment = getExperiment(scenarioPath) + org.opendc.experiments.base.runner.runExperiment(experiment) + val simulationEnd = System.currentTimeMillis() + println("Simulation time: ${(simulationEnd - startTime) / 1000} ms") + + if (m3saPath != null) { + m3saAnalyze( + outputFolderPath = getOutputFolder(scenarioPath), + m3saSetupPath = m3saPath.toString(), + m3saExecPath = m3saExec.toString(), + ) + } else { + println( + "\n" + + "===================================================\n" + + "|M3SA path is not provided. Skipping M3SA analysis.|\n" + + "===================================================", + ) + } + + val endTime = System.currentTimeMillis() + println("OpenDC time: ${(simulationEnd - startTime) / 1000.0} s") + println("M3SA time: ${(endTime - simulationEnd) / 1000.0} s") + println("Total operation time: ${(endTime - startTime) / 1000.0} s") + + file.appendText("$currentIteration. OpenDC time: ${(simulationEnd - startTime) / 1000.0} s\n") + file.appendText("$currentIteration. M3SA time: ${(endTime - simulationEnd) / 1000.0} s\n") + file.appendText("$currentIteration. Total operation time: ${(endTime - startTime) / 1000.0} s\n\n") + + iterations -= 1 + currentIteration += 1 + } + + file.appendText("===================================================\n") + println("Finished $scenarioPath") } } diff --git a/opendc-experiments/opendc-experiments-m3sa/src/main/kotlin/org/opendc/experiments/m3sa/runner/M3SARunner.kt b/opendc-experiments/opendc-experiments-m3sa/src/main/kotlin/org/opendc/experiments/m3sa/runner/M3SARunner.kt index 49bbdb96..9bc7045f 100644 --- a/opendc-experiments/opendc-experiments-m3sa/src/main/kotlin/org/opendc/experiments/m3sa/runner/M3SARunner.kt +++ b/opendc-experiments/opendc-experiments-m3sa/src/main/kotlin/org/opendc/experiments/m3sa/runner/M3SARunner.kt @@ -25,7 +25,10 @@ package org.opendc.experiments.m3sa.runner import org.opendc.experiments.base.experiment.Scenario +import org.opendc.experiments.base.runner.runScenario import org.opendc.experiments.base.runner.setupOutputFolderStructure +import java.io.File +import java.util.Optional /** * Run scenario when no pool is available for parallel execution @@ -35,9 +38,35 @@ import org.opendc.experiments.base.runner.setupOutputFolderStructure */ public fun runExperiment( experiment: List<Scenario>, - parallelism: Int, + extraSimDataPath: Optional<String>, ) { + val ansiReset = "\u001B[0m" + val ansiGreen = "\u001B[32m" + val ansiBlue = "\u001B[34m" + setupOutputFolderStructure(experiment[0].outputFolder) - runExperiment(experiment, parallelism) + var latestScenarioId = experiment.map { it.id }.maxOrNull() ?: 0 + + for (scenario in experiment) { + println( + "\n\n$ansiGreen================================================================================$ansiReset", + ) + println("$ansiBlue Running scenario: ${scenario.name} $ansiReset") + println("$ansiGreen================================================================================$ansiReset") + runScenario( + scenario, + ) + } + + if (extraSimDataPath.isEmpty) return + + for (directory in File(extraSimDataPath.get()).listFiles()!!) { + if (!directory.isDirectory) continue + latestScenarioId += 1 + + val copyPath = "${experiment[0].outputFolder}/raw-output/$latestScenarioId" + File(copyPath).mkdirs() + directory.copyRecursively(File(copyPath), true) + } } |
