Skip to content
Snippets Groups Projects
Commit 5ddc2fd3 authored by Julia Rossow's avatar Julia Rossow
Browse files

New strategy InitialGuessSearchStrategy

parent 7c2acb21
No related branches found
No related tags found
1 merge request!215Redesign Strategy, Load, and Resources data types
...@@ -13,7 +13,13 @@ private val logger = KotlinLogging.logger {} ...@@ -13,7 +13,13 @@ private val logger = KotlinLogging.logger {}
* @param benchmarkExecutor Benchmark executor which runs the individual benchmarks. * @param benchmarkExecutor Benchmark executor which runs the individual benchmarks.
*/ */
class BinarySearch(benchmarkExecutor: BenchmarkExecutor) : SearchStrategy(benchmarkExecutor) { class BinarySearch(benchmarkExecutor: BenchmarkExecutor) : SearchStrategy(benchmarkExecutor) {
override fun findSuitableResource(load: LoadDimension, resources: List<Resource>): Resource? { override fun findSuitableResource(load: LoadDimension, resources: List<Resource>,
lastLowestResource: Resource?): Resource? {
if (lastLowestResource != null) {
logger.info { "Running LinearSearch with a set lastLowestResource value doesn't make sense." }
}
val result = binarySearch(load, resources, 0, resources.size - 1) val result = binarySearch(load, resources, 0, resources.size - 1)
if (result == -1) { if (result == -1) {
return null return null
......
...@@ -20,7 +20,8 @@ class CompositeStrategy( ...@@ -20,7 +20,8 @@ class CompositeStrategy(
val restrictionStrategies: Set<RestrictionStrategy> val restrictionStrategies: Set<RestrictionStrategy>
) : SearchStrategy(benchmarkExecutor) { ) : SearchStrategy(benchmarkExecutor) {
override fun findSuitableResource(load: LoadDimension, resources: List<Resource>): Resource? { override fun findSuitableResource(load: LoadDimension, resources: List<Resource>,
lastLowestResource: Resource?): Resource? {
var restrictedResources = resources.toList() var restrictedResources = resources.toList()
for (strategy in this.restrictionStrategies) { for (strategy in this.restrictionStrategies) {
restrictedResources = restrictedResources.intersect(strategy.apply(load, resources)).toList() restrictedResources = restrictedResources.intersect(strategy.apply(load, resources)).toList()
......
...@@ -17,7 +17,12 @@ private val logger = KotlinLogging.logger {} ...@@ -17,7 +17,12 @@ private val logger = KotlinLogging.logger {}
*/ */
class FullSearch(benchmarkExecutor: BenchmarkExecutor) : SearchStrategy(benchmarkExecutor) { class FullSearch(benchmarkExecutor: BenchmarkExecutor) : SearchStrategy(benchmarkExecutor) {
override fun findSuitableResource(load: LoadDimension, resources: List<Resource>): Resource? { override fun findSuitableResource(load: LoadDimension, resources: List<Resource>,
lastLowestResource: Resource?): Resource? {
if (lastLowestResource != null) {
logger.info { "Running LinearSearch with a set lastLowestResource value doesn't make sense." }
}
var minimalSuitableResources: Resource? = null var minimalSuitableResources: Resource? = null
for (res in resources) { for (res in resources) {
logger.info { "Running experiment with load '${load.get()}' and resources '${res.get()}'" } logger.info { "Running experiment with load '${load.get()}' and resources '${res.get()}'" }
......
package theodolite.strategies.searchstrategy
import mu.KotlinLogging
import theodolite.execution.BenchmarkExecutor
import theodolite.util.LoadDimension
import theodolite.util.Resource
private val logger = KotlinLogging.logger {}
/**
* Linear-search-like implementation for determining the smallest suitable number of instances.
*
* @param benchmarkExecutor Benchmark executor which runs the individual benchmarks.
*/
class InitialGuessSearchStrategy(benchmarkExecutor: BenchmarkExecutor) : SearchStrategy(benchmarkExecutor) {
override fun findSuitableResource(load: LoadDimension, resources: List<Resource>, lastLowestResource: Resource?): Resource? {
if (lastLowestResource != null) {
val resourcesToCheck: List<Resource>
val startIndex: Int = resources.indexOf(lastLowestResource)
logger.info { "Running experiment with load '${load.get()}' and resources '${lastLowestResource.get()}'" }
if (this.benchmarkExecutor.runExperiment(load, lastLowestResource)) {
resourcesToCheck = resources.subList(0, startIndex).reversed()
if(resourcesToCheck.isEmpty()) return lastLowestResource
var currentMin : Resource = lastLowestResource
for (res in resourcesToCheck) {
logger.info { "Running experiment with load '${load.get()}' and resources '${res.get()}'" }
if (this.benchmarkExecutor.runExperiment(load, res)) {
currentMin = res
}
}
return currentMin
}
else {
if (resources.size <= startIndex + 1) {
logger.info{ "No more resources left to check." }
return null
}
resourcesToCheck = resources.subList(startIndex + 1, resources.size)
for (res in resourcesToCheck) {
logger.info { "Running experiment with load '${load.get()}' and resources '${res.get()}'" }
if (this.benchmarkExecutor.runExperiment(load, res)) return res
}
}
}
else {
logger.info { "InitialGuessSearchStrategy called without lastLowestResource value, which is needed as a " +
"starting point!" }
}
return null
}
}
\ No newline at end of file
...@@ -14,12 +14,18 @@ private val logger = KotlinLogging.logger {} ...@@ -14,12 +14,18 @@ private val logger = KotlinLogging.logger {}
*/ */
class LinearSearch(benchmarkExecutor: BenchmarkExecutor) : SearchStrategy(benchmarkExecutor) { class LinearSearch(benchmarkExecutor: BenchmarkExecutor) : SearchStrategy(benchmarkExecutor) {
override fun findSuitableResource(load: LoadDimension, resources: List<Resource>): Resource? { override fun findSuitableResource(load: LoadDimension, resources: List<Resource>,
lastLowestResource: Resource?): Resource? {
if (lastLowestResource != null) {
logger.info { "Running LinearSearch with a set lastLowestResource value doesn't make sense." }
}
for (res in resources) { for (res in resources) {
logger.info { "Running experiment with load '${load.get()}' and resources '${res.get()}'" } logger.info { "Running experiment with load '${load.get()}' and resources '${res.get()}'" }
if (this.benchmarkExecutor.runExperiment(load, res)) return res if (this.benchmarkExecutor.runExperiment(load, res)) return res
} }
return null return null
} }
} }
...@@ -20,5 +20,5 @@ abstract class SearchStrategy(val benchmarkExecutor: BenchmarkExecutor) { ...@@ -20,5 +20,5 @@ abstract class SearchStrategy(val benchmarkExecutor: BenchmarkExecutor) {
* *
* @return suitable resource for the specified load, or null if no suitable resource exists. * @return suitable resource for the specified load, or null if no suitable resource exists.
*/ */
abstract fun findSuitableResource(load: LoadDimension, resources: List<Resource>): Resource? abstract fun findSuitableResource(load: LoadDimension, resources: List<Resource>, lastLowestResource: Resource? = null): Resource?
} }
package theodolite
import io.quarkus.test.junit.QuarkusTest
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test
import theodolite.benchmark.BenchmarkExecution
import theodolite.strategies.searchstrategy.InitialGuessSearchStrategy
import theodolite.util.LoadDimension
import theodolite.util.Resource
import theodolite.util.Results
import mu.KotlinLogging
private val logger = KotlinLogging.logger {}
@QuarkusTest
class InitialGuessSearchStrategyTest {
@Test
fun testEnd2EndInitialGuessSearch() {
val mockResults = arrayOf(
arrayOf(true, true, true, true, true, true, true),
arrayOf(false, false, true, true, true, true, true),
arrayOf(false, false, true, true, true, true, true),
arrayOf(false, false, false, true, true, true, true),
arrayOf(false, false, false, false, true, true, true),
arrayOf(false, false, false, false, false, false, true),
arrayOf(false, false, false, false, false, false, false)
)
val mockLoads: List<LoadDimension> = (0..6).map { number -> LoadDimension(number, emptyList()) }
val mockResources: List<Resource> = (0..6).map { number -> Resource(number, emptyList()) }
val results = Results()
val benchmark = TestBenchmark()
val sloChecker: BenchmarkExecution.Slo = BenchmarkExecution.Slo()
val benchmarkExecutor = TestBenchmarkExecutorImpl(mockResults, benchmark, results, sloChecker, 0, 0, 5)
val strategy = InitialGuessSearchStrategy(benchmarkExecutor)
val actual: ArrayList<Resource?> = ArrayList()
val expected: ArrayList<Resource?> = ArrayList(listOf(0, 2, 2, 3, 4, 6).map { x -> Resource(x, emptyList()) })
expected.add(null)
var currentResource : Resource? = mockResources[0]
for (load in mockLoads) {
val returnVal : Resource? = strategy.findSuitableResource(load, mockResources, currentResource)
if(returnVal != null) {
logger.info { "returnVal '${returnVal.get()}'" }
}
else {
logger.info { "returnVal is null." }
}
actual.add(returnVal)
currentResource = returnVal
}
assertEquals(actual, expected)
}
@Test
fun testEnd2EndInitialGuessSearchLowerResourceDemandHigherLoad() {
val mockResults = arrayOf(
arrayOf(true, true, true, true, true, true, true),
arrayOf(false, false, true, true, true, true, true),
arrayOf(false, false, true, true, true, true, true),
arrayOf(false, true, true, true, true, true, true),
arrayOf(false, false, false, false, true, true, true),
arrayOf(false, false, false, false, false, false, true),
arrayOf(false, false, false, false, false, false, false)
)
val mockLoads: List<LoadDimension> = (0..6).map { number -> LoadDimension(number, emptyList()) }
val mockResources: List<Resource> = (0..6).map { number -> Resource(number, emptyList()) }
val results = Results()
val benchmark = TestBenchmark()
val sloChecker: BenchmarkExecution.Slo = BenchmarkExecution.Slo()
val benchmarkExecutor = TestBenchmarkExecutorImpl(mockResults, benchmark, results, sloChecker, 0, 0, 5)
val strategy = InitialGuessSearchStrategy(benchmarkExecutor)
val actual: ArrayList<Resource?> = ArrayList()
val expected: ArrayList<Resource?> = ArrayList(listOf(0, 2, 2, 1, 4, 6).map { x -> Resource(x, emptyList()) })
expected.add(null)
var currentResource : Resource? = mockResources[0]
for (load in mockLoads) {
val returnVal : Resource? = strategy.findSuitableResource(load, mockResources, currentResource)
if(returnVal != null) {
logger.info { "returnVal '${returnVal.get()}'" }
}
else {
logger.info { "returnVal is null." }
}
actual.add(returnVal)
currentResource = returnVal
}
assertEquals(actual, expected)
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment