summaryrefslogtreecommitdiff
path: root/odcsim
diff options
context:
space:
mode:
authorFabian Mastenbroek <mail.fabianm@gmail.com>2020-04-12 14:49:27 +0200
committerFabian Mastenbroek <mail.fabianm@gmail.com>2020-04-12 14:49:50 +0200
commit8a8ebe8b2630007d900770d434b985a2f62303a8 (patch)
treee0f5cb22ebdb4b5fbf54349d3a8564ddc4db63e5 /odcsim
parenta584b53847ca6089d892a08fcd65b8694f262603 (diff)
perf: Address profiling hotspot in simulation engine
Diffstat (limited to 'odcsim')
-rw-r--r--odcsim/odcsim-engine-omega/src/main/kotlin/com/atlarge/odcsim/engine/omega/OmegaSimulationEngine.kt50
1 files changed, 24 insertions, 26 deletions
diff --git a/odcsim/odcsim-engine-omega/src/main/kotlin/com/atlarge/odcsim/engine/omega/OmegaSimulationEngine.kt b/odcsim/odcsim-engine-omega/src/main/kotlin/com/atlarge/odcsim/engine/omega/OmegaSimulationEngine.kt
index 934af293..0133832c 100644
--- a/odcsim/odcsim-engine-omega/src/main/kotlin/com/atlarge/odcsim/engine/omega/OmegaSimulationEngine.kt
+++ b/odcsim/odcsim-engine-omega/src/main/kotlin/com/atlarge/odcsim/engine/omega/OmegaSimulationEngine.kt
@@ -46,7 +46,6 @@ import kotlinx.coroutines.InternalCoroutinesApi
import kotlinx.coroutines.Job
import kotlinx.coroutines.Runnable
import kotlinx.coroutines.SupervisorJob
-import kotlinx.coroutines.isActive
import org.jetbrains.annotations.Async
import org.slf4j.Logger
@@ -72,7 +71,12 @@ public class OmegaSimulationEngine(override val name: String) : SimulationEngine
/**
* The event queue to process
*/
- private val queue: PriorityQueue<Event> = PriorityQueue()
+ private val queue: PriorityQueue<Event> = PriorityQueue(Comparator<Event> { lhs, rhs ->
+ // Note that Comparator gives better performance than Comparable according to
+ // profiling
+ val cmp = lhs.time.compareTo(rhs.time)
+ if (cmp == 0) lhs.id.compareTo(rhs.id) else cmp
+ })
/**
* The active processes in the simulation engine.
@@ -97,7 +101,9 @@ public class OmegaSimulationEngine(override val name: String) : SimulationEngine
state = SimulationEngineState.STARTED
}
- while (coroutineContext.isActive) {
+ val job = coroutineContext[Job]
+
+ while (job?.isActive == true) {
val event = queue.peek() ?: break
val delivery = event.time
@@ -126,8 +132,18 @@ public class OmegaSimulationEngine(override val name: String) : SimulationEngine
/**
* Process the delivery of an event.
*/
+ @OptIn(ExperimentalCoroutinesApi::class)
private fun process(@Async.Execute event: Event) {
- event.run()
+ // This has been inlined into this method for performance
+ when (event) {
+ is Event.Dispatch ->
+ event.block.run()
+ is Event.Resume ->
+ with(event.continuation) { event.dispatcher.resumeUndispatched(Unit) }
+ is Event.Timeout ->
+ if (!event.isCancelled)
+ event.block.run()
+ }
}
/**
@@ -142,7 +158,7 @@ public class OmegaSimulationEngine(override val name: String) : SimulationEngine
private fun newDomain(parent: DomainImpl?): Domain {
val name = "$" + UUID.randomUUID()
- return newDomainImpl(name, null)
+ return newDomainImpl(name, parent)
}
private fun newDomain(name: String, parent: DomainImpl?): Domain {
@@ -214,36 +230,18 @@ public class OmegaSimulationEngine(override val name: String) : SimulationEngine
*
* @property time The point in time to deliver the message.
*/
- private sealed class Event(val time: Long, val id: Long) : Comparable<Event>, Runnable {
- override fun compareTo(other: Event): Int {
- val cmp = time.compareTo(other.time)
- return if (cmp == 0) id.compareTo(other.id) else cmp
- }
-
+ private sealed class Event(val time: Long, val id: Long) {
class Dispatch(time: Long, id: Long, val block: Runnable) : Event(time, id) {
- override fun run() = block.run()
-
override fun toString(): String = "Dispatch[$time]"
}
class Resume(time: Long, id: Long, val dispatcher: CoroutineDispatcher, val continuation: CancellableContinuation<Unit>) : Event(time, id) {
- @ExperimentalCoroutinesApi
- override fun run() {
- with(continuation) { dispatcher.resumeUndispatched(Unit) }
- }
-
override fun toString(): String = "Resume[$time]"
}
- class Timeout(time: Long, id: Long, val block: Runnable, var cancelled: Boolean = false) : Event(time, id), DisposableHandle {
- override fun run() {
- if (!cancelled) {
- block.run()
- }
- }
-
+ class Timeout(time: Long, id: Long, val block: Runnable, var isCancelled: Boolean = false) : Event(time, id), DisposableHandle {
override fun dispose() {
- cancelled = true
+ isCancelled = true
}
override fun toString(): String = "Timeout[$time]"