summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFabian Mastenbroek <mail.fabianm@gmail.com>2021-10-25 16:16:13 +0200
committerGitHub <noreply@github.com>2021-10-25 16:16:13 +0200
commita41cd2504f15f3e3e49eb533faca390911cc5110 (patch)
treef35e7e5c65e2985cf34ad7689526d5b5c0815230
parentaa9b32f8cd1467e9718959f400f6777e5d71737d (diff)
parentfe8cd32c3f79d2a6c898a1c8809792e35440a539 (diff)
merge: Address several regressions in simulator
This pull request addresses several regressions that have been introduced in the past few pull requests. - Fix queue resizing logic - Change clock resolution from milliseconds to nanoseconds in `OtelClockAdapter` - Compute energy usage in absence of convergence - Fix duplicate classpath entries - Fix release workflow **Breaking API Changes** - `OtelClockAdapter` now exports time in nanoseconds as the method contract describes.
-rw-r--r--.github/workflows/release.yml6
-rw-r--r--buildSrc/src/main/kotlin/benchmark-conventions.gradle.kts16
-rw-r--r--opendc-experiments/opendc-experiments-capelin/src/test/kotlin/org/opendc/experiments/capelin/CapelinIntegrationTest.kt4
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimBareMetalMachine.kt20
-rw-r--r--opendc-simulator/opendc-simulator-flow/build.gradle.kts2
-rw-r--r--opendc-simulator/opendc-simulator-flow/src/main/kotlin/org/opendc/simulator/flow/internal/FlowDeque.kt7
-rw-r--r--opendc-simulator/opendc-simulator-flow/src/main/kotlin/org/opendc/simulator/flow/internal/FlowTimerQueue.kt7
-rw-r--r--opendc-telemetry/opendc-telemetry-sdk/src/main/kotlin/org/opendc/telemetry/sdk/OtelClockAdapter.kt2
8 files changed, 53 insertions, 11 deletions
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index c525eb97..c1f2864c 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -24,9 +24,9 @@ jobs:
run: chmod +x gradlew
- uses: actions/cache@v2
with:
- path:|
- ~/.gradle/caches
- ~/.gradle/wrapper
+ path: |
+ ~/.gradle/caches
+ ~/.gradle/wrapper
key: ${{ runner.os }}-${{ matrix.java }}-gradle-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-${{ matrix.java }}-gradle-
diff --git a/buildSrc/src/main/kotlin/benchmark-conventions.gradle.kts b/buildSrc/src/main/kotlin/benchmark-conventions.gradle.kts
index 65608e8f..7d8775c6 100644
--- a/buildSrc/src/main/kotlin/benchmark-conventions.gradle.kts
+++ b/buildSrc/src/main/kotlin/benchmark-conventions.gradle.kts
@@ -20,6 +20,7 @@
* SOFTWARE.
*/
+import me.champeau.jmh.JMHTask
import org.jetbrains.kotlin.allopen.gradle.*
plugins {
@@ -37,4 +38,19 @@ jmh {
profilers.add("stack")
profilers.add("gc")
+
+ includeTests.set(false) // Do not include tests by default
+}
+
+tasks.named("jmh", JMHTask::class) {
+ outputs.upToDateWhen { false } // XXX Do not cache the output of this task
+
+ testRuntimeClasspath.setFrom() // XXX Clear test runtime classpath to eliminate duplicate dependencies on classpath
+}
+
+dependencies {
+ constraints {
+ val libs = Libs(project)
+ jmh(libs["commons.math3"]) // XXX Force JMH to use the same commons-math3 version as OpenDC
+ }
}
diff --git a/opendc-experiments/opendc-experiments-capelin/src/test/kotlin/org/opendc/experiments/capelin/CapelinIntegrationTest.kt b/opendc-experiments/opendc-experiments-capelin/src/test/kotlin/org/opendc/experiments/capelin/CapelinIntegrationTest.kt
index e34c5bdc..94e92c1b 100644
--- a/opendc-experiments/opendc-experiments-capelin/src/test/kotlin/org/opendc/experiments/capelin/CapelinIntegrationTest.kt
+++ b/opendc-experiments/opendc-experiments-capelin/src/test/kotlin/org/opendc/experiments/capelin/CapelinIntegrationTest.kt
@@ -120,7 +120,7 @@ class CapelinIntegrationTest {
{ assertEquals(67006560, this@CapelinIntegrationTest.exporter.activeTime) { "Incorrect active time" } },
{ assertEquals(3159377, this@CapelinIntegrationTest.exporter.stealTime) { "Incorrect steal time" } },
{ assertEquals(0, this@CapelinIntegrationTest.exporter.lostTime) { "Incorrect lost time" } },
- { assertEquals(5.840212485920686E9, this@CapelinIntegrationTest.exporter.energyUsage, 0.01) { "Incorrect power draw" } },
+ { assertEquals(5.840862926294953E9, this@CapelinIntegrationTest.exporter.energyUsage, 0.01) { "Incorrect power draw" } },
)
}
@@ -164,7 +164,7 @@ class CapelinIntegrationTest {
{ assertEquals(9740289, this@CapelinIntegrationTest.exporter.activeTime) { "Active time incorrect" } },
{ assertEquals(0, this@CapelinIntegrationTest.exporter.stealTime) { "Steal time incorrect" } },
{ assertEquals(0, this@CapelinIntegrationTest.exporter.lostTime) { "Lost time incorrect" } },
- { assertEquals(7.0099453912813E8, this@CapelinIntegrationTest.exporter.energyUsage, 0.01) { "Incorrect power draw" } }
+ { assertEquals(7.010642279990053E8, this@CapelinIntegrationTest.exporter.energyUsage, 0.01) { "Incorrect power draw" } }
)
}
diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimBareMetalMachine.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimBareMetalMachine.kt
index 9140d31b..5df03d45 100644
--- a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimBareMetalMachine.kt
+++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimBareMetalMachine.kt
@@ -60,8 +60,12 @@ public class SimBareMetalMachine(
* The total energy usage of the machine (without PSU loss) in Joules.
*/
public val energyUsage: Double
- get() = _energyUsage
+ get() {
+ computeEnergyUsage(engine.clock.millis())
+ return _energyUsage
+ }
private var _energyUsage = 0.0
+ private var _energyLastComputation = 0L
/**
* The processing units of the machine.
@@ -86,13 +90,25 @@ public class SimBareMetalMachine(
val duration = max(0, now - lastConverge)
if (duration > 0) {
// Compute the power and energy usage of the machine
- _energyUsage += _powerUsage * (duration / 1000.0)
+ computeEnergyUsage(now)
_powerUsage = powerDriverLogic.computePower()
}
}
init {
psu.connect(powerDriverLogic)
+ _powerUsage = powerDriverLogic.computePower()
+ }
+
+ /**
+ * Helper method to compute total energy usage.
+ */
+ private fun computeEnergyUsage(now: Long) {
+ val duration = max(0, now - _energyLastComputation)
+ _energyLastComputation = now
+
+ // Compute the energy usage of the machine
+ _energyUsage += _powerUsage * (duration / 1000.0)
}
/**
diff --git a/opendc-simulator/opendc-simulator-flow/build.gradle.kts b/opendc-simulator/opendc-simulator-flow/build.gradle.kts
index 05e21c3c..f5b67851 100644
--- a/opendc-simulator/opendc-simulator-flow/build.gradle.kts
+++ b/opendc-simulator/opendc-simulator-flow/build.gradle.kts
@@ -36,4 +36,6 @@ dependencies {
testImplementation(projects.opendcSimulator.opendcSimulatorCore)
testImplementation(libs.slf4j.simple)
+
+ jmhImplementation(projects.opendcSimulator.opendcSimulatorCore)
}
diff --git a/opendc-simulator/opendc-simulator-flow/src/main/kotlin/org/opendc/simulator/flow/internal/FlowDeque.kt b/opendc-simulator/opendc-simulator-flow/src/main/kotlin/org/opendc/simulator/flow/internal/FlowDeque.kt
index c6cba4b7..94232954 100644
--- a/opendc-simulator/opendc-simulator-flow/src/main/kotlin/org/opendc/simulator/flow/internal/FlowDeque.kt
+++ b/opendc-simulator/opendc-simulator-flow/src/main/kotlin/org/opendc/simulator/flow/internal/FlowDeque.kt
@@ -25,7 +25,10 @@ package org.opendc.simulator.flow.internal
import java.util.*
/**
- * A specialized [ArrayDeque] for [FlowConsumerContextImpl] implementations.
+ * A specialized [ArrayDeque] that tracks the [FlowConsumerContextImpl] instances that have updated in an interpreter
+ * cycle.
+ *
+ * By using a specialized class, we reduce the overhead caused by type-erasure.
*/
internal class FlowDeque(initialCapacity: Int = 256) {
/**
@@ -106,7 +109,7 @@ internal class FlowDeque(initialCapacity: Int = 256) {
val a = arrayOfNulls<FlowConsumerContextImpl>(newCapacity)
- _elements.copyInto(a, 0, p, r)
+ _elements.copyInto(a, 0, p, n)
_elements.copyInto(a, r, 0, p)
_elements = a
diff --git a/opendc-simulator/opendc-simulator-flow/src/main/kotlin/org/opendc/simulator/flow/internal/FlowTimerQueue.kt b/opendc-simulator/opendc-simulator-flow/src/main/kotlin/org/opendc/simulator/flow/internal/FlowTimerQueue.kt
index 22a390e6..47061a91 100644
--- a/opendc-simulator/opendc-simulator-flow/src/main/kotlin/org/opendc/simulator/flow/internal/FlowTimerQueue.kt
+++ b/opendc-simulator/opendc-simulator-flow/src/main/kotlin/org/opendc/simulator/flow/internal/FlowTimerQueue.kt
@@ -24,6 +24,9 @@ package org.opendc.simulator.flow.internal
/**
* Specialized priority queue for flow timers.
+ *
+ * By using a specialized priority queue, we reduce the overhead caused by the default priority queue implementation
+ * being generic.
*/
internal class FlowTimerQueue(initialCapacity: Int = 256) {
/**
@@ -46,9 +49,11 @@ internal class FlowTimerQueue(initialCapacity: Int = 256) {
*/
fun add(ctx: FlowConsumerContextImpl, deadline: Long) {
val i = size
- val deadlines = _deadlines
+ var deadlines = _deadlines
if (i >= deadlines.size) {
grow()
+ // Re-fetch the resized array
+ deadlines = _deadlines
}
siftUp(deadlines, _pending, i, ctx, deadline)
diff --git a/opendc-telemetry/opendc-telemetry-sdk/src/main/kotlin/org/opendc/telemetry/sdk/OtelClockAdapter.kt b/opendc-telemetry/opendc-telemetry-sdk/src/main/kotlin/org/opendc/telemetry/sdk/OtelClockAdapter.kt
index 86f6647e..cd191652 100644
--- a/opendc-telemetry/opendc-telemetry-sdk/src/main/kotlin/org/opendc/telemetry/sdk/OtelClockAdapter.kt
+++ b/opendc-telemetry/opendc-telemetry-sdk/src/main/kotlin/org/opendc/telemetry/sdk/OtelClockAdapter.kt
@@ -28,7 +28,7 @@ import io.opentelemetry.sdk.common.Clock
* An adapter class that bridges a [java.time.Clock] to a [Clock]
*/
public class OtelClockAdapter(private val clock: java.time.Clock) : Clock {
- override fun now(): Long = clock.millis()
+ override fun now(): Long = nanoTime()
override fun nanoTime(): Long = clock.millis() * 1_000_000L
}