diff options
| author | Dante Niewenhuis <d.niewenhuis@hotmail.com> | 2025-03-24 09:15:53 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-03-24 09:15:53 +0100 |
| commit | 24f89ae21df182bb91d92e4a60b4049829ac4d9e (patch) | |
| tree | fd74543f27aabac92a9554808aeedbb60f657b21 | |
| parent | fb7d3010d6141dd518d8ebfacd41d399c3f9758d (diff) | |
Updated AllocationPolicy input (#324)
19 files changed, 343 insertions, 135 deletions
diff --git a/opendc-compute/opendc-compute-simulator/src/main/java/org/opendc/compute/simulator/service/ComputeService.java b/opendc-compute/opendc-compute-simulator/src/main/java/org/opendc/compute/simulator/service/ComputeService.java index 0538a951..657e7f1e 100644 --- a/opendc-compute/opendc-compute-simulator/src/main/java/org/opendc/compute/simulator/service/ComputeService.java +++ b/opendc-compute/opendc-compute-simulator/src/main/java/org/opendc/compute/simulator/service/ComputeService.java @@ -413,7 +413,7 @@ public final class ComputeService implements AutoCloseable, CarbonReceiver { long now = clock.millis(); SchedulingRequest request = new SchedulingRequest(task, now); - task.launchedAt = Instant.ofEpochMilli(now); + task.scheduledAt = Instant.ofEpochMilli(now); taskQueue.add(request); tasksPending++; requestSchedulingCycle(); diff --git a/opendc-compute/opendc-compute-simulator/src/main/java/org/opendc/compute/simulator/service/ServiceTask.java b/opendc-compute/opendc-compute-simulator/src/main/java/org/opendc/compute/simulator/service/ServiceTask.java index 4d5611a8..9fb9b5f0 100644 --- a/opendc-compute/opendc-compute-simulator/src/main/java/org/opendc/compute/simulator/service/ServiceTask.java +++ b/opendc-compute/opendc-compute-simulator/src/main/java/org/opendc/compute/simulator/service/ServiceTask.java @@ -56,12 +56,12 @@ public class ServiceTask { private ServiceFlavor flavor; public Workload workload; - private Map<String, ?> meta; // TODO: remove this + private final Map<String, ?> meta; // TODO: remove this private final List<TaskWatcher> watchers = new ArrayList<>(); private TaskState state = TaskState.CREATED; - Instant launchedAt = null; - Instant createdAt; + Instant scheduledAt = null; + Instant submittedAt; Instant finishedAt; SimHost host = null; private SchedulingRequest request = null; @@ -88,7 +88,7 @@ public class ServiceTask { this.workload = workload; this.meta = meta; - this.createdAt = this.service.getClock().instant(); + this.submittedAt = this.service.getClock().instant(); } @NotNull @@ -136,13 +136,13 @@ public class ServiceTask { } @Nullable - public Instant getLaunchedAt() { - return launchedAt; + public Instant getScheduledAt() { + return scheduledAt; } @Nullable - public Instant getCreatedAt() { - return createdAt; + public Instant getSubmittedAt() { + return submittedAt; } @Nullable diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/scheduler/ComputeSchedulers.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/scheduler/ComputeSchedulers.kt index 2e4a5bf1..ecf4804a 100644 --- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/scheduler/ComputeSchedulers.kt +++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/scheduler/ComputeSchedulers.kt @@ -50,18 +50,18 @@ public enum class ComputeSchedulerEnum { TimeshiftNoPeak, } -public fun createComputeScheduler( +public fun createPrefabComputeScheduler( name: String, seeder: RandomGenerator, clock: InstantSource, ): ComputeScheduler { - return createComputeScheduler(ComputeSchedulerEnum.valueOf(name.uppercase()), seeder, clock) + return createPrefabComputeScheduler(ComputeSchedulerEnum.valueOf(name.uppercase()), seeder, clock) } /** * Create a [ComputeScheduler] for the experiment. */ -public fun createComputeScheduler( +public fun createPrefabComputeScheduler( name: ComputeSchedulerEnum, seeder: RandomGenerator, clock: InstantSource, diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/parquet/DfltHostExportColumns.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/parquet/DfltHostExportColumns.kt index 13304b47..f43f4b31 100644 --- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/parquet/DfltHostExportColumns.kt +++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/parquet/DfltHostExportColumns.kt @@ -87,12 +87,12 @@ public object DfltHostExportColumns { public val GUESTS_TERMINATED: ExportColumn<HostTableReader> = ExportColumn( field = Types.required(INT32).named("guests_terminated"), - ) { it.guestsTerminated } + ) { it.tasksTerminated } public val GUESTS_RUNNING: ExportColumn<HostTableReader> = ExportColumn( field = Types.required(INT32).named("guests_running"), - ) { it.guestsRunning } + ) { it.tasksActive } public val GUESTS_ERROR: ExportColumn<HostTableReader> = ExportColumn( @@ -169,11 +169,6 @@ public object DfltHostExportColumns { field = Types.optional(INT64).named("boot_time"), ) { it.bootTime?.toEpochMilli() } - public val BOOT_TIME_ABS: ExportColumn<HostTableReader> = - ExportColumn( - field = Types.optional(INT64).named("boot_time_absolute"), - ) { it.bootTimeAbsolute?.toEpochMilli() } - /** * The columns that are always included in the output file. */ diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/parquet/DfltTaskExportColumns.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/parquet/DfltTaskExportColumns.kt index 52a84236..8603f669 100644 --- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/parquet/DfltTaskExportColumns.kt +++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/parquet/DfltTaskExportColumns.kt @@ -142,26 +142,21 @@ public object DfltTaskExportColumns { field = Types.optional(INT64).named("provision_time"), ) { it.provisionTime?.toEpochMilli() } - public val BOOT_TIME: ExportColumn<TaskTableReader> = + public val SCHEDULE_TIME: ExportColumn<TaskTableReader> = ExportColumn( - field = Types.optional(INT64).named("boot_time"), - ) { it.bootTime?.toEpochMilli() } + field = Types.optional(INT64).named("schedule_time"), + ) { it.scheduleTime?.toEpochMilli() } - public val CREATION_TIME: ExportColumn<TaskTableReader> = + public val SUBMISSION_TIME: ExportColumn<TaskTableReader> = ExportColumn( - field = Types.optional(INT64).named("creation_time"), - ) { it.creationTime?.toEpochMilli() } + field = Types.optional(INT64).named("submission_time"), + ) { it.submissionTime?.toEpochMilli() } public val FINISH_TIME: ExportColumn<TaskTableReader> = ExportColumn( field = Types.optional(INT64).named("finish_time"), ) { it.finishTime?.toEpochMilli() } - public val BOOT_TIME_ABS: ExportColumn<TaskTableReader> = - ExportColumn( - field = Types.optional(INT64).named("boot_time_absolute"), - ) { it.bootTimeAbsolute?.toEpochMilli() } - public val TASK_STATE: ExportColumn<TaskTableReader> = ExportColumn( field = diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/host/HostTableReader.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/host/HostTableReader.kt index 1d3d46d9..53282b9f 100644 --- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/host/HostTableReader.kt +++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/host/HostTableReader.kt @@ -55,12 +55,12 @@ public interface HostTableReader : Exportable { /** * The number of guests that are in a terminated state. */ - public val guestsTerminated: Int + public val tasksTerminated: Int /** - * The number of guests that are in a running state. + * The number of guests that are active on the Host state. */ - public val guestsRunning: Int + public val tasksActive: Int /** * The number of guests that are in an error state. @@ -136,9 +136,4 @@ public interface HostTableReader : Exportable { * The [Instant] at which the host booted relative to the start of the workload. */ public val bootTime: Instant? - - /** - * The [Instant] at which the host booted. - */ - public val bootTimeAbsolute: Instant? } diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/host/HostTableReaderImpl.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/host/HostTableReaderImpl.kt index 5babb864..4990f0a3 100644 --- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/host/HostTableReaderImpl.kt +++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/host/HostTableReaderImpl.kt @@ -45,8 +45,8 @@ public class HostTableReaderImpl( _timestamp = table.timestamp _timestampAbsolute = table.timestampAbsolute - _guestsTerminated = table.guestsTerminated - _guestsRunning = table.guestsRunning + _tasksTerminated = table.tasksTerminated + _tasksActive = table.tasksActive _guestsError = table.guestsError _guestsInvalid = table.guestsInvalid _cpuLimit = table.cpuLimit @@ -62,7 +62,6 @@ public class HostTableReaderImpl( _uptime = table.uptime _downtime = table.downtime _bootTime = table.bootTime - _bootTimeAbsolute = table.bootTimeAbsolute } override val hostInfo: HostInfo = @@ -83,13 +82,13 @@ public class HostTableReaderImpl( get() = _timestampAbsolute private var _timestampAbsolute = Instant.MIN - override val guestsTerminated: Int - get() = _guestsTerminated - private var _guestsTerminated = 0 + override val tasksTerminated: Int + get() = _tasksTerminated + private var _tasksTerminated = 0 - override val guestsRunning: Int - get() = _guestsRunning - private var _guestsRunning = 0 + override val tasksActive: Int + get() = _tasksActive + private var _tasksActive = 0 override val guestsError: Int get() = _guestsError @@ -158,10 +157,6 @@ public class HostTableReaderImpl( get() = _bootTime private var _bootTime: Instant? = null - override val bootTimeAbsolute: Instant? - get() = _bootTimeAbsolute - private var _bootTimeAbsolute: Instant? = null - /** * Record the next cycle. */ @@ -172,8 +167,8 @@ public class HostTableReaderImpl( _timestamp = now _timestampAbsolute = now + startTime - _guestsTerminated = hostSysStats.guestsTerminated - _guestsRunning = hostSysStats.guestsRunning + _tasksTerminated = hostSysStats.guestsTerminated + _tasksActive = hostSysStats.guestsRunning _guestsError = hostSysStats.guestsError _guestsInvalid = hostSysStats.guestsInvalid _cpuLimit = hostCpuStats.capacity @@ -205,8 +200,8 @@ public class HostTableReaderImpl( previousUptime = _uptime previousDowntime = _downtime - _guestsTerminated = 0 - _guestsRunning = 0 + _tasksTerminated = 0 + _tasksActive = 0 _guestsError = 0 _guestsInvalid = 0 diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/task/TaskTableReader.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/task/TaskTableReader.kt index 97d8ca88..85e030aa 100644 --- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/task/TaskTableReader.kt +++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/task/TaskTableReader.kt @@ -76,19 +76,14 @@ public interface TaskTableReader : Exportable { public val provisionTime: Instant? /** - * The [Instant] at which the task booted relative to the start of the workload. + * The [Instant] at which the task was scheduled relative to the start of the workload. */ - public val bootTime: Instant? + public val scheduleTime: Instant? /** - * The [Instant] at which the task booted. - */ - public val bootTimeAbsolute: Instant? - - /** - * The [Instant] at which the task booted relative to the start of the workload. + * The [Instant] at which the task was submitted relative to the start of the workload. */ - public val creationTime: Instant? + public val submissionTime: Instant? /** * The [Instant] at which the task booted relative to the start of the workload. diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/task/TaskTableReaderImpl.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/task/TaskTableReaderImpl.kt index 07462b14..d8c6a06e 100644 --- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/task/TaskTableReaderImpl.kt +++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/task/TaskTableReaderImpl.kt @@ -65,10 +65,9 @@ public class TaskTableReaderImpl( _uptime = table.uptime _downtime = table.downtime _provisionTime = table.provisionTime - _bootTime = table.bootTime - _bootTimeAbsolute = table.bootTimeAbsolute + _scheduleTime = table.scheduleTime - _creationTime = table.creationTime + _submissionTime = table.submissionTime _finishTime = table.finishTime _taskState = table.taskState @@ -115,13 +114,13 @@ public class TaskTableReaderImpl( get() = _provisionTime private var _provisionTime: Instant? = null - override val bootTime: Instant? - get() = _bootTime - private var _bootTime: Instant? = null + override val scheduleTime: Instant? + get() = _scheduleTime + private var _scheduleTime: Instant? = null - override val creationTime: Instant? - get() = _creationTime - private var _creationTime: Instant? = null + override val submissionTime: Instant? + get() = _submissionTime + private var _submissionTime: Instant? = null override val finishTime: Instant? get() = _finishTime @@ -159,10 +158,6 @@ public class TaskTableReaderImpl( private var _cpuLostTime = 0L private var previousCpuLostTime = 0L - override val bootTimeAbsolute: Instant? - get() = _bootTimeAbsolute - private var _bootTimeAbsolute: Instant? = null - override val taskState: TaskState? get() = _taskState private var _taskState: TaskState? = null @@ -200,18 +195,12 @@ public class TaskTableReaderImpl( _cpuLostTime = cpuStats?.lostTime ?: _cpuLostTime _uptime = sysStats?.uptime?.toMillis() ?: _uptime _downtime = sysStats?.downtime?.toMillis() ?: _downtime - _provisionTime = task.launchedAt - _bootTime = sysStats?.bootTime ?: _bootTime - _creationTime = task.createdAt + _provisionTime = task.scheduledAt + _scheduleTime = sysStats?.bootTime ?: _scheduleTime + _submissionTime = task.submittedAt _finishTime = task.finishedAt _taskState = task.state - - if (sysStats != null) { - _bootTimeAbsolute = sysStats.bootTime + startTime - } else { - _bootTimeAbsolute = null - } } /** diff --git a/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/experiment/Scenario.kt b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/experiment/Scenario.kt index 64ff51ad..06b7b89d 100644 --- a/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/experiment/Scenario.kt +++ b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/experiment/Scenario.kt @@ -22,12 +22,12 @@ package org.opendc.experiments.base.experiment -import org.opendc.experiments.base.experiment.specs.AllocationPolicySpec import org.opendc.experiments.base.experiment.specs.CheckpointModelSpec import org.opendc.experiments.base.experiment.specs.ExportModelSpec import org.opendc.experiments.base.experiment.specs.FailureModelSpec import org.opendc.experiments.base.experiment.specs.ScenarioTopologySpec import org.opendc.experiments.base.experiment.specs.WorkloadSpec +import org.opendc.experiments.base.experiment.specs.allocation.AllocationPolicySpec /** * A data class representing a scenario for a set of experiments. diff --git a/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/experiment/specs/AllocationPolicySpec.kt b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/experiment/specs/AllocationPolicySpec.kt deleted file mode 100644 index 0bd3d476..00000000 --- a/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/experiment/specs/AllocationPolicySpec.kt +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2024 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.base.experiment.specs - -import kotlinx.serialization.Serializable -import org.opendc.compute.simulator.scheduler.ComputeSchedulerEnum - -/** - * specification describing how tasks are allocated - * - * @property policyType - * - * TODO: expand with more variables such as allowed over-subscription - */ -@Serializable -public data class AllocationPolicySpec( - val policyType: ComputeSchedulerEnum = ComputeSchedulerEnum.Mem, -) { - public val name: String = policyType.toString() -} diff --git a/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/experiment/specs/ExperimentSpec.kt b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/experiment/specs/ExperimentSpec.kt index 91d0b986..df0a862d 100644 --- a/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/experiment/specs/ExperimentSpec.kt +++ b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/experiment/specs/ExperimentSpec.kt @@ -25,7 +25,10 @@ package org.opendc.experiments.base.experiment.specs import kotlinx.serialization.Serializable import org.opendc.common.logger.infoNewLine import org.opendc.common.logger.logger +import org.opendc.compute.simulator.scheduler.ComputeSchedulerEnum import org.opendc.compute.simulator.telemetry.parquet.ComputeExportConfig +import org.opendc.experiments.base.experiment.specs.allocation.AllocationPolicySpec +import org.opendc.experiments.base.experiment.specs.allocation.PrefabAllocationPolicySpec import java.util.UUID /** @@ -55,7 +58,7 @@ public data class ExperimentSpec( val maxNumFailures: Set<Int> = setOf(10), val topologies: Set<ScenarioTopologySpec>, val workloads: Set<WorkloadSpec>, - val allocationPolicies: Set<AllocationPolicySpec> = setOf(AllocationPolicySpec()), + val allocationPolicies: Set<AllocationPolicySpec> = setOf(PrefabAllocationPolicySpec(ComputeSchedulerEnum.Mem)), val failureModels: Set<FailureModelSpec?> = setOf(null), val checkpointModels: Set<CheckpointModelSpec?> = setOf(null), ) { diff --git a/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/experiment/specs/ScenarioSpec.kt b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/experiment/specs/ScenarioSpec.kt index eb0d71ed..7d24c55d 100644 --- a/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/experiment/specs/ScenarioSpec.kt +++ b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/experiment/specs/ScenarioSpec.kt @@ -23,6 +23,9 @@ package org.opendc.experiments.base.experiment.specs import kotlinx.serialization.Serializable +import org.opendc.compute.simulator.scheduler.ComputeSchedulerEnum +import org.opendc.experiments.base.experiment.specs.allocation.AllocationPolicySpec +import org.opendc.experiments.base.experiment.specs.allocation.PrefabAllocationPolicySpec @Serializable public data class ScenarioSpec( @@ -31,7 +34,7 @@ public data class ScenarioSpec( val outputFolder: String = "output", val topology: ScenarioTopologySpec, val workload: WorkloadSpec, - val allocationPolicy: AllocationPolicySpec = AllocationPolicySpec(), + val allocationPolicy: AllocationPolicySpec = PrefabAllocationPolicySpec(ComputeSchedulerEnum.Mem), val exportModel: ExportModelSpec = ExportModelSpec(), val failureModel: FailureModelSpec? = null, val checkpointModel: CheckpointModelSpec? = null, diff --git a/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/experiment/specs/allocation/AllocationPolicySpec.kt b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/experiment/specs/allocation/AllocationPolicySpec.kt new file mode 100644 index 00000000..686bb84e --- /dev/null +++ b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/experiment/specs/allocation/AllocationPolicySpec.kt @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2024 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.base.experiment.specs.allocation + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import org.opendc.compute.simulator.scheduler.ComputeScheduler +import org.opendc.compute.simulator.scheduler.ComputeSchedulerEnum +import org.opendc.compute.simulator.scheduler.FilterScheduler +import org.opendc.compute.simulator.scheduler.TimeshiftScheduler +import org.opendc.compute.simulator.scheduler.createPrefabComputeScheduler +import java.time.InstantSource +import java.util.random.RandomGenerator + +/** + * specification describing how tasks are allocated + */ +@Serializable +public sealed interface AllocationPolicySpec + +@Serializable +@SerialName("prefab") +public data class PrefabAllocationPolicySpec( + val policyName: ComputeSchedulerEnum = ComputeSchedulerEnum.Mem, +) : AllocationPolicySpec { + public val name: String = policyName.toString() +} + +@Serializable +@SerialName("filter") +public data class FilterAllocationPolicySpec( + val filters: List<HostFilterSpec>, + val weighers: List<HostWeigherSpec>, + val subsetSize: Int = 1, +) : AllocationPolicySpec + +@Serializable +@SerialName("timeshift") +public data class TimeShiftAllocationPolicySpec( + val filters: List<HostFilterSpec>, + val weighers: List<HostWeigherSpec>, + val windowSize: Int = 168, + val subsetSize: Int = 1, + val peakShift: Boolean = true, +) : AllocationPolicySpec + +public fun createComputeScheduler( + spec: AllocationPolicySpec, + seeder: RandomGenerator, + clock: InstantSource, +): ComputeScheduler { + return when (spec) { + is PrefabAllocationPolicySpec -> createPrefabComputeScheduler(spec.policyName, seeder, clock) + is FilterAllocationPolicySpec -> { + val filters = spec.filters.map { createHostFilter(it) } + val weighers = spec.weighers.map { createHostWeigher(it) } + FilterScheduler(filters, weighers, spec.subsetSize, seeder) + } + is TimeShiftAllocationPolicySpec -> { + val filters = spec.filters.map { createHostFilter(it) } + val weighers = spec.weighers.map { createHostWeigher(it) } + TimeshiftScheduler(filters, weighers, spec.windowSize, clock, spec.subsetSize, spec.peakShift, seeder) + } + } +} diff --git a/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/experiment/specs/allocation/HostFilterSpec.kt b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/experiment/specs/allocation/HostFilterSpec.kt new file mode 100644 index 00000000..6a0ed2b8 --- /dev/null +++ b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/experiment/specs/allocation/HostFilterSpec.kt @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2025 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.base.experiment.specs.allocation + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import org.opendc.compute.simulator.scheduler.filters.ComputeFilter +import org.opendc.compute.simulator.scheduler.filters.DifferentHostFilter +import org.opendc.compute.simulator.scheduler.filters.HostFilter +import org.opendc.compute.simulator.scheduler.filters.InstanceCountFilter +import org.opendc.compute.simulator.scheduler.filters.RamFilter +import org.opendc.compute.simulator.scheduler.filters.SameHostFilter +import org.opendc.compute.simulator.scheduler.filters.VCpuCapacityFilter +import org.opendc.compute.simulator.scheduler.filters.VCpuFilter + +public enum class HostFilterEnum { + Compute, + DifferentHost, + InstanceCount, + Ram, + SameHost, + VCpuCapacity, + VCpu, +} + +/** + * A specification for a host filter. + * + * A host filter can be defined in a JSON file by adding the serialName as the type parameter. + * + * The user then has to specify any additional parameters required for the filter. + */ +@Serializable +public sealed class HostFilterSpec + +@Serializable +@SerialName("Compute") +public data class ComputeFilterSpec( + val filterName: HostFilterEnum = HostFilterEnum.Compute, +) : HostFilterSpec() + +@Serializable +@SerialName("DifferentHost") +public data class DifferentHostFilterSpec( + val filterName: HostFilterEnum = HostFilterEnum.DifferentHost, +) : HostFilterSpec() + +@Serializable +@SerialName("InstanceCount") +public data class InstanceCountHostFilterSpec( + val filterName: HostFilterEnum = HostFilterEnum.InstanceCount, + val limit: Int, +) : HostFilterSpec() + +@Serializable +@SerialName("Ram") +public data class RamHostFilterSpec( + val filterName: HostFilterEnum = HostFilterEnum.Ram, + val allocationRatio: Double = 1.0, +) : HostFilterSpec() + +@Serializable +@SerialName("SameHost") +public data class SameHostHostFilterSpec( + val filterName: HostFilterEnum = HostFilterEnum.SameHost, +) : HostFilterSpec() + +@Serializable +@SerialName("VCpuCapacity") +public data class VCpuCapacityHostFilterSpec( + val filterName: HostFilterEnum = HostFilterEnum.VCpuCapacity, +) : HostFilterSpec() + +@Serializable +@SerialName("VCpu") +public data class VCpuHostFilterSpec( + val filterName: HostFilterEnum = HostFilterEnum.VCpu, + val allocationRatio: Double = 1.0, +) : HostFilterSpec() + +public fun createHostFilter(filterSpec: HostFilterSpec): HostFilter { + return when (filterSpec) { + is ComputeFilterSpec -> ComputeFilter() + is DifferentHostFilterSpec -> DifferentHostFilter() + is InstanceCountHostFilterSpec -> InstanceCountFilter(filterSpec.limit) + is RamHostFilterSpec -> RamFilter(filterSpec.allocationRatio) + is SameHostHostFilterSpec -> SameHostFilter() + is VCpuCapacityHostFilterSpec -> VCpuCapacityFilter() + is VCpuHostFilterSpec -> VCpuFilter(filterSpec.allocationRatio) + } +} diff --git a/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/experiment/specs/allocation/HostWeigherSpec.kt b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/experiment/specs/allocation/HostWeigherSpec.kt new file mode 100644 index 00000000..60f5ff8b --- /dev/null +++ b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/experiment/specs/allocation/HostWeigherSpec.kt @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2025 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.base.experiment.specs.allocation + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import org.opendc.compute.simulator.scheduler.weights.CoreRamWeigher +import org.opendc.compute.simulator.scheduler.weights.HostWeigher +import org.opendc.compute.simulator.scheduler.weights.InstanceCountWeigher +import org.opendc.compute.simulator.scheduler.weights.RamWeigher +import org.opendc.compute.simulator.scheduler.weights.VCpuCapacityWeigher +import org.opendc.compute.simulator.scheduler.weights.VCpuWeigher + +/** + * A specification for a host weigher. + * + * A host weigher can be defined in a JSON file by adding the serialName as the type parameter. + * + * The user then has to specify any additional parameters required for the weigher. + */ +@Serializable +public sealed class HostWeigherSpec + +@Serializable +@SerialName("CoreRam") +public data class CoreRamWeigherSpec( + val multiplier: Double, +) : HostWeigherSpec() + +@Serializable +@SerialName("InstanceCount") +public data class InstanceCountWeigherSpec( + val multiplier: Double, +) : HostWeigherSpec() + +@Serializable +@SerialName("Ram") +public data class RamWeigherSpec( + val multiplier: Double, +) : HostWeigherSpec() + +@Serializable +@SerialName("VCpuCapacity") +public data class VCpuCapacityWeigherSpec( + val multiplier: Double, +) : HostWeigherSpec() + +@Serializable +@SerialName("VCpu") +public data class VCpuWeigherSpec( + val multiplier: Double, +) : HostWeigherSpec() + +public fun createHostWeigher(weigherSpec: HostWeigherSpec): HostWeigher { + return when (weigherSpec) { + is CoreRamWeigherSpec -> CoreRamWeigher(weigherSpec.multiplier) + is InstanceCountWeigherSpec -> InstanceCountWeigher(weigherSpec.multiplier) + is RamWeigherSpec -> RamWeigher(weigherSpec.multiplier) + is VCpuCapacityWeigherSpec -> VCpuCapacityWeigher(weigherSpec.multiplier) + is VCpuWeigherSpec -> VCpuWeigher(weigherSpec.multiplier) + } +} diff --git a/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/runner/ScenarioRunner.kt b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/runner/ScenarioRunner.kt index f8cbb4fd..43bab2f5 100644 --- a/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/runner/ScenarioRunner.kt +++ b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/runner/ScenarioRunner.kt @@ -28,11 +28,11 @@ import org.opendc.compute.simulator.provisioner.Provisioner import org.opendc.compute.simulator.provisioner.registerComputeMonitor import org.opendc.compute.simulator.provisioner.setupComputeService import org.opendc.compute.simulator.provisioner.setupHosts -import org.opendc.compute.simulator.scheduler.createComputeScheduler import org.opendc.compute.simulator.service.ComputeService import org.opendc.compute.simulator.telemetry.parquet.ParquetComputeMonitor import org.opendc.compute.topology.clusterTopology import org.opendc.experiments.base.experiment.Scenario +import org.opendc.experiments.base.experiment.specs.allocation.createComputeScheduler import org.opendc.experiments.base.experiment.specs.getScalingPolicy import org.opendc.experiments.base.experiment.specs.getWorkloadLoader import org.opendc.simulator.compute.power.CarbonReceiver @@ -108,7 +108,7 @@ public fun runScenario( { val computeScheduler = createComputeScheduler( - scenario.allocationPolicySpec.policyType, + scenario.allocationPolicySpec, Random(it.seeder.nextLong()), timeSource, ) diff --git a/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/OpenDCRunner.kt b/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/OpenDCRunner.kt index 9a1b398e..09aaf9fa 100644 --- a/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/OpenDCRunner.kt +++ b/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/OpenDCRunner.kt @@ -29,7 +29,7 @@ import org.opendc.compute.simulator.provisioner.Provisioner import org.opendc.compute.simulator.provisioner.registerComputeMonitor import org.opendc.compute.simulator.provisioner.setupComputeService import org.opendc.compute.simulator.provisioner.setupHosts -import org.opendc.compute.simulator.scheduler.createComputeScheduler +import org.opendc.compute.simulator.scheduler.createPrefabComputeScheduler import org.opendc.compute.simulator.service.ComputeService import org.opendc.compute.topology.specs.ClusterSpec import org.opendc.compute.topology.specs.HostSpec @@ -279,7 +279,7 @@ public class OpenDCRunner( provisioner.runSteps( setupComputeService( serviceDomain, - { createComputeScheduler(scenario.schedulerName, Random(it.seeder.nextLong()), timeSource) }, + { createPrefabComputeScheduler(scenario.schedulerName, Random(it.seeder.nextLong()), timeSource) }, ), registerComputeMonitor(serviceDomain, monitor), setupHosts(serviceDomain, topology, listOf(), startTime), diff --git a/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/internal/WebComputeMonitor.kt b/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/internal/WebComputeMonitor.kt index fbb33593..9288b403 100644 --- a/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/internal/WebComputeMonitor.kt +++ b/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/internal/WebComputeMonitor.kt @@ -44,14 +44,14 @@ internal class WebComputeMonitor : ComputeMonitor { hostAggregateMetrics.totalLostTime + reader.cpuLostTime, hostAggregateMetrics.totalPowerDraw + reader.energyUsage, hostAggregateMetrics.totalFailureSlices + slices, - hostAggregateMetrics.totalFailureVmSlices + reader.guestsRunning * slices, + hostAggregateMetrics.totalFailureVmSlices + reader.tasksActive * slices, ) hostMetrics.compute(reader.hostInfo.name) { _, prev -> HostMetrics( reader.cpuUsage + (prev?.cpuUsage ?: 0.0), reader.cpuDemand + (prev?.cpuDemand ?: 0.0), - reader.guestsRunning + (prev?.instanceCount ?: 0), + reader.tasksActive + (prev?.instanceCount ?: 0), 1 + (prev?.count ?: 0), ) } |
