Skip to content

Commit

Permalink
added carbon tests (#292)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
DanteNiewenhuis authored Jan 17, 2025
1 parent 1fc2017 commit 5c193e7
Show file tree
Hide file tree
Showing 16 changed files with 348 additions and 6 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
@@ -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" }
},
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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,
Expand All @@ -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)!!
Expand Down Expand Up @@ -145,6 +149,7 @@ class TestComputeMonitor : ComputeMonitor {
var tasksCompleted = 0

var timestamps = ArrayList<Long>()
var absoluteTimestamps = ArrayList<Long>()

var maxTimestamp = 0L

Expand All @@ -158,6 +163,7 @@ class TestComputeMonitor : ComputeMonitor {
tasksCompleted = reader.tasksCompleted

timestamps.add(reader.timestamp.toEpochMilli())
absoluteTimestamps.add(reader.timestampAbsolute.toEpochMilli())
maxTimestamp = reader.timestamp.toEpochMilli()
}

Expand Down Expand Up @@ -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)
}
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -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"
}
}
]
}
Original file line number Diff line number Diff line change
@@ -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"
}
}
]
}
Original file line number Diff line number Diff line change
@@ -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"
}
}
]
}
Loading

0 comments on commit 5c193e7

Please sign in to comment.