From 754d95dd64752438ce87160f0293bd8d53eb604a Mon Sep 17 00:00:00 2001 From: Marcel Becker <stu117960@mail.uni-kiel.de> Date: Thu, 17 Feb 2022 16:40:17 +0100 Subject: [PATCH] Comments and Clean-up --- theodolite/crd/crd-execution.yaml | 2 +- .../examples/operator/example-execution.yaml | 2 +- .../kotlin/theodolite/benchmark/Benchmark.kt | 4 +-- .../benchmark/BenchmarkExecution.kt | 19 ++++++----- .../benchmark/KubernetesBenchmark.kt | 10 +++--- .../theodolite/execution/BenchmarkExecutor.kt | 8 +++-- .../execution/BenchmarkExecutorImpl.kt | 9 +----- .../execution/TheodoliteExecutor.kt | 10 +++--- .../theodolite/strategies/StrategyFactory.kt | 32 +++++++++++-------- .../restriction/LowerBoundRestriction.kt | 6 ++-- .../restriction/RestrictionStrategy.kt | 9 +++--- .../strategies/searchstrategy/BinarySearch.kt | 20 ++++++------ .../strategies/searchstrategy/FullSearch.kt | 7 ++-- .../searchstrategy/GuessStrategy.kt | 13 ++++---- .../InitialGuessSearchStrategy.kt | 1 - .../strategies/searchstrategy/LinearSearch.kt | 3 +- .../searchstrategy/PrevInstanceOptGuess.kt | 28 ++++++++++++++++ .../searchstrategy/PrevResourceMinGuess.kt | 24 -------------- .../searchstrategy/RestrictionSearch.kt | 13 ++++++-- .../searchstrategy/SearchStrategy.kt | 18 ++++++++--- .../src/main/kotlin/theodolite/util/Config.kt | 4 +-- .../main/kotlin/theodolite/util/Results.kt | 8 ++--- .../InitialGuessSearchStrategyTest.kt | 8 ++--- .../execution/operator/ExecutionCRDummy.kt | 2 +- .../kotlin/theodolite/util/ResultsTest.kt | 1 - .../k8s-resource-files/test-execution-1.yaml | 2 +- .../test-execution-update.yaml | 2 +- .../k8s-resource-files/test-execution.yaml | 2 +- 28 files changed, 145 insertions(+), 122 deletions(-) create mode 100644 theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/PrevInstanceOptGuess.kt delete mode 100644 theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/PrevResourceMinGuess.kt diff --git a/theodolite/crd/crd-execution.yaml b/theodolite/crd/crd-execution.yaml index f83771d00..181d72b49 100644 --- a/theodolite/crd/crd-execution.yaml +++ b/theodolite/crd/crd-execution.yaml @@ -29,7 +29,7 @@ spec: benchmark: description: The name of the benchmark this execution is referring to. type: string - load: # definition of the load dimension + loads: # definition of the load dimension description: Specifies the load values that are benchmarked. type: object required: ["loadType", "loadValues"] diff --git a/theodolite/examples/operator/example-execution.yaml b/theodolite/examples/operator/example-execution.yaml index cb811a35c..b94aa9b26 100644 --- a/theodolite/examples/operator/example-execution.yaml +++ b/theodolite/examples/operator/example-execution.yaml @@ -4,7 +4,7 @@ metadata: name: theodolite-example-execution spec: benchmark: "example-benchmark" - load: + loads: loadType: "NumSensors" loadValues: [25000, 50000, 75000, 100000, 125000, 150000] resources: diff --git a/theodolite/src/main/kotlin/theodolite/benchmark/Benchmark.kt b/theodolite/src/main/kotlin/theodolite/benchmark/Benchmark.kt index cd6e05e49..f2b587cba 100644 --- a/theodolite/src/main/kotlin/theodolite/benchmark/Benchmark.kt +++ b/theodolite/src/main/kotlin/theodolite/benchmark/Benchmark.kt @@ -6,8 +6,8 @@ import theodolite.util.PatcherDefinition /** * A Benchmark contains: - * - The [Resource]s that can be scaled for the benchmark. - * - The [LoadDimension]s that can be scaled the benchmark. + * - The Resource that can be scaled for the benchmark. + * - The Load that can be scaled the benchmark. * - additional [ConfigurationOverride]s. */ @RegisterForReflection diff --git a/theodolite/src/main/kotlin/theodolite/benchmark/BenchmarkExecution.kt b/theodolite/src/main/kotlin/theodolite/benchmark/BenchmarkExecution.kt index 838b74642..66f20e94b 100644 --- a/theodolite/src/main/kotlin/theodolite/benchmark/BenchmarkExecution.kt +++ b/theodolite/src/main/kotlin/theodolite/benchmark/BenchmarkExecution.kt @@ -12,8 +12,8 @@ import kotlin.properties.Delegates * A BenchmarkExecution consists of: * - A [name]. * - The [benchmark] that should be executed. - * - The [load] that should be checked in the benchmark. - * - The resources that should be checked in the benchmark. + * - The [loads]s that should be checked in the benchmark. + * - The [resources] that should be checked in the benchmark. * - A list of [slos] that are used for the evaluation of the experiments. * - An [execution] that encapsulates: the strategy, the duration, and the restrictions * for the execution of the benchmark. @@ -28,7 +28,7 @@ class BenchmarkExecution : KubernetesResource { var executionId: Int = 0 lateinit var name: String lateinit var benchmark: String - lateinit var load: LoadDefinition + lateinit var loads: LoadDefinition lateinit var resources: ResourceDefinition lateinit var slos: List<Slo> lateinit var execution: Execution @@ -41,7 +41,7 @@ class BenchmarkExecution : KubernetesResource { @JsonDeserialize @RegisterForReflection class Execution : KubernetesResource { - var metric = "demand" //irgendwie mag er es nicht mit den default laden, wenn lateinit dann gibt es bei den tests fehler und muss bei var setzen + var metric = "demand" lateinit var strategy: Strategy var duration by Delegates.notNull<Long>() var repetitions by Delegates.notNull<Int>() @@ -50,7 +50,9 @@ class BenchmarkExecution : KubernetesResource { } /** - * This Strategy encapsulates the [restrictions] which is used for restricting the resources. + * This Strategy encapsulates the [restrictions], [guessStrategy] and [searchStrategy], + * which are used for restricting the resources, the guess Strategy for the [InitialGuessSearchStrategy] and + * the actual [SearchStrategy] which is used. */ @JsonDeserialize @RegisterForReflection @@ -80,8 +82,8 @@ class BenchmarkExecution : KubernetesResource { } /** - * Represents a Load that should be created and checked. - * It can be set to [loadValues]. + * Represents the Loads that should be created and checked if the demand metric is in use or + * represents a Load that can be scaled to [loadValues] if the capacity metric is in use. */ @JsonDeserialize @RegisterForReflection @@ -91,7 +93,8 @@ class BenchmarkExecution : KubernetesResource { } /** - * Represents a resource that can be scaled to [resourceValues]. + * Represents a resource that can be scaled to [resourceValues] if the demand metric is in use or + * represents the Resources that should be created and checked if the capacity metric is in use. */ @JsonDeserialize @RegisterForReflection diff --git a/theodolite/src/main/kotlin/theodolite/benchmark/KubernetesBenchmark.kt b/theodolite/src/main/kotlin/theodolite/benchmark/KubernetesBenchmark.kt index 215b14e71..a7fa2858c 100644 --- a/theodolite/src/main/kotlin/theodolite/benchmark/KubernetesBenchmark.kt +++ b/theodolite/src/main/kotlin/theodolite/benchmark/KubernetesBenchmark.kt @@ -8,7 +8,6 @@ import io.quarkus.runtime.annotations.RegisterForReflection import mu.KotlinLogging import theodolite.k8s.K8sManager import theodolite.k8s.resourceLoader.K8sResourceLoader -import theodolite.patcher.Patcher import theodolite.patcher.PatcherFactory import theodolite.util.* @@ -76,10 +75,11 @@ class KubernetesBenchmark : KubernetesResource, Benchmark { /** * Builds a deployment. - * First loads all required resources and then patches them to the concrete load and resources for the experiment. - * Afterwards patches additional configurations(cluster depending) into the resources. - * @param load concrete load that will be benchmarked in this experiment. - * @param res concrete resource that will be scaled for this experiment. + * First loads all required resources and then patches them to the concrete load and resources for the experiment for the demand metric + * or loads all loads and then patches them to the concrete load and resources for the experiment. + * Afterwards patches additional configurations(cluster depending) into the resources (or loads). + * @param load concrete load that will be benchmarked in this experiment (demand metric), or scaled (capacity metric). + * @param resource concrete resource that will be scaled for this experiment (demand metric), or benchmarked (capacity metric). * @param configurationOverrides * @return a [BenchmarkDeployment] */ diff --git a/theodolite/src/main/kotlin/theodolite/execution/BenchmarkExecutor.kt b/theodolite/src/main/kotlin/theodolite/execution/BenchmarkExecutor.kt index 470f63fcd..55233246f 100644 --- a/theodolite/src/main/kotlin/theodolite/execution/BenchmarkExecutor.kt +++ b/theodolite/src/main/kotlin/theodolite/execution/BenchmarkExecutor.kt @@ -40,10 +40,12 @@ abstract class BenchmarkExecutor( * Run a experiment for the given parametrization, evaluate the * experiment and save the result. * - * @param load load to be tested. - * @param res resources to be tested. + * @param load to be tested. + * @param resource to be tested. * @return True, if the number of resources are suitable for the - * given load, false otherwise. + * given load, false otherwise (demand metric), or + * True, if there is a load suitable for the + * given resource, false otherwise. */ abstract fun runExperiment(load: Int, resource: Int): Boolean diff --git a/theodolite/src/main/kotlin/theodolite/execution/BenchmarkExecutorImpl.kt b/theodolite/src/main/kotlin/theodolite/execution/BenchmarkExecutorImpl.kt index f463ce452..3e86a4ee9 100644 --- a/theodolite/src/main/kotlin/theodolite/execution/BenchmarkExecutorImpl.kt +++ b/theodolite/src/main/kotlin/theodolite/execution/BenchmarkExecutorImpl.kt @@ -56,7 +56,6 @@ class BenchmarkExecutorImpl( break } } - /** * Analyse the experiment, if [run] is true, otherwise the experiment was canceled by the user. */ @@ -71,16 +70,10 @@ class BenchmarkExecutorImpl( } result = (false !in experimentResults) - // differentiate metric here on first/second ele pairs, also wenn demand so und wenn capacity dann mit (resource,load) - // so könnten wir die Methoden in Results so lassen und müssten keine Dopplung einbauen - // wird alles sehr undurchsichtig damit wenn man die vertauscht, evtl mit metric zu den Results klarer machen this.results.setResult(Pair(load, resource), result) - } - - if(!this.run.get()) { + } else { throw ExecutionFailedException("The execution was interrupted") } - return result } diff --git a/theodolite/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt b/theodolite/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt index 49503b8a7..77ebd099d 100644 --- a/theodolite/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt +++ b/theodolite/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt @@ -51,7 +51,7 @@ class TheodoliteExecutor( val loadDimensionPatcherDefinition = PatcherDefinitionFactory().createPatcherDefinition( - config.load.loadType, + config.loads.loadType, this.kubernetesBenchmark.loadTypes ) @@ -71,11 +71,11 @@ class TheodoliteExecutor( resourcePatcherDefinitions = resourcePatcherDefinition ) - if (config.load.loadValues != config.load.loadValues.sorted()) { - config.load.loadValues = config.load.loadValues.sorted() + if (config.loads.loadValues != config.loads.loadValues.sorted()) { + config.loads.loadValues = config.loads.loadValues.sorted() logger.info { "Load values are not sorted correctly, Theodolite sorts them in ascending order." + - "New order is: ${config.load.loadValues}" + "New order is: ${config.loads.loadValues}" } } @@ -88,7 +88,7 @@ class TheodoliteExecutor( } return Config( - loads = config.load.loadValues, + loads = config.loads.loadValues, loadPatcherDefinitions = loadDimensionPatcherDefinition, resources = config.resources.resourceValues, resourcePatcherDefinitions = resourcePatcherDefinition, diff --git a/theodolite/src/main/kotlin/theodolite/strategies/StrategyFactory.kt b/theodolite/src/main/kotlin/theodolite/strategies/StrategyFactory.kt index 5f9bb6a33..505681716 100644 --- a/theodolite/src/main/kotlin/theodolite/strategies/StrategyFactory.kt +++ b/theodolite/src/main/kotlin/theodolite/strategies/StrategyFactory.kt @@ -16,27 +16,31 @@ class StrategyFactory { * Create a [SearchStrategy]. * * @param executor The [theodolite.execution.BenchmarkExecutor] that executes individual experiments. - * @param searchStrategyString Specifies the [SearchStrategy]. Must either be the string 'LinearSearch', - * or 'BinarySearch'. + * @param searchStrategyObject Specifies the [SearchStrategy]. Must either be an object with name 'FullSearch', + * 'LinearSearch', 'BinarySearch', 'RestrictionSearch' or 'InitialGuessSearch'. + * @param results The [Results] saves the state of the Theodolite benchmark run. * * @throws IllegalArgumentException if the [SearchStrategy] was not one of the allowed options. */ - fun createSearchStrategy(executor: BenchmarkExecutor, searchStrategyObject: BenchmarkExecution.Strategy, results: Results): SearchStrategy { + fun createSearchStrategy(executor: BenchmarkExecutor, searchStrategyObject: BenchmarkExecution.Strategy, + results: Results): SearchStrategy { var strategy : SearchStrategy = when (searchStrategyObject.name) { "FullSearch" -> FullSearch(executor) "LinearSearch" -> LinearSearch(executor) "BinarySearch" -> BinarySearch(executor) "RestrictionSearch" -> when (searchStrategyObject.searchStrategy){ - //TODO: Do we only need LinearSearch here as valid searchstrat? Or actually just allow all? - // If we dont have restriction Strat specified but still RestrictionSearch just do normal Search - "FullSearch" -> composeSearchRestrictionStrategy(executor, FullSearch(executor), results, searchStrategyObject.restrictions) - "LinearSearch" -> composeSearchRestrictionStrategy(executor, LinearSearch(executor), results, searchStrategyObject.restrictions) - "BinarySearch" -> composeSearchRestrictionStrategy(executor, BinarySearch(executor), results, searchStrategyObject.restrictions) - else -> throw IllegalArgumentException("Search Strategy ${searchStrategyObject.searchStrategy} for RestrictionSearch not found") + "FullSearch" -> composeSearchRestrictionStrategy(executor, FullSearch(executor), results, + searchStrategyObject.restrictions) + "LinearSearch" -> composeSearchRestrictionStrategy(executor, LinearSearch(executor), results, + searchStrategyObject.restrictions) + "BinarySearch" -> composeSearchRestrictionStrategy(executor, BinarySearch(executor), results, + searchStrategyObject.restrictions) + else -> throw IllegalArgumentException( + "Search Strategy ${searchStrategyObject.searchStrategy} for RestrictionSearch not found") } "InitialGuessSearch" -> when (searchStrategyObject.guessStrategy){ - "PrevResourceMinGuess" -> InitialGuessSearchStrategy(executor,PrevResourceMinGuess(), results) + "PrevResourceMinGuess" -> InitialGuessSearchStrategy(executor,PrevInstanceOptGuess(), results) else -> throw IllegalArgumentException("Guess Strategy ${searchStrategyObject.guessStrategy} not found") } else -> throw IllegalArgumentException("Search Strategy $searchStrategyObject not found") @@ -50,8 +54,8 @@ class StrategyFactory { * * @param results The [Results] saves the state of the Theodolite benchmark run. * @param restrictionStrings Specifies the list of [RestrictionStrategy] that are used to restrict the amount - * of Resource for a fixed LoadDimension. Must equal the string - * 'LowerBound'. + * of Resource for a fixed load or resource (depending on the metric). + * Must equal the string 'LowerBound'. * * @throws IllegalArgumentException if param searchStrategyString was not one of the allowed options. */ @@ -70,9 +74,9 @@ class StrategyFactory { * searchStrategy. * * @param executor The [theodolite.execution.BenchmarkExecutor] that executes individual experiments. - * @param searchStrategy The [SearchStrategy] to use + * @param searchStrategy The [SearchStrategy] to use. * @param results The [Results] saves the state of the Theodolite benchmark run. - * @param restrictions The [RestrictionStrategy]'s to use + * @param restrictions The [RestrictionStrategy]'s to use. */ private fun composeSearchRestrictionStrategy(executor: BenchmarkExecutor, searchStrategy: SearchStrategy, results: Results, restrictions: List<String>): SearchStrategy { diff --git a/theodolite/src/main/kotlin/theodolite/strategies/restriction/LowerBoundRestriction.kt b/theodolite/src/main/kotlin/theodolite/strategies/restriction/LowerBoundRestriction.kt index be9eede10..1203d7293 100644 --- a/theodolite/src/main/kotlin/theodolite/strategies/restriction/LowerBoundRestriction.kt +++ b/theodolite/src/main/kotlin/theodolite/strategies/restriction/LowerBoundRestriction.kt @@ -3,8 +3,10 @@ package theodolite.strategies.restriction import theodolite.util.Results /** - * The [LowerBoundRestriction] sets the lower bound of the resources to be examined to the value - * needed to successfully execute the next smaller load. + * The [LowerBoundRestriction] sets the lower bound of the resources to be examined in the experiment to the value + * needed to successfully execute the previous smaller load (demand metric), or sets the lower bound of the loads + * to be examined in the experiment to the largest value, which still successfully executed the previous smaller + * resource (capacity metric). * * @param results [Result] object used as a basis to restrict the resources. */ diff --git a/theodolite/src/main/kotlin/theodolite/strategies/restriction/RestrictionStrategy.kt b/theodolite/src/main/kotlin/theodolite/strategies/restriction/RestrictionStrategy.kt index 986c15f3c..1ac9d201c 100644 --- a/theodolite/src/main/kotlin/theodolite/strategies/restriction/RestrictionStrategy.kt +++ b/theodolite/src/main/kotlin/theodolite/strategies/restriction/RestrictionStrategy.kt @@ -4,7 +4,7 @@ import io.quarkus.runtime.annotations.RegisterForReflection import theodolite.util.Results /** - * A 'Restriction Strategy' restricts a list of resources based on the current + * A 'Restriction Strategy' restricts a list of resources or loads depending on the metric based on the current * results of all previously performed benchmarks. * * @param results the [Results] object @@ -12,10 +12,11 @@ import theodolite.util.Results @RegisterForReflection abstract class RestrictionStrategy(val results: Results) { /** - * Apply the restriction of the given resource list for the given load based on the results object. + * Apply the restriction of the given resource list for the given load based on the results object (demand metric), + * or apply the restriction of the given load list for the given resource based on the results object (capacity metric). * - * @param load LoadDimension for which a subset of resources is required. - * @param resources List of Resource s to be restricted. + * @param xValue The value to be examined in the experiment, can be load (demand metric) or resource (capacity metric). + * @param yValues List of values to be restricted, can be resources (demand metric) or loads (capacity metric). * @return Returns a list containing only elements that have not been filtered out by the * restriction (possibly empty). */ diff --git a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/BinarySearch.kt b/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/BinarySearch.kt index 08934bb5d..e2af7b26a 100644 --- a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/BinarySearch.kt +++ b/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/BinarySearch.kt @@ -28,12 +28,12 @@ class BinarySearch(benchmarkExecutor: BenchmarkExecutor) : SearchStrategy(benchm } /** - * Apply binary search for metric demand. + * Apply binary search for the demand metric. * - * @param load the load dimension to perform experiments for - * @param resources the list in which binary search is performed - * @param lower lower bound for binary search (inclusive) - * @param upper upper bound for binary search (inclusive) + * @param load the load to perform experiments for. + * @param resources the list of resources in which binary search is performed. + * @param lower lower bound for binary search (inclusive). + * @param upper upper bound for binary search (inclusive). */ private fun binarySearchDemand(load: Int, resources: List<Int>, lower: Int, upper: Int): Int { if (lower > upper) { @@ -68,12 +68,12 @@ class BinarySearch(benchmarkExecutor: BenchmarkExecutor) : SearchStrategy(benchm /** - * Apply binary search for metric capacity. + * Apply binary search for the capacity metric. * - * @param resource the load dimension to perform experiments for - * @param loads the list in which binary search is performed - * @param lower lower bound for binary search (inclusive) - * @param upper upper bound for binary search (inclusive) + * @param resource the resource to perform experiments for. + * @param loads the list of loads in which binary search is performed. + * @param lower lower bound for binary search (inclusive). + * @param upper upper bound for binary search (inclusive). */ private fun binarySearchCapacity(resource: Int, loads: List<Int>, lower: Int, upper: Int): Int { if (lower > upper) { diff --git a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/FullSearch.kt b/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/FullSearch.kt index 7f9158853..6af6aa160 100644 --- a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/FullSearch.kt +++ b/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/FullSearch.kt @@ -6,10 +6,11 @@ import theodolite.execution.BenchmarkExecutor private val logger = KotlinLogging.logger {} /** - * [SearchStrategy] that executes experiment for provides resources in a linear-search-like fashion, but **without - * stopping** once a suitable resource amount is found. + * [SearchStrategy] that executes an experiment for a load and a resource list (demand metric) or for a resource and a + * load list (capacity metric) in a linear-search-like fashion, but **without stopping** once the desired + * resource (demand) or load (capacity) is found. * - * @see LinearSearch for a SearchStrategy that stops once a suitable resource amount is found. + * @see LinearSearch for a SearchStrategy that stops once the desired resource (demand) or load (capacity) is found. * * @param benchmarkExecutor Benchmark executor which runs the individual benchmarks. */ diff --git a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/GuessStrategy.kt b/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/GuessStrategy.kt index f0686975e..f243b8e40 100644 --- a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/GuessStrategy.kt +++ b/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/GuessStrategy.kt @@ -4,18 +4,19 @@ import io.quarkus.runtime.annotations.RegisterForReflection /** * Base class for the implementation of Guess strategies. Guess strategies are strategies to determine the resource - * demand we start with in our initial guess search strategy. + * demand (demand metric) or load (capacity metric) we start with in our initial guess search strategy. */ @RegisterForReflection abstract class GuessStrategy { /** - * Computing the resource demand for the initial guess search strategy to start with. + * Computing the resource demand (demand metric) or load (capacity metric) for the initial guess search strategy + * to start with. * - * @param resources List of all possible resources. - * @param lastLowestResource Previous resource demand needed for the given load. + * @param valuesToCheck List of all possible resources/loads. + * @param lastOptValue Previous minimal/maximal resource/load value for the given load/resource. * - * @return Returns the resource demand to start the initial guess search strategy with or null + * @return the resource/load to start the initial guess search strategy with or null */ - abstract fun firstGuess(resources: List<Int>, lastLowestResource: Int?): Int? + abstract fun firstGuess(valuesToCheck: List<Int>, lastOptValue: Int?): Int? } \ No newline at end of file diff --git a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/InitialGuessSearchStrategy.kt b/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/InitialGuessSearchStrategy.kt index cfdb5de3e..7a7100189 100644 --- a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/InitialGuessSearchStrategy.kt +++ b/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/InitialGuessSearchStrategy.kt @@ -6,7 +6,6 @@ import theodolite.util.Results private val logger = KotlinLogging.logger {} -// TODO: Is actually just a heuristic approach. Not ensured to have opt solution. Maybe Talk to Sören about it. /** * Search strategy implementation for determining the smallest suitable resource demand. * Starting with a resource amount provided by a guess strategy. diff --git a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/LinearSearch.kt b/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/LinearSearch.kt index a02505844..1991431a9 100644 --- a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/LinearSearch.kt +++ b/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/LinearSearch.kt @@ -6,7 +6,8 @@ import theodolite.execution.BenchmarkExecutor private val logger = KotlinLogging.logger {} /** - * Linear-search-like implementation for determining the smallest suitable number of instances. + * Linear-search-like implementation for determining the smallest/biggest suitable number of resources/loads, + * depending on the metric. * * @param benchmarkExecutor Benchmark executor which runs the individual benchmarks. */ diff --git a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/PrevInstanceOptGuess.kt b/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/PrevInstanceOptGuess.kt new file mode 100644 index 000000000..c919b4759 --- /dev/null +++ b/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/PrevInstanceOptGuess.kt @@ -0,0 +1,28 @@ +package theodolite.strategies.searchstrategy + + +/** + * [PrevInstanceOptGuess] is a [GuessStrategy] that implements the function [firstGuess], + * where it returns the optimal result of the previous run. + */ + +class PrevInstanceOptGuess() : GuessStrategy(){ + + /** + * If the metric is + * + * - "demand", [valuesToCheck] is a List of resources and [lastOptValue] a resource value. + * - "capacity", [valuesToCheck] is a List of loads and [lastOptValue] a load value. + * + * @param valuesToCheck List of all possible resources/loads. + * @param lastOptValue Previous minimal/maximal resource/load value for the given load/resource. + * + * @return the value of [lastOptValue] if given otherwise the first element of the [valuesToCheck] list or null + */ + override fun firstGuess(valuesToCheck: List<Int>, lastOptValue: Int?): Int? { + + if (lastOptValue != null) return lastOptValue + else if(valuesToCheck.isNotEmpty()) return valuesToCheck[0] + else return null + } +} \ No newline at end of file diff --git a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/PrevResourceMinGuess.kt b/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/PrevResourceMinGuess.kt deleted file mode 100644 index 04d68c373..000000000 --- a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/PrevResourceMinGuess.kt +++ /dev/null @@ -1,24 +0,0 @@ -package theodolite.strategies.searchstrategy - - -/** - * This Guess strategy takes the minimal resource demand of the previous load, which is given as an argument for the - * firstGuess function. - */ - -class PrevResourceMinGuess() : GuessStrategy(){ - - /** - * @param resources List of all possible Resources. - * @param lastLowestResource Previous resource demand needed for the given load. - * - * @return the value of lastLowestResource if given otherwise the first element of the resource list or null - */ - // TODO verallgemeinern für loads - override fun firstGuess(resources: List<Int>, lastLowestResource: Int?): Int? { - - if (lastLowestResource != null) return lastLowestResource - else if(resources.isNotEmpty()) return resources[0] - else return null - } -} \ No newline at end of file diff --git a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/RestrictionSearch.kt b/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/RestrictionSearch.kt index f7e4ea66d..0a136d6ff 100644 --- a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/RestrictionSearch.kt +++ b/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/RestrictionSearch.kt @@ -7,17 +7,21 @@ import theodolite.strategies.restriction.RestrictionStrategy /** * Strategy that combines a SearchStrategy and a set of RestrictionStrategy. * - * @param searchStrategy the [SearchStrategy] that is executed as part of this [RestrictionSearch]. - * @param restrictionStrategies the set of [RestrictionStrategy] that are connected conjunctive to restrict the Resource * @param benchmarkExecutor Benchmark executor which runs the individual benchmarks. + * @param searchStrategy the [SearchStrategy] that is executed as part of this [RestrictionSearch]. + * @param restrictionStrategies the set of [RestrictionStrategy] that are connected conjunctive to restrict the Resource. + * */ @RegisterForReflection class RestrictionSearch( benchmarkExecutor: BenchmarkExecutor, private val searchStrategy: SearchStrategy, - val restrictionStrategies: Set<RestrictionStrategy> + private val restrictionStrategies: Set<RestrictionStrategy> ) : SearchStrategy(benchmarkExecutor) { + /** + * Restricting the possible resources and calling findSuitableResource of the given [SearchStrategy]. + */ override fun findSuitableResource(load: Int, resources: List<Int>): Int? { var restrictedResources = resources for (strategy in this.restrictionStrategies) { @@ -26,6 +30,9 @@ class RestrictionSearch( return this.searchStrategy.findSuitableResource(load, restrictedResources) } + /** + * Restricting the possible loads and calling findSuitableLoad of the given [SearchStrategy]. + */ override fun findSuitableLoad(resource: Int, loads: List<Int>): Int? { var restrictedLoads = loads for (strategy in this.restrictionStrategies) { diff --git a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/SearchStrategy.kt b/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/SearchStrategy.kt index bbd0f0b51..85453934f 100644 --- a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/SearchStrategy.kt +++ b/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/SearchStrategy.kt @@ -6,7 +6,8 @@ import theodolite.strategies.Metric import theodolite.util.Results /** - * Base class for the implementation for SearchStrategies. SearchStrategies determine the smallest suitable number of instances. + * Base class for the implementation for SearchStrategies. SearchStrategies determine the smallest suitable number + * of resources/loads for a load/resource (depending on the metric). * * @param benchmarkExecutor Benchmark executor which runs the individual benchmarks. * @param guessStrategy Guess strategy for the initial resource amount in case the InitialGuessStrategy is selected. @@ -17,17 +18,24 @@ abstract class SearchStrategy(val benchmarkExecutor: BenchmarkExecutor, val gues val results: Results? = null) { + /** + * Calling findSuitableResource or findSuitableLoad for each load/resource depending on the chosen metric. + * + * @param loads List of possible loads for the experiments. + * @param resources List of possible resources for the experiments. + * @param metric The [Metric] for the experiments, either "demand" or "capacity". + */ fun applySearchStrategyByMetric(loads: List<Int>, resources: List<Int>, metric: Metric) { if (metric.value == "demand") { - //demand metric + // demand metric for (load in loads) { if (benchmarkExecutor.run.get()) { this.findSuitableResource(load, resources) } } } else { - //capacity metric + // capacity metric for (resource in resources) { if (benchmarkExecutor.run.get()) { this.findSuitableLoad(resource, loads) @@ -37,7 +45,7 @@ abstract class SearchStrategy(val benchmarkExecutor: BenchmarkExecutor, val gues } /** - * Find smallest suitable resource from the specified resource list for the given load. + * Find the smallest suitable resource from the specified resource list for the given load. * * @param load the load to be tested. * @param resources List of all possible resources. @@ -47,7 +55,7 @@ abstract class SearchStrategy(val benchmarkExecutor: BenchmarkExecutor, val gues abstract fun findSuitableResource(load: Int, resources: List<Int>): Int? /** - * Find biggest suitable load from the specified load list for the given resource amount. + * Find the biggest suitable load from the specified load list for the given resource amount. * * @param resource the resource to be tested. * @param loads List of all possible loads. diff --git a/theodolite/src/main/kotlin/theodolite/util/Config.kt b/theodolite/src/main/kotlin/theodolite/util/Config.kt index e1b6a4c07..675caea5f 100644 --- a/theodolite/src/main/kotlin/theodolite/util/Config.kt +++ b/theodolite/src/main/kotlin/theodolite/util/Config.kt @@ -7,8 +7,8 @@ import theodolite.strategies.searchstrategy.SearchStrategy /** * Config class that represents a configuration of a theodolite run. * - * @param loads the LoadDimension of the execution - * @param resources the Resource of the execution + * @param loads the possible loads of the execution + * @param resources the possible resources of the execution * @param searchStrategy the [SearchStrategy] of the execution * @param metric the Metric of the execution */ diff --git a/theodolite/src/main/kotlin/theodolite/util/Results.kt b/theodolite/src/main/kotlin/theodolite/util/Results.kt index aeccfdc6a..3d56e0129 100644 --- a/theodolite/src/main/kotlin/theodolite/util/Results.kt +++ b/theodolite/src/main/kotlin/theodolite/util/Results.kt @@ -10,13 +10,11 @@ import theodolite.strategies.Metric */ @RegisterForReflection class Results (val metric: Metric) { - //TODO: enum statt Boolean für successful - - // (load,resource) -> Boolean map + // (load, resource) -> Boolean map private val results: MutableMap<Pair<Int, Int>, Boolean> = mutableMapOf() - // if metric is "demand" : load -> resource - // if metric is "capacity": resource -> load + // if metric is "demand" : load -> resource + // if metric is "capacity": resource -> load private var optInstances: MutableMap<Int, Int> = mutableMapOf() diff --git a/theodolite/src/test/kotlin/theodolite/InitialGuessSearchStrategyTest.kt b/theodolite/src/test/kotlin/theodolite/InitialGuessSearchStrategyTest.kt index 8dcd31481..de7a1f8f1 100644 --- a/theodolite/src/test/kotlin/theodolite/InitialGuessSearchStrategyTest.kt +++ b/theodolite/src/test/kotlin/theodolite/InitialGuessSearchStrategyTest.kt @@ -8,7 +8,7 @@ import theodolite.strategies.searchstrategy.InitialGuessSearchStrategy import theodolite.strategies.Metric import theodolite.util.Results import mu.KotlinLogging -import theodolite.strategies.searchstrategy.PrevResourceMinGuess +import theodolite.strategies.searchstrategy.PrevInstanceOptGuess private val logger = KotlinLogging.logger {} @@ -30,7 +30,7 @@ class InitialGuessSearchStrategyTest { val mockResources: List<Int> = (0..6).toList() val results = Results(Metric.from("demand")) val benchmark = TestBenchmark() - val guessStrategy = PrevResourceMinGuess() + val guessStrategy = PrevInstanceOptGuess() val sloChecker: BenchmarkExecution.Slo = BenchmarkExecution.Slo() val benchmarkExecutor = TestBenchmarkExecutorImpl(mockResults, benchmark, results, listOf(sloChecker), 0, 0, 5) val strategy = InitialGuessSearchStrategy(benchmarkExecutor,guessStrategy, results) @@ -68,7 +68,7 @@ class InitialGuessSearchStrategyTest { val mockResources: List<Int> = (0..6).toList() val results = Results(Metric.from("demand")) val benchmark = TestBenchmark() - val guessStrategy = PrevResourceMinGuess() + val guessStrategy = PrevInstanceOptGuess() val sloChecker: BenchmarkExecution.Slo = BenchmarkExecution.Slo() val benchmarkExecutor = TestBenchmarkExecutorImpl(mockResults, benchmark, results, listOf(sloChecker), 0, 0, 5) val strategy = InitialGuessSearchStrategy(benchmarkExecutor,guessStrategy, results) @@ -106,7 +106,7 @@ class InitialGuessSearchStrategyTest { val mockResources: List<Int> = (0..6).toList() val results = Results(Metric.from("demand")) val benchmark = TestBenchmark() - val guessStrategy = PrevResourceMinGuess() + val guessStrategy = PrevInstanceOptGuess() val sloChecker: BenchmarkExecution.Slo = BenchmarkExecution.Slo() val benchmarkExecutor = TestBenchmarkExecutorImpl(mockResults, benchmark, results, listOf(sloChecker), 0, 0, 5) val strategy = InitialGuessSearchStrategy(benchmarkExecutor, guessStrategy, results) diff --git a/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionCRDummy.kt b/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionCRDummy.kt index 489b1b5fc..961c813f4 100644 --- a/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionCRDummy.kt +++ b/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionCRDummy.kt @@ -53,7 +53,7 @@ class ExecutionCRDummy(name: String, benchmark: String) { execution.benchmark = benchmark - execution.load = loadType + execution.loads = loadType execution.resources = resourceDef execution.slos = emptyList() execution.execution = exec diff --git a/theodolite/src/test/kotlin/theodolite/util/ResultsTest.kt b/theodolite/src/test/kotlin/theodolite/util/ResultsTest.kt index cef83da3c..d453587a9 100644 --- a/theodolite/src/test/kotlin/theodolite/util/ResultsTest.kt +++ b/theodolite/src/test/kotlin/theodolite/util/ResultsTest.kt @@ -3,7 +3,6 @@ package theodolite.util import io.quarkus.test.junit.QuarkusTest import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertNotNull -import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test import theodolite.strategies.Metric diff --git a/theodolite/src/test/resources/k8s-resource-files/test-execution-1.yaml b/theodolite/src/test/resources/k8s-resource-files/test-execution-1.yaml index 1a9b57449..e250d8a96 100644 --- a/theodolite/src/test/resources/k8s-resource-files/test-execution-1.yaml +++ b/theodolite/src/test/resources/k8s-resource-files/test-execution-1.yaml @@ -5,7 +5,7 @@ metadata: spec: name: test benchmark: "uc1-kstreams" - load: + loads: loadType: "NumSensors" loadValues: [25000, 50000, 75000, 100000, 125000, 150000] resources: diff --git a/theodolite/src/test/resources/k8s-resource-files/test-execution-update.yaml b/theodolite/src/test/resources/k8s-resource-files/test-execution-update.yaml index 37b83edbd..80476ba5c 100644 --- a/theodolite/src/test/resources/k8s-resource-files/test-execution-update.yaml +++ b/theodolite/src/test/resources/k8s-resource-files/test-execution-update.yaml @@ -5,7 +5,7 @@ metadata: spec: name: test benchmark: "uc1-kstreams-update" - load: + loads: loadType: "NumSensors" loadValues: [25000, 50000, 75000, 100000, 125000, 150000] resources: diff --git a/theodolite/src/test/resources/k8s-resource-files/test-execution.yaml b/theodolite/src/test/resources/k8s-resource-files/test-execution.yaml index aee12f5fd..2df4760cd 100644 --- a/theodolite/src/test/resources/k8s-resource-files/test-execution.yaml +++ b/theodolite/src/test/resources/k8s-resource-files/test-execution.yaml @@ -5,7 +5,7 @@ metadata: spec: name: test benchmark: "uc1-kstreams" - load: + loads: loadType: "NumSensors" loadValues: [25000, 50000, 75000, 100000, 125000, 150000] resources: -- GitLab