diff options
| author | Fabian Mastenbroek <mail.fabianm@gmail.com> | 2021-10-01 20:08:21 +0200 |
|---|---|---|
| committer | Fabian Mastenbroek <mail.fabianm@gmail.com> | 2021-10-03 17:17:41 +0200 |
| commit | 6e424e9b44687d01e618e7bc38afc427610cd845 (patch) | |
| tree | d7fa113d8a31257cf8aceb7215c041df6a8d5807 | |
| parent | de8509b50d5acb7e739eb5cb4d29b03a627c8985 (diff) | |
perf(simulator): Optimize hot path in SimTraceWorkload
This change optimizes the hot path of the SimTraceWorkload class. This
class is used by multiple experiments to replay workload traces and
consumes a considerable amount of time of the total time of the
experiments.
By inlining the isExpired method, marking the properties on the Fragment
class as field, and caching several properties locally in the class, we
reduce the amount of virtual method calls in the hot path.
| -rw-r--r-- | opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/workload/SimTraceWorkload.kt | 28 |
1 files changed, 15 insertions, 13 deletions
diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/workload/SimTraceWorkload.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/workload/SimTraceWorkload.kt index a877dac1..49ae5933 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/workload/SimTraceWorkload.kt +++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/workload/SimTraceWorkload.kt @@ -53,14 +53,15 @@ public class SimTraceWorkload(public val trace: Sequence<Fragment>, private val * Obtain the fragment with a timestamp equal or greater than [now]. */ private fun pullFragment(now: Long): Fragment? { + // Return the most recent fragment if its starting time + duration is later than `now` var fragment = fragment - if (fragment != null && !fragment.isExpired(now)) { + if (fragment != null && fragment.timestamp + offset + fragment.duration > now) { return fragment } while (iterator.hasNext()) { fragment = iterator.next() - if (!fragment.isExpired(now)) { + if (fragment.timestamp + offset + fragment.duration > now) { this.fragment = fragment return fragment } @@ -70,15 +71,11 @@ public class SimTraceWorkload(public val trace: Sequence<Fragment>, private val return null } - /** - * Determine if the specified [Fragment] is expired, i.e., it has already passed. - */ - private fun Fragment.isExpired(now: Long): Boolean { - val timestamp = this.timestamp + offset - return now >= timestamp + duration - } + private inner class Consumer(cpu: ProcessingUnit) : FlowSource { + private val offset = this@SimTraceWorkload.offset + private val id = cpu.id + private val coreCount = cpu.node.coreCount - private inner class Consumer(val cpu: ProcessingUnit) : FlowSource { override fun onPull(conn: FlowConnection, now: Long, delta: Long): Long { val fragment = pullFragment(now) @@ -95,7 +92,7 @@ public class SimTraceWorkload(public val trace: Sequence<Fragment>, private val return timestamp - now } - val cores = min(cpu.node.coreCount, fragment.cores) + val cores = min(coreCount, fragment.cores) val usage = if (fragment.cores > 0) fragment.usage / cores else @@ -103,7 +100,7 @@ public class SimTraceWorkload(public val trace: Sequence<Fragment>, private val val deadline = timestamp + fragment.duration val duration = deadline - now - conn.push(if (cpu.id < cores && usage > 0.0) usage else 0.0) + conn.push(if (id < cores && usage > 0.0) usage else 0.0) return duration } @@ -117,5 +114,10 @@ public class SimTraceWorkload(public val trace: Sequence<Fragment>, private val * @param usage The CPU usage during the fragment. * @param cores The amount of cores utilized during the fragment. */ - public data class Fragment(val timestamp: Long, val duration: Long, val usage: Double, val cores: Int) + public data class Fragment( + @JvmField val timestamp: Long, + @JvmField val duration: Long, + @JvmField val usage: Double, + @JvmField val cores: Int + ) } |
