From 127686493ff44f536ee134575cd23bc96eebf075 Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Wed, 6 Jan 2021 22:52:07 +0100 Subject: Add rudimentary console runner for harness --- .../kotlin/kotlin-library-convention.gradle.kts | 1 + simulator/opendc-harness/build.gradle.kts | 4 + .../runner/console/ConsoleExperimentReporter.kt | 79 +++++++++++++++++ .../opendc/harness/runner/console/ConsoleRunner.kt | 99 ++++++++++++++++++++++ .../opendc-harness/src/main/resources/log4j2.xml | 40 +++++++++ 5 files changed, 223 insertions(+) create mode 100644 simulator/opendc-harness/src/main/kotlin/org/opendc/harness/runner/console/ConsoleExperimentReporter.kt create mode 100644 simulator/opendc-harness/src/main/kotlin/org/opendc/harness/runner/console/ConsoleRunner.kt create mode 100644 simulator/opendc-harness/src/main/resources/log4j2.xml (limited to 'simulator') diff --git a/simulator/buildSrc/src/main/kotlin/kotlin-library-convention.gradle.kts b/simulator/buildSrc/src/main/kotlin/kotlin-library-convention.gradle.kts index bbecf346..f9d8a966 100644 --- a/simulator/buildSrc/src/main/kotlin/kotlin-library-convention.gradle.kts +++ b/simulator/buildSrc/src/main/kotlin/kotlin-library-convention.gradle.kts @@ -33,6 +33,7 @@ plugins { /* Project configuration */ repositories { + mavenCentral() jcenter() } diff --git a/simulator/opendc-harness/build.gradle.kts b/simulator/opendc-harness/build.gradle.kts index 76d1f2cd..359d2384 100644 --- a/simulator/opendc-harness/build.gradle.kts +++ b/simulator/opendc-harness/build.gradle.kts @@ -30,14 +30,18 @@ plugins { dependencies { api("org.jetbrains.kotlinx:kotlinx-coroutines-core:${Library.KOTLINX_COROUTINES}") api("org.junit.platform:junit-platform-commons:${Library.JUNIT_PLATFORM}") + implementation("io.github.classgraph:classgraph:4.8.98") implementation("me.tongfei:progressbar:0.9.0") implementation("io.github.microutils:kotlin-logging:2.0.4") + implementation("com.github.ajalt.clikt:clikt:3.1.0") api("org.junit.platform:junit-platform-engine:${Library.JUNIT_PLATFORM}") api("org.junit.platform:junit-platform-suite-api:${Library.JUNIT_PLATFORM}") api("org.junit.platform:junit-platform-launcher:${Library.JUNIT_PLATFORM}") + runtimeOnly("org.apache.logging.log4j:log4j-slf4j-impl:2.14.0") + testImplementation("org.junit.jupiter:junit-jupiter-api:${Library.JUNIT_JUPITER}") testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${Library.JUNIT_JUPITER}") } diff --git a/simulator/opendc-harness/src/main/kotlin/org/opendc/harness/runner/console/ConsoleExperimentReporter.kt b/simulator/opendc-harness/src/main/kotlin/org/opendc/harness/runner/console/ConsoleExperimentReporter.kt new file mode 100644 index 00000000..2db74ef4 --- /dev/null +++ b/simulator/opendc-harness/src/main/kotlin/org/opendc/harness/runner/console/ConsoleExperimentReporter.kt @@ -0,0 +1,79 @@ +/* + * 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.harness.runner.console + +import me.tongfei.progressbar.ProgressBar +import me.tongfei.progressbar.ProgressBarBuilder +import mu.KotlinLogging +import org.opendc.harness.api.Trial +import org.opendc.harness.engine.ExperimentExecutionListener + +/** + * A reporter that reports the experiment progress to the console. + */ +public class ConsoleExperimentReporter : ExperimentExecutionListener, AutoCloseable { + /** + * The active [Trial]s. + */ + private val trials: MutableSet = mutableSetOf() + + /** + * The total number of runs. + */ + private var total = 0 + + /** + * The logger for this reporter. + */ + private val logger = KotlinLogging.logger {} + + /** + * The progress bar to keep track of the progress. + */ + private val pb: ProgressBar = ProgressBarBuilder() + .setTaskName("") + .setInitialMax(1) + .build() + + override fun trialFinished(trial: Trial, throwable: Throwable?) { + trials -= trial + + pb.stepTo(total - trials.size.toLong()) + if (trials.isEmpty()) { + pb.close() + } + + if (throwable != null) { + logger.warn(throwable) { "Trial $trial failed" } + } + } + + override fun trialStarted(trial: Trial) { + trials += trial + pb.maxHint((++total).toLong()) + } + + override fun close() { + pb.close() + } +} diff --git a/simulator/opendc-harness/src/main/kotlin/org/opendc/harness/runner/console/ConsoleRunner.kt b/simulator/opendc-harness/src/main/kotlin/org/opendc/harness/runner/console/ConsoleRunner.kt new file mode 100644 index 00000000..ae221c7f --- /dev/null +++ b/simulator/opendc-harness/src/main/kotlin/org/opendc/harness/runner/console/ConsoleRunner.kt @@ -0,0 +1,99 @@ +/* + * 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.harness.runner.console + +import com.github.ajalt.clikt.core.CliktCommand +import com.github.ajalt.clikt.parameters.options.default +import com.github.ajalt.clikt.parameters.options.multiple +import com.github.ajalt.clikt.parameters.options.option +import com.github.ajalt.clikt.parameters.types.int +import mu.KotlinLogging +import org.opendc.harness.engine.ExperimentEngineLauncher +import org.opendc.harness.engine.discovery.DiscoveryProvider +import org.opendc.harness.engine.discovery.DiscoveryRequest +import org.opendc.harness.engine.discovery.DiscoverySelector +import org.opendc.harness.engine.scheduler.ThreadPoolExperimentScheduler + +/** + * The logger for this experiment runner. + */ +private val logger = KotlinLogging.logger {} + +/** + * The command line interface for the console experiment runner. + */ +public class ConsoleRunner : CliktCommand(name = "opendc-harness") { + /** + * The number of repeats per scenario. + */ + private val repeats by option("-r", "--repeats", help = "Number of repeats per scenario") + .int() + .default(1) + + /** + * The selected experiments to run by name. + */ + private val experiments by option("-e", "--experiments", help = "Names of experiments to explore") + .multiple(emptyList()) + + /** + * The maximum number of worker threads to use. + */ + private val parallelism by option("-p", "--parallelism", help = "Maximum number of concurrent simulation runs") + .int() + .default(Runtime.getRuntime().availableProcessors()) + + override fun run() { + logger.info { "Starting OpenDC Console Experiment Runner" } + + val discovery = DiscoveryProvider.createComposite() + val experiments = discovery.discover( + DiscoveryRequest( + selectors = experiments.map { DiscoverySelector.Name(it) } + ) + ) + + val reporter = ConsoleExperimentReporter() + val scheduler = ThreadPoolExperimentScheduler(parallelism) + + try { + ExperimentEngineLauncher() + .withListener(reporter) + .withRepeats(repeats) + .withScheduler(scheduler) + .runBlocking(experiments) + } catch (e: Throwable) { + logger.error(e) { "Failed to finish experiments" } + } finally { + reporter.close() + scheduler.close() + } + + logger.info { "Finished all experiments. Exiting." } + } +} + +/** + * Main entry point of the experiment runner. + */ +public fun main(args: Array): Unit = ConsoleRunner().main(args) diff --git a/simulator/opendc-harness/src/main/resources/log4j2.xml b/simulator/opendc-harness/src/main/resources/log4j2.xml new file mode 100644 index 00000000..9553d964 --- /dev/null +++ b/simulator/opendc-harness/src/main/resources/log4j2.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + -- cgit v1.2.3