summaryrefslogtreecommitdiff
path: root/opendc-experiments/opendc-experiments-faas/src/main/kotlin
diff options
context:
space:
mode:
authorFabian Mastenbroek <mail.fabianm@gmail.com>2022-09-28 16:21:09 +0200
committerFabian Mastenbroek <mail.fabianm@gmail.com>2022-10-03 17:35:59 +0200
commit4010d0cfb49bb8a0ffdb2c3ac26fc0c8417a0bbf (patch)
tree9f287e56e503a2b98472790c1a3373149af53d85 /opendc-experiments/opendc-experiments-faas/src/main/kotlin
parentc453e27abe54221f76648bc91edadb2efcd1ec07 (diff)
feat(exp/faas): Add provisioners for FaaS service
This change adds a new module `opendc-experiments-faas` that provides provisioner implementations for experiments to use for setting up the FaaS service of OpenDC.
Diffstat (limited to 'opendc-experiments/opendc-experiments-faas/src/main/kotlin')
-rw-r--r--opendc-experiments/opendc-experiments-faas/src/main/kotlin/org/opendc/experiments/faas/FaaSServiceProvisioningStep.kt71
-rw-r--r--opendc-experiments/opendc-experiments-faas/src/main/kotlin/org/opendc/experiments/faas/FaaSSteps.kt51
-rw-r--r--opendc-experiments/opendc-experiments-faas/src/main/kotlin/org/opendc/experiments/faas/FunctionSample.kt44
-rw-r--r--opendc-experiments/opendc-experiments-faas/src/main/kotlin/org/opendc/experiments/faas/FunctionTrace.kt28
-rw-r--r--opendc-experiments/opendc-experiments-faas/src/main/kotlin/org/opendc/experiments/faas/FunctionTraceWorkload.kt37
-rw-r--r--opendc-experiments/opendc-experiments-faas/src/main/kotlin/org/opendc/experiments/faas/ServerlessTraceReader.kt136
-rw-r--r--opendc-experiments/opendc-experiments-faas/src/main/kotlin/org/opendc/experiments/faas/TraceHelpers.kt71
7 files changed, 438 insertions, 0 deletions
diff --git a/opendc-experiments/opendc-experiments-faas/src/main/kotlin/org/opendc/experiments/faas/FaaSServiceProvisioningStep.kt b/opendc-experiments/opendc-experiments-faas/src/main/kotlin/org/opendc/experiments/faas/FaaSServiceProvisioningStep.kt
new file mode 100644
index 00000000..d977042e
--- /dev/null
+++ b/opendc-experiments/opendc-experiments-faas/src/main/kotlin/org/opendc/experiments/faas/FaaSServiceProvisioningStep.kt
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2022 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.experiments.faas
+
+import org.opendc.experiments.provisioner.ProvisioningContext
+import org.opendc.experiments.provisioner.ProvisioningStep
+import org.opendc.faas.service.FaaSService
+import org.opendc.faas.service.autoscaler.FunctionTerminationPolicy
+import org.opendc.faas.service.router.RoutingPolicy
+import org.opendc.faas.simulator.SimFunctionDeployer
+import org.opendc.faas.simulator.delay.ColdStartModel
+import org.opendc.faas.simulator.delay.StochasticDelayInjector
+import org.opendc.faas.simulator.delay.ZeroDelayInjector
+import org.opendc.simulator.compute.model.MachineModel
+import java.util.*
+
+/**
+ * A [ProvisioningStep] implementation for a [FaaSService].
+ *
+ * @param serviceDomain The domain name under which to register the compute service.
+ * @param routingPolicy The routing policy to use.
+ * @param terminationPolicy The function termination policy to use.
+ * @param machineModel The [MachineModel] that models the physical machine on which the functions run.
+ * @param coldStartModel The cold start models to test.
+ */
+public class FaaSServiceProvisioningStep internal constructor(
+ private val serviceDomain: String,
+ private val routingPolicy: (ProvisioningContext) -> RoutingPolicy,
+ private val terminationPolicy: (ProvisioningContext) -> FunctionTerminationPolicy,
+ private val machineModel: MachineModel,
+ private val coldStartModel: ColdStartModel?
+) : ProvisioningStep {
+ override fun apply(ctx: ProvisioningContext): AutoCloseable {
+ val delayInjector = if (coldStartModel != null)
+ StochasticDelayInjector(coldStartModel, Random(ctx.seeder.nextLong()))
+ else
+ ZeroDelayInjector
+ val deployer = SimFunctionDeployer(ctx.coroutineContext, ctx.clock, machineModel, delayInjector)
+ val service = FaaSService(
+ ctx.coroutineContext,
+ ctx.clock,
+ deployer,
+ routingPolicy(ctx),
+ terminationPolicy(ctx)
+ )
+
+ ctx.registry.register(serviceDomain, FaaSService::class.java, service)
+
+ return AutoCloseable { service.close() }
+ }
+}
diff --git a/opendc-experiments/opendc-experiments-faas/src/main/kotlin/org/opendc/experiments/faas/FaaSSteps.kt b/opendc-experiments/opendc-experiments-faas/src/main/kotlin/org/opendc/experiments/faas/FaaSSteps.kt
new file mode 100644
index 00000000..40e5627b
--- /dev/null
+++ b/opendc-experiments/opendc-experiments-faas/src/main/kotlin/org/opendc/experiments/faas/FaaSSteps.kt
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2022 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+@file:JvmName("FaaSSteps")
+package org.opendc.experiments.faas
+
+import org.opendc.experiments.provisioner.ProvisioningContext
+import org.opendc.experiments.provisioner.ProvisioningStep
+import org.opendc.faas.service.FaaSService
+import org.opendc.faas.service.autoscaler.FunctionTerminationPolicy
+import org.opendc.faas.service.router.RoutingPolicy
+import org.opendc.faas.simulator.delay.ColdStartModel
+import org.opendc.simulator.compute.model.MachineModel
+
+/**
+ * Return a [ProvisioningStep] that sets up a [FaaSService].
+ *
+ * @param serviceDomain The domain name under which to register the compute service.
+ * @param routingPolicy The routing policy to use.
+ * @param terminationPolicy The function termination policy to use.
+ * @param machineModel The [MachineModel] that models the physical machine on which the functions run.
+ * @param coldStartModel The cold start models to test.
+ */
+public fun setupFaaSService(
+ serviceDomain: String,
+ routingPolicy: (ProvisioningContext) -> RoutingPolicy,
+ terminationPolicy: (ProvisioningContext) -> FunctionTerminationPolicy,
+ machineModel: MachineModel,
+ coldStartModel: ColdStartModel? = null
+): ProvisioningStep {
+ return FaaSServiceProvisioningStep(serviceDomain, routingPolicy, terminationPolicy, machineModel, coldStartModel)
+}
diff --git a/opendc-experiments/opendc-experiments-faas/src/main/kotlin/org/opendc/experiments/faas/FunctionSample.kt b/opendc-experiments/opendc-experiments-faas/src/main/kotlin/org/opendc/experiments/faas/FunctionSample.kt
new file mode 100644
index 00000000..4ce2b136
--- /dev/null
+++ b/opendc-experiments/opendc-experiments-faas/src/main/kotlin/org/opendc/experiments/faas/FunctionSample.kt
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2021 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.experiments.faas
+
+/**
+ * A sample of a single function.
+ *
+ * @param timestamp The timestamp of the function.
+ * @param duration The average execution time of the function.
+ * @param invocations The number of invocations.
+ * @param provisionedCpu The provisioned CPU for this function in MHz.
+ * @param provisionedMem The amount of memory provisioned for this function in MB.
+ * @param cpuUsage The actual CPU usage in MHz.
+ * @param memUsage The actual memory usage in MB.
+ */
+public data class FunctionSample(
+ val timestamp: Long,
+ val duration: Long,
+ val invocations: Int,
+ val provisionedCpu: Int,
+ val provisionedMem: Int,
+ val cpuUsage: Double,
+ val memUsage: Double
+)
diff --git a/opendc-experiments/opendc-experiments-faas/src/main/kotlin/org/opendc/experiments/faas/FunctionTrace.kt b/opendc-experiments/opendc-experiments-faas/src/main/kotlin/org/opendc/experiments/faas/FunctionTrace.kt
new file mode 100644
index 00000000..5268811c
--- /dev/null
+++ b/opendc-experiments/opendc-experiments-faas/src/main/kotlin/org/opendc/experiments/faas/FunctionTrace.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2022 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.experiments.faas
+
+/**
+ * A trace for a single function
+ */
+public data class FunctionTrace(val id: String, val maxMemory: Int, val samples: List<FunctionSample>)
diff --git a/opendc-experiments/opendc-experiments-faas/src/main/kotlin/org/opendc/experiments/faas/FunctionTraceWorkload.kt b/opendc-experiments/opendc-experiments-faas/src/main/kotlin/org/opendc/experiments/faas/FunctionTraceWorkload.kt
new file mode 100644
index 00000000..90e76dac
--- /dev/null
+++ b/opendc-experiments/opendc-experiments-faas/src/main/kotlin/org/opendc/experiments/faas/FunctionTraceWorkload.kt
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2022 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.experiments.faas
+
+import org.opendc.faas.simulator.workload.SimFaaSWorkload
+import org.opendc.simulator.compute.workload.SimTrace
+import org.opendc.simulator.compute.workload.SimTraceFragment
+import org.opendc.simulator.compute.workload.SimTraceWorkload
+import org.opendc.simulator.compute.workload.SimWorkload
+
+/**
+ * A [SimFaaSWorkload] for a [FunctionTrace].
+ */
+public class FunctionTraceWorkload(trace: FunctionTrace) :
+ SimFaaSWorkload, SimWorkload by SimTraceWorkload(SimTrace.ofFragments(trace.samples.map { SimTraceFragment(it.timestamp, it.duration, it.cpuUsage, 1) })) {
+ override suspend fun invoke() {}
+}
diff --git a/opendc-experiments/opendc-experiments-faas/src/main/kotlin/org/opendc/experiments/faas/ServerlessTraceReader.kt b/opendc-experiments/opendc-experiments-faas/src/main/kotlin/org/opendc/experiments/faas/ServerlessTraceReader.kt
new file mode 100644
index 00000000..7b6b3ef7
--- /dev/null
+++ b/opendc-experiments/opendc-experiments-faas/src/main/kotlin/org/opendc/experiments/faas/ServerlessTraceReader.kt
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2022 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.experiments.faas
+
+import com.fasterxml.jackson.core.JsonToken
+import com.fasterxml.jackson.dataformat.csv.CsvFactory
+import com.fasterxml.jackson.dataformat.csv.CsvParser
+import com.fasterxml.jackson.dataformat.csv.CsvSchema
+import mu.KotlinLogging
+import java.io.File
+import kotlin.math.max
+
+/**
+ * A trace reader for the serverless workload trace used in the OpenDC Serverless thesis.
+ */
+public class ServerlessTraceReader {
+ /**
+ * The logger for this trace reader instance.
+ */
+ private val logger = KotlinLogging.logger {}
+
+ /**
+ * The [CsvFactory] used to create the parser.
+ */
+ private val factory = CsvFactory()
+ .enable(CsvParser.Feature.ALLOW_COMMENTS)
+ .enable(CsvParser.Feature.TRIM_SPACES)
+
+ /**
+ * Parse the traces at the specified [path].
+ */
+ public fun parse(path: File): List<FunctionTrace> {
+ return if (path.isFile) {
+ listOf(parseSingle(path))
+ } else {
+ path.walk()
+ .filterNot { it.isDirectory }
+ .sorted()
+ .map { file ->
+ logger.info { "Parsing $file" }
+ parseSingle(file)
+ }
+ .toList()
+ }
+ }
+
+ /**
+ * Parse a single trace.
+ */
+ private fun parseSingle(path: File): FunctionTrace {
+ val samples = mutableListOf<FunctionSample>()
+
+ val parser = factory.createParser(path)
+ parser.schema = schema
+
+ var id = ""
+ var timestamp = 0L
+ var invocations = 0
+ var execTime = 0L
+ var provisionedCpu = 0
+ var provisionedMem = 0
+ var cpuUsage = 0.0
+ var memUsage = 0.0
+ var maxMemory = 0
+
+ while (!parser.isClosed) {
+ val token = parser.nextValue()
+ if (token == JsonToken.END_OBJECT) {
+ maxMemory = max(maxMemory, provisionedMem)
+ samples.add(FunctionSample(timestamp, execTime, invocations, provisionedCpu, provisionedMem, cpuUsage, memUsage))
+
+ id = ""
+ timestamp = 0
+ invocations = 0
+ execTime = 0
+ provisionedCpu = 0
+ provisionedMem = 0
+ cpuUsage = 0.0
+ memUsage = 0.0
+
+ continue
+ }
+
+ when (parser.currentName) {
+ "Timestamp [ms]" -> timestamp = parser.valueAsLong
+ "Invocations" -> invocations = parser.valueAsInt
+ "Avg Exec time per Invocation" -> execTime = parser.valueAsLong
+ "Provisioned CPU [Mhz]" -> provisionedCpu = parser.valueAsInt
+ "Provisioned Memory [mb]" -> provisionedMem = parser.valueAsInt
+ "Avg cpu usage per Invocation [Mhz]" -> cpuUsage = parser.valueAsDouble
+ "Avg mem usage per Invocation [mb]" -> memUsage = parser.valueAsDouble
+ "name" -> id = parser.text
+ }
+ }
+
+ return FunctionTrace(id, maxMemory, samples)
+ }
+
+ private companion object {
+ /**
+ * The [CsvSchema] that is used to parse the trace.
+ */
+ val schema = CsvSchema.builder()
+ .addColumn("Timestamp [ms]", CsvSchema.ColumnType.NUMBER)
+ .addColumn("Invocations", CsvSchema.ColumnType.NUMBER)
+ .addColumn("Avg Exec time per Invocation", CsvSchema.ColumnType.NUMBER)
+ .addColumn("Provisioned CPU [Mhz]", CsvSchema.ColumnType.NUMBER)
+ .addColumn("Provisioned Memory [mb]", CsvSchema.ColumnType.NUMBER)
+ .addColumn("Avg cpu usage per Invocation [Mhz]", CsvSchema.ColumnType.NUMBER)
+ .addColumn("Avg mem usage per Invocation [mb]", CsvSchema.ColumnType.NUMBER)
+ .addColumn("name", CsvSchema.ColumnType.STRING)
+ .setAllowComments(true)
+ .setUseHeader(true)
+ .build()
+ }
+}
diff --git a/opendc-experiments/opendc-experiments-faas/src/main/kotlin/org/opendc/experiments/faas/TraceHelpers.kt b/opendc-experiments/opendc-experiments-faas/src/main/kotlin/org/opendc/experiments/faas/TraceHelpers.kt
new file mode 100644
index 00000000..cf278606
--- /dev/null
+++ b/opendc-experiments/opendc-experiments-faas/src/main/kotlin/org/opendc/experiments/faas/TraceHelpers.kt
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2022 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+@file:JvmName("TraceHelpers")
+package org.opendc.experiments.faas
+
+import kotlinx.coroutines.coroutineScope
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
+import org.opendc.faas.service.FaaSService
+import java.time.Clock
+import kotlin.math.max
+
+/**
+ * Run a simulation of the [FaaSService] by replaying the workload trace given by [trace].
+ *
+ * @param clock A [Clock] instance tracking simulation time.
+ * @param trace The trace to simulate.
+ */
+public suspend fun FaaSService.replay(clock: Clock, trace: List<FunctionTrace>) {
+ val client = newClient()
+ try {
+ coroutineScope {
+ for (entry in trace) {
+ launch {
+ val workload = FunctionTraceWorkload(entry)
+ val function = client.newFunction(entry.id, entry.maxMemory.toLong(), meta = mapOf("workload" to workload))
+
+ var offset = Long.MIN_VALUE
+
+ for (sample in entry.samples) {
+ if (sample.invocations == 0) {
+ continue
+ }
+
+ if (offset < 0) {
+ offset = sample.timestamp - clock.millis()
+ }
+
+ delay(max(0, (sample.timestamp - offset) - clock.millis()))
+
+ repeat(sample.invocations) {
+ function.invoke()
+ }
+ }
+ }
+ }
+ }
+ } finally {
+ client.close()
+ }
+}