Skip to content
Snippets Groups Projects
Commit 247966a3 authored by Julia Rossow's avatar Julia Rossow Committed by Sören Henning
Browse files

New strategy InitialGuessSearchStrategy

parent 150f9fa1
No related branches found
No related tags found
1 merge request!210Add "Initial Guess" Search Strategy
...@@ -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.
Finish editing this message first!
Please register or to comment