summaryrefslogtreecommitdiff
path: root/opendc-simulator/opendc-simulator-compute/src/main/kotlin
diff options
context:
space:
mode:
authorFabian Mastenbroek <mail.fabianm@gmail.com>2022-09-05 20:23:45 +0200
committerFabian Mastenbroek <mail.fabianm@gmail.com>2022-09-21 11:31:15 +0200
commit35ec0060fb73149e687655851a682f12486f0086 (patch)
tree8e6a4f5e14b00584d4054e3a21dc27ddda745b44 /opendc-simulator/opendc-simulator-compute/src/main/kotlin
parent2ec5e8f1e44239916779655d4d68a9c6dae8e894 (diff)
refactor(sim/compute): Move interference logic into VmInterferenceMember
This change updates the design of the VM interference model, where we move more of the logic into the `VmInterferenceMember` interface. This removes the dependency on the `VmInterferenceModel` for the hypervisor interface.
Diffstat (limited to 'opendc-simulator/opendc-simulator-compute/src/main/kotlin')
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimAbstractHypervisor.kt48
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimFairShareHypervisor.kt8
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimFairShareHypervisorProvider.kt4
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimHypervisor.kt4
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimHypervisorProvider.kt7
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimSpaceSharedHypervisorProvider.kt2
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/interference/VmInterferenceDomain.kt37
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/interference/VmInterferenceMember.kt (renamed from opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/interference/VmInterferenceKey.kt)23
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/interference/VmInterferenceModel.kt197
9 files changed, 134 insertions, 196 deletions
diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimAbstractHypervisor.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimAbstractHypervisor.kt
index b3898004..98dab28f 100644
--- a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimAbstractHypervisor.kt
+++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimAbstractHypervisor.kt
@@ -25,8 +25,7 @@ package org.opendc.simulator.compute.kernel
import org.opendc.simulator.compute.*
import org.opendc.simulator.compute.kernel.cpufreq.ScalingGovernor
import org.opendc.simulator.compute.kernel.cpufreq.ScalingPolicy
-import org.opendc.simulator.compute.kernel.interference.VmInterferenceDomain
-import org.opendc.simulator.compute.kernel.interference.VmInterferenceKey
+import org.opendc.simulator.compute.kernel.interference.VmInterferenceMember
import org.opendc.simulator.compute.model.MachineModel
import org.opendc.simulator.compute.model.ProcessingUnit
import org.opendc.simulator.compute.workload.SimWorkload
@@ -42,8 +41,7 @@ import kotlin.math.roundToLong
*/
public abstract class SimAbstractHypervisor(
protected val engine: FlowEngine,
- private val scalingGovernor: ScalingGovernor?,
- protected val interferenceDomain: VmInterferenceDomain? = null
+ private val scalingGovernor: ScalingGovernor?
) : SimHypervisor, FlowConvergenceListener {
/**
* The machine on which the hypervisor runs.
@@ -93,7 +91,7 @@ public abstract class SimAbstractHypervisor(
private val governors = mutableListOf<ScalingGovernor.Logic>()
/* SimHypervisor */
- override fun newMachine(model: MachineModel, interferenceKey: VmInterferenceKey?): SimVirtualMachine {
+ override fun newMachine(model: MachineModel, interferenceKey: VmInterferenceMember?): SimVirtualMachine {
require(canFit(model)) { "Machine does not fit" }
val vm = VirtualMachine(model, interferenceKey)
_vms.add(vm)
@@ -163,7 +161,7 @@ public abstract class SimAbstractHypervisor(
*/
private inner class VirtualMachine(
model: MachineModel,
- private val interferenceKey: VmInterferenceKey? = null
+ private val interferenceKey: VmInterferenceMember? = null
) : SimAbstractMachine(engine, model), SimVirtualMachine, AutoCloseable {
/**
* A flag to indicate that the machine is closed.
@@ -180,7 +178,7 @@ public abstract class SimAbstractHypervisor(
*/
override val counters: SimHypervisorCounters
get() = _counters
- @JvmField val _counters = VmCountersImpl(cpus, interferenceDomain, interferenceKey)
+ @JvmField val _counters = VmCountersImpl(cpus, interferenceKey)
/**
* The CPU capacity of the hypervisor in MHz.
@@ -206,17 +204,18 @@ public abstract class SimAbstractHypervisor(
return super.startWorkload(
object : SimWorkload {
override fun onStart(ctx: SimMachineContext) {
+ val interferenceKey = interferenceKey
try {
- joinInterferenceDomain()
+ interferenceKey?.activate()
workload.onStart(ctx)
} catch (cause: Throwable) {
- leaveInterferenceDomain()
+ interferenceKey?.deactivate()
throw cause
}
}
override fun onStop(ctx: SimMachineContext) {
- leaveInterferenceDomain()
+ interferenceKey?.deactivate()
workload.onStop(ctx)
}
},
@@ -236,26 +235,6 @@ public abstract class SimAbstractHypervisor(
cpu.close()
}
}
-
- /**
- * Join the interference domain of the hypervisor.
- */
- private fun joinInterferenceDomain() {
- val interferenceKey = interferenceKey
- if (interferenceKey != null) {
- interferenceDomain?.join(interferenceKey)
- }
- }
-
- /**
- * Leave the interference domain of the hypervisor.
- */
- private fun leaveInterferenceDomain() {
- val interferenceKey = interferenceKey
- if (interferenceKey != null) {
- interferenceDomain?.leave(interferenceKey)
- }
- }
}
/**
@@ -353,8 +332,7 @@ public abstract class SimAbstractHypervisor(
*/
private inner class VmCountersImpl(
private val cpus: List<VCpu>,
- private val interferenceDomain: VmInterferenceDomain?,
- private val key: VmInterferenceKey?
+ private val key: VmInterferenceMember?
) : SimHypervisorCounters {
private val d = cpus.size / cpus.sumOf { it.model.frequency } * 1000
@@ -403,11 +381,11 @@ public abstract class SimAbstractHypervisor(
cpuTime[2] += ((demandDelta - actualDelta) * d).roundToLong()
// Compute the performance penalty due to flow interference
- val interferenceDomain = interferenceDomain
- if (interferenceDomain != null) {
+ val key = key
+ if (key != null) {
val mux = mux
val load = mux.rate / mux.capacity.coerceAtLeast(1.0)
- val penalty = 1 - interferenceDomain.apply(key, load)
+ val penalty = 1 - key.apply(load)
val interference = (actualDelta * d * penalty).roundToLong()
if (interference > 0) {
diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimFairShareHypervisor.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimFairShareHypervisor.kt
index a12c5517..66453835 100644
--- a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimFairShareHypervisor.kt
+++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimFairShareHypervisor.kt
@@ -24,7 +24,6 @@ package org.opendc.simulator.compute.kernel
import org.opendc.simulator.compute.SimMachine
import org.opendc.simulator.compute.kernel.cpufreq.ScalingGovernor
-import org.opendc.simulator.compute.kernel.interference.VmInterferenceDomain
import org.opendc.simulator.compute.model.MachineModel
import org.opendc.simulator.compute.workload.SimWorkload
import org.opendc.simulator.flow.FlowEngine
@@ -36,15 +35,12 @@ import org.opendc.simulator.flow.mux.MaxMinFlowMultiplexer
* concurrently using weighted fair sharing.
*
* @param engine The [FlowEngine] to manage the machine's resources.
- * @param listener The listener for the convergence of the system.
* @param scalingGovernor The CPU frequency scaling governor to use for the hypervisor.
- * @param interferenceDomain The resource interference domain to which the hypervisor belongs.
*/
public class SimFairShareHypervisor(
engine: FlowEngine,
- scalingGovernor: ScalingGovernor?,
- interferenceDomain: VmInterferenceDomain?,
-) : SimAbstractHypervisor(engine, scalingGovernor, interferenceDomain) {
+ scalingGovernor: ScalingGovernor?
+) : SimAbstractHypervisor(engine, scalingGovernor) {
/**
* The multiplexer that distributes the computing capacity.
*/
diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimFairShareHypervisorProvider.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimFairShareHypervisorProvider.kt
index 204b4860..ad8177d3 100644
--- a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimFairShareHypervisorProvider.kt
+++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimFairShareHypervisorProvider.kt
@@ -23,7 +23,6 @@
package org.opendc.simulator.compute.kernel
import org.opendc.simulator.compute.kernel.cpufreq.ScalingGovernor
-import org.opendc.simulator.compute.kernel.interference.VmInterferenceDomain
import org.opendc.simulator.flow.FlowEngine
/**
@@ -35,6 +34,5 @@ public class SimFairShareHypervisorProvider : SimHypervisorProvider {
override fun create(
engine: FlowEngine,
scalingGovernor: ScalingGovernor?,
- interferenceDomain: VmInterferenceDomain?,
- ): SimHypervisor = SimFairShareHypervisor(engine, scalingGovernor, interferenceDomain)
+ ): SimHypervisor = SimFairShareHypervisor(engine, scalingGovernor)
}
diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimHypervisor.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimHypervisor.kt
index 229e569c..f53d0c5d 100644
--- a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimHypervisor.kt
+++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimHypervisor.kt
@@ -23,7 +23,7 @@
package org.opendc.simulator.compute.kernel
import org.opendc.simulator.compute.SimMachine
-import org.opendc.simulator.compute.kernel.interference.VmInterferenceKey
+import org.opendc.simulator.compute.kernel.interference.VmInterferenceMember
import org.opendc.simulator.compute.model.MachineModel
import org.opendc.simulator.compute.workload.SimWorkload
@@ -68,7 +68,7 @@ public interface SimHypervisor : SimWorkload {
* @param model The machine to create.
* @param interferenceKey The key of the machine in the interference model.
*/
- public fun newMachine(model: MachineModel, interferenceKey: VmInterferenceKey? = null): SimVirtualMachine
+ public fun newMachine(model: MachineModel, interferenceKey: VmInterferenceMember? = null): SimVirtualMachine
/**
* Remove the specified [machine] from the hypervisor.
diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimHypervisorProvider.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimHypervisorProvider.kt
index b7e8760a..6ee523fd 100644
--- a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimHypervisorProvider.kt
+++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimHypervisorProvider.kt
@@ -23,7 +23,6 @@
package org.opendc.simulator.compute.kernel
import org.opendc.simulator.compute.kernel.cpufreq.ScalingGovernor
-import org.opendc.simulator.compute.kernel.interference.VmInterferenceDomain
import org.opendc.simulator.flow.FlowEngine
/**
@@ -41,9 +40,5 @@ public interface SimHypervisorProvider {
/**
* Create a new [SimHypervisor] instance.
*/
- public fun create(
- engine: FlowEngine,
- scalingGovernor: ScalingGovernor? = null,
- interferenceDomain: VmInterferenceDomain? = null,
- ): SimHypervisor
+ public fun create(engine: FlowEngine, scalingGovernor: ScalingGovernor? = null): SimHypervisor
}
diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimSpaceSharedHypervisorProvider.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimSpaceSharedHypervisorProvider.kt
index 96b73e69..f7456797 100644
--- a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimSpaceSharedHypervisorProvider.kt
+++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/SimSpaceSharedHypervisorProvider.kt
@@ -23,7 +23,6 @@
package org.opendc.simulator.compute.kernel
import org.opendc.simulator.compute.kernel.cpufreq.ScalingGovernor
-import org.opendc.simulator.compute.kernel.interference.VmInterferenceDomain
import org.opendc.simulator.flow.FlowEngine
/**
@@ -35,6 +34,5 @@ public class SimSpaceSharedHypervisorProvider : SimHypervisorProvider {
override fun create(
engine: FlowEngine,
scalingGovernor: ScalingGovernor?,
- interferenceDomain: VmInterferenceDomain?,
): SimHypervisor = SimSpaceSharedHypervisor(engine, scalingGovernor)
}
diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/interference/VmInterferenceDomain.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/interference/VmInterferenceDomain.kt
index 5220fa2d..3b355f1e 100644
--- a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/interference/VmInterferenceDomain.kt
+++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/interference/VmInterferenceDomain.kt
@@ -27,40 +27,11 @@ package org.opendc.simulator.compute.kernel.interference
*/
public interface VmInterferenceDomain {
/**
- * Compute the performance score of a participant in this interference domain.
- *
- * @param key The participant to obtain the score of or `null` if the participant has no key.
- * @param load The overall load on the interference domain.
- * @return A score representing the performance score to be applied to the resource consumer, with 1
- * meaning no influence, <1 means that performance degrades, and >1 means that performance improves.
- */
- public fun apply(key: VmInterferenceKey?, load: Double): Double
-
- /**
- * Construct an [VmInterferenceKey] for the specified [id].
+ * Return the [VmInterferenceMember] associated with the specified [id].
*
* @param id The identifier of the virtual machine.
- * @return A key identifying the virtual machine as part of the interference domain. `null` if the virtual machine
- * does not participate in the domain.
- */
- public fun createKey(id: String): VmInterferenceKey?
-
- /**
- * Remove the specified [key] from this domain.
- */
- public fun removeKey(key: VmInterferenceKey)
-
- /**
- * Mark the specified [key] as active in this interference domain.
- *
- * @param key The key to join the interference domain with.
- */
- public fun join(key: VmInterferenceKey)
-
- /**
- * Mark the specified [key] as inactive in this interference domain.
- *
- * @param key The key of the virtual machine that wants to leave the domain.
+ * @return A [VmInterferenceMember] representing the virtual machine as part of the interference domain. `null` if
+ * the virtual machine does not participate in the domain.
*/
- public fun leave(key: VmInterferenceKey)
+ public fun getMember(id: String): VmInterferenceMember?
}
diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/interference/VmInterferenceKey.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/interference/VmInterferenceMember.kt
index 8d720ea9..2f3dd74b 100644
--- a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/interference/VmInterferenceKey.kt
+++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/interference/VmInterferenceMember.kt
@@ -23,6 +23,25 @@
package org.opendc.simulator.compute.kernel.interference
/**
- * A key that uniquely identifies a participant of an interference domain.
+ * A participant of an interference domain.
*/
-public interface VmInterferenceKey
+public interface VmInterferenceMember {
+ /**
+ * Mark this member as active in this interference domain.
+ */
+ public fun activate()
+
+ /**
+ * Mark this member as inactive in this interference domain.
+ */
+ public fun deactivate()
+
+ /**
+ * Compute the performance score of the member in this interference domain.
+ *
+ * @param load The overall load on the interference domain.
+ * @return A score representing the performance score to be applied to the member, with 1
+ * meaning no influence, <1 means that performance degrades, and >1 means that performance improves.
+ */
+ public fun apply(load: Double): Double
+}
diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/interference/VmInterferenceModel.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/interference/VmInterferenceModel.kt
index 7cc545c8..bfda3121 100644
--- a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/interference/VmInterferenceModel.kt
+++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/kernel/interference/VmInterferenceModel.kt
@@ -35,11 +35,11 @@ import java.util.*
* @param seed The seed to use for randomly selecting the virtual machines that are affected.
*/
public class VmInterferenceModel private constructor(
- private val targets: DoubleArray,
- private val scores: DoubleArray,
private val idMapping: Map<String, Int>,
private val members: Array<IntArray>,
private val membership: Array<IntArray>,
+ private val targets: DoubleArray,
+ private val scores: DoubleArray,
private val size: Int,
seed: Long,
) {
@@ -51,13 +51,13 @@ public class VmInterferenceModel private constructor(
/**
* Construct a new [VmInterferenceDomain].
*/
- public fun newDomain(): VmInterferenceDomain = InterferenceDomainImpl(targets, scores, idMapping, members, membership, random)
+ public fun newDomain(): VmInterferenceDomain = InterferenceDomainImpl(idMapping, members, membership, targets, scores, random)
/**
* Create a copy of this model with a different seed.
*/
public fun withSeed(seed: Long): VmInterferenceModel {
- return VmInterferenceModel(targets, scores, idMapping, members, membership, size, seed)
+ return VmInterferenceModel(idMapping, members, membership, targets, scores, size, seed)
}
public companion object {
@@ -171,11 +171,11 @@ public class VmInterferenceModel private constructor(
@Suppress("UNCHECKED_CAST")
return VmInterferenceModel(
- newTargets,
- newScores,
idMapping,
newMembers as Array<IntArray>,
membership.map { it.value.toIntArray() }.toTypedArray(),
+ newTargets,
+ newScores,
size,
seed
)
@@ -197,127 +197,62 @@ public class VmInterferenceModel private constructor(
* Internal implementation of [VmInterferenceDomain].
*/
private class InterferenceDomainImpl(
- private val targets: DoubleArray,
- private val scores: DoubleArray,
private val idMapping: Map<String, Int>,
private val members: Array<IntArray>,
private val membership: Array<IntArray>,
+ private val targets: DoubleArray,
+ private val scores: DoubleArray,
private val random: SplittableRandom
) : VmInterferenceDomain {
/**
* Keys registered with this domain.
*/
- private val keys = HashMap<Int, InterferenceKeyImpl>()
+ private val keys = HashMap<Int, InterferenceMemberImpl>()
/**
* The set of keys active in this domain.
*/
- private val activeKeys = ArrayList<InterferenceKeyImpl>()
-
- override fun createKey(id: String): VmInterferenceKey? {
- val intId = idMapping[id] ?: return null
- return keys.computeIfAbsent(intId) { InterferenceKeyImpl(intId) }
- }
-
- override fun removeKey(key: VmInterferenceKey) {
- if (key !is InterferenceKeyImpl) {
- return
- }
+ private val activeKeys = ArrayList<InterferenceMemberImpl>()
- if (activeKeys.remove(key)) {
- computeActiveGroups(key.id)
- }
+ /**
+ * Queue of participants that will be removed or added to the active groups.
+ */
+ private val participants = ArrayDeque<InterferenceMemberImpl>()
- keys.remove(key.id)
+ override fun getMember(id: String): VmInterferenceMember? {
+ val intId = idMapping[id] ?: return null
+ return keys.computeIfAbsent(intId) { InterferenceMemberImpl(it, this, members, targets, scores, random) }
}
- override fun join(key: VmInterferenceKey) {
- if (key !is InterferenceKeyImpl) {
- return
- }
+ override fun toString(): String = "VmInterferenceDomain"
- if (key.acquire()) {
- val pos = activeKeys.binarySearch(key)
- if (pos < 0) {
- activeKeys.add(-pos - 1, key)
- }
- computeActiveGroups(key.id)
+ fun join(key: InterferenceMemberImpl) {
+ val activeKeys = activeKeys
+ val pos = activeKeys.binarySearch(key)
+ if (pos < 0) {
+ activeKeys.add(-pos - 1, key)
}
- }
- override fun leave(key: VmInterferenceKey) {
- if (key is InterferenceKeyImpl && key.release()) {
- activeKeys.remove(key)
- computeActiveGroups(key.id)
- }
+ computeActiveGroups(activeKeys, key.id)
}
- override fun apply(key: VmInterferenceKey?, load: Double): Double {
- if (key == null || key !is InterferenceKeyImpl) {
- return 1.0
- }
-
- val groups = key.groups
- val groupSize = groups.size
-
- if (groupSize == 0) {
- return 1.0
- }
-
- val targets = targets
- val scores = scores
- var low = 0
- var high = groups.size - 1
-
- var group = -1
- var score = 1.0
-
- // Perform binary search over the groups based on target load
- while (low <= high) {
- val mid = low + high ushr 1
- val midGroup = groups[mid]
- val target = targets[midGroup]
-
- if (target < load) {
- low = mid + 1
- group = midGroup
- score = scores[midGroup]
- } else if (target > load) {
- high = mid - 1
- } else {
- group = midGroup
- score = scores[midGroup]
- break
- }
- }
-
- return if (group >= 0 && random.nextInt(members[group].size) == 0) {
- score
- } else {
- 1.0
- }
+ fun leave(key: InterferenceMemberImpl) {
+ val activeKeys = activeKeys
+ activeKeys.remove(key)
+ computeActiveGroups(activeKeys, key.id)
}
- override fun toString(): String = "VmInterferenceDomain"
-
- /**
- * Queue of participants that will be removed or added to the active groups.
- */
- private val _participants = ArrayDeque<InterferenceKeyImpl>()
-
/**
- * (Re-)Compute the active groups.
+ * (Re-)compute the active groups.
*/
- private fun computeActiveGroups(id: Int) {
- val activeKeys = activeKeys
- val groups = membership[id]
-
+ private fun computeActiveGroups(activeKeys: ArrayList<InterferenceMemberImpl>, id: Int) {
if (activeKeys.isEmpty()) {
return
}
+ val groups = membership[id]
val members = members
- val participants = _participants
+ val participants = participants
for (group in groups) {
val groupMembers = members[group]
@@ -366,7 +301,14 @@ public class VmInterferenceModel private constructor(
*
* @param id The identifier of the member.
*/
- private class InterferenceKeyImpl(@JvmField val id: Int) : VmInterferenceKey, Comparable<InterferenceKeyImpl> {
+ private class InterferenceMemberImpl(
+ @JvmField val id: Int,
+ private val domain: InterferenceDomainImpl,
+ private val members: Array<IntArray>,
+ private val targets: DoubleArray,
+ private val scores: DoubleArray,
+ private val random: SplittableRandom
+ ) : VmInterferenceMember, Comparable<InterferenceMemberImpl> {
/**
* The active groups to which the key belongs.
*/
@@ -377,16 +319,57 @@ public class VmInterferenceModel private constructor(
*/
private var refCount: Int = 0
- /**
- * Join the domain.
- */
- fun acquire(): Boolean = refCount++ <= 0
+ override fun activate() {
+ if (refCount++ <= 0) {
+ domain.join(this)
+ }
+ }
- /**
- * Leave the domain.
- */
- fun release(): Boolean = --refCount <= 0
+ override fun deactivate() {
+ if (--refCount <= 0) {
+ domain.leave(this)
+ }
+ }
+
+ override fun apply(load: Double): Double {
+ val groups = groups
+ val groupSize = groups.size
+
+ if (groupSize == 0) {
+ return 1.0
+ }
+
+ val targets = targets
+ val scores = scores
+ var low = 0
+ var high = groups.size - 1
+
+ var group = -1
+
+ // Perform binary search over the groups based on target load
+ while (low <= high) {
+ val mid = low + high ushr 1
+ val midGroup = groups[mid]
+ val target = targets[midGroup]
+
+ if (target < load) {
+ low = mid + 1
+ group = midGroup
+ } else if (target > load) {
+ high = mid - 1
+ } else {
+ group = midGroup
+ break
+ }
+ }
+
+ return if (group >= 0 && random.nextInt(members[group].size) == 0) {
+ scores[group]
+ } else {
+ 1.0
+ }
+ }
- override fun compareTo(other: InterferenceKeyImpl): Int = id.compareTo(other.id)
+ override fun compareTo(other: InterferenceMemberImpl): Int = id.compareTo(other.id)
}
}