diff options
| author | Dante Niewenhuis <d.niewenhuis@hotmail.com> | 2025-01-17 13:22:48 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-01-17 13:22:48 +0100 |
| commit | 5c193e77812c306e968e9fae6855ebbc39cdf0fc (patch) | |
| tree | 72840a59395ba57326cbe4757ad620a72bb8171d | |
| parent | 1fc201745b1984db492350ab5b4e11d2a3363aa5 (diff) | |
added carbon tests (#292)
* Initial push
* Added carbon tests
* spotless
* small update to test
* Updated build file
* Updated build file
* small test
* small update
* Test
* Test
* Updated CarbonTraces to UTC. updated the tests accordingly
* spotless
16 files changed, 348 insertions, 6 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2f4db50c..807c6d26 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -24,12 +24,12 @@ jobs: - name: Validate Gradle wrapper uses: gradle/wrapper-validation-action@v1 - name: Set up JDK - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: 'zulu' java-version: ${{ matrix.java }} - name: Build with Gradle - uses: gradle/gradle-build-action@v2 + uses: gradle/gradle-build-action@v3 with: arguments: build assembleDist codeCoverageReport # Only write to the cache for builds on the 'master' branch. diff --git a/opendc-experiments/opendc-experiments-base/src/test/kotlin/org/opendc/experiments/base/CarbonTest.kt b/opendc-experiments/opendc-experiments-base/src/test/kotlin/org/opendc/experiments/base/CarbonTest.kt new file mode 100644 index 00000000..091f506a --- /dev/null +++ b/opendc-experiments/opendc-experiments-base/src/test/kotlin/org/opendc/experiments/base/CarbonTest.kt @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2020 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 + +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertAll +import org.opendc.compute.workload.Task +import org.opendc.simulator.compute.workload.TraceFragment +import java.util.ArrayList + +/** + * Testing suite containing tests that specifically test the FlowDistributor + */ +class CarbonTest { + /** + * Carbon test 1: One static task running on 4 different carbon traces + * In this test, a single task is scheduled that takes 120 min to complete + * + * Four different carbon traces are used to calculate the carbon emissions. + * + * We check if the energy is the same for all four carbon traces, while the carbon emissions are different. + */ + @Test + fun testCarbon1() { + val workload: ArrayList<Task> = + arrayListOf( + createTestTask( + name = "0", + fragments = + arrayListOf( + TraceFragment(120 * 60 * 1000, 1000.0, 1), + ), + submissionTime = "2022-01-01T00:00", + ), + ) + + val topologyBe = createTopology("single_1_2000_BE.json") + val monitorBe = runTest(topologyBe, workload) + + val topologyDe = createTopology("single_1_2000_DE.json") + val monitorDe = runTest(topologyDe, workload) + + val topologyFr = createTopology("single_1_2000_FR.json") + val monitorFr = runTest(topologyFr, workload) + + val topologyNl = createTopology("single_1_2000_NL.json") + val monitorNl = runTest(topologyNl, workload) + + assertAll( + { assertEquals(120 * 60 * 150.0, monitorBe.energyUsages.sum()) { "The total power usage is not correct" } }, + { assertEquals(120 * 60 * 150.0, monitorDe.energyUsages.sum()) { "The total power usage is not correct" } }, + { assertEquals(120 * 60 * 150.0, monitorFr.energyUsages.sum()) { "The total power usage is not correct" } }, + { assertEquals(120 * 60 * 150.0, monitorNl.energyUsages.sum()) { "The total power usage is not correct" } }, + { assertEquals(8.6798, monitorBe.carbonEmissions.sum(), 1e-3) { "The total power usage is not correct" } }, + { assertEquals(31.8332, monitorDe.carbonEmissions.sum(), 1e-3) { "The total power usage is not correct" } }, + { assertEquals(4.5813, monitorFr.carbonEmissions.sum(), 1e-3) { "The total power usage is not correct" } }, + { assertEquals(49.7641, monitorNl.carbonEmissions.sum(), 1e-3) { "The total power usage is not correct" } }, + ) + } + + /** + * Carbon test 2: One changing task running on 4 different carbon traces + * In this test, a single task is scheduled that takes 320 min to complete. + * The demanded cpu is changing every 40 minutes. + * + * Four different carbon traces are used to calculate the carbon emissions. + * + * We check if the energy is the same for all four carbon traces, while the carbon emissions are different. + */ + @Test + fun testCarbon2() { + val workload: ArrayList<Task> = + arrayListOf( + createTestTask( + name = "0", + fragments = + arrayListOf( + TraceFragment(40 * 60 * 1000, 1000.0, 1), + TraceFragment(40 * 60 * 1000, 2000.0, 1), + TraceFragment(40 * 60 * 1000, 1000.0, 1), + TraceFragment(40 * 60 * 1000, 2000.0, 1), + TraceFragment(40 * 60 * 1000, 1000.0, 1), + TraceFragment(40 * 60 * 1000, 2000.0, 1), + TraceFragment(40 * 60 * 1000, 1000.0, 1), + TraceFragment(40 * 60 * 1000, 2000.0, 1), + ), + submissionTime = "2022-01-01T00:00", + ), + ) + + val topologyBe = createTopology("single_1_2000_BE.json") + val monitorBe = runTest(topologyBe, workload) + + val topologyDe = createTopology("single_1_2000_DE.json") + val monitorDe = runTest(topologyDe, workload) + + val topologyFr = createTopology("single_1_2000_FR.json") + val monitorFr = runTest(topologyFr, workload) + + val topologyNl = createTopology("single_1_2000_NL.json") + val monitorNl = runTest(topologyNl, workload) + + assertAll( + { + assertEquals( + (160 * 60 * 150.0) + (160 * 60 * 200.0), + monitorBe.energyUsages.sum(), + ) { "The total power usage is not correct" } + }, + { + assertEquals( + (160 * 60 * 150.0) + (160 * 60 * 200.0), + monitorDe.energyUsages.sum(), + ) { "The total power usage is not correct" } + }, + { + assertEquals( + (160 * 60 * 150.0) + (160 * 60 * 200.0), + monitorFr.energyUsages.sum(), + ) { "The total power usage is not correct" } + }, + { + assertEquals( + (160 * 60 * 150.0) + (160 * 60 * 200.0), + monitorNl.energyUsages.sum(), + ) { "The total power usage is not correct" } + }, + ) + } + + /** + * Carbon test 3: A single task on the NL carbon trace + * In this test, a single task is scheduled with a carbon trace from the Netherlands + * + * + * We check if the carbon intensity and carbon emission change at the correct moments. + * We also check the total energy usage, and total carbon emissions. + */ + @Test + fun testCarbon3() { + val workload: ArrayList<Task> = + arrayListOf( + createTestTask( + name = "0", + fragments = + arrayListOf( + TraceFragment(60 * 60 * 1000, 1000.0, 1), + ), + submissionTime = "2022-01-01T00:00", + ), + ) + + val topologyNl = createTopology("single_1_2000_NL.json") + val monitorNl = runTest(topologyNl, workload) + + assertAll( + { assertEquals(164.5177, monitorNl.carbonIntensities.get(0), 1e-3) { "The Carbon Intensity is incorrect" } }, + { assertEquals(164.5177, monitorNl.carbonIntensities.get(13), 1e-3) { "The Carbon Intensity is incorrect" } }, + { assertEquals(162.9489, monitorNl.carbonIntensities.get(14), 1e-3) { "The Carbon Intensity is incorrect" } }, + { assertEquals(162.9489, monitorNl.carbonIntensities.get(28), 1e-3) { "The Carbon Intensity is incorrect" } }, + { assertEquals(164.3010, monitorNl.carbonIntensities.get(29), 1e-3) { "The Carbon Intensity is incorrect" } }, + { assertEquals(164.3010, monitorNl.carbonIntensities.get(43), 1e-3) { "The Carbon Intensity is incorrect" } }, + { assertEquals(167.5809, monitorNl.carbonIntensities.get(44), 1e-3) { "The Carbon Intensity is incorrect" } }, + { assertEquals(167.5809, monitorNl.carbonIntensities.get(58), 1e-3) { "The Carbon Intensity is incorrect" } }, + { assertEquals(0.411294, monitorNl.carbonEmissions.get(0), 1e-3) { "The Carbon Emissions are incorrect" } }, + { assertEquals(0.411294, monitorNl.carbonEmissions.get(14), 1e-3) { "The Carbon Intensity is incorrect" } }, + { assertEquals(0.407372, monitorNl.carbonEmissions.get(15), 1e-3) { "The Carbon Intensity is incorrect" } }, + { assertEquals(0.407372, monitorNl.carbonEmissions.get(29), 1e-3) { "The Carbon Intensity is incorrect" } }, + { assertEquals(0.411382, monitorNl.carbonEmissions.get(30), 1e-3) { "The Carbon Intensity is incorrect" } }, + { assertEquals(0.411382, monitorNl.carbonEmissions.get(44), 1e-3) { "The Carbon Intensity is incorrect" } }, + { assertEquals(0.418734, monitorNl.carbonEmissions.get(45), 1e-3) { "The Carbon Intensity is incorrect" } }, + { assertEquals(0.418734, monitorNl.carbonEmissions.get(59), 1e-3) { "The Carbon Intensity is incorrect" } }, + { assertEquals(0.0, monitorNl.carbonEmissions.get(60), 1e-3) { "The Carbon Intensity is incorrect" } }, + { assertEquals((60 * 60 * 150.0), monitorNl.energyUsages.sum()) { "The total energy usage is incorrect" } }, + { + assertEquals( + (0.411294 * 15) + (0.407372 * 15) + + (0.411382 * 15) + (0.418734 * 15), + monitorNl.carbonEmissions.sum(), + 1e-1, + ) { "The total carbon emission is incorrect" } + }, + ) + } +} diff --git a/opendc-experiments/opendc-experiments-base/src/test/kotlin/org/opendc/experiments/base/TestingUtils.kt b/opendc-experiments/opendc-experiments-base/src/test/kotlin/org/opendc/experiments/base/TestingUtils.kt index 228ebd4e..eadd97e4 100644 --- a/opendc-experiments/opendc-experiments-base/src/test/kotlin/org/opendc/experiments/base/TestingUtils.kt +++ b/opendc-experiments/opendc-experiments-base/src/test/kotlin/org/opendc/experiments/base/TestingUtils.kt @@ -48,7 +48,7 @@ import org.opendc.simulator.compute.workload.TraceWorkload import org.opendc.simulator.kotlin.runSimulation import java.time.Duration import java.time.LocalDateTime -import java.time.ZoneId +import java.time.ZoneOffset import java.util.UUID import kotlin.collections.ArrayList @@ -77,7 +77,7 @@ fun createTestTask( fragments.maxOf { it.cpuUsage }, memCapacity, 1800000.0, - LocalDateTime.parse(submissionTime).atZone(ZoneId.systemDefault()).toInstant(), + LocalDateTime.parse(submissionTime).toInstant(ZoneOffset.UTC), duration, TraceWorkload( fragments, @@ -103,10 +103,14 @@ fun runTest( runSimulation { val seed = 0L Provisioner(dispatcher, seed).use { provisioner -> + + val startTimeLong = workload.minOf { it.submissionTime }.toEpochMilli() + val startTime = Duration.ofMillis(startTimeLong) + provisioner.runSteps( setupComputeService(serviceDomain = "compute.opendc.org", { computeScheduler }), - registerComputeMonitor(serviceDomain = "compute.opendc.org", monitor, exportInterval = Duration.ofMinutes(1)), - setupHosts(serviceDomain = "compute.opendc.org", topology), + registerComputeMonitor(serviceDomain = "compute.opendc.org", monitor, exportInterval = Duration.ofMinutes(1), startTime), + setupHosts(serviceDomain = "compute.opendc.org", topology, startTimeLong), ) val service = provisioner.registry.resolve("compute.opendc.org", ComputeService::class.java)!! @@ -145,6 +149,7 @@ class TestComputeMonitor : ComputeMonitor { var tasksCompleted = 0 var timestamps = ArrayList<Long>() + var absoluteTimestamps = ArrayList<Long>() var maxTimestamp = 0L @@ -158,6 +163,7 @@ class TestComputeMonitor : ComputeMonitor { tasksCompleted = reader.tasksCompleted timestamps.add(reader.timestamp.toEpochMilli()) + absoluteTimestamps.add(reader.timestampAbsolute.toEpochMilli()) maxTimestamp = reader.timestamp.toEpochMilli() } @@ -200,8 +206,14 @@ class TestComputeMonitor : ComputeMonitor { var powerDraws = ArrayList<Double>() var energyUsages = ArrayList<Double>() + var carbonIntensities = ArrayList<Double>() + var carbonEmissions = ArrayList<Double>() + override fun record(reader: PowerSourceTableReader) { powerDraws.add(reader.powerDraw) energyUsages.add(reader.energyUsage) + + carbonIntensities.add(reader.carbonIntensity) + carbonEmissions.add(reader.carbonEmission) } } diff --git a/opendc-experiments/opendc-experiments-base/src/test/resources/carbonTraces/2022-01-01_2022-12-31_BE.parquet b/opendc-experiments/opendc-experiments-base/src/test/resources/carbonTraces/2022-01-01_2022-12-31_BE.parquet Binary files differnew file mode 100644 index 00000000..ab2b5f8b --- /dev/null +++ b/opendc-experiments/opendc-experiments-base/src/test/resources/carbonTraces/2022-01-01_2022-12-31_BE.parquet diff --git a/opendc-experiments/opendc-experiments-base/src/test/resources/carbonTraces/2022-01-01_2022-12-31_DE.parquet b/opendc-experiments/opendc-experiments-base/src/test/resources/carbonTraces/2022-01-01_2022-12-31_DE.parquet Binary files differnew file mode 100644 index 00000000..213e24a4 --- /dev/null +++ b/opendc-experiments/opendc-experiments-base/src/test/resources/carbonTraces/2022-01-01_2022-12-31_DE.parquet diff --git a/opendc-experiments/opendc-experiments-base/src/test/resources/carbonTraces/2022-01-01_2022-12-31_FR.parquet b/opendc-experiments/opendc-experiments-base/src/test/resources/carbonTraces/2022-01-01_2022-12-31_FR.parquet Binary files differnew file mode 100644 index 00000000..a2d64d8f --- /dev/null +++ b/opendc-experiments/opendc-experiments-base/src/test/resources/carbonTraces/2022-01-01_2022-12-31_FR.parquet diff --git a/opendc-experiments/opendc-experiments-base/src/test/resources/carbonTraces/2022-01-01_2022-12-31_NL.parquet b/opendc-experiments/opendc-experiments-base/src/test/resources/carbonTraces/2022-01-01_2022-12-31_NL.parquet Binary files differnew file mode 100644 index 00000000..6b4a05ad --- /dev/null +++ b/opendc-experiments/opendc-experiments-base/src/test/resources/carbonTraces/2022-01-01_2022-12-31_NL.parquet diff --git a/opendc-experiments/opendc-experiments-base/src/test/resources/topologies/single_1_2000_BE.json b/opendc-experiments/opendc-experiments-base/src/test/resources/topologies/single_1_2000_BE.json new file mode 100644 index 00000000..3a04b275 --- /dev/null +++ b/opendc-experiments/opendc-experiments-base/src/test/resources/topologies/single_1_2000_BE.json @@ -0,0 +1,31 @@ +{ + "clusters": + [ + { + "name": "C01", + "hosts" : + [ + { + "name": "H01", + "cpu": + { + "coreCount": 1, + "coreSpeed": 2000 + }, + "memory": { + "memorySize": 140457600000 + }, + "powerModel": { + "modelType": "linear", + "power": 400.0, + "idlePower": 100.0, + "maxPower": 200.0 + } + } + ], + "powerSource": { + "carbonTracePath": "src/test/resources/carbonTraces/2022-01-01_2022-12-31_BE.parquet" + } + } + ] +} diff --git a/opendc-experiments/opendc-experiments-base/src/test/resources/topologies/single_1_2000_DE.json b/opendc-experiments/opendc-experiments-base/src/test/resources/topologies/single_1_2000_DE.json new file mode 100644 index 00000000..651e8b54 --- /dev/null +++ b/opendc-experiments/opendc-experiments-base/src/test/resources/topologies/single_1_2000_DE.json @@ -0,0 +1,31 @@ +{ + "clusters": + [ + { + "name": "C01", + "hosts" : + [ + { + "name": "H01", + "cpu": + { + "coreCount": 1, + "coreSpeed": 2000 + }, + "memory": { + "memorySize": 140457600000 + }, + "powerModel": { + "modelType": "linear", + "power": 400.0, + "idlePower": 100.0, + "maxPower": 200.0 + } + } + ], + "powerSource": { + "carbonTracePath": "src/test/resources/carbonTraces/2022-01-01_2022-12-31_DE.parquet" + } + } + ] +} diff --git a/opendc-experiments/opendc-experiments-base/src/test/resources/topologies/single_1_2000_FR.json b/opendc-experiments/opendc-experiments-base/src/test/resources/topologies/single_1_2000_FR.json new file mode 100644 index 00000000..fed097e9 --- /dev/null +++ b/opendc-experiments/opendc-experiments-base/src/test/resources/topologies/single_1_2000_FR.json @@ -0,0 +1,31 @@ +{ + "clusters": + [ + { + "name": "C01", + "hosts" : + [ + { + "name": "H01", + "cpu": + { + "coreCount": 1, + "coreSpeed": 2000 + }, + "memory": { + "memorySize": 140457600000 + }, + "powerModel": { + "modelType": "linear", + "power": 400.0, + "idlePower": 100.0, + "maxPower": 200.0 + } + } + ], + "powerSource": { + "carbonTracePath": "src/test/resources/carbonTraces/2022-01-01_2022-12-31_FR.parquet" + } + } + ] +} diff --git a/opendc-experiments/opendc-experiments-base/src/test/resources/topologies/single_1_2000_NL.json b/opendc-experiments/opendc-experiments-base/src/test/resources/topologies/single_1_2000_NL.json new file mode 100644 index 00000000..05805c88 --- /dev/null +++ b/opendc-experiments/opendc-experiments-base/src/test/resources/topologies/single_1_2000_NL.json @@ -0,0 +1,31 @@ +{ + "clusters": + [ + { + "name": "C01", + "hosts" : + [ + { + "name": "H01", + "cpu": + { + "coreCount": 1, + "coreSpeed": 2000 + }, + "memory": { + "memorySize": 140457600000 + }, + "powerModel": { + "modelType": "linear", + "power": 400.0, + "idlePower": 100.0, + "maxPower": 200.0 + } + } + ], + "powerSource": { + "carbonTracePath": "src/test/resources/carbonTraces/2022-01-01_2022-12-31_NL.parquet" + } + } + ] +} diff --git a/opendc-experiments/opendc-experiments-base/src/test/resources/workload_traces/bitbrains-small/fragments.parquet b/opendc-experiments/opendc-experiments-base/src/test/resources/workloadTraces/bitbrains-small/fragments.parquet Binary files differindex 240f58e3..240f58e3 100644 --- a/opendc-experiments/opendc-experiments-base/src/test/resources/workload_traces/bitbrains-small/fragments.parquet +++ b/opendc-experiments/opendc-experiments-base/src/test/resources/workloadTraces/bitbrains-small/fragments.parquet diff --git a/opendc-experiments/opendc-experiments-base/src/test/resources/workload_traces/bitbrains-small/interference-model.json b/opendc-experiments/opendc-experiments-base/src/test/resources/workloadTraces/bitbrains-small/interference-model.json index 51fc6366..51fc6366 100644 --- a/opendc-experiments/opendc-experiments-base/src/test/resources/workload_traces/bitbrains-small/interference-model.json +++ b/opendc-experiments/opendc-experiments-base/src/test/resources/workloadTraces/bitbrains-small/interference-model.json diff --git a/opendc-experiments/opendc-experiments-base/src/test/resources/workload_traces/bitbrains-small/tasks.parquet b/opendc-experiments/opendc-experiments-base/src/test/resources/workloadTraces/bitbrains-small/tasks.parquet Binary files differindex 8e9dcea7..8e9dcea7 100644 --- a/opendc-experiments/opendc-experiments-base/src/test/resources/workload_traces/bitbrains-small/tasks.parquet +++ b/opendc-experiments/opendc-experiments-base/src/test/resources/workloadTraces/bitbrains-small/tasks.parquet diff --git a/opendc-experiments/opendc-experiments-base/src/test/resources/workload_traces/single_task/fragments.parquet b/opendc-experiments/opendc-experiments-base/src/test/resources/workloadTraces/single_task/fragments.parquet Binary files differindex 94a2d69e..94a2d69e 100644 --- a/opendc-experiments/opendc-experiments-base/src/test/resources/workload_traces/single_task/fragments.parquet +++ b/opendc-experiments/opendc-experiments-base/src/test/resources/workloadTraces/single_task/fragments.parquet diff --git a/opendc-experiments/opendc-experiments-base/src/test/resources/workload_traces/single_task/tasks.parquet b/opendc-experiments/opendc-experiments-base/src/test/resources/workloadTraces/single_task/tasks.parquet Binary files differindex 2a7da2eb..2a7da2eb 100644 --- a/opendc-experiments/opendc-experiments-base/src/test/resources/workload_traces/single_task/tasks.parquet +++ b/opendc-experiments/opendc-experiments-base/src/test/resources/workloadTraces/single_task/tasks.parquet |
