From dd3b6173ad84d94e7c88a18f170108a7367da124 Mon Sep 17 00:00:00 2001 From: Marcel Becker <stu117960@mail.uni-kiel.de> Date: Sun, 12 Dec 2021 19:40:22 +0100 Subject: [PATCH] Added GuessStrategy Interface Implementation --- .../searchstrategy/GuessStrategy.kt | 22 +++++++++++++++++ .../InitialGuessSearchStrategy.kt | 18 +++++++------- .../searchstrategy/PrevResourceMinGuess.kt | 24 +++++++++++++++++++ .../searchstrategy/SearchStrategy.kt | 4 +++- .../InitialGuessSearchStrategyTest.kt | 16 ++++++++----- 5 files changed, 68 insertions(+), 16 deletions(-) create mode 100644 theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/GuessStrategy.kt create mode 100644 theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/PrevResourceMinGuess.kt diff --git a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/GuessStrategy.kt b/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/GuessStrategy.kt new file mode 100644 index 000000000..786a3baf1 --- /dev/null +++ b/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/GuessStrategy.kt @@ -0,0 +1,22 @@ +package theodolite.strategies.searchstrategy + +import io.quarkus.runtime.annotations.RegisterForReflection +import theodolite.util.Resource + +/** + * 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. + */ + +@RegisterForReflection +abstract class GuessStrategy { + /** + * Computing the resource demand for the initial guess search strategy to start with. + * + * @param resources List of all possible [Resource]s. + * @param lastLowestResource Previous resource demand needed for the given load. + * + * @return Returns the resource demand to start the initial guess search strategy with or null + */ + abstract fun firstGuess(resources: List<Resource>, lastLowestResource: Resource?): Resource? +} \ 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 44d6928d6..432f08fde 100644 --- a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/InitialGuessSearchStrategy.kt +++ b/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/InitialGuessSearchStrategy.kt @@ -8,23 +8,23 @@ import theodolite.util.Resource private val logger = KotlinLogging.logger {} /** - * Search strategy implementation for determining the smallest suitable number of instances, which takes the - * resource demand of the previous load into account as a starting point for the search. + * Search strategy implementation for determining the smallest suitable resource demand. + * Starting with a resource amount provided by a guess strategy. * * @param benchmarkExecutor Benchmark executor which runs the individual benchmarks. + * @param guessStrategy Strategy that provides us with a guess for the first resource amount. */ -class InitialGuessSearchStrategy(benchmarkExecutor: BenchmarkExecutor) : SearchStrategy(benchmarkExecutor) { +class InitialGuessSearchStrategy(benchmarkExecutor: BenchmarkExecutor, guessStrategy: GuessStrategy) : SearchStrategy(benchmarkExecutor, guessStrategy) { override fun findSuitableResource(load: LoadDimension, resources: List<Resource>, lastLowestResource: Resource?): Resource? { - var lastLowestResourceToUse = lastLowestResource - - // This Search strategy needs a resource demand to start the search with, - // if this is not provided it will be set to the first resource of the given resource-list - if(lastLowestResource == null && resources.isNotEmpty()){ - lastLowestResourceToUse = resources[0] + if(guessStrategy == null){ + logger.info { "Your InitialGuessSearchStrategy doesn't have a GuessStrategy. This is not supported." } + return null } + var lastLowestResourceToUse = this.guessStrategy.firstGuess(resources, lastLowestResource) + if (lastLowestResourceToUse != null) { val resourcesToCheck: List<Resource> val startIndex: Int = resources.indexOf(lastLowestResourceToUse) diff --git a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/PrevResourceMinGuess.kt b/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/PrevResourceMinGuess.kt new file mode 100644 index 000000000..413eecea2 --- /dev/null +++ b/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/PrevResourceMinGuess.kt @@ -0,0 +1,24 @@ +package theodolite.strategies.searchstrategy + +import theodolite.util.Resource + +/** + * 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 [Resource]s. + * @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 + */ + override fun firstGuess(resources: List<Resource>, lastLowestResource: Resource?): Resource? { + + 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/SearchStrategy.kt b/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/SearchStrategy.kt index b7994617b..e37cc32b5 100644 --- a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/SearchStrategy.kt +++ b/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/SearchStrategy.kt @@ -9,14 +9,16 @@ import theodolite.util.Resource * Base class for the implementation for SearchStrategies. SearchStrategies determine the smallest suitable number of instances. * * @param benchmarkExecutor Benchmark executor which runs the individual benchmarks. + * @param guessStrategy Guess strategy for the initial resource amount in case the InitialGuessStrategy is selected. */ @RegisterForReflection -abstract class SearchStrategy(val benchmarkExecutor: BenchmarkExecutor) { +abstract class SearchStrategy(val benchmarkExecutor: BenchmarkExecutor, val guessStrategy: GuessStrategy? = null) { /** * Find smallest suitable resource from the specified resource list for the given load. * * @param load the [LoadDimension] to be tested. * @param resources List of all possible [Resource]s. + * @param lastLowestResource Previous resource demand needed for the given load. * * @return suitable resource for the specified load, or null if no suitable resource exists. */ diff --git a/theodolite/src/test/kotlin/theodolite/InitialGuessSearchStrategyTest.kt b/theodolite/src/test/kotlin/theodolite/InitialGuessSearchStrategyTest.kt index f90b96ee1..f7f52a6da 100644 --- a/theodolite/src/test/kotlin/theodolite/InitialGuessSearchStrategyTest.kt +++ b/theodolite/src/test/kotlin/theodolite/InitialGuessSearchStrategyTest.kt @@ -9,6 +9,7 @@ import theodolite.util.LoadDimension import theodolite.util.Resource import theodolite.util.Results import mu.KotlinLogging +import theodolite.strategies.searchstrategy.PrevResourceMinGuess private val logger = KotlinLogging.logger {} @@ -16,7 +17,7 @@ private val logger = KotlinLogging.logger {} class InitialGuessSearchStrategyTest { @Test - fun testEnd2EndInitialGuessSearch() { + fun testInitialGuessSearch() { val mockResults = arrayOf( arrayOf(true, true, true, true, true, true, true), arrayOf(false, false, true, true, true, true, true), @@ -30,9 +31,10 @@ class InitialGuessSearchStrategyTest { val mockResources: List<Resource> = (0..6).map { number -> Resource(number, emptyList()) } val results = Results() val benchmark = TestBenchmark() + val guessStrategy = PrevResourceMinGuess() val sloChecker: BenchmarkExecution.Slo = BenchmarkExecution.Slo() val benchmarkExecutor = TestBenchmarkExecutorImpl(mockResults, benchmark, results, listOf(sloChecker), 0, 0, 5) - val strategy = InitialGuessSearchStrategy(benchmarkExecutor) + val strategy = InitialGuessSearchStrategy(benchmarkExecutor,guessStrategy) val actual: ArrayList<Resource?> = ArrayList() val expected: ArrayList<Resource?> = ArrayList(listOf(0, 2, 2, 3, 4, 6).map { x -> Resource(x, emptyList()) }) @@ -56,7 +58,7 @@ class InitialGuessSearchStrategyTest { } @Test - fun testEnd2EndInitialGuessSearchLowerResourceDemandHigherLoad() { + fun testInitialGuessSearchLowerResourceDemandHigherLoad() { val mockResults = arrayOf( arrayOf(true, true, true, true, true, true, true), arrayOf(false, false, true, true, true, true, true), @@ -70,9 +72,10 @@ class InitialGuessSearchStrategyTest { val mockResources: List<Resource> = (0..6).map { number -> Resource(number, emptyList()) } val results = Results() val benchmark = TestBenchmark() + val guessStrategy = PrevResourceMinGuess() val sloChecker: BenchmarkExecution.Slo = BenchmarkExecution.Slo() val benchmarkExecutor = TestBenchmarkExecutorImpl(mockResults, benchmark, results, listOf(sloChecker), 0, 0, 5) - val strategy = InitialGuessSearchStrategy(benchmarkExecutor) + val strategy = InitialGuessSearchStrategy(benchmarkExecutor,guessStrategy) val actual: ArrayList<Resource?> = ArrayList() val expected: ArrayList<Resource?> = ArrayList(listOf(0, 2, 2, 1, 4, 6).map { x -> Resource(x, emptyList()) }) @@ -96,7 +99,7 @@ class InitialGuessSearchStrategyTest { } @Test - fun testEnd2EndInitialGuessSearchFirstNotDoable() { + fun testInitialGuessSearchFirstNotDoable() { val mockResults = arrayOf( arrayOf(false, false, false, false, false, false, false), arrayOf(false, false, true, true, true, true, true), @@ -110,9 +113,10 @@ class InitialGuessSearchStrategyTest { val mockResources: List<Resource> = (0..6).map { number -> Resource(number, emptyList()) } val results = Results() val benchmark = TestBenchmark() + val guessStrategy = PrevResourceMinGuess() val sloChecker: BenchmarkExecution.Slo = BenchmarkExecution.Slo() val benchmarkExecutor = TestBenchmarkExecutorImpl(mockResults, benchmark, results, listOf(sloChecker), 0, 0, 5) - val strategy = InitialGuessSearchStrategy(benchmarkExecutor) + val strategy = InitialGuessSearchStrategy(benchmarkExecutor, guessStrategy) val actual: ArrayList<Resource?> = ArrayList() var expected: ArrayList<Resource?> = ArrayList(listOf(2, 3, 0, 4, 6).map { x -> Resource(x, emptyList()) }) -- GitLab