diff options
| author | Dante Niewenhuis <d.niewenhuis@hotmail.com> | 2024-04-17 18:17:17 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-04-17 18:17:17 +0200 |
| commit | d652fa2fa76556edd81d3b8087a0c943d462ec49 (patch) | |
| tree | 072c2d033704452e44ebf44ea76943bc0f0f89e5 /opendc-compute/opendc-compute-carbon/src/main | |
| parent | fff89d25bd3c7b874e68261d21695c473c30ed7d (diff) | |
Added support for carbon traces (#218)
* Started with the carbon trace implementation
* Moved the carbon trace system to the proper folders
Diffstat (limited to 'opendc-compute/opendc-compute-carbon/src/main')
3 files changed, 301 insertions, 0 deletions
diff --git a/opendc-compute/opendc-compute-carbon/src/main/kotlin/org/opendc/compute/carbon/CarbonTrace.kt b/opendc-compute/opendc-compute-carbon/src/main/kotlin/org/opendc/compute/carbon/CarbonTrace.kt new file mode 100644 index 00000000..2ba3e4e3 --- /dev/null +++ b/opendc-compute/opendc-compute-carbon/src/main/kotlin/org/opendc/compute/carbon/CarbonTrace.kt @@ -0,0 +1,113 @@ +/* + * 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.compute.carbon + +import java.time.Instant + +/** + * A virtual machine workload. + * + * @param uid The unique identifier of the virtual machine. + * @param name The name of the virtual machine. + * @param cpuCapacity The required CPU capacity for the VM in MHz. + * @param cpuCount The number of vCPUs in the VM. + * @param memCapacity The provisioned memory for the VM in MB. + * @param startTime The start time of the VM. + * @param stopTime The stop time of the VM. + * @param trace The trace that belong to this VM. + * @param interferenceProfile The interference profile of this virtual machine. + */ +public data class CarbonFragment( + var startTime: Long, + var endTime: Long, + var carbonIntensity: Double, +) { + init { + require(endTime > startTime) { + "The end time of a report should be higher than the start time -> start time: $startTime, end time: $endTime" + } + require(carbonIntensity >= 0.0) { "carbon intensity cannot be negative" } + } +} + +public class CarbonTrace(reports: List<CarbonFragment>? = null) { + private var index: Int = 0 + private val numberOfReports = reports?.size + private val reports = reports?.sortedBy { it.startTime } + + private fun hasPreviousReport(): Boolean { + return index > 0 + } + + private fun hasNextReport(): Boolean { + if (numberOfReports == null) { + return false + } + + return index < numberOfReports + } + + public fun getCarbonIntensity(timestamp: Instant): Double { + return getCarbonIntensity(timestamp.toEpochMilli()) + } + + /** + * Get the carbon intensity of the energy at a given timestamp + * Returns the carbon intensity of the first or last [CarbonFragment] + * if the given timestamp is outside the information + * + * @param timestamp + * @return The carbon intensity at the given timestamp in gCO2/kWh + */ + public fun getCarbonIntensity(timestamp: Long): Double { + if (reports == null) { + return 0.0 + } + + var currentFragment: CarbonFragment + + while (true) { + currentFragment = reports[index] + + if (currentFragment.startTime > timestamp) { + if (hasPreviousReport()) { + index-- + continue + } + break + } + + if (currentFragment.endTime <= timestamp) { + if (hasNextReport()) { + index++ + continue + } + break + } + + break + } + + return currentFragment.carbonIntensity + } +} diff --git a/opendc-compute/opendc-compute-carbon/src/main/kotlin/org/opendc/compute/carbon/CarbonTraceLoader.kt b/opendc-compute/opendc-compute-carbon/src/main/kotlin/org/opendc/compute/carbon/CarbonTraceLoader.kt new file mode 100644 index 00000000..685a1fb3 --- /dev/null +++ b/opendc-compute/opendc-compute-carbon/src/main/kotlin/org/opendc/compute/carbon/CarbonTraceLoader.kt @@ -0,0 +1,136 @@ +/* + * 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.compute.carbon + +import mu.KotlinLogging +import org.opendc.trace.Trace +import org.opendc.trace.conv.CARBON_INTENSITY_TIMESTAMP +import org.opendc.trace.conv.CARBON_INTENSITY_VALUE +import org.opendc.trace.conv.TABLE_CARBON_INTENSITY +import java.io.File +import java.lang.ref.SoftReference +import java.time.Instant +import java.util.concurrent.ConcurrentHashMap + +/** + * A helper class for loading compute workload traces into memory. + * + * @param baseDir The directory containing the traces. + */ +public class CarbonTraceLoader { + /** + * The logger for this instance. + */ + private val logger = KotlinLogging.logger {} + + /** + * The cache of workloads. + */ + private val cache = ConcurrentHashMap<String, SoftReference<List<CarbonFragment>>>() + + private val builder = CarbonFragmentBuilder() + + /** + * Read the metadata into a workload. + */ + private fun parseCarbon(trace: Trace): List<CarbonFragment> { + val reader = checkNotNull(trace.getTable(TABLE_CARBON_INTENSITY)).newReader() + + val startTimeCol = reader.resolve(CARBON_INTENSITY_TIMESTAMP) + val carbonIntensityCol = reader.resolve(CARBON_INTENSITY_VALUE) + + val entries = mutableListOf<CarbonFragment>() + + try { + while (reader.nextRow()) { + val startTime = reader.getInstant(startTimeCol)!! + val carbonIntensity = reader.getDouble(carbonIntensityCol) + + builder.add(startTime, carbonIntensity) + } + + // Make sure the virtual machines are ordered by start time + builder.fixReportTimes() + + return builder.fragments + } catch (e: Exception) { + e.printStackTrace() + throw e + } finally { + reader.close() + } + } + + /** + * Load the trace with the specified [name] and [format]. + */ + public fun get(pathToFile: File): List<CarbonFragment> { + val trace = Trace.open(pathToFile, "carbon") + + return parseCarbon(trace) + } + + /** + * Clear the workload cache. + */ + public fun reset() { + cache.clear() + } + + /** + * A builder for a VM trace. + */ + private class CarbonFragmentBuilder { + /** + * The total load of the trace. + */ + public val fragments: MutableList<CarbonFragment> = mutableListOf<CarbonFragment>() + + /** + * Add a fragment to the trace. + * + * @param startTime Timestamp at which the fragment starts (in epoch millis). + * @param carbonIntensity The carbon intensity during this fragment + */ + fun add( + startTime: Instant, + carbonIntensity: Double, + ) { + fragments.add( + CarbonFragment(startTime.toEpochMilli(), Long.MAX_VALUE, carbonIntensity), + ) + } + + fun fixReportTimes() { + fragments.sortBy { it.startTime } + + // For each report, set the end time to the start time of the next report + for (i in 0..fragments.size - 2) { + fragments[i].endTime = fragments[i + 1].startTime + } + + // Set the start time of each report to the minimum value + fragments[0].startTime = Long.MIN_VALUE + } + } +} diff --git a/opendc-compute/opendc-compute-carbon/src/main/kotlin/org/opendc/compute/carbon/CarbonTraceReader.kt b/opendc-compute/opendc-compute-carbon/src/main/kotlin/org/opendc/compute/carbon/CarbonTraceReader.kt new file mode 100644 index 00000000..3e0269f8 --- /dev/null +++ b/opendc-compute/opendc-compute-carbon/src/main/kotlin/org/opendc/compute/carbon/CarbonTraceReader.kt @@ -0,0 +1,52 @@ +/* + * 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. + */ + +@file:JvmName("ComputeWorkloads") + +package org.opendc.compute.carbon + +import java.io.File +import javax.management.InvalidAttributeValueException + +/** + * Construct a workload from a trace. + */ +public fun getCarbonTrace(pathToFile: String?): CarbonTrace { + if (pathToFile == null) { + return CarbonTrace(null) + } + + return getCarbonTrace(File(pathToFile)) +} + +/** + * Construct a workload from a trace. + */ +public fun getCarbonTrace(file: File): CarbonTrace { + if (!file.exists()) { + throw InvalidAttributeValueException("The carbon trace cannot be found") + } + + val fragments = CarbonTraceLoader().get(file) + + return CarbonTrace(fragments) +} |
