summaryrefslogtreecommitdiff
path: root/opendc-faas/opendc-faas-simulator
diff options
context:
space:
mode:
Diffstat (limited to 'opendc-faas/opendc-faas-simulator')
-rw-r--r--opendc-faas/opendc-faas-simulator/build.gradle.kts2
-rw-r--r--opendc-faas/opendc-faas-simulator/src/main/kotlin/org/opendc/faas/simulator/SimFunctionDeployer.kt69
-rw-r--r--opendc-faas/opendc-faas-simulator/src/main/kotlin/org/opendc/faas/simulator/delay/ColdStartModel.kt2
-rw-r--r--opendc-faas/opendc-faas-simulator/src/test/kotlin/org/opendc/faas/simulator/SimFaaSServiceTest.kt80
4 files changed, 82 insertions, 71 deletions
diff --git a/opendc-faas/opendc-faas-simulator/build.gradle.kts b/opendc-faas/opendc-faas-simulator/build.gradle.kts
index 5f8c8667..20374324 100644
--- a/opendc-faas/opendc-faas-simulator/build.gradle.kts
+++ b/opendc-faas/opendc-faas-simulator/build.gradle.kts
@@ -22,7 +22,7 @@
description = "Simulator for the OpenDC FaaS platform"
-/* Build configuration */
+// Build configuration
plugins {
`kotlin-library-conventions`
}
diff --git a/opendc-faas/opendc-faas-simulator/src/main/kotlin/org/opendc/faas/simulator/SimFunctionDeployer.kt b/opendc-faas/opendc-faas-simulator/src/main/kotlin/org/opendc/faas/simulator/SimFunctionDeployer.kt
index 47b4d4fa..c81dc523 100644
--- a/opendc-faas/opendc-faas-simulator/src/main/kotlin/org/opendc/faas/simulator/SimFunctionDeployer.kt
+++ b/opendc-faas/opendc-faas-simulator/src/main/kotlin/org/opendc/faas/simulator/SimFunctionDeployer.kt
@@ -58,14 +58,17 @@ public class SimFunctionDeployer(
private val dispatcher: Dispatcher,
private val model: MachineModel,
private val delayInjector: DelayInjector,
- private val mapper: SimFaaSWorkloadMapper = SimMetaFaaSWorkloadMapper()
+ private val mapper: SimFaaSWorkloadMapper = SimMetaFaaSWorkloadMapper(),
) : FunctionDeployer, AutoCloseable {
/**
* The [CoroutineScope] of this deployer.
*/
private val scope = CoroutineScope(dispatcher.asCoroutineDispatcher() + Job())
- override fun deploy(function: FunctionObject, listener: FunctionInstanceListener): Instance {
+ override fun deploy(
+ function: FunctionObject,
+ listener: FunctionInstanceListener,
+ ): Instance {
val instance = Instance(function, listener)
instance.start()
return instance
@@ -84,10 +87,11 @@ public class SimFunctionDeployer(
/**
* The machine that will execute the workloads.
*/
- public val machine: SimMachine = SimBareMetalMachine.create(
- FlowEngine.create(dispatcher).newGraph(),
- model
- )
+ public val machine: SimMachine =
+ SimBareMetalMachine.create(
+ FlowEngine.create(dispatcher).newGraph(),
+ model,
+ )
/**
* The job associated with the lifecycle of the instance.
@@ -134,38 +138,39 @@ public class SimFunctionDeployer(
*/
internal fun start() {
check(state == FunctionInstanceState.Provisioning) { "Invalid state of function instance" }
- job = scope.launch {
- delay(delayInjector.getColdStartDelay(this@Instance))
-
- launch {
- try {
- machine.runWorkload(workload)
- } finally {
- state = FunctionInstanceState.Deleted
- }
- }
+ job =
+ scope.launch {
+ delay(delayInjector.getColdStartDelay(this@Instance))
- while (isActive) {
- if (queue.isEmpty()) {
- chan.receive()
+ launch {
+ try {
+ machine.runWorkload(workload)
+ } finally {
+ state = FunctionInstanceState.Deleted
+ }
}
- state = FunctionInstanceState.Active
- while (queue.isNotEmpty()) {
- val request = queue.poll()
- try {
- workload.invoke()
- request.cont.resume(Unit)
- } catch (cause: CancellationException) {
- request.cont.resumeWithException(cause)
- throw cause
- } catch (cause: Throwable) {
- request.cont.resumeWithException(cause)
+ while (isActive) {
+ if (queue.isEmpty()) {
+ chan.receive()
+ }
+
+ state = FunctionInstanceState.Active
+ while (queue.isNotEmpty()) {
+ val request = queue.poll()
+ try {
+ workload.invoke()
+ request.cont.resume(Unit)
+ } catch (cause: CancellationException) {
+ request.cont.resumeWithException(cause)
+ throw cause
+ } catch (cause: Throwable) {
+ request.cont.resumeWithException(cause)
+ }
}
+ state = FunctionInstanceState.Idle
}
- state = FunctionInstanceState.Idle
}
- }
}
/**
diff --git a/opendc-faas/opendc-faas-simulator/src/main/kotlin/org/opendc/faas/simulator/delay/ColdStartModel.kt b/opendc-faas/opendc-faas-simulator/src/main/kotlin/org/opendc/faas/simulator/delay/ColdStartModel.kt
index 624067be..f5035ca2 100644
--- a/opendc-faas/opendc-faas-simulator/src/main/kotlin/org/opendc/faas/simulator/delay/ColdStartModel.kt
+++ b/opendc-faas/opendc-faas-simulator/src/main/kotlin/org/opendc/faas/simulator/delay/ColdStartModel.kt
@@ -60,7 +60,7 @@ public enum class ColdStartModel {
else -> Pair(0.0, 1.0)
}
}
- };
+ }, ;
/**
* Obtain the stochastic parameters for the cold start models.
diff --git a/opendc-faas/opendc-faas-simulator/src/test/kotlin/org/opendc/faas/simulator/SimFaaSServiceTest.kt b/opendc-faas/opendc-faas-simulator/src/test/kotlin/org/opendc/faas/simulator/SimFaaSServiceTest.kt
index ee9114b5..f68860e3 100644
--- a/opendc-faas/opendc-faas-simulator/src/test/kotlin/org/opendc/faas/simulator/SimFaaSServiceTest.kt
+++ b/opendc-faas/opendc-faas-simulator/src/test/kotlin/org/opendc/faas/simulator/SimFaaSServiceTest.kt
@@ -50,57 +50,63 @@ import java.util.Random
* A test suite for the [FaaSService] implementation under simulated conditions.
*/
internal class SimFaaSServiceTest {
-
private lateinit var machineModel: MachineModel
@BeforeEach
fun setUp() {
val cpuNode = ProcessingNode("Intel", "Xeon", "amd64", 2)
- machineModel = MachineModel(
- /*cpus*/ List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 1000.0) },
- /*memory*/ List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) }
- )
+ machineModel =
+ MachineModel(
+ List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 1000.0) },
+ List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) },
+ )
}
@Test
- fun testSmoke() = runSimulation {
- val random = Random(0)
- val workload = spyk(object : SimFaaSWorkload, SimWorkload by SimWorkloads.runtime(1000, 1.0) {
- override suspend fun invoke() {
- delay(random.nextInt(1000).toLong())
- }
- })
+ fun testSmoke() =
+ runSimulation {
+ val random = Random(0)
+ val workload =
+ spyk(
+ object : SimFaaSWorkload, SimWorkload by SimWorkloads.runtime(1000, 1.0) {
+ override suspend fun invoke() {
+ delay(random.nextInt(1000).toLong())
+ }
+ },
+ )
- val delayInjector = StochasticDelayInjector(ColdStartModel.GOOGLE, random)
- val deployer = SimFunctionDeployer(dispatcher, machineModel, delayInjector) { workload }
- val service = FaaSService(
- dispatcher,
- deployer,
- RandomRoutingPolicy(),
- FunctionTerminationPolicyFixed(dispatcher, timeout = Duration.ofMillis(10000))
- )
+ val delayInjector = StochasticDelayInjector(ColdStartModel.GOOGLE, random)
+ val deployer = SimFunctionDeployer(dispatcher, machineModel, delayInjector) { workload }
+ val service =
+ FaaSService(
+ dispatcher,
+ deployer,
+ RandomRoutingPolicy(),
+ FunctionTerminationPolicyFixed(dispatcher, timeout = Duration.ofMillis(10000)),
+ )
- val client = service.newClient()
+ val client = service.newClient()
- val function = client.newFunction("test", 128)
- function.invoke()
- delay(2000)
+ val function = client.newFunction("test", 128)
+ function.invoke()
+ delay(2000)
- service.close()
- deployer.close()
+ service.close()
+ deployer.close()
- yield()
+ yield()
- val funcStats = service.getFunctionStats(function)
+ val funcStats = service.getFunctionStats(function)
- assertAll(
- { coVerify { workload.invoke() } },
- { assertEquals(1, funcStats.totalInvocations) },
- { assertEquals(1, funcStats.delayedInvocations) },
- { assertEquals(0, funcStats.failedInvocations) },
- { assertEquals(0.0, funcStats.waitTime.mean) }, // fixme: this is probably wrong, and should be 100
- { assertEquals(1285.0, funcStats.activeTime.mean) }
- )
- }
+ // fixme: waitTime is probably wrong, and should be 100
+ assertAll(
+ { coVerify { workload.invoke() } },
+ { assertEquals(1, funcStats.totalInvocations) },
+ { assertEquals(1, funcStats.delayedInvocations) },
+ { assertEquals(0, funcStats.failedInvocations) },
+ { assertEquals(0.0, funcStats.waitTime.mean) },
+ { assertEquals(1285.0, funcStats.activeTime.mean) },
+ )
+ }
}