Add advanced passivation strategies (#31124)
This commit is contained in:
parent
7a25618748
commit
61c27ae69c
27 changed files with 4611 additions and 665 deletions
|
|
@ -100,6 +100,24 @@ private[akka] final class FrequencyList[A](dynamicAging: Boolean, clock: OptionV
|
|||
|
||||
def contains(value: A): Boolean = lookupNode.contains(value)
|
||||
|
||||
def leastFrequent: OptionVal[A] = frequency.getFirst match {
|
||||
case OptionVal.Some(least) =>
|
||||
least.nodes.getFirst match {
|
||||
case OptionVal.Some(first) => OptionVal.Some(first.value)
|
||||
case _ => OptionVal.none
|
||||
}
|
||||
case _ => OptionVal.none
|
||||
}
|
||||
|
||||
def mostFrequent: OptionVal[A] = frequency.getLast match {
|
||||
case OptionVal.Some(most) =>
|
||||
most.nodes.getLast match {
|
||||
case OptionVal.Some(last) => OptionVal.Some(last.value)
|
||||
case _ => OptionVal.none
|
||||
}
|
||||
case _ => OptionVal.none
|
||||
}
|
||||
|
||||
def leastToMostFrequent: Iterator[A] = forwardIterator.map(_.value)
|
||||
|
||||
def mostToLeastFrequent: Iterator[A] = backwardIterator.map(_.value)
|
||||
|
|
|
|||
|
|
@ -76,6 +76,16 @@ private[akka] final class RecencyList[A](clock: RecencyList.Clock) {
|
|||
|
||||
def contains(value: A): Boolean = lookupNode.contains(value)
|
||||
|
||||
def leastRecent: OptionVal[A] = recency.getFirst match {
|
||||
case OptionVal.Some(first) => OptionVal.Some(first.value)
|
||||
case _ => OptionVal.none
|
||||
}
|
||||
|
||||
def mostRecent: OptionVal[A] = recency.getLast match {
|
||||
case OptionVal.Some(last) => OptionVal.Some(last.value)
|
||||
case _ => OptionVal.none
|
||||
}
|
||||
|
||||
def leastToMostRecent: Iterator[A] = recency.forwardIterator.map(_.value)
|
||||
|
||||
def mostToLeastRecent: Iterator[A] = recency.backwardIterator.map(_.value)
|
||||
|
|
|
|||
|
|
@ -89,6 +89,11 @@ private[akka] final class SegmentedRecencyList[A](
|
|||
|
||||
def contains(value: A): Boolean = lookupNode.contains(value)
|
||||
|
||||
def leastRecent: OptionVal[A] = segments(lowest).getFirst match {
|
||||
case OptionVal.Some(first) => OptionVal.Some(first.value)
|
||||
case _ => OptionVal.none
|
||||
}
|
||||
|
||||
def leastToMostRecentOf(level: Int): Iterator[A] = segments(level).forwardIterator.map(_.value)
|
||||
|
||||
def removeLeastRecentOverLimit(): immutable.Seq[A] = {
|
||||
|
|
|
|||
|
|
@ -171,13 +171,33 @@ object ClusterShardingSettings {
|
|||
val idleEntitySettings: Option[PassivationStrategySettings.IdleSettings],
|
||||
val activeEntityLimit: Option[Int],
|
||||
val replacementPolicySettings: Option[PassivationStrategySettings.PolicySettings],
|
||||
val admissionSettings: Option[PassivationStrategySettings.AdmissionSettings],
|
||||
private[akka] val oldSettingUsed: Boolean) {
|
||||
|
||||
private[akka] def this(
|
||||
idleEntitySettings: Option[PassivationStrategySettings.IdleSettings],
|
||||
activeEntityLimit: Option[Int],
|
||||
replacementPolicySettings: Option[PassivationStrategySettings.PolicySettings],
|
||||
oldSettingUsed: Boolean) =
|
||||
this(idleEntitySettings, activeEntityLimit, replacementPolicySettings, admissionSettings = None, oldSettingUsed)
|
||||
|
||||
def this(
|
||||
idleEntitySettings: Option[PassivationStrategySettings.IdleSettings],
|
||||
activeEntityLimit: Option[Int],
|
||||
replacementPolicySettings: Option[PassivationStrategySettings.PolicySettings],
|
||||
admissionSettings: Option[PassivationStrategySettings.AdmissionSettings]) =
|
||||
this(idleEntitySettings, activeEntityLimit, replacementPolicySettings, admissionSettings, oldSettingUsed = false)
|
||||
|
||||
def this(
|
||||
idleEntitySettings: Option[PassivationStrategySettings.IdleSettings],
|
||||
activeEntityLimit: Option[Int],
|
||||
replacementPolicySettings: Option[PassivationStrategySettings.PolicySettings]) =
|
||||
this(idleEntitySettings, activeEntityLimit, replacementPolicySettings, oldSettingUsed = false)
|
||||
this(
|
||||
idleEntitySettings,
|
||||
activeEntityLimit,
|
||||
replacementPolicySettings,
|
||||
admissionSettings = None,
|
||||
oldSettingUsed = false)
|
||||
|
||||
import PassivationStrategySettings._
|
||||
|
||||
|
|
@ -213,19 +233,29 @@ object ClusterShardingSettings {
|
|||
def withLeastFrequentlyUsedReplacement(): PassivationStrategySettings =
|
||||
withReplacementPolicy(LeastFrequentlyUsedSettings.defaults)
|
||||
|
||||
def withAdmission(settings: AdmissionSettings): PassivationStrategySettings =
|
||||
copy(admissionSettings = Some(settings))
|
||||
|
||||
private[akka] def withOldIdleStrategy(timeout: FiniteDuration): PassivationStrategySettings =
|
||||
copy(
|
||||
idleEntitySettings = Some(new IdleSettings(timeout, None)),
|
||||
activeEntityLimit = None,
|
||||
replacementPolicySettings = None,
|
||||
admissionSettings = None,
|
||||
oldSettingUsed = true)
|
||||
|
||||
private def copy(
|
||||
idleEntitySettings: Option[IdleSettings] = idleEntitySettings,
|
||||
activeEntityLimit: Option[Int] = activeEntityLimit,
|
||||
replacementPolicySettings: Option[PolicySettings] = replacementPolicySettings,
|
||||
admissionSettings: Option[AdmissionSettings] = admissionSettings,
|
||||
oldSettingUsed: Boolean = oldSettingUsed): PassivationStrategySettings =
|
||||
new PassivationStrategySettings(idleEntitySettings, activeEntityLimit, replacementPolicySettings, oldSettingUsed)
|
||||
new PassivationStrategySettings(
|
||||
idleEntitySettings,
|
||||
activeEntityLimit,
|
||||
replacementPolicySettings,
|
||||
admissionSettings,
|
||||
oldSettingUsed)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -239,6 +269,7 @@ object ClusterShardingSettings {
|
|||
idleEntitySettings = None,
|
||||
activeEntityLimit = None,
|
||||
replacementPolicySettings = None,
|
||||
admissionSettings = None,
|
||||
oldSettingUsed = false)
|
||||
|
||||
val disabled: PassivationStrategySettings = defaults
|
||||
|
|
@ -248,6 +279,7 @@ object ClusterShardingSettings {
|
|||
classic.idleEntitySettings.map(IdleSettings.apply),
|
||||
classic.activeEntityLimit,
|
||||
classic.replacementPolicySettings.map(PolicySettings.apply),
|
||||
classic.admissionSettings.map(AdmissionSettings.apply),
|
||||
classic.oldSettingUsed)
|
||||
|
||||
def toClassic(settings: PassivationStrategySettings): ClassicPassivationStrategySettings =
|
||||
|
|
@ -255,6 +287,7 @@ object ClusterShardingSettings {
|
|||
settings.idleEntitySettings.map(IdleSettings.toClassic),
|
||||
settings.activeEntityLimit,
|
||||
settings.replacementPolicySettings.map(PolicySettings.toClassic),
|
||||
settings.admissionSettings.map(AdmissionSettings.toClassic),
|
||||
settings.oldSettingUsed)
|
||||
|
||||
object IdleSettings {
|
||||
|
|
@ -390,6 +423,221 @@ object ClusterShardingSettings {
|
|||
new LeastFrequentlyUsedSettings(dynamicAging)
|
||||
}
|
||||
|
||||
object AdmissionSettings {
|
||||
val defaults = new AdmissionSettings(filter = None, window = None)
|
||||
|
||||
object FilterSettings {
|
||||
def apply(classic: ClassicPassivationStrategySettings.AdmissionSettings.FilterSettings): FilterSettings =
|
||||
classic match {
|
||||
case classic: ClassicPassivationStrategySettings.AdmissionSettings.FrequencySketchSettings =>
|
||||
FrequencySketchSettings(classic)
|
||||
}
|
||||
|
||||
def toClassic(settings: FilterSettings): ClassicPassivationStrategySettings.AdmissionSettings.FilterSettings =
|
||||
settings match {
|
||||
case settings: FrequencySketchSettings => FrequencySketchSettings.toClassic(settings)
|
||||
}
|
||||
}
|
||||
|
||||
sealed trait FilterSettings
|
||||
|
||||
object FrequencySketchSettings {
|
||||
val defaults =
|
||||
new FrequencySketchSettings(depth = 4, counterBits = 4, widthMultiplier = 4, resetMultiplier = 10.0)
|
||||
|
||||
def apply(classic: ClassicPassivationStrategySettings.AdmissionSettings.FrequencySketchSettings)
|
||||
: FrequencySketchSettings =
|
||||
new FrequencySketchSettings(
|
||||
classic.depth,
|
||||
classic.counterBits,
|
||||
classic.widthMultiplier,
|
||||
classic.resetMultiplier)
|
||||
|
||||
def toClassic(settings: FrequencySketchSettings)
|
||||
: ClassicPassivationStrategySettings.AdmissionSettings.FrequencySketchSettings =
|
||||
new ClassicPassivationStrategySettings.AdmissionSettings.FrequencySketchSettings(
|
||||
settings.depth,
|
||||
settings.counterBits,
|
||||
settings.widthMultiplier,
|
||||
settings.resetMultiplier)
|
||||
}
|
||||
|
||||
final class FrequencySketchSettings(
|
||||
val depth: Int,
|
||||
val counterBits: Int,
|
||||
val widthMultiplier: Int,
|
||||
val resetMultiplier: Double)
|
||||
extends FilterSettings {
|
||||
|
||||
def withDepth(depth: Int): FrequencySketchSettings =
|
||||
copy(depth = depth)
|
||||
|
||||
def withCounterBits(bits: Int): FrequencySketchSettings =
|
||||
copy(counterBits = bits)
|
||||
|
||||
def withWidthMultiplier(multiplier: Int): FrequencySketchSettings =
|
||||
copy(widthMultiplier = multiplier)
|
||||
|
||||
def withResetMultiplier(multiplier: Double): FrequencySketchSettings =
|
||||
copy(resetMultiplier = multiplier)
|
||||
|
||||
private def copy(
|
||||
depth: Int = depth,
|
||||
counterBits: Int = counterBits,
|
||||
widthMultiplier: Int = widthMultiplier,
|
||||
resetMultiplier: Double = resetMultiplier): FrequencySketchSettings =
|
||||
new FrequencySketchSettings(depth, counterBits, widthMultiplier, resetMultiplier)
|
||||
|
||||
}
|
||||
|
||||
object WindowSettings {
|
||||
val defaults: WindowSettings = new WindowSettings(
|
||||
initialProportion = 0.01,
|
||||
minimumProportion = 0.01,
|
||||
maximumProportion = 1.0,
|
||||
optimizer = None,
|
||||
policy = None)
|
||||
|
||||
def apply(classic: ClassicPassivationStrategySettings.AdmissionSettings.WindowSettings): WindowSettings =
|
||||
new WindowSettings(
|
||||
classic.initialProportion,
|
||||
classic.minimumProportion,
|
||||
classic.maximumProportion,
|
||||
classic.optimizer.map(OptimizerSettings.apply),
|
||||
classic.policy.map(PolicySettings.apply))
|
||||
|
||||
def toClassic(settings: WindowSettings): ClassicPassivationStrategySettings.AdmissionSettings.WindowSettings =
|
||||
new ClassicPassivationStrategySettings.AdmissionSettings.WindowSettings(
|
||||
settings.initialProportion,
|
||||
settings.minimumProportion,
|
||||
settings.maximumProportion,
|
||||
settings.optimizer.map(OptimizerSettings.toClassic),
|
||||
settings.policy.map(PolicySettings.toClassic))
|
||||
}
|
||||
|
||||
final class WindowSettings(
|
||||
val initialProportion: Double,
|
||||
val minimumProportion: Double,
|
||||
val maximumProportion: Double,
|
||||
val optimizer: Option[OptimizerSettings],
|
||||
val policy: Option[PolicySettings]) {
|
||||
|
||||
def withInitialProportion(proportion: Double): WindowSettings =
|
||||
copy(initialProportion = proportion)
|
||||
|
||||
def withMinimumProportion(proportion: Double): WindowSettings =
|
||||
copy(minimumProportion = proportion)
|
||||
|
||||
def withMaximumProportion(proportion: Double): WindowSettings =
|
||||
copy(maximumProportion = proportion)
|
||||
|
||||
def withOptimizer(settings: OptimizerSettings): WindowSettings =
|
||||
copy(optimizer = Some(settings))
|
||||
|
||||
def withPolicy(settings: PolicySettings): WindowSettings =
|
||||
copy(policy = Some(settings))
|
||||
|
||||
private def copy(
|
||||
initialProportion: Double = initialProportion,
|
||||
minimumProportion: Double = minimumProportion,
|
||||
maximumProportion: Double = maximumProportion,
|
||||
optimizer: Option[OptimizerSettings] = optimizer,
|
||||
policy: Option[PolicySettings] = policy): WindowSettings =
|
||||
new WindowSettings(initialProportion, minimumProportion, maximumProportion, optimizer, policy)
|
||||
}
|
||||
|
||||
object OptimizerSettings {
|
||||
def apply(classic: ClassicPassivationStrategySettings.AdmissionSettings.OptimizerSettings): OptimizerSettings =
|
||||
classic match {
|
||||
case classic: ClassicPassivationStrategySettings.AdmissionSettings.HillClimbingSettings =>
|
||||
HillClimbingSettings(classic)
|
||||
}
|
||||
|
||||
def toClassic(
|
||||
settings: OptimizerSettings): ClassicPassivationStrategySettings.AdmissionSettings.OptimizerSettings =
|
||||
settings match {
|
||||
case settings: HillClimbingSettings => HillClimbingSettings.toClassic(settings)
|
||||
}
|
||||
}
|
||||
|
||||
sealed trait OptimizerSettings
|
||||
|
||||
object HillClimbingSettings {
|
||||
val defaults: HillClimbingSettings = new HillClimbingSettings(
|
||||
adjustMultiplier = 10.0,
|
||||
initialStep = 0.0625,
|
||||
restartThreshold = 0.05,
|
||||
stepDecay = 0.98)
|
||||
|
||||
def apply(
|
||||
classic: ClassicPassivationStrategySettings.AdmissionSettings.HillClimbingSettings): HillClimbingSettings =
|
||||
new HillClimbingSettings(
|
||||
classic.adjustMultiplier,
|
||||
classic.initialStep,
|
||||
classic.restartThreshold,
|
||||
classic.stepDecay)
|
||||
|
||||
def toClassic(
|
||||
settings: HillClimbingSettings): ClassicPassivationStrategySettings.AdmissionSettings.HillClimbingSettings =
|
||||
new ClassicPassivationStrategySettings.AdmissionSettings.HillClimbingSettings(
|
||||
settings.adjustMultiplier,
|
||||
settings.initialStep,
|
||||
settings.restartThreshold,
|
||||
settings.stepDecay)
|
||||
}
|
||||
|
||||
final class HillClimbingSettings(
|
||||
val adjustMultiplier: Double,
|
||||
val initialStep: Double,
|
||||
val restartThreshold: Double,
|
||||
val stepDecay: Double)
|
||||
extends OptimizerSettings {
|
||||
|
||||
def withAdjustMultiplier(multiplier: Double): HillClimbingSettings =
|
||||
copy(adjustMultiplier = multiplier)
|
||||
|
||||
def withInitialStep(step: Double): HillClimbingSettings =
|
||||
copy(initialStep = step)
|
||||
|
||||
def withRestartThreshold(threshold: Double): HillClimbingSettings =
|
||||
copy(restartThreshold = threshold)
|
||||
|
||||
def withStepDecay(decay: Double): HillClimbingSettings =
|
||||
copy(stepDecay = decay)
|
||||
|
||||
private def copy(
|
||||
adjustMultiplier: Double = adjustMultiplier,
|
||||
initialStep: Double = initialStep,
|
||||
restartThreshold: Double = restartThreshold,
|
||||
stepDecay: Double = stepDecay): HillClimbingSettings =
|
||||
new HillClimbingSettings(adjustMultiplier, initialStep, restartThreshold, stepDecay)
|
||||
}
|
||||
|
||||
def apply(classic: ClassicPassivationStrategySettings.AdmissionSettings): AdmissionSettings =
|
||||
new AdmissionSettings(classic.filter.map(FilterSettings.apply), classic.window.map(WindowSettings.apply))
|
||||
|
||||
def toClassic(settings: AdmissionSettings): ClassicPassivationStrategySettings.AdmissionSettings =
|
||||
new ClassicPassivationStrategySettings.AdmissionSettings(
|
||||
settings.filter.map(FilterSettings.toClassic),
|
||||
settings.window.map(WindowSettings.toClassic))
|
||||
}
|
||||
|
||||
final class AdmissionSettings(
|
||||
val filter: Option[AdmissionSettings.FilterSettings],
|
||||
val window: Option[AdmissionSettings.WindowSettings]) {
|
||||
|
||||
def withFilter(settings: AdmissionSettings.FilterSettings): AdmissionSettings =
|
||||
copy(filter = Some(settings))
|
||||
|
||||
def withWindow(settings: AdmissionSettings.WindowSettings): AdmissionSettings =
|
||||
copy(window = Some(settings))
|
||||
|
||||
private def copy(
|
||||
filter: Option[AdmissionSettings.FilterSettings] = filter,
|
||||
window: Option[AdmissionSettings.WindowSettings] = window): AdmissionSettings =
|
||||
new AdmissionSettings(filter, window)
|
||||
}
|
||||
|
||||
private[akka] def oldDefault(idleTimeout: FiniteDuration): PassivationStrategySettings =
|
||||
disabled.withOldIdleStrategy(idleTimeout)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,12 +53,22 @@ akka.cluster.sharding {
|
|||
}
|
||||
|
||||
# Recommended default strategy for automatic passivation with an active entity limit.
|
||||
# Configured with a segmented least recently used (SLRU) replacement policy.
|
||||
# Configured with an adaptive recency-based admission window, a frequency-based admission filter, and
|
||||
# a segmented least recently used (SLRU) replacement policy for the main active entity tracking.
|
||||
default-strategy {
|
||||
# Default limit of 100k active entities in a shard region (in a cluster node).
|
||||
active-entity-limit = 100000
|
||||
|
||||
# Segmented LRU replacement policy with an 80% "protected" level by default.
|
||||
# Admisson window with LRU policy and adaptive sizing, and a frequency sketch admission filter to the main area.
|
||||
admission {
|
||||
window {
|
||||
policy = least-recently-used
|
||||
optimizer = hill-climbing
|
||||
}
|
||||
filter = frequency-sketch
|
||||
}
|
||||
|
||||
# Main area with segmented LRU replacement policy with an 80% "protected" level by default.
|
||||
replacement {
|
||||
policy = least-recently-used
|
||||
least-recently-used {
|
||||
|
|
@ -118,6 +128,84 @@ akka.cluster.sharding {
|
|||
dynamic-aging = off
|
||||
}
|
||||
}
|
||||
|
||||
# An optional admission area, with a window for newly and recently activated entities, and an admission filter
|
||||
# to determine whether a candidate should be admitted to the main area of the passivation strategy.
|
||||
admission {
|
||||
# An optional window area, where newly created entities will be admitted initially, and when evicted
|
||||
# from the window area have an opportunity to move to the main area based on the admission filter.
|
||||
window {
|
||||
# The initial sizing for the window area (if enabled), as a fraction of the total active entity limit.
|
||||
proportion = 0.01
|
||||
|
||||
# The minimum adaptive sizing for the window area, as a fraction of the total active entity limit.
|
||||
# Only applies when an adaptive window optimizer is enabled.
|
||||
minimum-proportion = 0.01
|
||||
|
||||
# The maximum adaptive sizing for the window area, as a fraction of the total active entity limit.
|
||||
# Only applies when an adaptive window optimizer is enabled.
|
||||
maximum-proportion = 1.0
|
||||
|
||||
# Adaptive optimizer to use for dynamically resizing the window area. Possible values are:
|
||||
# - "hill-climbing"
|
||||
# Set to "none" or "off" to disable adaptive sizing of the window area.
|
||||
optimizer = off
|
||||
|
||||
# A window proportion optimizer using a simple hill-climbing algorithm.
|
||||
hill-climbing {
|
||||
# Multiplier of the active entity limit for how often (in accesses) to adjust the window proportion.
|
||||
adjust-multiplier = 10.0
|
||||
|
||||
# The size of the initial step to take (also used when the climbing restarts).
|
||||
initial-step = 0.0625
|
||||
|
||||
# A threshold for the change in active rate (hit rate) to restart climbing.
|
||||
restart-threshold = 0.05
|
||||
|
||||
# The decay ratio applied on each climbing step.
|
||||
step-decay = 0.98
|
||||
}
|
||||
|
||||
# Replacement policy to use for the window area.
|
||||
# Entities that are evicted from the window area may move to the main area, based on the admission filter.
|
||||
# Possible values are the same as for the main replacement policy.
|
||||
# Set to "none" or "off" to disable the window area.
|
||||
policy = none
|
||||
|
||||
least-recently-used {
|
||||
segmented {
|
||||
levels = none
|
||||
proportions = []
|
||||
}
|
||||
}
|
||||
|
||||
most-recently-used {}
|
||||
|
||||
least-frequently-used {
|
||||
dynamic-aging = off
|
||||
}
|
||||
}
|
||||
|
||||
# The admission filter for the main area of the passivation strategy. Possible values are:
|
||||
# - "frequency-sketch"
|
||||
# Set to "none" or "off" to disable the admission filter and always admit to the main area.
|
||||
filter = none
|
||||
|
||||
# An admission filter based on a frequency sketch (a variation of a count-min sketch).
|
||||
frequency-sketch {
|
||||
# The depth of the frequency sketch (the number of hash functions).
|
||||
depth = 4
|
||||
|
||||
# The size of the frequency counters in bits: 2, 4, 8, 16, 32, or 64 bits.
|
||||
counter-bits = 4
|
||||
|
||||
# Multiplier of the active entity limit for the width of the frequency sketch.
|
||||
width-multiplier = 4
|
||||
|
||||
# Multiplier of the active entity limit for how often the reset operation of the frequency sketch is applied.
|
||||
reset-multiplier = 10.0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -137,13 +137,33 @@ object ClusterShardingSettings {
|
|||
val idleEntitySettings: Option[PassivationStrategySettings.IdleSettings],
|
||||
val activeEntityLimit: Option[Int],
|
||||
val replacementPolicySettings: Option[PassivationStrategySettings.PolicySettings],
|
||||
val admissionSettings: Option[PassivationStrategySettings.AdmissionSettings],
|
||||
private[akka] val oldSettingUsed: Boolean) {
|
||||
|
||||
private[akka] def this(
|
||||
idleEntitySettings: Option[PassivationStrategySettings.IdleSettings],
|
||||
activeEntityLimit: Option[Int],
|
||||
replacementPolicySettings: Option[PassivationStrategySettings.PolicySettings],
|
||||
oldSettingUsed: Boolean) =
|
||||
this(idleEntitySettings, activeEntityLimit, replacementPolicySettings, admissionSettings = None, oldSettingUsed)
|
||||
|
||||
def this(
|
||||
idleEntitySettings: Option[PassivationStrategySettings.IdleSettings],
|
||||
activeEntityLimit: Option[Int],
|
||||
replacementPolicySettings: Option[PassivationStrategySettings.PolicySettings],
|
||||
admissionSettings: Option[PassivationStrategySettings.AdmissionSettings]) =
|
||||
this(idleEntitySettings, activeEntityLimit, replacementPolicySettings, admissionSettings, oldSettingUsed = false)
|
||||
|
||||
def this(
|
||||
idleEntitySettings: Option[PassivationStrategySettings.IdleSettings],
|
||||
activeEntityLimit: Option[Int],
|
||||
replacementPolicySettings: Option[PassivationStrategySettings.PolicySettings]) =
|
||||
this(idleEntitySettings, activeEntityLimit, replacementPolicySettings, oldSettingUsed = false)
|
||||
this(
|
||||
idleEntitySettings,
|
||||
activeEntityLimit,
|
||||
replacementPolicySettings,
|
||||
admissionSettings = None,
|
||||
oldSettingUsed = false)
|
||||
|
||||
import PassivationStrategySettings._
|
||||
|
||||
|
|
@ -179,19 +199,29 @@ object ClusterShardingSettings {
|
|||
def withLeastFrequentlyUsedReplacement(): PassivationStrategySettings =
|
||||
withReplacementPolicy(LeastFrequentlyUsedSettings.defaults)
|
||||
|
||||
def withAdmission(settings: AdmissionSettings): PassivationStrategySettings =
|
||||
copy(admissionSettings = Some(settings))
|
||||
|
||||
private[akka] def withOldIdleStrategy(timeout: FiniteDuration): PassivationStrategySettings =
|
||||
copy(
|
||||
idleEntitySettings = Some(new IdleSettings(timeout, None)),
|
||||
activeEntityLimit = None,
|
||||
replacementPolicySettings = None,
|
||||
admissionSettings = None,
|
||||
oldSettingUsed = true)
|
||||
|
||||
private def copy(
|
||||
idleEntitySettings: Option[IdleSettings] = idleEntitySettings,
|
||||
activeEntityLimit: Option[Int] = activeEntityLimit,
|
||||
replacementPolicySettings: Option[PolicySettings] = replacementPolicySettings,
|
||||
admissionSettings: Option[AdmissionSettings] = admissionSettings,
|
||||
oldSettingUsed: Boolean = oldSettingUsed): PassivationStrategySettings =
|
||||
new PassivationStrategySettings(idleEntitySettings, activeEntityLimit, replacementPolicySettings, oldSettingUsed)
|
||||
new PassivationStrategySettings(
|
||||
idleEntitySettings,
|
||||
activeEntityLimit,
|
||||
replacementPolicySettings,
|
||||
admissionSettings,
|
||||
oldSettingUsed)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -203,6 +233,7 @@ object ClusterShardingSettings {
|
|||
idleEntitySettings = None,
|
||||
activeEntityLimit = None,
|
||||
replacementPolicySettings = None,
|
||||
admissionSettings = None,
|
||||
oldSettingUsed = false)
|
||||
|
||||
val disabled: PassivationStrategySettings = defaults
|
||||
|
|
@ -340,6 +371,195 @@ object ClusterShardingSettings {
|
|||
new LeastFrequentlyUsedSettings(dynamicAging)
|
||||
}
|
||||
|
||||
object AdmissionSettings {
|
||||
val defaults = new AdmissionSettings(filter = None, window = None)
|
||||
|
||||
object FilterSettings {
|
||||
def optional(config: Config): Option[FilterSettings] =
|
||||
toRootLowerCase(config.getString("filter")) match {
|
||||
case "off" | "none" => None
|
||||
case "frequency-sketch" => Some(FrequencySketchSettings(config.getConfig("frequency-sketch")))
|
||||
case _ => None
|
||||
}
|
||||
}
|
||||
|
||||
sealed trait FilterSettings
|
||||
|
||||
object FrequencySketchSettings {
|
||||
val defaults =
|
||||
new FrequencySketchSettings(depth = 4, counterBits = 4, widthMultiplier = 4, resetMultiplier = 10.0)
|
||||
|
||||
def apply(config: Config): FrequencySketchSettings = {
|
||||
val depth = config.getInt("depth")
|
||||
val counterBits = config.getInt("counter-bits")
|
||||
val widthMultiplier = config.getInt("width-multiplier")
|
||||
val resetMultiplier = config.getDouble("reset-multiplier")
|
||||
new FrequencySketchSettings(depth, counterBits, widthMultiplier, resetMultiplier)
|
||||
}
|
||||
}
|
||||
|
||||
final class FrequencySketchSettings(
|
||||
val depth: Int,
|
||||
val counterBits: Int,
|
||||
val widthMultiplier: Int,
|
||||
val resetMultiplier: Double)
|
||||
extends FilterSettings {
|
||||
|
||||
def withDepth(depth: Int): FrequencySketchSettings =
|
||||
copy(depth = depth)
|
||||
|
||||
def withCounterBits(bits: Int): FrequencySketchSettings =
|
||||
copy(counterBits = bits)
|
||||
|
||||
def withWidthMultiplier(multiplier: Int): FrequencySketchSettings =
|
||||
copy(widthMultiplier = multiplier)
|
||||
|
||||
def withResetMultiplier(multiplier: Double): FrequencySketchSettings =
|
||||
copy(resetMultiplier = multiplier)
|
||||
|
||||
private def copy(
|
||||
depth: Int = depth,
|
||||
counterBits: Int = counterBits,
|
||||
widthMultiplier: Int = widthMultiplier,
|
||||
resetMultiplier: Double = resetMultiplier): FrequencySketchSettings =
|
||||
new FrequencySketchSettings(depth, counterBits, widthMultiplier, resetMultiplier)
|
||||
|
||||
}
|
||||
|
||||
object WindowSettings {
|
||||
val defaults: WindowSettings = new WindowSettings(
|
||||
initialProportion = 0.01,
|
||||
minimumProportion = 0.01,
|
||||
maximumProportion = 1.0,
|
||||
optimizer = None,
|
||||
policy = None)
|
||||
|
||||
def apply(config: Config): WindowSettings = {
|
||||
val initialProportion = config.getDouble("proportion")
|
||||
val minimumProportion = config.getDouble("minimum-proportion")
|
||||
val maximumProportion = config.getDouble("maximum-proportion")
|
||||
val optimizer = OptimizerSettings.optional(config)
|
||||
val policy = PolicySettings.optional(config)
|
||||
new WindowSettings(initialProportion, minimumProportion, maximumProportion, optimizer, policy)
|
||||
}
|
||||
|
||||
def optional(config: Config): Option[WindowSettings] =
|
||||
toRootLowerCase(config.getString("policy")) match {
|
||||
case "off" | "none" => None
|
||||
case _ => Some(WindowSettings(config))
|
||||
}
|
||||
}
|
||||
|
||||
final class WindowSettings(
|
||||
val initialProportion: Double,
|
||||
val minimumProportion: Double,
|
||||
val maximumProportion: Double,
|
||||
val optimizer: Option[OptimizerSettings],
|
||||
val policy: Option[PolicySettings]) {
|
||||
|
||||
def withInitialProportion(proportion: Double): WindowSettings =
|
||||
copy(initialProportion = proportion)
|
||||
|
||||
def withMinimumProportion(proportion: Double): WindowSettings =
|
||||
copy(minimumProportion = proportion)
|
||||
|
||||
def withMaximumProportion(proportion: Double): WindowSettings =
|
||||
copy(maximumProportion = proportion)
|
||||
|
||||
def withOptimizer(settings: OptimizerSettings): WindowSettings =
|
||||
copy(optimizer = Some(settings))
|
||||
|
||||
def withPolicy(settings: PolicySettings): WindowSettings =
|
||||
copy(policy = Some(settings))
|
||||
|
||||
private def copy(
|
||||
initialProportion: Double = initialProportion,
|
||||
minimumProportion: Double = minimumProportion,
|
||||
maximumProportion: Double = maximumProportion,
|
||||
optimizer: Option[OptimizerSettings] = optimizer,
|
||||
policy: Option[PolicySettings] = policy): WindowSettings =
|
||||
new WindowSettings(initialProportion, minimumProportion, maximumProportion, optimizer, policy)
|
||||
}
|
||||
|
||||
object OptimizerSettings {
|
||||
def optional(config: Config): Option[OptimizerSettings] =
|
||||
toRootLowerCase(config.getString("optimizer")) match {
|
||||
case "off" | "none" => None
|
||||
case "hill-climbing" => Some(HillClimbingSettings(config.getConfig("hill-climbing")))
|
||||
case _ => None
|
||||
}
|
||||
}
|
||||
|
||||
sealed trait OptimizerSettings
|
||||
|
||||
object HillClimbingSettings {
|
||||
val defaults: HillClimbingSettings = new HillClimbingSettings(
|
||||
adjustMultiplier = 10.0,
|
||||
initialStep = 0.0625,
|
||||
restartThreshold = 0.05,
|
||||
stepDecay = 0.98)
|
||||
|
||||
def apply(config: Config): HillClimbingSettings = {
|
||||
val adjustMultiplier = config.getDouble("adjust-multiplier")
|
||||
val initialStep = config.getDouble("initial-step")
|
||||
val restartThreshold = config.getDouble("restart-threshold")
|
||||
val stepDecay = config.getDouble("step-decay")
|
||||
new HillClimbingSettings(adjustMultiplier, initialStep, restartThreshold, stepDecay)
|
||||
}
|
||||
}
|
||||
|
||||
final class HillClimbingSettings(
|
||||
val adjustMultiplier: Double,
|
||||
val initialStep: Double,
|
||||
val restartThreshold: Double,
|
||||
val stepDecay: Double)
|
||||
extends OptimizerSettings {
|
||||
|
||||
def withAdjustMultiplier(multiplier: Double): HillClimbingSettings =
|
||||
copy(adjustMultiplier = multiplier)
|
||||
|
||||
def withInitialStep(step: Double): HillClimbingSettings =
|
||||
copy(initialStep = step)
|
||||
|
||||
def withRestartThreshold(threshold: Double): HillClimbingSettings =
|
||||
copy(restartThreshold = threshold)
|
||||
|
||||
def withStepDecay(decay: Double): HillClimbingSettings =
|
||||
copy(stepDecay = decay)
|
||||
|
||||
private def copy(
|
||||
adjustMultiplier: Double = adjustMultiplier,
|
||||
initialStep: Double = initialStep,
|
||||
restartThreshold: Double = restartThreshold,
|
||||
stepDecay: Double = stepDecay): HillClimbingSettings =
|
||||
new HillClimbingSettings(adjustMultiplier, initialStep, restartThreshold, stepDecay)
|
||||
}
|
||||
|
||||
def optional(config: Config): Option[AdmissionSettings] = {
|
||||
val filter = FilterSettings.optional(config)
|
||||
val window = WindowSettings.optional(config.getConfig("window"))
|
||||
if (filter.isDefined || window.isDefined)
|
||||
Some(new AdmissionSettings(filter, window))
|
||||
else None
|
||||
}
|
||||
}
|
||||
|
||||
final class AdmissionSettings(
|
||||
val filter: Option[AdmissionSettings.FilterSettings],
|
||||
val window: Option[AdmissionSettings.WindowSettings]) {
|
||||
|
||||
def withFilter(settings: AdmissionSettings.FilterSettings): AdmissionSettings =
|
||||
copy(filter = Some(settings))
|
||||
|
||||
def withWindow(settings: AdmissionSettings.WindowSettings): AdmissionSettings =
|
||||
copy(window = Some(settings))
|
||||
|
||||
private def copy(
|
||||
filter: Option[AdmissionSettings.FilterSettings] = filter,
|
||||
window: Option[AdmissionSettings.WindowSettings] = window): AdmissionSettings =
|
||||
new AdmissionSettings(filter, window)
|
||||
}
|
||||
|
||||
/**
|
||||
* API MAY CHANGE: Settings and configuration for passivation strategies may change after additional
|
||||
* testing and feedback.
|
||||
|
|
@ -357,7 +577,12 @@ object ClusterShardingSettings {
|
|||
case _ => Some(strategyConfig.getInt("active-entity-limit"))
|
||||
}
|
||||
val replacementPolicySettings = PolicySettings.optional(strategyConfig.getConfig("replacement"))
|
||||
new PassivationStrategySettings(idleEntitySettings, activeEntityLimit, replacementPolicySettings)
|
||||
val admissionSettings = AdmissionSettings.optional(strategyConfig.getConfig("admission"))
|
||||
new PassivationStrategySettings(
|
||||
idleEntitySettings,
|
||||
activeEntityLimit,
|
||||
replacementPolicySettings,
|
||||
admissionSettings)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -465,6 +690,101 @@ object ClusterShardingSettings {
|
|||
idle: Option[IdlePassivationStrategy])
|
||||
extends PassivationStrategy
|
||||
|
||||
/**
|
||||
* INTERNAL API
|
||||
*/
|
||||
@InternalApi
|
||||
private[akka] object CompositePassivationStrategy {
|
||||
object AdmissionFilter {
|
||||
def apply(filterSettings: Option[PassivationStrategySettings.AdmissionSettings.FilterSettings]): AdmissionFilter =
|
||||
filterSettings match {
|
||||
case Some(settings: PassivationStrategySettings.AdmissionSettings.FrequencySketchSettings) =>
|
||||
FrequencySketchAdmissionFilter(
|
||||
widthMultiplier = settings.widthMultiplier,
|
||||
resetMultiplier = settings.resetMultiplier,
|
||||
depth = settings.depth,
|
||||
counterBits = settings.counterBits)
|
||||
case _ => AlwaysAdmissionFilter
|
||||
}
|
||||
}
|
||||
|
||||
sealed trait AdmissionFilter
|
||||
|
||||
case object AlwaysAdmissionFilter extends AdmissionFilter
|
||||
|
||||
case class FrequencySketchAdmissionFilter(
|
||||
widthMultiplier: Int,
|
||||
resetMultiplier: Double,
|
||||
depth: Int,
|
||||
counterBits: Int)
|
||||
extends AdmissionFilter
|
||||
|
||||
object AdmissionOptimizer {
|
||||
def apply(optimizerSettings: Option[PassivationStrategySettings.AdmissionSettings.OptimizerSettings])
|
||||
: AdmissionOptimizer =
|
||||
optimizerSettings match {
|
||||
case Some(settings: PassivationStrategySettings.AdmissionSettings.HillClimbingSettings) =>
|
||||
HillClimbingAdmissionOptimizer(
|
||||
adjustMultiplier = settings.adjustMultiplier,
|
||||
initialStep = settings.initialStep,
|
||||
restartThreshold = settings.restartThreshold,
|
||||
stepDecay = settings.stepDecay)
|
||||
case _ => NoAdmissionOptimizer
|
||||
}
|
||||
}
|
||||
|
||||
sealed trait AdmissionOptimizer
|
||||
|
||||
case object NoAdmissionOptimizer extends AdmissionOptimizer
|
||||
|
||||
case class HillClimbingAdmissionOptimizer(
|
||||
adjustMultiplier: Double,
|
||||
initialStep: Double,
|
||||
restartThreshold: Double,
|
||||
stepDecay: Double)
|
||||
extends AdmissionOptimizer
|
||||
|
||||
def apply(
|
||||
limit: Int,
|
||||
mainSettings: Option[PassivationStrategySettings.PolicySettings],
|
||||
admissionSettings: PassivationStrategySettings.AdmissionSettings,
|
||||
idle: Option[IdlePassivationStrategy]): CompositePassivationStrategy = {
|
||||
val mainStrategy = PassivationStrategy(mainSettings, limit = 0, idle = None)
|
||||
val windowStrategy = PassivationStrategy(admissionSettings.window.flatMap(_.policy), limit = 0, idle = None)
|
||||
val initialWindowProportion = admissionSettings.window.fold(0.0)(_.initialProportion)
|
||||
val minimumWindowProportion = admissionSettings.window.fold(0.0)(_.minimumProportion)
|
||||
val maximumWindowProportion = admissionSettings.window.fold(0.0)(_.maximumProportion)
|
||||
val windowOptimizer = AdmissionOptimizer(admissionSettings.window.flatMap(_.optimizer))
|
||||
val admissionFilter = AdmissionFilter(admissionSettings.filter)
|
||||
CompositePassivationStrategy(
|
||||
limit,
|
||||
mainStrategy,
|
||||
windowStrategy,
|
||||
initialWindowProportion,
|
||||
minimumWindowProportion,
|
||||
maximumWindowProportion,
|
||||
windowOptimizer,
|
||||
admissionFilter,
|
||||
idle)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL API
|
||||
*/
|
||||
@InternalApi
|
||||
private[akka] case class CompositePassivationStrategy(
|
||||
limit: Int,
|
||||
mainStrategy: PassivationStrategy,
|
||||
windowStrategy: PassivationStrategy,
|
||||
initialWindowProportion: Double,
|
||||
minimumWindowProportion: Double,
|
||||
maximumWindowProportion: Double,
|
||||
windowOptimizer: CompositePassivationStrategy.AdmissionOptimizer,
|
||||
admissionFilter: CompositePassivationStrategy.AdmissionFilter,
|
||||
idle: Option[IdlePassivationStrategy])
|
||||
extends PassivationStrategy
|
||||
|
||||
/**
|
||||
* INTERNAL API
|
||||
* Determine the passivation strategy to use from settings.
|
||||
|
|
@ -481,18 +801,103 @@ object ClusterShardingSettings {
|
|||
}
|
||||
settings.passivationStrategySettings.activeEntityLimit match {
|
||||
case Some(limit) =>
|
||||
settings.passivationStrategySettings.replacementPolicySettings match {
|
||||
case Some(settings: PassivationStrategySettings.LeastRecentlyUsedSettings) =>
|
||||
LeastRecentlyUsedPassivationStrategy(settings, limit, idle)
|
||||
case Some(_: PassivationStrategySettings.MostRecentlyUsedSettings) =>
|
||||
MostRecentlyUsedPassivationStrategy(limit, idle)
|
||||
case Some(settings: PassivationStrategySettings.LeastFrequentlyUsedSettings) =>
|
||||
LeastFrequentlyUsedPassivationStrategy(settings, limit, idle)
|
||||
case _ => idle.getOrElse(NoPassivationStrategy)
|
||||
settings.passivationStrategySettings.admissionSettings match {
|
||||
case Some(admission) =>
|
||||
val main = settings.passivationStrategySettings.replacementPolicySettings
|
||||
CompositePassivationStrategy(limit, main, admission, idle)
|
||||
case _ =>
|
||||
PassivationStrategy(settings.passivationStrategySettings.replacementPolicySettings, limit, idle)
|
||||
}
|
||||
case _ => idle.getOrElse(NoPassivationStrategy)
|
||||
}
|
||||
}
|
||||
|
||||
def apply(
|
||||
policySettings: Option[PassivationStrategySettings.PolicySettings],
|
||||
limit: Int,
|
||||
idle: Option[IdlePassivationStrategy]): PassivationStrategy = policySettings match {
|
||||
case Some(settings: PassivationStrategySettings.LeastRecentlyUsedSettings) =>
|
||||
LeastRecentlyUsedPassivationStrategy(settings, limit, idle)
|
||||
case Some(_: PassivationStrategySettings.MostRecentlyUsedSettings) =>
|
||||
MostRecentlyUsedPassivationStrategy(limit, idle)
|
||||
case Some(settings: PassivationStrategySettings.LeastFrequentlyUsedSettings) =>
|
||||
LeastFrequentlyUsedPassivationStrategy(settings, limit, idle)
|
||||
case _ => idle.getOrElse(NoPassivationStrategy)
|
||||
}
|
||||
|
||||
def describe(strategy: PassivationStrategy): String = {
|
||||
import akka.util.PrettyDuration._
|
||||
strategy match {
|
||||
case NoPassivationStrategy =>
|
||||
"disabled"
|
||||
case IdlePassivationStrategy(timeout, interval) =>
|
||||
s"idle entities after [${timeout.pretty}], checked every [${interval.pretty}]"
|
||||
case LeastRecentlyUsedPassivationStrategy(limit, segmented, idle) =>
|
||||
s"least recently used entities" +
|
||||
(if (limit > 0) s" when over [$limit] entities" else "") +
|
||||
(if (segmented.nonEmpty) {
|
||||
val levels = segmented.size
|
||||
val proportions = segmented.map(proportion => "%.2f".format(proportion)).mkString(", ")
|
||||
s" (segmented with [$levels] levels with proportions of [$proportions])"
|
||||
} else "") +
|
||||
idle.fold("")(idle => " and " + describe(idle))
|
||||
case MostRecentlyUsedPassivationStrategy(limit, idle) =>
|
||||
s"most recently used entities" +
|
||||
(if (limit > 0) s" when over [$limit] entities" else "") +
|
||||
idle.fold("")(idle => " and " + describe(idle))
|
||||
case LeastFrequentlyUsedPassivationStrategy(limit, dynamicAging, idle) =>
|
||||
s"least frequently used entities" +
|
||||
(if (limit > 0) s" when over [$limit] entities" else "") +
|
||||
(if (dynamicAging) " (with dynamic aging)" else "") +
|
||||
idle.fold("")(idle => " and " + describe(idle))
|
||||
case CompositePassivationStrategy(
|
||||
limit,
|
||||
mainStrategy,
|
||||
windowStrategy,
|
||||
initialWindowProportion,
|
||||
minimumWindowProportion,
|
||||
maximumWindowProportion,
|
||||
windowOptimizer,
|
||||
admissionFilter,
|
||||
idle) =>
|
||||
val describeWindow = windowStrategy match {
|
||||
case NoPassivationStrategy => "no admission window"
|
||||
case _ =>
|
||||
s"admission window (${describe(windowStrategy)})" +
|
||||
(windowOptimizer match {
|
||||
case CompositePassivationStrategy.NoAdmissionOptimizer =>
|
||||
s" with proportion [$initialWindowProportion]"
|
||||
case CompositePassivationStrategy.HillClimbingAdmissionOptimizer(
|
||||
adjustMultiplier,
|
||||
initialStep,
|
||||
restartThreshold,
|
||||
stepDecay) =>
|
||||
s" with proportions [initial = $initialWindowProportion, min = $minimumWindowProportion, max = $maximumWindowProportion]" +
|
||||
" adapting with hill-climbing optimizer [" +
|
||||
s"adjust multiplier = $adjustMultiplier, " +
|
||||
s"initial step = $initialStep, " +
|
||||
s"restart threshold = $restartThreshold, " +
|
||||
s"step decay = $stepDecay]"
|
||||
})
|
||||
}
|
||||
val describeFilter = admissionFilter match {
|
||||
case CompositePassivationStrategy.AlwaysAdmissionFilter => "always admit"
|
||||
case CompositePassivationStrategy.FrequencySketchAdmissionFilter(
|
||||
widthMultiplier,
|
||||
resetMultiplier,
|
||||
depth,
|
||||
counterBits) =>
|
||||
"admit using frequency sketch [" +
|
||||
s"width multiplier = $widthMultiplier, " +
|
||||
s"reset multiplier = $resetMultiplier, " +
|
||||
s"depth = $depth, " +
|
||||
s"counter bits = $counterBits]"
|
||||
}
|
||||
s"composite strategy with limit of [$limit] active entities, " +
|
||||
s"$describeWindow, $describeFilter, main (${describe(mainStrategy)})" +
|
||||
idle.fold("")(idle => " and " + describe(idle))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TuningParameters(
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@
|
|||
package akka.cluster.sharding
|
||||
|
||||
import java.net.URLEncoder
|
||||
|
||||
import scala.annotation.tailrec
|
||||
import scala.collection.immutable
|
||||
import scala.concurrent.{ Future, Promise }
|
||||
|
|
@ -23,13 +22,13 @@ import akka.cluster.ClusterSettings
|
|||
import akka.cluster.ClusterSettings.DataCenter
|
||||
import akka.cluster.Member
|
||||
import akka.cluster.MemberStatus
|
||||
import akka.cluster.sharding.ClusterShardingSettings.PassivationStrategy
|
||||
import akka.cluster.sharding.Shard.ShardStats
|
||||
import akka.cluster.sharding.internal.RememberEntitiesProvider
|
||||
import akka.event.Logging
|
||||
import akka.pattern.ask
|
||||
import akka.pattern.pipe
|
||||
import akka.util.MessageBufferMap
|
||||
import akka.util.PrettyDuration
|
||||
import akka.util.Timeout
|
||||
|
||||
/**
|
||||
|
|
@ -689,42 +688,13 @@ private[akka] class ShardRegion(
|
|||
if (settings.rememberEntities) {
|
||||
log.debug("{}: Entities will not be passivated automatically because 'rememberEntities' is enabled.", typeName)
|
||||
} else {
|
||||
logPassivation(settings.passivationStrategy)
|
||||
log.info(
|
||||
"{}: Automatic entity passivation: {}",
|
||||
typeName,
|
||||
PassivationStrategy.describe(settings.passivationStrategy))
|
||||
}
|
||||
}
|
||||
|
||||
private def logPassivation(strategy: ClusterShardingSettings.PassivationStrategy): Unit =
|
||||
strategy match {
|
||||
case ClusterShardingSettings.IdlePassivationStrategy(timeout, interval) =>
|
||||
log.info(
|
||||
"{}: Idle entities will be passivated after [{}], checked every [{}]",
|
||||
typeName,
|
||||
PrettyDuration.format(timeout),
|
||||
PrettyDuration.format(interval))
|
||||
case ClusterShardingSettings.LeastRecentlyUsedPassivationStrategy(limit, segmented, idle) =>
|
||||
log.info("{}: Least recently used entities will be passivated when over [{}] entities", typeName, limit)
|
||||
if (segmented.nonEmpty) {
|
||||
log.info(
|
||||
"{}: Least recently used strategy is segmented with [{}] levels with proportions of [{}]",
|
||||
typeName,
|
||||
segmented.size,
|
||||
segmented.map(proportion => "%.2f".format(proportion)).mkString(", "))
|
||||
}
|
||||
idle.foreach(logPassivation)
|
||||
case ClusterShardingSettings.MostRecentlyUsedPassivationStrategy(limit, idle) =>
|
||||
log.info("{}: Most recently used entities will be passivated when over [{}] entities", typeName, limit)
|
||||
idle.foreach(logPassivation)
|
||||
case ClusterShardingSettings.LeastFrequentlyUsedPassivationStrategy(limit, dynamicAging, idle) =>
|
||||
log.info(
|
||||
"{}: Least frequently used entities will be passivated when over [{}] entities {}",
|
||||
typeName,
|
||||
limit,
|
||||
if (dynamicAging) "with dynamic aging" else "")
|
||||
idle.foreach(logPassivation)
|
||||
case _ =>
|
||||
log.debug("{}: Entities will not be passivated automatically", typeName)
|
||||
}
|
||||
|
||||
// when using proxy the data center can be different from the own data center
|
||||
private val targetDcRole = dataCenter match {
|
||||
case Some(t) => ClusterSettings.DcRolePrefix + t
|
||||
|
|
|
|||
|
|
@ -7,6 +7,9 @@ package akka.cluster.sharding.internal
|
|||
import akka.annotation.InternalApi
|
||||
import akka.cluster.sharding.ClusterShardingSettings
|
||||
import akka.cluster.sharding.ShardRegion.EntityId
|
||||
import akka.util.FastFrequencySketch
|
||||
import akka.util.FrequencySketch
|
||||
import akka.util.OptionVal
|
||||
import akka.util.{ FrequencyList, RecencyList, SegmentedRecencyList }
|
||||
|
||||
import scala.collection.immutable
|
||||
|
|
@ -37,6 +40,31 @@ private[akka] object EntityPassivationStrategy {
|
|||
case ClusterShardingSettings.LeastFrequentlyUsedPassivationStrategy(limit, dynamicAging, idle) =>
|
||||
val idleCheck = idle.map(idle => new IdleCheck(idle.timeout, idle.interval))
|
||||
new LeastFrequentlyUsedEntityPassivationStrategy(limit, dynamicAging, idleCheck)
|
||||
case composite: ClusterShardingSettings.CompositePassivationStrategy =>
|
||||
val main = ActiveEntities(composite.mainStrategy, composite.idle.isDefined)
|
||||
if (main eq NoActiveEntities) DisabledEntityPassivationStrategy
|
||||
else {
|
||||
val initialLimit = composite.limit
|
||||
val window = ActiveEntities(composite.windowStrategy, composite.idle.isDefined)
|
||||
val initialWindowProportion = if (window eq NoActiveEntities) 0.0 else composite.initialWindowProportion
|
||||
val minimumWindowProportion = if (window eq NoActiveEntities) 0.0 else composite.minimumWindowProportion
|
||||
val maximumWindowProportion = if (window eq NoActiveEntities) 0.0 else composite.maximumWindowProportion
|
||||
val windowOptimizer =
|
||||
if (window eq NoActiveEntities) NoAdmissionOptimizer
|
||||
else AdmissionOptimizer(composite.limit, composite.windowOptimizer)
|
||||
val admissionFilter = AdmissionFilter(composite.limit, composite.admissionFilter)
|
||||
val idleCheck = composite.idle.map(idle => new IdleCheck(idle.timeout, idle.interval))
|
||||
new CompositeEntityPassivationStrategy(
|
||||
initialLimit,
|
||||
window,
|
||||
initialWindowProportion,
|
||||
minimumWindowProportion,
|
||||
maximumWindowProportion,
|
||||
windowOptimizer,
|
||||
admissionFilter,
|
||||
main,
|
||||
idleCheck)
|
||||
}
|
||||
case _ => DisabledEntityPassivationStrategy
|
||||
}
|
||||
}
|
||||
|
|
@ -165,37 +193,31 @@ private[akka] abstract class LimitBasedEntityPassivationStrategy(initialLimit: I
|
|||
}
|
||||
|
||||
/**
|
||||
* INTERNAL API: Passivate the least recently used entities when the number of active entities in a shard region
|
||||
* INTERNAL API
|
||||
*
|
||||
* Passivate the least recently used entities when the number of active entities in a shard region
|
||||
* reaches a limit. The per-region limit is divided evenly among the active shards in a region.
|
||||
*
|
||||
* @param initialLimit initial active entity capacity for a shard region
|
||||
* @param idleCheck optionally passivate idle entities after the given timeout, checking every interval
|
||||
*/
|
||||
@InternalApi
|
||||
private[akka] final class LeastRecentlyUsedEntityPassivationStrategy(initialLimit: Int, idleCheck: Option[IdleCheck])
|
||||
extends LimitBasedEntityPassivationStrategy(initialLimit) {
|
||||
|
||||
import EntityPassivationStrategy.PassivateEntities
|
||||
|
||||
private val recencyList = RecencyList.empty[EntityId]
|
||||
val active = new LeastRecentlyUsedReplacementPolicy(initialLimit)
|
||||
|
||||
override val scheduledInterval: Option[FiniteDuration] = idleCheck.map(_.interval)
|
||||
override protected def passivateEntitiesOnLimitUpdate(): PassivateEntities = active.updateLimit(perShardLimit)
|
||||
|
||||
override def entityTouched(id: EntityId): PassivateEntities = {
|
||||
recencyList.update(id)
|
||||
passivateExcessEntities()
|
||||
}
|
||||
override def entityTouched(id: EntityId): PassivateEntities = active.update(id)
|
||||
|
||||
override def entityTerminated(id: EntityId): Unit = recencyList.remove(id)
|
||||
override def entityTerminated(id: EntityId): Unit = active.remove(id)
|
||||
|
||||
override def scheduledInterval: Option[FiniteDuration] = idleCheck.map(_.interval)
|
||||
|
||||
override def intervalPassed(): PassivateEntities = idleCheck.fold(PassivateEntities.none) { idle =>
|
||||
recencyList.removeLeastRecentOutside(idle.timeout)
|
||||
}
|
||||
|
||||
override protected def passivateEntitiesOnLimitUpdate(): PassivateEntities = passivateExcessEntities()
|
||||
|
||||
private def passivateExcessEntities(): PassivateEntities = {
|
||||
val excess = recencyList.size - perShardLimit
|
||||
if (excess > 0) recencyList.removeLeastRecent(excess) else PassivateEntities.none
|
||||
active.removeIdle(idle.timeout)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -207,6 +229,7 @@ private[akka] final class LeastRecentlyUsedEntityPassivationStrategy(initialLimi
|
|||
* Active entities are tracked in multiple recency lists, where entities are promoted to higher-level
|
||||
* segments on subsequent accesses, and demoted through levels when segments become full.
|
||||
* The proportions of the segmented levels can be configured as fractions of the overall limit.
|
||||
*
|
||||
* @param initialLimit initial active entity capacity for a shard region
|
||||
* @param proportions proportions of the segmented levels
|
||||
* @param idleCheck optionally passivate idle entities after the given timeout, checking every interval
|
||||
|
|
@ -220,31 +243,19 @@ private[akka] final class SegmentedLeastRecentlyUsedEntityPassivationStrategy(
|
|||
|
||||
import EntityPassivationStrategy.PassivateEntities
|
||||
|
||||
private def limits: immutable.Seq[Int] = proportions.map(p => (p * perShardLimit).toInt)
|
||||
val active = new SegmentedLeastRecentlyUsedReplacementPolicy(initialLimit, proportions, idleCheck.isDefined)
|
||||
|
||||
private val segmentedRecencyList =
|
||||
if (idleCheck.isDefined) SegmentedRecencyList.withOverallRecency.empty[EntityId](limits)
|
||||
else SegmentedRecencyList.empty[EntityId](limits)
|
||||
override protected def passivateEntitiesOnLimitUpdate(): PassivateEntities = active.updateLimit(perShardLimit)
|
||||
|
||||
override val scheduledInterval: Option[FiniteDuration] = idleCheck.map(_.interval)
|
||||
override def entityTouched(id: EntityId): PassivateEntities = active.update(id)
|
||||
|
||||
override def entityTouched(id: EntityId): PassivateEntities = {
|
||||
segmentedRecencyList.update(id)
|
||||
passivateExcessEntities()
|
||||
}
|
||||
override def entityTerminated(id: EntityId): Unit = active.remove(id)
|
||||
|
||||
override def entityTerminated(id: EntityId): Unit = segmentedRecencyList.remove(id)
|
||||
override def scheduledInterval: Option[FiniteDuration] = idleCheck.map(_.interval)
|
||||
|
||||
override def intervalPassed(): PassivateEntities = idleCheck.fold(PassivateEntities.none) { idle =>
|
||||
segmentedRecencyList.removeOverallLeastRecentOutside(idle.timeout)
|
||||
active.removeIdle(idle.timeout)
|
||||
}
|
||||
|
||||
override protected def passivateEntitiesOnLimitUpdate(): PassivateEntities = {
|
||||
segmentedRecencyList.updateLimits(limits)
|
||||
passivateExcessEntities()
|
||||
}
|
||||
|
||||
private def passivateExcessEntities(): PassivateEntities = segmentedRecencyList.removeLeastRecentOverLimit()
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -252,6 +263,7 @@ private[akka] final class SegmentedLeastRecentlyUsedEntityPassivationStrategy(
|
|||
*
|
||||
* Passivate the most recently used entities when the number of active entities in a shard region
|
||||
* reaches a limit. The per-region limit is divided evenly among the active shards in a region.
|
||||
*
|
||||
* @param initialLimit initial active entity capacity for a shard region
|
||||
* @param idleCheck optionally passivate idle entities after the given timeout, checking every interval
|
||||
*/
|
||||
|
|
@ -261,26 +273,18 @@ private[akka] final class MostRecentlyUsedEntityPassivationStrategy(initialLimit
|
|||
|
||||
import EntityPassivationStrategy.PassivateEntities
|
||||
|
||||
private val recencyList = RecencyList.empty[EntityId]
|
||||
val active = new MostRecentlyUsedReplacementPolicy(initialLimit)
|
||||
|
||||
override val scheduledInterval: Option[FiniteDuration] = idleCheck.map(_.interval)
|
||||
override protected def passivateEntitiesOnLimitUpdate(): PassivateEntities = active.updateLimit(perShardLimit)
|
||||
|
||||
override def entityTouched(id: EntityId): PassivateEntities = {
|
||||
recencyList.update(id)
|
||||
passivateExcessEntities(skip = 1) // remove most recent before adding this created entity
|
||||
}
|
||||
override def entityTouched(id: EntityId): PassivateEntities = active.update(id)
|
||||
|
||||
override def entityTerminated(id: EntityId): Unit = recencyList.remove(id)
|
||||
override def entityTerminated(id: EntityId): Unit = active.remove(id)
|
||||
|
||||
override def scheduledInterval: Option[FiniteDuration] = idleCheck.map(_.interval)
|
||||
|
||||
override def intervalPassed(): PassivateEntities = idleCheck.fold(PassivateEntities.none) { idle =>
|
||||
recencyList.removeLeastRecentOutside(idle.timeout)
|
||||
}
|
||||
|
||||
override protected def passivateEntitiesOnLimitUpdate(): PassivateEntities = passivateExcessEntities()
|
||||
|
||||
private def passivateExcessEntities(skip: Int = 0): PassivateEntities = {
|
||||
val excess = recencyList.size - perShardLimit
|
||||
if (excess > 0) recencyList.removeMostRecent(excess, skip) else PassivateEntities.none
|
||||
active.removeIdle(idle.timeout)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -289,6 +293,7 @@ private[akka] final class MostRecentlyUsedEntityPassivationStrategy(initialLimit
|
|||
*
|
||||
* Passivate the least frequently used entities when the number of active entities in a shard region
|
||||
* reaches a limit. The per-region limit is divided evenly among the active shards in a region.
|
||||
*
|
||||
* @param initialLimit initial active entity capacity for a shard region
|
||||
* @param dynamicAging whether to apply "dynamic aging" as entities are passivated
|
||||
* @param idleCheck optionally passivate idle entities after the given timeout, checking every interval
|
||||
|
|
@ -302,33 +307,670 @@ private[akka] final class LeastFrequentlyUsedEntityPassivationStrategy(
|
|||
|
||||
import EntityPassivationStrategy.PassivateEntities
|
||||
|
||||
val active = new LeastFrequentlyUsedReplacementPolicy(initialLimit, dynamicAging, idleCheck.isDefined)
|
||||
|
||||
override protected def passivateEntitiesOnLimitUpdate(): PassivateEntities = active.updateLimit(perShardLimit)
|
||||
|
||||
override def entityTouched(id: EntityId): PassivateEntities = active.update(id)
|
||||
|
||||
override def entityTerminated(id: EntityId): Unit = active.remove(id)
|
||||
|
||||
override def scheduledInterval: Option[FiniteDuration] = idleCheck.map(_.interval)
|
||||
|
||||
override def intervalPassed(): PassivateEntities = idleCheck.fold(PassivateEntities.none) { idle =>
|
||||
active.removeIdle(idle.timeout)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL API
|
||||
*/
|
||||
@InternalApi
|
||||
private[akka] object ActiveEntities {
|
||||
def apply(strategy: ClusterShardingSettings.PassivationStrategy, idleEnabled: Boolean): ActiveEntities =
|
||||
strategy match {
|
||||
case ClusterShardingSettings.LeastRecentlyUsedPassivationStrategy(_, segmented, _) =>
|
||||
if (segmented.isEmpty) new LeastRecentlyUsedReplacementPolicy(initialLimit = 0)
|
||||
else new SegmentedLeastRecentlyUsedReplacementPolicy(initialLimit = 0, segmented, idleEnabled)
|
||||
case ClusterShardingSettings.MostRecentlyUsedPassivationStrategy(_, _) =>
|
||||
new MostRecentlyUsedReplacementPolicy(initialLimit = 0)
|
||||
case ClusterShardingSettings.LeastFrequentlyUsedPassivationStrategy(_, dynamicAging, _) =>
|
||||
new LeastFrequentlyUsedReplacementPolicy(initialLimit = 0, dynamicAging, idleEnabled)
|
||||
case _ => NoActiveEntities
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL API
|
||||
*
|
||||
* Active entity tracking for entity passivation strategies, implemented with a replacement policy.
|
||||
*/
|
||||
@InternalApi
|
||||
private[akka] sealed abstract class ActiveEntities {
|
||||
import EntityPassivationStrategy.PassivateEntities
|
||||
|
||||
/**
|
||||
* The current number of active entities being tracked.
|
||||
* @return size of active entities
|
||||
*/
|
||||
def size: Int
|
||||
|
||||
/**
|
||||
* Check whether the entity id is currently tracked as active.
|
||||
* @param id the entity id to check
|
||||
* @return whether the entity is active
|
||||
*/
|
||||
def isActive(id: EntityId): Boolean
|
||||
|
||||
/**
|
||||
* The per-shard active entity limit has been updated, which can trigger passivation.
|
||||
* @param newLimit the new per-shard active entity limit
|
||||
* @return entities to passivate in the associated shard
|
||||
*/
|
||||
def updateLimit(newLimit: Int): PassivateEntities
|
||||
|
||||
/**
|
||||
* An entity instance has been touched. Recorded before message delivery.
|
||||
* @param id entity id for the touched entity instance
|
||||
* @return entities to passivate, when active capacity has been reached
|
||||
*/
|
||||
def update(id: EntityId): PassivateEntities
|
||||
|
||||
/**
|
||||
* Select the entity that would be passivated by the replacement policy, when active capacity has been reached.
|
||||
* @return entity that would be passivated
|
||||
*/
|
||||
def select: OptionVal[EntityId]
|
||||
|
||||
/**
|
||||
* An entity instance should be removed from active tracking.
|
||||
* @param id entity id for the removed entity instance
|
||||
*/
|
||||
def remove(id: EntityId): Unit
|
||||
|
||||
/**
|
||||
* Remove entity instances that have not been active for the given timeout.
|
||||
* @param timeout the idle timeout for entities
|
||||
* @return entities to passivate, if deemed inactive
|
||||
*/
|
||||
def removeIdle(timeout: FiniteDuration): PassivateEntities
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL API
|
||||
*
|
||||
* Disabled ActiveEntities (for no window in composite passivation strategies).
|
||||
*/
|
||||
@InternalApi
|
||||
private[akka] object NoActiveEntities extends ActiveEntities {
|
||||
import EntityPassivationStrategy.PassivateEntities
|
||||
|
||||
override def size: Int = 0
|
||||
override def isActive(id: EntityId): Boolean = false
|
||||
override def updateLimit(newLimit: Int): PassivateEntities = PassivateEntities.none
|
||||
override def update(id: EntityId): PassivateEntities = List(id)
|
||||
override def select: OptionVal[EntityId] = OptionVal.None
|
||||
override def remove(id: EntityId): Unit = ()
|
||||
override def removeIdle(timeout: FiniteDuration): PassivateEntities = PassivateEntities.none
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL API
|
||||
*
|
||||
* Passivate the least recently used entities when the number of active entities in a shard region
|
||||
* reaches a limit. The per-region limit is divided evenly among the active shards in a region.
|
||||
*
|
||||
* @param initialLimit initial active entity capacity for a shard
|
||||
*/
|
||||
@InternalApi
|
||||
private[akka] final class LeastRecentlyUsedReplacementPolicy(initialLimit: Int) extends ActiveEntities {
|
||||
import EntityPassivationStrategy.PassivateEntities
|
||||
|
||||
private var limit = initialLimit
|
||||
private val recencyList = RecencyList.empty[EntityId]
|
||||
|
||||
override def size: Int = recencyList.size
|
||||
|
||||
override def isActive(id: EntityId): Boolean = recencyList.contains(id)
|
||||
|
||||
override def updateLimit(newLimit: Int): PassivateEntities = {
|
||||
limit = newLimit
|
||||
removeExcess()
|
||||
}
|
||||
|
||||
override def update(id: EntityId): PassivateEntities = {
|
||||
recencyList.update(id)
|
||||
removeExcess()
|
||||
}
|
||||
|
||||
override def select: OptionVal[EntityId] = recencyList.leastRecent
|
||||
|
||||
override def remove(id: EntityId): Unit = recencyList.remove(id)
|
||||
|
||||
override def removeIdle(timeout: FiniteDuration): PassivateEntities = recencyList.removeLeastRecentOutside(timeout)
|
||||
|
||||
private def removeExcess(): PassivateEntities = {
|
||||
val excess = recencyList.size - limit
|
||||
if (excess > 0) recencyList.removeLeastRecent(excess) else PassivateEntities.none
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL API
|
||||
*
|
||||
* Passivate the least recently used entities when the number of active entities in a shard region
|
||||
* reaches a limit. The per-region limit is divided evenly among the active shards in a region.
|
||||
* Active entities are tracked in multiple recency lists, where entities are promoted to higher-level
|
||||
* segments on subsequent accesses, and demoted through levels when segments become full.
|
||||
* The proportions of the segmented levels can be configured as fractions of the overall limit.
|
||||
*
|
||||
* @param initialLimit initial active entity capacity for a shard
|
||||
* @param proportions proportions of the segmented levels
|
||||
* @param idleEnabled whether idle entity passivation is enabled
|
||||
*/
|
||||
@InternalApi
|
||||
private[akka] final class SegmentedLeastRecentlyUsedReplacementPolicy(
|
||||
initialLimit: Int,
|
||||
proportions: immutable.Seq[Double],
|
||||
idleEnabled: Boolean)
|
||||
extends ActiveEntities {
|
||||
|
||||
import EntityPassivationStrategy.PassivateEntities
|
||||
|
||||
private var limit = initialLimit
|
||||
private def segmentLimits: immutable.Seq[Int] = {
|
||||
// assign the first segment with the leftover, to have an accurate total limit
|
||||
val higherLimits = proportions.drop(1).map(p => (p * limit).toInt)
|
||||
(limit - higherLimits.sum) +: higherLimits
|
||||
}
|
||||
|
||||
private val segmentedRecencyList =
|
||||
if (idleEnabled) SegmentedRecencyList.withOverallRecency.empty[EntityId](segmentLimits)
|
||||
else SegmentedRecencyList.empty[EntityId](segmentLimits)
|
||||
|
||||
override def size: Int = segmentedRecencyList.size
|
||||
|
||||
override def isActive(id: EntityId): Boolean = segmentedRecencyList.contains(id)
|
||||
|
||||
override def updateLimit(newLimit: Int): PassivateEntities = {
|
||||
limit = newLimit
|
||||
segmentedRecencyList.updateLimits(segmentLimits)
|
||||
removeExcess()
|
||||
}
|
||||
|
||||
override def update(id: EntityId): PassivateEntities = {
|
||||
segmentedRecencyList.update(id)
|
||||
removeExcess()
|
||||
}
|
||||
|
||||
override def select: OptionVal[EntityId] = segmentedRecencyList.leastRecent
|
||||
|
||||
override def remove(id: EntityId): Unit = segmentedRecencyList.remove(id)
|
||||
|
||||
override def removeIdle(timeout: FiniteDuration): PassivateEntities =
|
||||
segmentedRecencyList.removeOverallLeastRecentOutside(timeout)
|
||||
|
||||
private def removeExcess(): PassivateEntities = segmentedRecencyList.removeLeastRecentOverLimit()
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL API
|
||||
*
|
||||
* Passivate the most recently used entities when the number of active entities in a shard region
|
||||
* reaches a limit. The per-region limit is divided evenly among the active shards in a region.
|
||||
*
|
||||
* @param initialLimit initial active entity capacity for a shard
|
||||
*/
|
||||
@InternalApi
|
||||
private[akka] final class MostRecentlyUsedReplacementPolicy(initialLimit: Int) extends ActiveEntities {
|
||||
import EntityPassivationStrategy.PassivateEntities
|
||||
|
||||
private var limit = initialLimit
|
||||
private val recencyList = RecencyList.empty[EntityId]
|
||||
|
||||
override def size: Int = recencyList.size
|
||||
|
||||
override def isActive(id: EntityId): Boolean = recencyList.contains(id)
|
||||
|
||||
override def updateLimit(newLimit: Int): PassivateEntities = {
|
||||
limit = newLimit
|
||||
removeExcess()
|
||||
}
|
||||
|
||||
override def update(id: EntityId): PassivateEntities = {
|
||||
recencyList.update(id)
|
||||
removeExcess(skip = 1) // remove the most recent entity before the just touched entity
|
||||
}
|
||||
|
||||
override def select: OptionVal[EntityId] = recencyList.mostRecent
|
||||
|
||||
override def remove(id: EntityId): Unit = recencyList.remove(id)
|
||||
|
||||
override def removeIdle(timeout: FiniteDuration): PassivateEntities = recencyList.removeLeastRecentOutside(timeout)
|
||||
|
||||
private def removeExcess(skip: Int = 0): PassivateEntities = {
|
||||
val excess = recencyList.size - limit
|
||||
if (excess > 0) recencyList.removeMostRecent(excess, skip) else PassivateEntities.none
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL API
|
||||
*
|
||||
* Passivate the least frequently used entities when the number of active entities in a shard region
|
||||
* reaches a limit. The per-region limit is divided evenly among the active shards in a region.
|
||||
*
|
||||
* @param initialLimit initial active entity capacity for a shard
|
||||
* @param dynamicAging whether to apply "dynamic aging" as entities are passivated
|
||||
* @param idleEnabled whether idle entity passivation is enabled
|
||||
*/
|
||||
@InternalApi
|
||||
private[akka] final class LeastFrequentlyUsedReplacementPolicy(
|
||||
initialLimit: Int,
|
||||
dynamicAging: Boolean,
|
||||
idleEnabled: Boolean)
|
||||
extends ActiveEntities {
|
||||
|
||||
import EntityPassivationStrategy.PassivateEntities
|
||||
|
||||
private var limit = initialLimit
|
||||
|
||||
private val frequencyList =
|
||||
if (idleCheck.isDefined) FrequencyList.withOverallRecency.empty[EntityId](dynamicAging)
|
||||
if (idleEnabled) FrequencyList.withOverallRecency.empty[EntityId](dynamicAging)
|
||||
else FrequencyList.empty[EntityId](dynamicAging)
|
||||
|
||||
override val scheduledInterval: Option[FiniteDuration] = idleCheck.map(_.interval)
|
||||
override def size: Int = frequencyList.size
|
||||
|
||||
override def entityTouched(id: EntityId): PassivateEntities = {
|
||||
override def isActive(id: EntityId): Boolean = frequencyList.contains(id)
|
||||
|
||||
override def updateLimit(newLimit: Int): PassivateEntities = {
|
||||
limit = newLimit
|
||||
removeExcess()
|
||||
}
|
||||
|
||||
override def update(id: EntityId): PassivateEntities = {
|
||||
// first remove excess entities so that dynamic aging is updated
|
||||
// and the adjusted age is applied to any new entities on update
|
||||
// adjust the expected size by 1 if this is a newly activated entity
|
||||
val adjustment = if (frequencyList.contains(id)) 0 else 1
|
||||
val passivated = passivateExcessEntities(adjustment)
|
||||
val passivated = removeExcess(adjustment)
|
||||
frequencyList.update(id)
|
||||
passivated
|
||||
}
|
||||
|
||||
override def entityTerminated(id: EntityId): Unit = frequencyList.remove(id)
|
||||
override def select: OptionVal[EntityId] = frequencyList.leastFrequent
|
||||
|
||||
override def intervalPassed(): PassivateEntities = idleCheck.fold(PassivateEntities.none) { idle =>
|
||||
frequencyList.removeOverallLeastRecentOutside(idle.timeout)
|
||||
}
|
||||
override def remove(id: EntityId): Unit = frequencyList.remove(id)
|
||||
|
||||
override protected def passivateEntitiesOnLimitUpdate(): PassivateEntities = passivateExcessEntities()
|
||||
override def removeIdle(timeout: FiniteDuration): PassivateEntities =
|
||||
frequencyList.removeOverallLeastRecentOutside(timeout)
|
||||
|
||||
private def passivateExcessEntities(adjustment: Int = 0): PassivateEntities = {
|
||||
val excess = frequencyList.size - perShardLimit + adjustment
|
||||
private def removeExcess(adjustment: Int = 0): PassivateEntities = {
|
||||
val excess = frequencyList.size - limit + adjustment
|
||||
if (excess > 0) frequencyList.removeLeastFrequent(excess) else PassivateEntities.none
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL API
|
||||
*
|
||||
* Passivate entities using a "composite" strategy, with an admission area before the main area, an admission
|
||||
* filter for admitting entities to the main area, and an optimizer for the proportion of the admission window.
|
||||
*
|
||||
* References:
|
||||
*
|
||||
* "TinyLFU: A Highly Efficient Cache Admission Policy"
|
||||
* Gil Einziger, Roy Friedman, Ben Manes
|
||||
*
|
||||
* "Adaptive Software Cache Management"
|
||||
* Gil Einziger, Ohad Eytan, Roy Friedman, Ben Manes
|
||||
*
|
||||
* @param initialLimit initial active entity capacity for a shard region
|
||||
* @param window the active entities tracking and replacement policy for the admission window
|
||||
* @param initialWindowProportion the initial proportion for the admission window
|
||||
* @param minimumWindowProportion the minimum proportion for the admission window (if being optimized)
|
||||
* @param maximumWindowProportion the maximum proportion for the admission window (if being optimized)
|
||||
* @param windowOptimizer the optimizer for the admission window proportion
|
||||
* @param admissionFilter the admission filter to apply for the main area
|
||||
* @param main the active entities tracking and replacement policy for the main area
|
||||
* @param idleCheck optionally passivate idle entities after the given timeout, checking every interval
|
||||
*/
|
||||
@InternalApi
|
||||
private[akka] final class CompositeEntityPassivationStrategy(
|
||||
initialLimit: Int,
|
||||
window: ActiveEntities,
|
||||
initialWindowProportion: Double,
|
||||
minimumWindowProportion: Double,
|
||||
maximumWindowProportion: Double,
|
||||
windowOptimizer: AdmissionOptimizer,
|
||||
admissionFilter: AdmissionFilter,
|
||||
main: ActiveEntities,
|
||||
idleCheck: Option[IdleCheck])
|
||||
extends LimitBasedEntityPassivationStrategy(initialLimit) {
|
||||
|
||||
import EntityPassivationStrategy.PassivateEntities
|
||||
|
||||
private var windowProportion = initialWindowProportion
|
||||
private var windowLimit = 0
|
||||
private var mainLimit = 0
|
||||
|
||||
private def calculateLimits(): Unit = {
|
||||
windowLimit = (windowProportion * perShardLimit).toInt
|
||||
mainLimit = perShardLimit - windowLimit
|
||||
}
|
||||
|
||||
// set initial limits based on initial window proportion
|
||||
calculateLimits()
|
||||
window.updateLimit(windowLimit)
|
||||
main.updateLimit(mainLimit)
|
||||
|
||||
override def entityTouched(id: EntityId): PassivateEntities = {
|
||||
admissionFilter.update(id)
|
||||
val passivated = if (window.isActive(id)) {
|
||||
windowOptimizer.recordActive()
|
||||
window.update(id)
|
||||
} else if (main.isActive(id)) {
|
||||
windowOptimizer.recordActive()
|
||||
main.update(id)
|
||||
} else {
|
||||
windowOptimizer.recordPassive()
|
||||
maybeAdmitToMain(window.update(id))
|
||||
}
|
||||
adaptWindow()
|
||||
passivated
|
||||
}
|
||||
|
||||
override def entityTerminated(id: EntityId): Unit = {
|
||||
window.remove(id)
|
||||
main.remove(id)
|
||||
}
|
||||
|
||||
override protected def passivateEntitiesOnLimitUpdate(): PassivateEntities = {
|
||||
calculateLimits()
|
||||
windowOptimizer.updateLimit(perShardLimit)
|
||||
admissionFilter.updateCapacity(perShardLimit)
|
||||
maybeAdmitToMain(window.updateLimit(windowLimit)) ++ main.updateLimit(mainLimit)
|
||||
}
|
||||
|
||||
override def scheduledInterval: Option[FiniteDuration] = idleCheck.map(_.interval)
|
||||
|
||||
override def intervalPassed(): PassivateEntities = idleCheck.fold(PassivateEntities.none) { idle =>
|
||||
window.removeIdle(idle.timeout) ++ main.removeIdle(idle.timeout)
|
||||
}
|
||||
|
||||
private def maybeAdmitToMain(candidates: PassivateEntities): PassivateEntities = {
|
||||
if (candidates.nonEmpty) {
|
||||
var passivated: PassivateEntities = PassivateEntities.none
|
||||
candidates.foreach { candidate =>
|
||||
if (main.size >= mainLimit) {
|
||||
main.select match {
|
||||
case OptionVal.Some(selected) =>
|
||||
if (admissionFilter.admit(candidate, selected))
|
||||
passivated ++= main.update(candidate)
|
||||
else passivated :+= candidate
|
||||
case _ => passivated ++= main.update(candidate)
|
||||
}
|
||||
} else passivated ++= main.update(candidate)
|
||||
}
|
||||
passivated
|
||||
} else PassivateEntities.none
|
||||
}
|
||||
|
||||
private def adaptWindow(): Unit = {
|
||||
val adjustment = windowOptimizer.calculateAdjustment()
|
||||
if (adjustment != 0.0) {
|
||||
windowProportion =
|
||||
math.max(minimumWindowProportion, math.min(maximumWindowProportion, windowProportion + adjustment))
|
||||
calculateLimits()
|
||||
// note: no passivations from adjustments, entities are transferred between window and main
|
||||
if (adjustment > 0.0) { // increase window limit
|
||||
window.updateLimit(windowLimit)
|
||||
main.updateLimit(mainLimit).foreach(window.update)
|
||||
} else { // decrease window limit
|
||||
main.updateLimit(mainLimit)
|
||||
window.updateLimit(windowLimit).foreach(main.update)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL API
|
||||
*/
|
||||
@InternalApi
|
||||
private[akka] object AdmissionOptimizer {
|
||||
def apply(
|
||||
initialLimit: Int,
|
||||
optimizer: ClusterShardingSettings.CompositePassivationStrategy.AdmissionOptimizer): AdmissionOptimizer =
|
||||
optimizer match {
|
||||
case ClusterShardingSettings.CompositePassivationStrategy.HillClimbingAdmissionOptimizer(
|
||||
adjustMultiplier,
|
||||
initialStep,
|
||||
restartThreshold,
|
||||
stepDecay) =>
|
||||
new HillClimbingAdmissionOptimizer(initialLimit, adjustMultiplier, initialStep, restartThreshold, stepDecay)
|
||||
case _ => NoAdmissionOptimizer
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL API
|
||||
*
|
||||
* An optimizer for the size of the admission window for a composite passivation strategy.
|
||||
*/
|
||||
@InternalApi
|
||||
private[akka] abstract class AdmissionOptimizer {
|
||||
|
||||
/**
|
||||
* An entity was accessed that is already active.
|
||||
*/
|
||||
def recordActive(): Unit
|
||||
|
||||
/**
|
||||
* An entity was accessed that was passive (needed to be activated).
|
||||
*/
|
||||
def recordPassive(): Unit
|
||||
|
||||
/**
|
||||
* The per-shard limit has been updated.
|
||||
* @param newLimit the new per-shard limit
|
||||
*/
|
||||
def updateLimit(newLimit: Int): Unit
|
||||
|
||||
/**
|
||||
* Calculate an adjustment to the proportion of the admission window.
|
||||
* Can be positive (to grow the window) or negative (to shrink the window).
|
||||
* Returns 0.0 if no adjustment should be made.
|
||||
* @return the adjustment to make to the admission window proportion
|
||||
*/
|
||||
def calculateAdjustment(): Double
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL API
|
||||
*
|
||||
* Disabled admission window proportion optimizer.
|
||||
*/
|
||||
@InternalApi
|
||||
private[akka] object NoAdmissionOptimizer extends AdmissionOptimizer {
|
||||
override def recordActive(): Unit = ()
|
||||
override def recordPassive(): Unit = ()
|
||||
override def updateLimit(newLimit: Int): Unit = ()
|
||||
override def calculateAdjustment(): Double = 0.0
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL API
|
||||
*
|
||||
* Optimizer for the admission window using a simple hill-climbing algorithm.
|
||||
*/
|
||||
@InternalApi
|
||||
private[akka] final class HillClimbingAdmissionOptimizer(
|
||||
initialLimit: Int,
|
||||
adjustMultiplier: Double,
|
||||
initialStep: Double,
|
||||
restartThreshold: Double,
|
||||
stepDecay: Double)
|
||||
extends AdmissionOptimizer {
|
||||
private var adjustSize = adjustMultiplier * initialLimit
|
||||
private var accesses = 0
|
||||
private var activeAccesses = 0
|
||||
private var previousActiveRate = 0.0
|
||||
private var nextStep = -initialStep // start in decreasing direction
|
||||
|
||||
override def recordActive(): Unit = {
|
||||
accesses += 1
|
||||
activeAccesses += 1
|
||||
}
|
||||
|
||||
override def recordPassive(): Unit = accesses += 1
|
||||
|
||||
override def updateLimit(newLimit: Int): Unit =
|
||||
adjustSize = adjustMultiplier * newLimit
|
||||
|
||||
override def calculateAdjustment(): Double = {
|
||||
if (accesses >= adjustSize) {
|
||||
val activeRate = activeAccesses.toDouble / accesses
|
||||
val delta = activeRate - previousActiveRate
|
||||
val adjustment = if (delta >= 0) nextStep else -nextStep
|
||||
val direction = if (adjustment >= 0) 1 else -1
|
||||
val restart = math.abs(delta) >= restartThreshold
|
||||
nextStep = if (restart) initialStep * direction else adjustment * stepDecay
|
||||
previousActiveRate = activeRate
|
||||
accesses = 0
|
||||
activeAccesses = 0
|
||||
adjustment
|
||||
} else 0.0
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL API
|
||||
*/
|
||||
@InternalApi
|
||||
private[akka] object AdmissionFilter {
|
||||
def apply(
|
||||
initialCapacity: Int,
|
||||
filter: ClusterShardingSettings.CompositePassivationStrategy.AdmissionFilter): AdmissionFilter = filter match {
|
||||
case ClusterShardingSettings.CompositePassivationStrategy
|
||||
.FrequencySketchAdmissionFilter(widthMultiplier, resetMultiplier, depth, counterBits) =>
|
||||
FrequencySketchAdmissionFilter(initialCapacity, widthMultiplier, resetMultiplier, depth, counterBits)
|
||||
case _ => AlwaysAdmissionFilter
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL API
|
||||
*
|
||||
* An admission filter for the main area for a composite passivation strategy.
|
||||
*/
|
||||
@InternalApi
|
||||
private[akka] abstract class AdmissionFilter {
|
||||
|
||||
/**
|
||||
* Update the capacity, the per-shard entity limit.
|
||||
* @param newCapacity the new capacity for the filter
|
||||
*/
|
||||
def updateCapacity(newCapacity: Int): Unit
|
||||
|
||||
/**
|
||||
* Update the filter when an entity is accessed
|
||||
* @param id the entity id that has been accessed
|
||||
*/
|
||||
def update(id: EntityId): Unit
|
||||
|
||||
/**
|
||||
* Determine whether an entity should be admitted to the main area.
|
||||
* The candidate has been removed from the admission window (according to its replacement policy)
|
||||
* and can replace an entity in the main area (selected by its replacement policy).
|
||||
* Whichever entity is not admitted or retained will be passivated.
|
||||
* @param candidate the candidate from the window that may be admitted to the main area
|
||||
* @param selected the entity selected from the main area to possibly be replaced by the candidate
|
||||
* @return whether to admit the candidate to the main area
|
||||
*/
|
||||
def admit(candidate: EntityId, selected: EntityId): Boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL API
|
||||
*
|
||||
* Disabled admission filter, always admit candidates to the main area.
|
||||
*/
|
||||
@InternalApi
|
||||
private[akka] object AlwaysAdmissionFilter extends AdmissionFilter {
|
||||
override def updateCapacity(newCapacity: Int): Unit = ()
|
||||
override def update(id: EntityId): Unit = ()
|
||||
override def admit(candidate: EntityId, selected: EntityId): Boolean = true
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL API
|
||||
*
|
||||
* Admission filter based on a frequency sketch.
|
||||
*/
|
||||
@InternalApi
|
||||
private[akka] object FrequencySketchAdmissionFilter {
|
||||
def apply(
|
||||
initialCapacity: Int,
|
||||
widthMultiplier: Int,
|
||||
resetMultiplier: Double,
|
||||
depth: Int,
|
||||
counterBits: Int): AdmissionFilter = {
|
||||
if (depth == 4 && counterBits == 4)
|
||||
new FastFrequencySketchAdmissionFilter(initialCapacity, widthMultiplier, resetMultiplier)
|
||||
else
|
||||
new FrequencySketchAdmissionFilter(initialCapacity, widthMultiplier, resetMultiplier, depth, counterBits)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL API
|
||||
*
|
||||
* Admission filter based on a frequency sketch.
|
||||
*/
|
||||
@InternalApi
|
||||
private[akka] final class FrequencySketchAdmissionFilter(
|
||||
initialCapacity: Int,
|
||||
widthMultiplier: Int,
|
||||
resetMultiplier: Double,
|
||||
depth: Int,
|
||||
counterBits: Int)
|
||||
extends AdmissionFilter {
|
||||
|
||||
private def createSketch(capacity: Int): FrequencySketch[EntityId] =
|
||||
FrequencySketch[EntityId](capacity, widthMultiplier, resetMultiplier, depth, counterBits)
|
||||
|
||||
private var frequencySketch = createSketch(initialCapacity)
|
||||
|
||||
override def updateCapacity(newCapacity: Int): Unit = frequencySketch = createSketch(newCapacity)
|
||||
|
||||
override def update(id: EntityId): Unit = frequencySketch.increment(id)
|
||||
|
||||
override def admit(candidate: EntityId, selected: EntityId): Boolean =
|
||||
frequencySketch.frequency(candidate) > frequencySketch.frequency(selected)
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL API
|
||||
*
|
||||
* Admission filter based on a frequency sketch (fast version with depth of 4 and 4-bit counters).
|
||||
*/
|
||||
@InternalApi
|
||||
private[akka] final class FastFrequencySketchAdmissionFilter(
|
||||
initialCapacity: Int,
|
||||
widthMultiplier: Int,
|
||||
resetMultiplier: Double)
|
||||
extends AdmissionFilter {
|
||||
|
||||
private def createSketch(capacity: Int): FastFrequencySketch[EntityId] =
|
||||
FastFrequencySketch[EntityId](capacity, widthMultiplier, resetMultiplier)
|
||||
|
||||
private var frequencySketch = createSketch(initialCapacity)
|
||||
|
||||
override def updateCapacity(newCapacity: Int): Unit = frequencySketch = createSketch(newCapacity)
|
||||
|
||||
override def update(id: EntityId): Unit = frequencySketch.increment(id)
|
||||
|
||||
override def admit(candidate: EntityId, selected: EntityId): Boolean =
|
||||
frequencySketch.frequency(candidate) > frequencySketch.frequency(selected)
|
||||
}
|
||||
|
|
|
|||
243
akka-cluster-sharding/src/test/resources/adaptivity-trace.conf
Normal file
243
akka-cluster-sharding/src/test/resources/adaptivity-trace.conf
Normal file
|
|
@ -0,0 +1,243 @@
|
|||
#
|
||||
# Run a joined trace for testing adaptivity, switching between a recency-biased R3 Corda trace and
|
||||
# a frequency-biased LIRS loop trace.
|
||||
#
|
||||
# Similar to the adaptivity test for Caffeine: https://github.com/ben-manes/caffeine/wiki/Efficiency
|
||||
#
|
||||
# Download LIRS traces from: https://github.com/zhongch4g/LIRS2
|
||||
#
|
||||
# Download Corda traces from: https://github.com/ben-manes/caffeine
|
||||
#
|
||||
# > akka-cluster-sharding/Test/runMain akka.cluster.sharding.passivation.simulator.Simulator adaptivity-trace
|
||||
#
|
||||
# ╔════════════════════╤═════════╤═══════════╤═════════════╤══════════════╗
|
||||
# ║ Run │ Active │ Accesses │ Activations │ Passivations ║
|
||||
# ╠════════════════════╪═════════╪═══════════╪═════════════╪══════════════╣
|
||||
# ║ OPT 500 │ 41.89 % │ 8,565,548 │ 4,977,489 │ 4,976,989 ║
|
||||
# ╟────────────────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ LRU 500 │ 15.63 % │ 8,565,548 │ 7,226,870 │ 7,226,370 ║
|
||||
# ╟────────────────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ SLRU 500 │ 7.31 % │ 8,565,548 │ 7,939,452 │ 7,938,952 ║
|
||||
# ╟────────────────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ S4LRU 500 │ 15.63 % │ 8,565,548 │ 7,226,902 │ 7,226,402 ║
|
||||
# ╟────────────────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ MRU 500 │ 0.03 % │ 8,565,548 │ 8,563,041 │ 8,562,541 ║
|
||||
# ╟────────────────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ LFU 500 │ 0.02 % │ 8,565,548 │ 8,564,051 │ 8,563,551 ║
|
||||
# ╟────────────────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ LFUDA 500 │ 15.63 % │ 8,565,548 │ 7,226,892 │ 7,226,392 ║
|
||||
# ╟────────────────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ LRU/FS/SLRU 500 │ 26.14 % │ 8,565,548 │ 6,326,555 │ 6,326,055 ║
|
||||
# ╟────────────────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ LRU/FS/SLRU/HC 500 │ 40.74 % │ 8,565,548 │ 5,076,280 │ 5,075,780 ║
|
||||
# ╚════════════════════╧═════════╧═══════════╧═════════════╧══════════════╝
|
||||
#
|
||||
|
||||
corda-traces="corda-traces"
|
||||
corda-traces=${?CORDA_TRACES}
|
||||
|
||||
lirs-traces="lirs-traces"
|
||||
lirs-traces=${?LIRS_TRACES}
|
||||
|
||||
akka.cluster.sharding {
|
||||
passivation.simulator {
|
||||
runs = [
|
||||
{
|
||||
name = "OPT 500"
|
||||
shards = 1
|
||||
regions = 1
|
||||
pattern = changing
|
||||
strategy = optimal-500
|
||||
},
|
||||
{
|
||||
name = "LRU 500"
|
||||
shards = 1
|
||||
regions = 1
|
||||
pattern = changing
|
||||
strategy = lru-500
|
||||
},
|
||||
{
|
||||
name = "SLRU 500"
|
||||
shards = 1
|
||||
regions = 1
|
||||
pattern = changing
|
||||
strategy = slru-500
|
||||
},
|
||||
{
|
||||
name = "S4LRU 500"
|
||||
shards = 1
|
||||
regions = 1
|
||||
pattern = changing
|
||||
strategy = s4lru-500
|
||||
},
|
||||
{
|
||||
name = "MRU 500"
|
||||
shards = 1
|
||||
regions = 1
|
||||
pattern = changing
|
||||
strategy = mru-500
|
||||
},
|
||||
{
|
||||
name = "LFU 500"
|
||||
shards = 1
|
||||
regions = 1
|
||||
pattern = changing
|
||||
strategy = lfu-500
|
||||
},
|
||||
{
|
||||
name = "LFUDA 500"
|
||||
shards = 1
|
||||
regions = 1
|
||||
pattern = changing
|
||||
strategy = lfuda-500
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU 500"
|
||||
shards = 1
|
||||
regions = 1
|
||||
pattern = changing
|
||||
strategy = lru-fs-slru-500
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU/HC 500"
|
||||
shards = 1
|
||||
regions = 1
|
||||
pattern = changing
|
||||
strategy = lru-fs-slru-hc-500
|
||||
},
|
||||
]
|
||||
|
||||
changing {
|
||||
pattern = joined
|
||||
joined = [
|
||||
corda-vaultservice,
|
||||
lirs-loop,
|
||||
lirs-loop,
|
||||
lirs-loop,
|
||||
corda-vaultservice-large,
|
||||
lirs-loop,
|
||||
lirs-loop,
|
||||
lirs-loop,
|
||||
corda-vaultservice,
|
||||
lirs-loop,
|
||||
lirs-loop,
|
||||
lirs-loop,
|
||||
corda-vaultservice-large,
|
||||
]
|
||||
}
|
||||
|
||||
# recency-biased
|
||||
corda-vaultservice {
|
||||
pattern = trace
|
||||
trace {
|
||||
format = corda
|
||||
path = ${corda-traces}"/vaultservice.trace"
|
||||
}
|
||||
}
|
||||
|
||||
# recency-biased
|
||||
corda-vaultservice-large {
|
||||
pattern = trace
|
||||
trace {
|
||||
format = corda
|
||||
path = ${corda-traces}"/vaultservice-large.trace"
|
||||
}
|
||||
}
|
||||
|
||||
# frequency-biased
|
||||
lirs-loop {
|
||||
pattern = trace
|
||||
trace {
|
||||
format = lirs
|
||||
path = ${lirs-traces}"/loop.trace"
|
||||
}
|
||||
}
|
||||
|
||||
optimal-500 {
|
||||
strategy = optimal
|
||||
optimal {
|
||||
per-region-limit = 500
|
||||
}
|
||||
}
|
||||
|
||||
lru-500 {
|
||||
strategy = least-recently-used
|
||||
least-recently-used {
|
||||
per-region-limit = 500
|
||||
}
|
||||
}
|
||||
|
||||
slru-500 {
|
||||
strategy = least-recently-used
|
||||
least-recently-used {
|
||||
per-region-limit = 500
|
||||
segmented {
|
||||
levels = 2
|
||||
proportions = [0.2, 0.8]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s4lru-500 {
|
||||
strategy = least-recently-used
|
||||
least-recently-used {
|
||||
per-region-limit = 500
|
||||
segmented.levels = 4
|
||||
}
|
||||
}
|
||||
|
||||
mru-500 {
|
||||
strategy = most-recently-used
|
||||
most-recently-used {
|
||||
per-region-limit = 500
|
||||
}
|
||||
}
|
||||
|
||||
lfu-500 {
|
||||
strategy = least-frequently-used
|
||||
least-frequently-used {
|
||||
per-region-limit = 500
|
||||
}
|
||||
}
|
||||
|
||||
lfuda-500 {
|
||||
strategy = least-frequently-used
|
||||
least-frequently-used {
|
||||
per-region-limit = 500
|
||||
dynamic-aging = on
|
||||
}
|
||||
}
|
||||
|
||||
lru-fs-slru {
|
||||
strategy = composite
|
||||
composite {
|
||||
admission {
|
||||
window.strategy = least-recently-used
|
||||
filter = frequency-sketch
|
||||
optimizer = none
|
||||
}
|
||||
main {
|
||||
strategy = least-recently-used
|
||||
least-recently-used {
|
||||
segmented {
|
||||
levels = 2
|
||||
proportions = [0.2, 0.8]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lru-fs-slru-500 = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru} {
|
||||
composite.per-region-limit = 500
|
||||
}
|
||||
|
||||
lru-fs-slru-hc = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru} {
|
||||
composite.admission.optimizer = hill-climbing
|
||||
}
|
||||
|
||||
lru-fs-slru-hc-500 = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru-hc} {
|
||||
composite.per-region-limit = 500
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8,65 +8,81 @@
|
|||
#
|
||||
# > akka-cluster-sharding/Test/runMain akka.cluster.sharding.passivation.simulator.Simulator arc-trace-database
|
||||
#
|
||||
# ╔══════════╤═════════╤════════════╤═════════════╤══════════════╗
|
||||
# ║ Run │ Active │ Accesses │ Activations │ Passivations ║
|
||||
# ╠══════════╪═════════╪════════════╪═════════════╪══════════════╣
|
||||
# ║ OPT 1M │ 20.19 % │ 43,704,979 │ 34,879,633 │ 33,879,633 ║
|
||||
# ╟──────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ OPT 2M │ 31.79 % │ 43,704,979 │ 29,810,905 │ 27,810,905 ║
|
||||
# ╟──────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ OPT 4M │ 48.09 % │ 43,704,979 │ 22,685,636 │ 18,685,636 ║
|
||||
# ╟──────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ OPT 8M │ 74.93 % │ 43,704,979 │ 10,957,661 │ 2,957,661 ║
|
||||
# ╠══════════╪═════════╪════════════╪═════════════╪══════════════╣
|
||||
# ║ LRU 1M │ 3.09 % │ 43,704,979 │ 42,356,500 │ 41,356,500 ║
|
||||
# ╟──────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LRU 2M │ 10.75 % │ 43,704,979 │ 39,007,141 │ 37,007,141 ║
|
||||
# ╟──────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LRU 4M │ 20.24 % │ 43,704,979 │ 34,857,131 │ 30,857,131 ║
|
||||
# ╟──────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LRU 8M │ 43.03 % │ 43,704,979 │ 24,896,638 │ 16,896,638 ║
|
||||
# ╠══════════╪═════════╪════════════╪═════════════╪══════════════╣
|
||||
# ║ SLRU 1M │ 6.13 % │ 43,704,979 │ 41,026,869 │ 40,026,869 ║
|
||||
# ╟──────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ SLRU 2M │ 23.37 % │ 43,704,979 │ 33,489,560 │ 31,489,560 ║
|
||||
# ╟──────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ SLRU 4M │ 39.06 % │ 43,704,979 │ 26,632,624 │ 22,632,624 ║
|
||||
# ╟──────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ SLRU 8M │ 57.55 % │ 43,704,979 │ 18,552,089 │ 10,552,089 ║
|
||||
# ╠══════════╪═════════╪════════════╪═════════════╪══════════════╣
|
||||
# ║ S4LRU 1M │ 6.13 % │ 43,704,979 │ 41,026,869 │ 40,026,869 ║
|
||||
# ╟──────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ S4LRU 2M │ 16.74 % │ 43,704,979 │ 36,387,353 │ 34,387,353 ║
|
||||
# ╟──────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ S4LRU 4M │ 30.27 % │ 43,704,979 │ 30,477,096 │ 26,477,096 ║
|
||||
# ╟──────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ S4LRU 8M │ 57.86 % │ 43,704,979 │ 18,419,181 │ 10,419,181 ║
|
||||
# ╠══════════╪═════════╪════════════╪═════════════╪══════════════╣
|
||||
# ║ MRU 1M │ 11.92 % │ 43,704,979 │ 38,493,369 │ 37,493,369 ║
|
||||
# ╟──────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ MRU 2M │ 25.67 % │ 43,704,979 │ 32,486,285 │ 30,486,285 ║
|
||||
# ╟──────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ MRU 4M │ 41.82 % │ 43,704,979 │ 25,429,608 │ 21,429,608 ║
|
||||
# ╟──────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ MRU 8M │ 68.01 % │ 43,704,979 │ 13,980,246 │ 5,980,246 ║
|
||||
# ╠══════════╪═════════╪════════════╪═════════════╪══════════════╣
|
||||
# ║ LFU 1M │ 6.13 % │ 43,704,979 │ 41,026,869 │ 40,026,869 ║
|
||||
# ╟──────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LFU 2M │ 23.39 % │ 43,704,979 │ 33,482,361 │ 31,482,361 ║
|
||||
# ╟──────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LFU 4M │ 39.06 % │ 43,704,979 │ 26,632,624 │ 22,632,624 ║
|
||||
# ╟──────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LFU 8M │ 57.55 % │ 43,704,979 │ 18,552,089 │ 10,552,089 ║
|
||||
# ╠══════════╪═════════╪════════════╪═════════════╪══════════════╣
|
||||
# ║ LFUDA 1M │ 3.25 % │ 43,704,979 │ 42,285,825 │ 41,285,825 ║
|
||||
# ╟──────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LFUDA 2M │ 11.02 % │ 43,704,979 │ 38,890,280 │ 36,890,280 ║
|
||||
# ╟──────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LFUDA 4M │ 21.96 % │ 43,704,979 │ 34,107,344 │ 30,107,344 ║
|
||||
# ╟──────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LFUDA 8M │ 54.72 % │ 43,704,979 │ 19,790,371 │ 11,790,371 ║
|
||||
# ╚══════════╧═════════╧════════════╧═════════════╧══════════════╝
|
||||
# ╔═══════════════════╤═════════╤════════════╤═════════════╤══════════════╗
|
||||
# ║ Run │ Active │ Accesses │ Activations │ Passivations ║
|
||||
# ╠═══════════════════╪═════════╪════════════╪═════════════╪══════════════╣
|
||||
# ║ OPT 1M │ 20.19 % │ 43,704,979 │ 34,879,633 │ 33,879,633 ║
|
||||
# ╟───────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ OPT 2M │ 31.79 % │ 43,704,979 │ 29,810,905 │ 27,810,905 ║
|
||||
# ╟───────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ OPT 4M │ 48.09 % │ 43,704,979 │ 22,685,636 │ 18,685,636 ║
|
||||
# ╟───────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ OPT 8M │ 74.93 % │ 43,704,979 │ 10,957,661 │ 2,957,661 ║
|
||||
# ╠═══════════════════╪═════════╪════════════╪═════════════╪══════════════╣
|
||||
# ║ LRU 1M │ 3.09 % │ 43,704,979 │ 42,356,500 │ 41,356,500 ║
|
||||
# ╟───────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LRU 2M │ 10.75 % │ 43,704,979 │ 39,007,141 │ 37,007,141 ║
|
||||
# ╟───────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LRU 4M │ 20.24 % │ 43,704,979 │ 34,857,131 │ 30,857,131 ║
|
||||
# ╟───────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LRU 8M │ 43.03 % │ 43,704,979 │ 24,896,638 │ 16,896,638 ║
|
||||
# ╠═══════════════════╪═════════╪════════════╪═════════════╪══════════════╣
|
||||
# ║ SLRU 1M │ 6.13 % │ 43,704,979 │ 41,026,869 │ 40,026,869 ║
|
||||
# ╟───────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ SLRU 2M │ 23.37 % │ 43,704,979 │ 33,489,560 │ 31,489,560 ║
|
||||
# ╟───────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ SLRU 4M │ 39.06 % │ 43,704,979 │ 26,632,624 │ 22,632,624 ║
|
||||
# ╟───────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ SLRU 8M │ 57.55 % │ 43,704,979 │ 18,552,089 │ 10,552,089 ║
|
||||
# ╠═══════════════════╪═════════╪════════════╪═════════════╪══════════════╣
|
||||
# ║ S4LRU 1M │ 6.13 % │ 43,704,979 │ 41,026,869 │ 40,026,869 ║
|
||||
# ╟───────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ S4LRU 2M │ 16.74 % │ 43,704,979 │ 36,387,353 │ 34,387,353 ║
|
||||
# ╟───────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ S4LRU 4M │ 30.27 % │ 43,704,979 │ 30,477,096 │ 26,477,096 ║
|
||||
# ╟───────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ S4LRU 8M │ 57.86 % │ 43,704,979 │ 18,419,181 │ 10,419,181 ║
|
||||
# ╠═══════════════════╪═════════╪════════════╪═════════════╪══════════════╣
|
||||
# ║ MRU 1M │ 11.92 % │ 43,704,979 │ 38,493,369 │ 37,493,369 ║
|
||||
# ╟───────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ MRU 2M │ 25.67 % │ 43,704,979 │ 32,486,285 │ 30,486,285 ║
|
||||
# ╟───────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ MRU 4M │ 41.82 % │ 43,704,979 │ 25,429,608 │ 21,429,608 ║
|
||||
# ╟───────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ MRU 8M │ 68.01 % │ 43,704,979 │ 13,980,246 │ 5,980,246 ║
|
||||
# ╠═══════════════════╪═════════╪════════════╪═════════════╪══════════════╣
|
||||
# ║ LFU 1M │ 6.13 % │ 43,704,979 │ 41,026,869 │ 40,026,869 ║
|
||||
# ╟───────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LFU 2M │ 23.39 % │ 43,704,979 │ 33,482,361 │ 31,482,361 ║
|
||||
# ╟───────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LFU 4M │ 39.06 % │ 43,704,979 │ 26,632,624 │ 22,632,624 ║
|
||||
# ╟───────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LFU 8M │ 57.55 % │ 43,704,979 │ 18,552,089 │ 10,552,089 ║
|
||||
# ╠═══════════════════╪═════════╪════════════╪═════════════╪══════════════╣
|
||||
# ║ LFUDA 1M │ 3.25 % │ 43,704,979 │ 42,285,825 │ 41,285,825 ║
|
||||
# ╟───────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LFUDA 2M │ 11.02 % │ 43,704,979 │ 38,890,280 │ 36,890,280 ║
|
||||
# ╟───────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LFUDA 4M │ 21.96 % │ 43,704,979 │ 34,107,344 │ 30,107,344 ║
|
||||
# ╟───────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LFUDA 8M │ 54.72 % │ 43,704,979 │ 19,790,371 │ 11,790,371 ║
|
||||
# ╠═══════════════════╪═════════╪════════════╪═════════════╪══════════════╣
|
||||
# ║ LRU/FS/SLRU 1M │ 14.36 % │ 43,704,979 │ 37,428,825 │ 36,428,825 ║
|
||||
# ╟───────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LRU/FS/SLRU 2M │ 28.61 % │ 43,704,979 │ 31,200,295 │ 29,200,295 ║
|
||||
# ╟───────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LRU/FS/SLRU 4M │ 45.36 % │ 43,704,979 │ 23,882,207 │ 19,882,207 ║
|
||||
# ╟───────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LRU/FS/SLRU 8M │ 70.73 % │ 43,704,979 │ 12,791,039 │ 4,791,039 ║
|
||||
# ╠═══════════════════╪═════════╪════════════╪═════════════╪══════════════╣
|
||||
# ║ LRU/FS/SLRU/HC 1M │ 14.28 % │ 43,704,979 │ 37,463,497 │ 36,463,497 ║
|
||||
# ╟───────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LRU/FS/SLRU/HC 2M │ 28.61 % │ 43,704,979 │ 31,200,295 │ 29,200,295 ║
|
||||
# ╟───────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LRU/FS/SLRU/HC 4M │ 45.36 % │ 43,704,979 │ 23,882,207 │ 19,882,207 ║
|
||||
# ╟───────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LRU/FS/SLRU/HC 8M │ 70.73 % │ 43,704,979 │ 12,791,039 │ 4,791,039 ║
|
||||
# ╚═══════════════════╧═════════╧════════════╧═════════════╧══════════════╝
|
||||
#
|
||||
|
||||
arc-traces="arc-traces"
|
||||
|
|
@ -271,6 +287,62 @@ akka.cluster.sharding {
|
|||
pattern = arc-database
|
||||
strategy = lfuda-800k
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU 1M"
|
||||
shards = 100
|
||||
regions = 10
|
||||
pattern = arc-database
|
||||
strategy = lru-fs-slru-100k
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU 2M"
|
||||
shards = 100
|
||||
regions = 10
|
||||
pattern = arc-database
|
||||
strategy = lru-fs-slru-200k
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU 4M"
|
||||
shards = 100
|
||||
regions = 10
|
||||
pattern = arc-database
|
||||
strategy = lru-fs-slru-400k
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU 8M"
|
||||
shards = 100
|
||||
regions = 10
|
||||
pattern = arc-database
|
||||
strategy = lru-fs-slru-800k
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU/HC 1M"
|
||||
shards = 100
|
||||
regions = 10
|
||||
pattern = arc-database
|
||||
strategy = lru-fs-slru-hc-100k
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU/HC 2M"
|
||||
shards = 100
|
||||
regions = 10
|
||||
pattern = arc-database
|
||||
strategy = lru-fs-slru-hc-200k
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU/HC 4M"
|
||||
shards = 100
|
||||
regions = 10
|
||||
pattern = arc-database
|
||||
strategy = lru-fs-slru-hc-400k
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU/HC 8M"
|
||||
shards = 100
|
||||
regions = 10
|
||||
pattern = arc-database
|
||||
strategy = lru-fs-slru-hc-800k
|
||||
},
|
||||
]
|
||||
|
||||
print-detailed-stats = true
|
||||
|
|
@ -502,5 +574,62 @@ akka.cluster.sharding {
|
|||
dynamic-aging = on
|
||||
}
|
||||
}
|
||||
|
||||
lru-fs-slru {
|
||||
strategy = composite
|
||||
composite {
|
||||
admission {
|
||||
window.strategy = least-recently-used
|
||||
filter = frequency-sketch
|
||||
optimizer = none
|
||||
}
|
||||
main {
|
||||
strategy = least-recently-used
|
||||
least-recently-used {
|
||||
segmented {
|
||||
levels = 2
|
||||
proportions = [0.2, 0.8]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lru-fs-slru-100k = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru} {
|
||||
composite.per-region-limit = 100000
|
||||
}
|
||||
|
||||
lru-fs-slru-200k = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru} {
|
||||
composite.per-region-limit = 200000
|
||||
}
|
||||
|
||||
lru-fs-slru-400k = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru} {
|
||||
composite.per-region-limit = 400000
|
||||
}
|
||||
|
||||
lru-fs-slru-800k = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru} {
|
||||
composite.per-region-limit = 800000
|
||||
}
|
||||
|
||||
lru-fs-slru-hc = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru} {
|
||||
composite.admission.optimizer = hill-climbing
|
||||
}
|
||||
|
||||
lru-fs-slru-hc-100k = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru-hc} {
|
||||
composite.per-region-limit = 100000
|
||||
}
|
||||
|
||||
lru-fs-slru-hc-200k = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru-hc} {
|
||||
composite.per-region-limit = 200000
|
||||
}
|
||||
|
||||
lru-fs-slru-hc-400k = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru-hc} {
|
||||
composite.per-region-limit = 400000
|
||||
}
|
||||
|
||||
lru-fs-slru-hc-800k = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru-hc} {
|
||||
composite.per-region-limit = 800000
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,51 +8,63 @@
|
|||
#
|
||||
# > akka-cluster-sharding/Test/runMain akka.cluster.sharding.passivation.simulator.Simulator arc-trace-search
|
||||
#
|
||||
# ╔════════════╤═════════╤════════════╤═════════════╤══════════════╗
|
||||
# ║ Run │ Active │ Accesses │ Activations │ Passivations ║
|
||||
# ╠════════════╪═════════╪════════════╪═════════════╪══════════════╣
|
||||
# ║ OPT 250k │ 30.13 % │ 37,656,092 │ 26,309,294 │ 26,059,294 ║
|
||||
# ╟────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ OPT 500k │ 45.95 % │ 37,656,092 │ 20,354,161 │ 19,854,161 ║
|
||||
# ╟────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ OPT 1M │ 65.55 % │ 37,656,092 │ 12,970,868 │ 11,970,868 ║
|
||||
# ╠════════════╪═════════╪════════════╪═════════════╪══════════════╣
|
||||
# ║ LRU 250k │ 3.07 % │ 37,656,092 │ 36,498,516 │ 36,248,516 ║
|
||||
# ╟────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LRU 500k │ 7.53 % │ 37,656,092 │ 34,822,122 │ 34,322,122 ║
|
||||
# ╟────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LRU 1M │ 25.37 % │ 37,656,092 │ 28,102,287 │ 27,102,287 ║
|
||||
# ╠════════════╪═════════╪════════════╪═════════════╪══════════════╣
|
||||
# ║ SLRU 250k │ 9.59 % │ 37,656,092 │ 34,044,825 │ 33,794,825 ║
|
||||
# ╟────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ SLRU 500k │ 16.76 % │ 37,656,092 │ 31,345,965 │ 30,845,965 ║
|
||||
# ╟────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ SLRU 1M │ 27.49 % │ 37,656,092 │ 27,305,632 │ 26,305,632 ║
|
||||
# ╠════════════╪═════════╪════════════╪═════════════╪══════════════╣
|
||||
# ║ S4LRU 250k │ 9.78 % │ 37,656,092 │ 33,973,161 │ 33,723,161 ║
|
||||
# ╟────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ S4LRU 500k │ 17.04 % │ 37,656,092 │ 31,241,138 │ 30,741,138 ║
|
||||
# ╟────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ S4LRU 1M │ 27.69 % │ 37,656,092 │ 27,229,802 │ 26,229,802 ║
|
||||
# ╠════════════╪═════════╪════════════╪═════════════╪══════════════╣
|
||||
# ║ MRU 250k │ 5.25 % │ 37,656,092 │ 35,680,111 │ 35,430,111 ║
|
||||
# ╟────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ MRU 500k │ 10.50 % │ 37,656,092 │ 33,702,975 │ 33,202,975 ║
|
||||
# ╟────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ MRU 1M │ 20.79 % │ 37,656,092 │ 29,826,997 │ 28,826,997 ║
|
||||
# ╠════════════╪═════════╪════════════╪═════════════╪══════════════╣
|
||||
# ║ LFU 250k │ 9.04 % │ 37,656,092 │ 34,253,102 │ 34,003,102 ║
|
||||
# ╟────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LFU 500k │ 16.42 % │ 37,656,092 │ 31,471,765 │ 30,971,765 ║
|
||||
# ╟────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LFU 1M │ 27.43 % │ 37,656,092 │ 27,328,351 │ 26,328,351 ║
|
||||
# ╠════════════╪═════════╪════════════╪═════════════╪══════════════╣
|
||||
# ║ LFUDA 250k │ 3.18 % │ 37,656,092 │ 36,457,345 │ 36,207,345 ║
|
||||
# ╟────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LFUDA 500k │ 8.95 % │ 37,656,092 │ 34,285,981 │ 33,785,981 ║
|
||||
# ╟────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LFUDA 1M │ 28.10 % │ 37,656,092 │ 27,073,194 │ 26,073,194 ║
|
||||
# ╚════════════╧═════════╧════════════╧═════════════╧══════════════╝
|
||||
# ╔═════════════════════╤═════════╤════════════╤═════════════╤══════════════╗
|
||||
# ║ Run │ Active │ Accesses │ Activations │ Passivations ║
|
||||
# ╠═════════════════════╪═════════╪════════════╪═════════════╪══════════════╣
|
||||
# ║ OPT 250k │ 30.13 % │ 37,656,092 │ 26,309,294 │ 26,059,294 ║
|
||||
# ╟─────────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ OPT 500k │ 45.95 % │ 37,656,092 │ 20,354,161 │ 19,854,161 ║
|
||||
# ╟─────────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ OPT 1M │ 65.55 % │ 37,656,092 │ 12,970,868 │ 11,970,868 ║
|
||||
# ╠═════════════════════╪═════════╪════════════╪═════════════╪══════════════╣
|
||||
# ║ LRU 250k │ 3.07 % │ 37,656,092 │ 36,498,516 │ 36,248,516 ║
|
||||
# ╟─────────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LRU 500k │ 7.53 % │ 37,656,092 │ 34,822,122 │ 34,322,122 ║
|
||||
# ╟─────────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LRU 1M │ 25.37 % │ 37,656,092 │ 28,102,287 │ 27,102,287 ║
|
||||
# ╠═════════════════════╪═════════╪════════════╪═════════════╪══════════════╣
|
||||
# ║ SLRU 250k │ 9.59 % │ 37,656,092 │ 34,044,825 │ 33,794,825 ║
|
||||
# ╟─────────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ SLRU 500k │ 16.76 % │ 37,656,092 │ 31,345,965 │ 30,845,965 ║
|
||||
# ╟─────────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ SLRU 1M │ 27.49 % │ 37,656,092 │ 27,305,632 │ 26,305,632 ║
|
||||
# ╠═════════════════════╪═════════╪════════════╪═════════════╪══════════════╣
|
||||
# ║ S4LRU 250k │ 9.78 % │ 37,656,092 │ 33,973,161 │ 33,723,161 ║
|
||||
# ╟─────────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ S4LRU 500k │ 17.04 % │ 37,656,092 │ 31,241,138 │ 30,741,138 ║
|
||||
# ╟─────────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ S4LRU 1M │ 27.69 % │ 37,656,092 │ 27,229,802 │ 26,229,802 ║
|
||||
# ╠═════════════════════╪═════════╪════════════╪═════════════╪══════════════╣
|
||||
# ║ MRU 250k │ 5.25 % │ 37,656,092 │ 35,680,111 │ 35,430,111 ║
|
||||
# ╟─────────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ MRU 500k │ 10.50 % │ 37,656,092 │ 33,702,975 │ 33,202,975 ║
|
||||
# ╟─────────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ MRU 1M │ 20.79 % │ 37,656,092 │ 29,826,997 │ 28,826,997 ║
|
||||
# ╠═════════════════════╪═════════╪════════════╪═════════════╪══════════════╣
|
||||
# ║ LFU 250k │ 9.04 % │ 37,656,092 │ 34,253,102 │ 34,003,102 ║
|
||||
# ╟─────────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LFU 500k │ 16.42 % │ 37,656,092 │ 31,471,765 │ 30,971,765 ║
|
||||
# ╟─────────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LFU 1M │ 27.43 % │ 37,656,092 │ 27,328,351 │ 26,328,351 ║
|
||||
# ╠═════════════════════╪═════════╪════════════╪═════════════╪══════════════╣
|
||||
# ║ LFUDA 250k │ 3.18 % │ 37,656,092 │ 36,457,345 │ 36,207,345 ║
|
||||
# ╟─────────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LFUDA 500k │ 8.95 % │ 37,656,092 │ 34,285,981 │ 33,785,981 ║
|
||||
# ╟─────────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LFUDA 1M │ 28.10 % │ 37,656,092 │ 27,073,194 │ 26,073,194 ║
|
||||
# ╠═════════════════════╪═════════╪════════════╪═════════════╪══════════════╣
|
||||
# ║ LRU/FS/SLRU 250k │ 13.05 % │ 37,656,092 │ 32,741,656 │ 32,491,656 ║
|
||||
# ╟─────────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LRU/FS/SLRU 500k │ 24.89 % │ 37,656,092 │ 28,281,835 │ 27,781,835 ║
|
||||
# ╟─────────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LRU/FS/SLRU 1M │ 44.63 % │ 37,656,092 │ 20,850,711 │ 19,850,711 ║
|
||||
# ╠═════════════════════╪═════════╪════════════╪═════════════╪══════════════╣
|
||||
# ║ LRU/FS/SLRU/HC 250k │ 12.48 % │ 37,656,092 │ 32,955,813 │ 32,705,813 ║
|
||||
# ╟─────────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LRU/FS/SLRU/HC 500k │ 24.76 % │ 37,656,092 │ 28,332,311 │ 27,832,311 ║
|
||||
# ╟─────────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LRU/FS/SLRU/HC 1M │ 44.63 % │ 37,656,092 │ 20,850,711 │ 19,850,711 ║
|
||||
# ╚═════════════════════╧═════════╧════════════╧═════════════╧══════════════╝
|
||||
#
|
||||
|
||||
arc-traces="arc-traces"
|
||||
|
|
@ -208,6 +220,48 @@ akka.cluster.sharding {
|
|||
pattern = arc-search-merged
|
||||
strategy = lfuda-100k
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU 250k"
|
||||
shards = 100
|
||||
regions = 10
|
||||
pattern = arc-search-merged
|
||||
strategy = lru-fs-slru-25k
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU 500k"
|
||||
shards = 100
|
||||
regions = 10
|
||||
pattern = arc-search-merged
|
||||
strategy = lru-fs-slru-50k
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU 1M"
|
||||
shards = 100
|
||||
regions = 10
|
||||
pattern = arc-search-merged
|
||||
strategy = lru-fs-slru-100k
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU/HC 250k"
|
||||
shards = 100
|
||||
regions = 10
|
||||
pattern = arc-search-merged
|
||||
strategy = lru-fs-slru-hc-25k
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU/HC 500k"
|
||||
shards = 100
|
||||
regions = 10
|
||||
pattern = arc-search-merged
|
||||
strategy = lru-fs-slru-hc-50k
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU/HC 1M"
|
||||
shards = 100
|
||||
regions = 10
|
||||
pattern = arc-search-merged
|
||||
strategy = lru-fs-slru-hc-100k
|
||||
},
|
||||
]
|
||||
|
||||
print-detailed-stats = true
|
||||
|
|
@ -384,5 +438,54 @@ akka.cluster.sharding {
|
|||
dynamic-aging = on
|
||||
}
|
||||
}
|
||||
|
||||
lru-fs-slru {
|
||||
strategy = composite
|
||||
composite {
|
||||
admission {
|
||||
window.strategy = least-recently-used
|
||||
filter = frequency-sketch
|
||||
optimizer = none
|
||||
}
|
||||
main {
|
||||
strategy = least-recently-used
|
||||
least-recently-used {
|
||||
segmented {
|
||||
levels = 2
|
||||
proportions = [0.2, 0.8]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lru-fs-slru-25k = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru} {
|
||||
composite.per-region-limit = 25000
|
||||
}
|
||||
|
||||
lru-fs-slru-50k = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru} {
|
||||
composite.per-region-limit = 50000
|
||||
}
|
||||
|
||||
lru-fs-slru-100k = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru} {
|
||||
composite.per-region-limit = 100000
|
||||
}
|
||||
|
||||
lru-fs-slru-hc = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru} {
|
||||
composite.admission.optimizer = hill-climbing
|
||||
}
|
||||
|
||||
lru-fs-slru-hc-25k = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru-hc} {
|
||||
composite.per-region-limit = 25000
|
||||
}
|
||||
|
||||
lru-fs-slru-hc-50k = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru-hc} {
|
||||
composite.per-region-limit = 50000
|
||||
}
|
||||
|
||||
lru-fs-slru-hc-100k = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru-hc} {
|
||||
composite.per-region-limit = 100000
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,65 +8,81 @@
|
|||
#
|
||||
# > akka-cluster-sharding/Test/runMain akka.cluster.sharding.passivation.simulator.Simulator lirs-trace-glimpse
|
||||
#
|
||||
# ╔════════════╤═════════╤══════════╤═════════════╤══════════════╗
|
||||
# ║ Run │ Active │ Accesses │ Activations │ Passivations ║
|
||||
# ╠════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ OPT 250 │ 17.70 % │ 6,016 │ 4,951 │ 4,701 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ OPT 500 │ 34.33 % │ 6,016 │ 3,951 │ 3,451 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ OPT 1000 │ 53.14 % │ 6,016 │ 2,819 │ 1,819 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ OPT 1500 │ 57.95 % │ 6,016 │ 2,530 │ 1,030 ║
|
||||
# ╠════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ LRU 250 │ 0.91 % │ 6,016 │ 5,961 │ 5,711 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LRU 500 │ 0.95 % │ 6,016 │ 5,959 │ 5,459 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LRU 1000 │ 11.20 % │ 6,016 │ 5,342 │ 4,342 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LRU 1500 │ 36.55 % │ 6,016 │ 3,817 │ 2,317 ║
|
||||
# ╠════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ SLRU 250 │ 1.38 % │ 6,016 │ 5,933 │ 5,683 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ SLRU 500 │ 1.38 % │ 6,016 │ 5,933 │ 5,433 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ SLRU 1000 │ 31.33 % │ 6,016 │ 4,131 │ 3,131 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ SLRU 1500 │ 51.85 % │ 6,016 │ 2,897 │ 1,397 ║
|
||||
# ╠════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ S4LRU 250 │ 1.38 % │ 6,016 │ 5,933 │ 5,693 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ S4LRU 500 │ 1.38 % │ 6,016 │ 5,933 │ 5,453 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ S4LRU 1000 │ 19.70 % │ 6,016 │ 4,831 │ 3,831 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ S4LRU 1500 │ 48.02 % │ 6,016 │ 3,127 │ 1,647 ║
|
||||
# ╠════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ MRU 250 │ 14.78 % │ 6,016 │ 5,127 │ 4,877 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ MRU 500 │ 31.40 % │ 6,016 │ 4,127 │ 3,627 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ MRU 1000 │ 48.62 % │ 6,016 │ 3,091 │ 2,091 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ MRU 1500 │ 53.37 % │ 6,016 │ 2,805 │ 1,305 ║
|
||||
# ╠════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ LFU 250 │ 1.38 % │ 6,016 │ 5,933 │ 5,683 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LFU 500 │ 1.38 % │ 6,016 │ 5,933 │ 5,433 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LFU 1000 │ 31.33 % │ 6,016 │ 4,131 │ 3,131 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LFU 1500 │ 51.85 % │ 6,016 │ 2,897 │ 1,397 ║
|
||||
# ╠════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ LFUDA 250 │ 1.11 % │ 6,016 │ 5,949 │ 5,699 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LFUDA 500 │ 1.25 % │ 6,016 │ 5,941 │ 5,441 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LFUDA 1000 │ 16.37 % │ 6,016 │ 5,031 │ 4,031 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LFUDA 1500 │ 51.85 % │ 6,016 │ 2,897 │ 1,397 ║
|
||||
# ╚════════════╧═════════╧══════════╧═════════════╧══════════════╝
|
||||
# ╔═════════════════════╤═════════╤══════════╤═════════════╤══════════════╗
|
||||
# ║ Run │ Active │ Accesses │ Activations │ Passivations ║
|
||||
# ╠═════════════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ OPT 250 │ 17.70 % │ 6,016 │ 4,951 │ 4,701 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ OPT 500 │ 34.33 % │ 6,016 │ 3,951 │ 3,451 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ OPT 1000 │ 53.14 % │ 6,016 │ 2,819 │ 1,819 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ OPT 1500 │ 57.95 % │ 6,016 │ 2,530 │ 1,030 ║
|
||||
# ╠═════════════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ LRU 250 │ 0.91 % │ 6,016 │ 5,961 │ 5,711 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LRU 500 │ 0.95 % │ 6,016 │ 5,959 │ 5,459 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LRU 1000 │ 11.20 % │ 6,016 │ 5,342 │ 4,342 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LRU 1500 │ 36.55 % │ 6,016 │ 3,817 │ 2,317 ║
|
||||
# ╠═════════════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ SLRU 250 │ 1.38 % │ 6,016 │ 5,933 │ 5,683 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ SLRU 500 │ 1.38 % │ 6,016 │ 5,933 │ 5,433 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ SLRU 1000 │ 31.33 % │ 6,016 │ 4,131 │ 3,131 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ SLRU 1500 │ 51.85 % │ 6,016 │ 2,897 │ 1,397 ║
|
||||
# ╠═════════════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ S4LRU 250 │ 1.38 % │ 6,016 │ 5,933 │ 5,693 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ S4LRU 500 │ 1.38 % │ 6,016 │ 5,933 │ 5,453 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ S4LRU 1000 │ 19.70 % │ 6,016 │ 4,831 │ 3,831 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ S4LRU 1500 │ 48.02 % │ 6,016 │ 3,127 │ 1,647 ║
|
||||
# ╠═════════════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ MRU 250 │ 14.78 % │ 6,016 │ 5,127 │ 4,877 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ MRU 500 │ 31.40 % │ 6,016 │ 4,127 │ 3,627 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ MRU 1000 │ 48.62 % │ 6,016 │ 3,091 │ 2,091 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ MRU 1500 │ 53.37 % │ 6,016 │ 2,805 │ 1,305 ║
|
||||
# ╠═════════════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ LFU 250 │ 1.38 % │ 6,016 │ 5,933 │ 5,683 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LFU 500 │ 1.38 % │ 6,016 │ 5,933 │ 5,433 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LFU 1000 │ 31.33 % │ 6,016 │ 4,131 │ 3,131 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LFU 1500 │ 51.85 % │ 6,016 │ 2,897 │ 1,397 ║
|
||||
# ╠═════════════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ LFUDA 250 │ 1.11 % │ 6,016 │ 5,949 │ 5,699 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LFUDA 500 │ 1.25 % │ 6,016 │ 5,941 │ 5,441 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LFUDA 1000 │ 16.37 % │ 6,016 │ 5,031 │ 4,031 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LFUDA 1500 │ 51.85 % │ 6,016 │ 2,897 │ 1,397 ║
|
||||
# ╠═════════════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ LRU/FS/SLRU 250 │ 13.43 % │ 6,016 │ 5,208 │ 4,958 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LRU/FS/SLRU 500 │ 32.40 % │ 6,016 │ 4,067 │ 3,567 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LRU/FS/SLRU 1000 │ 50.83 % │ 6,016 │ 2,958 │ 1,958 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LRU/FS/SLRU 1500 │ 53.54 % │ 6,016 │ 2,795 │ 1,295 ║
|
||||
# ╠═════════════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ LRU/FS/SLRU/HC 250 │ 13.43 % │ 6,016 │ 5,208 │ 4,958 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LRU/FS/SLRU/HC 500 │ 32.40 % │ 6,016 │ 4,067 │ 3,567 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LRU/FS/SLRU/HC 1000 │ 50.83 % │ 6,016 │ 2,958 │ 1,958 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LRU/FS/SLRU/HC 1500 │ 53.54 % │ 6,016 │ 2,795 │ 1,295 ║
|
||||
# ╚═════════════════════╧═════════╧══════════╧═════════════╧══════════════╝
|
||||
#
|
||||
|
||||
lirs-traces="lirs-traces"
|
||||
|
|
@ -271,6 +287,62 @@ akka.cluster.sharding {
|
|||
pattern = lirs-glimpse
|
||||
strategy = lfuda-1500
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU 250"
|
||||
shards = 10
|
||||
regions = 1
|
||||
pattern = lirs-glimpse
|
||||
strategy = lru-fs-slru-250
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU 500"
|
||||
shards = 10
|
||||
regions = 1
|
||||
pattern = lirs-glimpse
|
||||
strategy = lru-fs-slru-500
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU 1000"
|
||||
shards = 10
|
||||
regions = 1
|
||||
pattern = lirs-glimpse
|
||||
strategy = lru-fs-slru-1000
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU 1500"
|
||||
shards = 10
|
||||
regions = 1
|
||||
pattern = lirs-glimpse
|
||||
strategy = lru-fs-slru-1500
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU/HC 250"
|
||||
shards = 10
|
||||
regions = 1
|
||||
pattern = lirs-glimpse
|
||||
strategy = lru-fs-slru-hc-250
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU/HC 500"
|
||||
shards = 10
|
||||
regions = 1
|
||||
pattern = lirs-glimpse
|
||||
strategy = lru-fs-slru-hc-500
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU/HC 1000"
|
||||
shards = 10
|
||||
regions = 1
|
||||
pattern = lirs-glimpse
|
||||
strategy = lru-fs-slru-hc-1000
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU/HC 1500"
|
||||
shards = 10
|
||||
regions = 1
|
||||
pattern = lirs-glimpse
|
||||
strategy = lru-fs-slru-hc-1500
|
||||
},
|
||||
]
|
||||
|
||||
print-detailed-stats = true
|
||||
|
|
@ -502,5 +574,62 @@ akka.cluster.sharding {
|
|||
dynamic-aging = on
|
||||
}
|
||||
}
|
||||
|
||||
lru-fs-slru {
|
||||
strategy = composite
|
||||
composite {
|
||||
admission {
|
||||
window.strategy = least-recently-used
|
||||
filter = frequency-sketch
|
||||
optimizer = none
|
||||
}
|
||||
main {
|
||||
strategy = least-recently-used
|
||||
least-recently-used {
|
||||
segmented {
|
||||
levels = 2
|
||||
proportions = [0.2, 0.8]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lru-fs-slru-250 = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru} {
|
||||
composite.per-region-limit = 250
|
||||
}
|
||||
|
||||
lru-fs-slru-500 = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru} {
|
||||
composite.per-region-limit = 500
|
||||
}
|
||||
|
||||
lru-fs-slru-1000 = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru} {
|
||||
composite.per-region-limit = 1000
|
||||
}
|
||||
|
||||
lru-fs-slru-1500 = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru} {
|
||||
composite.per-region-limit = 1500
|
||||
}
|
||||
|
||||
lru-fs-slru-hc = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru} {
|
||||
composite.admission.optimizer = hill-climbing
|
||||
}
|
||||
|
||||
lru-fs-slru-hc-250 = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru-hc} {
|
||||
composite.per-region-limit = 250
|
||||
}
|
||||
|
||||
lru-fs-slru-hc-500 = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru-hc} {
|
||||
composite.per-region-limit = 500
|
||||
}
|
||||
|
||||
lru-fs-slru-hc-1000 = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru-hc} {
|
||||
composite.per-region-limit = 1000
|
||||
}
|
||||
|
||||
lru-fs-slru-hc-1500 = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru-hc} {
|
||||
composite.per-region-limit = 1500
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,79 +8,99 @@
|
|||
#
|
||||
# > akka-cluster-sharding/Test/runMain akka.cluster.sharding.passivation.simulator.Simulator lirs-trace-multi
|
||||
#
|
||||
# ╔════════════╤═════════╤══════════╤═════════════╤══════════════╗
|
||||
# ║ Run │ Active │ Accesses │ Activations │ Passivations ║
|
||||
# ╠════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ OPT 100 │ 31.20 % │ 30,241 │ 20,807 │ 20,707 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ OPT 200 │ 38.47 % │ 30,241 │ 18,607 │ 18,407 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ OPT 400 │ 47.14 % │ 30,241 │ 15,986 │ 15,586 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ OPT 800 │ 53.53 % │ 30,241 │ 14,054 │ 13,254 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ OPT 1600 │ 64.14 % │ 30,241 │ 10,844 │ 9,244 ║
|
||||
# ╠════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ LRU 100 │ 6.53 % │ 30,241 │ 28,266 │ 28,166 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LRU 200 │ 14.38 % │ 30,241 │ 25,891 │ 25,691 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LRU 400 │ 27.55 % │ 30,241 │ 21,909 │ 21,509 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LRU 800 │ 35.97 % │ 30,241 │ 19,364 │ 18,564 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LRU 1600 │ 44.23 % │ 30,241 │ 16,865 │ 15,265 ║
|
||||
# ╠════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ SLRU 100 │ 9.22 % │ 30,241 │ 27,454 │ 27,354 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ SLRU 200 │ 22.41 % │ 30,241 │ 23,463 │ 23,263 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ SLRU 400 │ 29.94 % │ 30,241 │ 21,186 │ 20,786 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ SLRU 800 │ 37.30 % │ 30,241 │ 18,961 │ 18,161 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ SLRU 1600 │ 46.51 % │ 30,241 │ 16,177 │ 14,577 ║
|
||||
# ╠════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ S4LRU 100 │ 8.43 % │ 30,241 │ 27,691 │ 27,611 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ S4LRU 200 │ 22.62 % │ 30,241 │ 23,401 │ 23,201 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ S4LRU 400 │ 30.10 % │ 30,241 │ 21,139 │ 20,739 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ S4LRU 800 │ 37.30 % │ 30,241 │ 18,962 │ 18,162 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ S4LRU 1600 │ 46.51 % │ 30,241 │ 16,177 │ 14,577 ║
|
||||
# ╠════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ MRU 100 │ 2.41 % │ 30,241 │ 29,512 │ 29,412 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ MRU 200 │ 4.20 % │ 30,241 │ 28,970 │ 28,770 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ MRU 400 │ 7.21 % │ 30,241 │ 28,062 │ 27,662 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ MRU 800 │ 14.11 % │ 30,241 │ 25,973 │ 25,173 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ MRU 1600 │ 26.31 % │ 30,241 │ 22,284 │ 20,684 ║
|
||||
# ╠════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ LFU 100 │ 8.88 % │ 30,241 │ 27,557 │ 27,457 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LFU 200 │ 22.14 % │ 30,241 │ 23,547 │ 23,347 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LFU 400 │ 29.85 % │ 30,241 │ 21,213 │ 20,813 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LFU 800 │ 37.30 % │ 30,241 │ 18,961 │ 18,161 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LFU 1600 │ 46.51 % │ 30,241 │ 16,177 │ 14,577 ║
|
||||
# ╠════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ LFUDA 100 │ 10.16 % │ 30,241 │ 27,168 │ 27,068 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LFUDA 200 │ 22.99 % │ 30,241 │ 23,290 │ 23,090 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LFUDA 400 │ 30.50 % │ 30,241 │ 21,019 │ 20,619 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LFUDA 800 │ 37.25 % │ 30,241 │ 18,977 │ 18,177 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LFUDA 1600 │ 46.21 % │ 30,241 │ 16,267 │ 14,667 ║
|
||||
# ╚════════════╧═════════╧══════════╧═════════════╧══════════════╝
|
||||
# ╔═════════════════════╤═════════╤══════════╤═════════════╤══════════════╗
|
||||
# ║ Run │ Active │ Accesses │ Activations │ Passivations ║
|
||||
# ╠═════════════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ OPT 100 │ 31.20 % │ 30,241 │ 20,807 │ 20,707 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ OPT 200 │ 38.47 % │ 30,241 │ 18,607 │ 18,407 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ OPT 400 │ 47.14 % │ 30,241 │ 15,986 │ 15,586 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ OPT 800 │ 53.53 % │ 30,241 │ 14,054 │ 13,254 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ OPT 1600 │ 64.14 % │ 30,241 │ 10,844 │ 9,244 ║
|
||||
# ╠═════════════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ LRU 100 │ 6.53 % │ 30,241 │ 28,266 │ 28,166 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LRU 200 │ 14.38 % │ 30,241 │ 25,891 │ 25,691 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LRU 400 │ 27.55 % │ 30,241 │ 21,909 │ 21,509 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LRU 800 │ 35.97 % │ 30,241 │ 19,364 │ 18,564 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LRU 1600 │ 44.23 % │ 30,241 │ 16,865 │ 15,265 ║
|
||||
# ╠═════════════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ SLRU 100 │ 9.22 % │ 30,241 │ 27,454 │ 27,354 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ SLRU 200 │ 22.41 % │ 30,241 │ 23,463 │ 23,263 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ SLRU 400 │ 29.94 % │ 30,241 │ 21,186 │ 20,786 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ SLRU 800 │ 37.30 % │ 30,241 │ 18,961 │ 18,161 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ SLRU 1600 │ 46.51 % │ 30,241 │ 16,177 │ 14,577 ║
|
||||
# ╠═════════════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ S4LRU 100 │ 8.43 % │ 30,241 │ 27,691 │ 27,611 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ S4LRU 200 │ 22.62 % │ 30,241 │ 23,401 │ 23,201 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ S4LRU 400 │ 30.10 % │ 30,241 │ 21,139 │ 20,739 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ S4LRU 800 │ 37.30 % │ 30,241 │ 18,962 │ 18,162 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ S4LRU 1600 │ 46.51 % │ 30,241 │ 16,177 │ 14,577 ║
|
||||
# ╠═════════════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ MRU 100 │ 2.41 % │ 30,241 │ 29,512 │ 29,412 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ MRU 200 │ 4.20 % │ 30,241 │ 28,970 │ 28,770 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ MRU 400 │ 7.21 % │ 30,241 │ 28,062 │ 27,662 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ MRU 800 │ 14.11 % │ 30,241 │ 25,973 │ 25,173 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ MRU 1600 │ 26.31 % │ 30,241 │ 22,284 │ 20,684 ║
|
||||
# ╠═════════════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ LFU 100 │ 8.88 % │ 30,241 │ 27,557 │ 27,457 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LFU 200 │ 22.14 % │ 30,241 │ 23,547 │ 23,347 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LFU 400 │ 29.85 % │ 30,241 │ 21,213 │ 20,813 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LFU 800 │ 37.30 % │ 30,241 │ 18,961 │ 18,161 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LFU 1600 │ 46.51 % │ 30,241 │ 16,177 │ 14,577 ║
|
||||
# ╠═════════════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ LFUDA 100 │ 10.16 % │ 30,241 │ 27,168 │ 27,068 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LFUDA 200 │ 22.99 % │ 30,241 │ 23,290 │ 23,090 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LFUDA 400 │ 30.50 % │ 30,241 │ 21,019 │ 20,619 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LFUDA 800 │ 37.25 % │ 30,241 │ 18,977 │ 18,177 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LFUDA 1600 │ 46.21 % │ 30,241 │ 16,267 │ 14,667 ║
|
||||
# ╠═════════════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ LRU/FS/SLRU 100 │ 25.96 % │ 30,241 │ 22,389 │ 22,289 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LRU/FS/SLRU 200 │ 32.56 % │ 30,241 │ 20,396 │ 20,196 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LRU/FS/SLRU 400 │ 42.64 % │ 30,241 │ 17,347 │ 16,947 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LRU/FS/SLRU 800 │ 46.94 % │ 30,241 │ 16,045 │ 15,245 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LRU/FS/SLRU 1600 │ 57.65 % │ 30,241 │ 12,807 │ 11,207 ║
|
||||
# ╠═════════════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ LRU/FS/SLRU/HC 100 │ 24.74 % │ 30,241 │ 22,760 │ 22,660 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LRU/FS/SLRU/HC 200 │ 32.38 % │ 30,241 │ 20,450 │ 20,250 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LRU/FS/SLRU/HC 400 │ 42.63 % │ 30,241 │ 17,348 │ 16,948 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LRU/FS/SLRU/HC 800 │ 47.11 % │ 30,241 │ 15,994 │ 15,194 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LRU/FS/SLRU/HC 1600 │ 57.65 % │ 30,241 │ 12,807 │ 11,207 ║
|
||||
# ╚═════════════════════╧═════════╧══════════╧═════════════╧══════════════╝
|
||||
#
|
||||
|
||||
lirs-traces="lirs-traces"
|
||||
|
|
@ -334,6 +354,76 @@ akka.cluster.sharding {
|
|||
pattern = lirs-multi3
|
||||
strategy = lfuda-1600
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU 100"
|
||||
shards = 10
|
||||
regions = 1
|
||||
pattern = lirs-multi3
|
||||
strategy = lru-fs-slru-100
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU 200"
|
||||
shards = 10
|
||||
regions = 1
|
||||
pattern = lirs-multi3
|
||||
strategy = lru-fs-slru-200
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU 400"
|
||||
shards = 10
|
||||
regions = 1
|
||||
pattern = lirs-multi3
|
||||
strategy = lru-fs-slru-400
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU 800"
|
||||
shards = 10
|
||||
regions = 1
|
||||
pattern = lirs-multi3
|
||||
strategy = lru-fs-slru-800
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU 1600"
|
||||
shards = 10
|
||||
regions = 1
|
||||
pattern = lirs-multi3
|
||||
strategy = lru-fs-slru-1600
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU/HC 100"
|
||||
shards = 10
|
||||
regions = 1
|
||||
pattern = lirs-multi3
|
||||
strategy = lru-fs-slru-hc-100
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU/HC 200"
|
||||
shards = 10
|
||||
regions = 1
|
||||
pattern = lirs-multi3
|
||||
strategy = lru-fs-slru-hc-200
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU/HC 400"
|
||||
shards = 10
|
||||
regions = 1
|
||||
pattern = lirs-multi3
|
||||
strategy = lru-fs-slru-hc-400
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU/HC 800"
|
||||
shards = 10
|
||||
regions = 1
|
||||
pattern = lirs-multi3
|
||||
strategy = lru-fs-slru-hc-800
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU/HC 1600"
|
||||
shards = 10
|
||||
regions = 1
|
||||
pattern = lirs-multi3
|
||||
strategy = lru-fs-slru-hc-1600
|
||||
},
|
||||
]
|
||||
|
||||
print-detailed-stats = true
|
||||
|
|
@ -620,5 +710,70 @@ akka.cluster.sharding {
|
|||
dynamic-aging = on
|
||||
}
|
||||
}
|
||||
|
||||
lru-fs-slru {
|
||||
strategy = composite
|
||||
composite {
|
||||
admission {
|
||||
window.strategy = least-recently-used
|
||||
filter = frequency-sketch
|
||||
optimizer = none
|
||||
}
|
||||
main {
|
||||
strategy = least-recently-used
|
||||
least-recently-used {
|
||||
segmented {
|
||||
levels = 2
|
||||
proportions = [0.2, 0.8]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lru-fs-slru-100 = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru} {
|
||||
composite.per-region-limit = 100
|
||||
}
|
||||
|
||||
lru-fs-slru-200 = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru} {
|
||||
composite.per-region-limit = 200
|
||||
}
|
||||
|
||||
lru-fs-slru-400 = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru} {
|
||||
composite.per-region-limit = 400
|
||||
}
|
||||
|
||||
lru-fs-slru-800 = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru} {
|
||||
composite.per-region-limit = 800
|
||||
}
|
||||
|
||||
lru-fs-slru-1600 = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru} {
|
||||
composite.per-region-limit = 1600
|
||||
}
|
||||
|
||||
lru-fs-slru-hc = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru} {
|
||||
composite.admission.optimizer = hill-climbing
|
||||
}
|
||||
|
||||
lru-fs-slru-hc-100 = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru-hc} {
|
||||
composite.per-region-limit = 100
|
||||
}
|
||||
|
||||
lru-fs-slru-hc-200 = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru-hc} {
|
||||
composite.per-region-limit = 200
|
||||
}
|
||||
|
||||
lru-fs-slru-hc-400 = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru-hc} {
|
||||
composite.per-region-limit = 400
|
||||
}
|
||||
|
||||
lru-fs-slru-hc-800 = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru-hc} {
|
||||
composite.per-region-limit = 800
|
||||
}
|
||||
|
||||
lru-fs-slru-hc-1600 = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru-hc} {
|
||||
composite.per-region-limit = 1600
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,65 +8,81 @@
|
|||
#
|
||||
# > akka-cluster-sharding/Test/runMain akka.cluster.sharding.passivation.simulator.Simulator lirs-trace-postgres
|
||||
#
|
||||
# ╔════════════╤═════════╤══════════╤═════════════╤══════════════╗
|
||||
# ║ Run │ Active │ Accesses │ Activations │ Passivations ║
|
||||
# ╠════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ OPT 125 │ 35.16 % │ 10,448 │ 6,774 │ 6,654 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ OPT 250 │ 53.33 % │ 10,448 │ 4,876 │ 4,626 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ OPT 500 │ 58.12 % │ 10,448 │ 4,376 │ 3,876 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ OPT 1000 │ 67.69 % │ 10,448 │ 3,376 │ 2,376 ║
|
||||
# ╠════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ LRU 125 │ 12.19 % │ 10,448 │ 9,174 │ 9,054 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LRU 250 │ 13.95 % │ 10,448 │ 8,991 │ 8,741 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LRU 500 │ 48.55 % │ 10,448 │ 5,376 │ 4,876 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LRU 1000 │ 48.55 % │ 10,448 │ 5,376 │ 4,376 ║
|
||||
# ╠════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ SLRU 125 │ 9.34 % │ 10,448 │ 9,472 │ 9,362 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ SLRU 250 │ 16.80 % │ 10,448 │ 8,693 │ 8,443 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ SLRU 500 │ 52.59 % │ 10,448 │ 4,953 │ 4,453 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ SLRU 1000 │ 52.59 % │ 10,448 │ 4,953 │ 3,953 ║
|
||||
# ╠════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ S4LRU 125 │ 9.34 % │ 10,448 │ 9,472 │ 9,352 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ S4LRU 250 │ 16.80 % │ 10,448 │ 8,693 │ 8,453 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ S4LRU 500 │ 51.95 % │ 10,448 │ 5,020 │ 4,540 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ S4LRU 1000 │ 52.59 % │ 10,448 │ 4,953 │ 3,953 ║
|
||||
# ╠════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ MRU 125 │ 14.23 % │ 10,448 │ 8,961 │ 8,841 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ MRU 250 │ 30.84 % │ 10,448 │ 7,226 │ 6,976 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ MRU 500 │ 45.67 % │ 10,448 │ 5,676 │ 5,176 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ MRU 1000 │ 64.41 % │ 10,448 │ 3,718 │ 2,718 ║
|
||||
# ╠════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ LFU 125 │ 9.34 % │ 10,448 │ 9,472 │ 9,352 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LFU 250 │ 16.80 % │ 10,448 │ 8,693 │ 8,443 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LFU 500 │ 52.59 % │ 10,448 │ 4,953 │ 4,453 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LFU 1000 │ 52.59 % │ 10,448 │ 4,953 │ 3,953 ║
|
||||
# ╠════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ LFUDA 125 │ 12.89 % │ 10,448 │ 9,101 │ 8,981 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LFUDA 250 │ 16.79 % │ 10,448 │ 8,694 │ 8,444 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LFUDA 500 │ 52.58 % │ 10,448 │ 4,954 │ 4,454 ║
|
||||
# ╟────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LFUDA 1000 │ 52.58 % │ 10,448 │ 4,954 │ 3,954 ║
|
||||
# ╚════════════╧═════════╧══════════╧═════════════╧══════════════╝
|
||||
# ╔═════════════════════╤═════════╤══════════╤═════════════╤══════════════╗
|
||||
# ║ Run │ Active │ Accesses │ Activations │ Passivations ║
|
||||
# ╠═════════════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ OPT 125 │ 35.16 % │ 10,448 │ 6,774 │ 6,654 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ OPT 250 │ 53.33 % │ 10,448 │ 4,876 │ 4,626 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ OPT 500 │ 58.12 % │ 10,448 │ 4,376 │ 3,876 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ OPT 1000 │ 67.69 % │ 10,448 │ 3,376 │ 2,376 ║
|
||||
# ╠═════════════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ LRU 125 │ 12.19 % │ 10,448 │ 9,174 │ 9,054 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LRU 250 │ 13.95 % │ 10,448 │ 8,991 │ 8,741 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LRU 500 │ 48.55 % │ 10,448 │ 5,376 │ 4,876 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LRU 1000 │ 48.55 % │ 10,448 │ 5,376 │ 4,376 ║
|
||||
# ╠═════════════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ SLRU 125 │ 9.34 % │ 10,448 │ 9,472 │ 9,362 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ SLRU 250 │ 16.80 % │ 10,448 │ 8,693 │ 8,443 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ SLRU 500 │ 52.59 % │ 10,448 │ 4,953 │ 4,453 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ SLRU 1000 │ 52.59 % │ 10,448 │ 4,953 │ 3,953 ║
|
||||
# ╠═════════════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ S4LRU 125 │ 9.34 % │ 10,448 │ 9,472 │ 9,352 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ S4LRU 250 │ 16.80 % │ 10,448 │ 8,693 │ 8,453 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ S4LRU 500 │ 51.95 % │ 10,448 │ 5,020 │ 4,540 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ S4LRU 1000 │ 52.59 % │ 10,448 │ 4,953 │ 3,953 ║
|
||||
# ╠═════════════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ MRU 125 │ 14.23 % │ 10,448 │ 8,961 │ 8,841 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ MRU 250 │ 30.84 % │ 10,448 │ 7,226 │ 6,976 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ MRU 500 │ 45.67 % │ 10,448 │ 5,676 │ 5,176 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ MRU 1000 │ 64.41 % │ 10,448 │ 3,718 │ 2,718 ║
|
||||
# ╠═════════════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ LFU 125 │ 9.34 % │ 10,448 │ 9,472 │ 9,352 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LFU 250 │ 16.80 % │ 10,448 │ 8,693 │ 8,443 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LFU 500 │ 52.59 % │ 10,448 │ 4,953 │ 4,453 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LFU 1000 │ 52.59 % │ 10,448 │ 4,953 │ 3,953 ║
|
||||
# ╠═════════════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ LFUDA 125 │ 12.89 % │ 10,448 │ 9,101 │ 8,981 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LFUDA 250 │ 16.79 % │ 10,448 │ 8,694 │ 8,444 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LFUDA 500 │ 52.58 % │ 10,448 │ 4,954 │ 4,454 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LFUDA 1000 │ 52.58 % │ 10,448 │ 4,954 │ 3,954 ║
|
||||
# ╠═════════════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ LRU/FS/SLRU 125 │ 30.64 % │ 10,448 │ 7,247 │ 7,127 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LRU/FS/SLRU 250 │ 52.41 % │ 10,448 │ 4,972 │ 4,722 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LRU/FS/SLRU 500 │ 55.98 % │ 10,448 │ 4,599 │ 4,099 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LRU/FS/SLRU 1000 │ 66.56 % │ 10,448 │ 3,494 │ 2,494 ║
|
||||
# ╠═════════════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ LRU/FS/SLRU/HC 125 │ 29.96 % │ 10,448 │ 7,318 │ 7,198 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LRU/FS/SLRU/HC 250 │ 52.38 % │ 10,448 │ 4,975 │ 4,725 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LRU/FS/SLRU/HC 500 │ 55.98 % │ 10,448 │ 4,599 │ 4,099 ║
|
||||
# ╟─────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LRU/FS/SLRU/HC 1000 │ 66.56 % │ 10,448 │ 3,494 │ 2,494 ║
|
||||
# ╚═════════════════════╧═════════╧══════════╧═════════════╧══════════════╝
|
||||
#
|
||||
|
||||
lirs-traces="lirs-traces"
|
||||
|
|
@ -271,6 +287,62 @@ akka.cluster.sharding {
|
|||
pattern = lirs-postgres
|
||||
strategy = lfuda-1000
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU 125"
|
||||
shards = 10
|
||||
regions = 1
|
||||
pattern = lirs-postgres
|
||||
strategy = lru-fs-slru-125
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU 250"
|
||||
shards = 10
|
||||
regions = 1
|
||||
pattern = lirs-postgres
|
||||
strategy = lru-fs-slru-250
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU 500"
|
||||
shards = 10
|
||||
regions = 1
|
||||
pattern = lirs-postgres
|
||||
strategy = lru-fs-slru-500
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU 1000"
|
||||
shards = 10
|
||||
regions = 1
|
||||
pattern = lirs-postgres
|
||||
strategy = lru-fs-slru-1000
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU/HC 125"
|
||||
shards = 10
|
||||
regions = 1
|
||||
pattern = lirs-postgres
|
||||
strategy = lru-fs-slru-hc-125
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU/HC 250"
|
||||
shards = 10
|
||||
regions = 1
|
||||
pattern = lirs-postgres
|
||||
strategy = lru-fs-slru-hc-250
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU/HC 500"
|
||||
shards = 10
|
||||
regions = 1
|
||||
pattern = lirs-postgres
|
||||
strategy = lru-fs-slru-hc-500
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU/HC 1000"
|
||||
shards = 10
|
||||
regions = 1
|
||||
pattern = lirs-postgres
|
||||
strategy = lru-fs-slru-hc-1000
|
||||
},
|
||||
]
|
||||
|
||||
print-detailed-stats = true
|
||||
|
|
@ -502,5 +574,62 @@ akka.cluster.sharding {
|
|||
dynamic-aging = on
|
||||
}
|
||||
}
|
||||
|
||||
lru-fs-slru {
|
||||
strategy = composite
|
||||
composite {
|
||||
admission {
|
||||
window.strategy = least-recently-used
|
||||
filter = frequency-sketch
|
||||
optimizer = none
|
||||
}
|
||||
main {
|
||||
strategy = least-recently-used
|
||||
least-recently-used {
|
||||
segmented {
|
||||
levels = 2
|
||||
proportions = [0.2, 0.8]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lru-fs-slru-125 = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru} {
|
||||
composite.per-region-limit = 125
|
||||
}
|
||||
|
||||
lru-fs-slru-250 = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru} {
|
||||
composite.per-region-limit = 250
|
||||
}
|
||||
|
||||
lru-fs-slru-500 = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru} {
|
||||
composite.per-region-limit = 500
|
||||
}
|
||||
|
||||
lru-fs-slru-1000 = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru} {
|
||||
composite.per-region-limit = 1000
|
||||
}
|
||||
|
||||
lru-fs-slru-hc = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru} {
|
||||
composite.admission.optimizer = hill-climbing
|
||||
}
|
||||
|
||||
lru-fs-slru-hc-125 = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru-hc} {
|
||||
composite.per-region-limit = 125
|
||||
}
|
||||
|
||||
lru-fs-slru-hc-250 = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru-hc} {
|
||||
composite.per-region-limit = 250
|
||||
}
|
||||
|
||||
lru-fs-slru-hc-500 = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru-hc} {
|
||||
composite.per-region-limit = 500
|
||||
}
|
||||
|
||||
lru-fs-slru-hc-1000 = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru-hc} {
|
||||
composite.per-region-limit = 1000
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,65 +11,81 @@
|
|||
#
|
||||
# > akka-cluster-sharding/Test/runMain akka.cluster.sharding.passivation.simulator.Simulator lirs2-trace-w106
|
||||
#
|
||||
# ╔═══════════╤═════════╤═══════════╤═════════════╤══════════════╗
|
||||
# ║ Run │ Active │ Accesses │ Activations │ Passivations ║
|
||||
# ╠═══════════╪═════════╪═══════════╪═════════════╪══════════════╣
|
||||
# ║ OPT 50 │ 57.92 % │ 5,292,456 │ 2,226,826 │ 2,226,776 ║
|
||||
# ╟───────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ OPT 100 │ 66.17 % │ 5,292,456 │ 1,790,310 │ 1,790,210 ║
|
||||
# ╟───────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ OPT 200 │ 71.69 % │ 5,292,456 │ 1,498,368 │ 1,498,168 ║
|
||||
# ╟───────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ OPT 500 │ 77.20 % │ 5,292,456 │ 1,206,445 │ 1,205,945 ║
|
||||
# ╠═══════════╪═════════╪═══════════╪═════════════╪══════════════╣
|
||||
# ║ LRU 50 │ 45.35 % │ 5,292,456 │ 2,892,538 │ 2,892,488 ║
|
||||
# ╟───────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ LRU 100 │ 53.47 % │ 5,292,456 │ 2,462,659 │ 2,462,559 ║
|
||||
# ╟───────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ LRU 200 │ 64.96 % │ 5,292,456 │ 1,854,353 │ 1,854,153 ║
|
||||
# ╟───────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ LRU 500 │ 70.97 % │ 5,292,456 │ 1,536,203 │ 1,535,703 ║
|
||||
# ╠═══════════╪═════════╪═══════════╪═════════════╪══════════════╣
|
||||
# ║ SLRU 50 │ 41.44 % │ 5,292,456 │ 3,099,112 │ 3,099,062 ║
|
||||
# ╟───────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ SLRU 100 │ 52.52 % │ 5,292,456 │ 2,513,049 │ 2,512,949 ║
|
||||
# ╟───────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ SLRU 200 │ 60.42 % │ 5,292,456 │ 2,094,936 │ 2,094,736 ║
|
||||
# ╟───────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ SLRU 500 │ 70.02 % │ 5,292,456 │ 1,586,665 │ 1,586,165 ║
|
||||
# ╠═══════════╪═════════╪═══════════╪═════════════╪══════════════╣
|
||||
# ║ S4LRU 50 │ 39.87 % │ 5,292,456 │ 3,182,347 │ 3,182,307 ║
|
||||
# ╟───────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ S4LRU 100 │ 54.30 % │ 5,292,456 │ 2,418,459 │ 2,418,359 ║
|
||||
# ╟───────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ S4LRU 200 │ 63.50 % │ 5,292,456 │ 1,931,759 │ 1,931,559 ║
|
||||
# ╟───────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ S4LRU 500 │ 70.68 % │ 5,292,456 │ 1,551,818 │ 1,551,318 ║
|
||||
# ╠═══════════╪═════════╪═══════════╪═════════════╪══════════════╣
|
||||
# ║ MRU 50 │ 22.23 % │ 5,292,456 │ 4,116,089 │ 4,116,039 ║
|
||||
# ╟───────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ MRU 100 │ 22.36 % │ 5,292,456 │ 4,109,089 │ 4,108,989 ║
|
||||
# ╟───────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ MRU 200 │ 22.68 % │ 5,292,456 │ 4,092,384 │ 4,092,184 ║
|
||||
# ╟───────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ MRU 500 │ 23.53 % │ 5,292,456 │ 4,046,928 │ 4,046,428 ║
|
||||
# ╠═══════════╪═════════╪═══════════╪═════════════╪══════════════╣
|
||||
# ║ LFU 50 │ 35.92 % │ 5,292,456 │ 3,391,594 │ 3,391,544 ║
|
||||
# ╟───────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ LFU 100 │ 42.52 % │ 5,292,456 │ 3,041,915 │ 3,041,815 ║
|
||||
# ╟───────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ LFU 200 │ 48.42 % │ 5,292,456 │ 2,729,711 │ 2,729,511 ║
|
||||
# ╟───────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ LFU 500 │ 53.57 % │ 5,292,456 │ 2,457,445 │ 2,456,945 ║
|
||||
# ╠═══════════╪═════════╪═══════════╪═════════════╪══════════════╣
|
||||
# ║ LFUDA 50 │ 46.11 % │ 5,292,456 │ 2,851,965 │ 2,851,915 ║
|
||||
# ╟───────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ LFUDA 100 │ 55.62 % │ 5,292,456 │ 2,348,665 │ 2,348,565 ║
|
||||
# ╟───────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ LFUDA 200 │ 64.83 % │ 5,292,456 │ 1,861,307 │ 1,861,107 ║
|
||||
# ╟───────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ LFUDA 500 │ 71.38 % │ 5,292,456 │ 1,514,631 │ 1,514,131 ║
|
||||
# ╚═══════════╧═════════╧═══════════╧═════════════╧══════════════╝
|
||||
# ╔════════════════════╤═════════╤═══════════╤═════════════╤══════════════╗
|
||||
# ║ Run │ Active │ Accesses │ Activations │ Passivations ║
|
||||
# ╠════════════════════╪═════════╪═══════════╪═════════════╪══════════════╣
|
||||
# ║ OPT 50 │ 57.92 % │ 5,292,456 │ 2,226,826 │ 2,226,776 ║
|
||||
# ╟────────────────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ OPT 100 │ 66.17 % │ 5,292,456 │ 1,790,310 │ 1,790,210 ║
|
||||
# ╟────────────────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ OPT 200 │ 71.69 % │ 5,292,456 │ 1,498,368 │ 1,498,168 ║
|
||||
# ╟────────────────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ OPT 500 │ 77.20 % │ 5,292,456 │ 1,206,445 │ 1,205,945 ║
|
||||
# ╠════════════════════╪═════════╪═══════════╪═════════════╪══════════════╣
|
||||
# ║ LRU 50 │ 45.35 % │ 5,292,456 │ 2,892,538 │ 2,892,488 ║
|
||||
# ╟────────────────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ LRU 100 │ 53.47 % │ 5,292,456 │ 2,462,659 │ 2,462,559 ║
|
||||
# ╟────────────────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ LRU 200 │ 64.96 % │ 5,292,456 │ 1,854,353 │ 1,854,153 ║
|
||||
# ╟────────────────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ LRU 500 │ 70.97 % │ 5,292,456 │ 1,536,203 │ 1,535,703 ║
|
||||
# ╠════════════════════╪═════════╪═══════════╪═════════════╪══════════════╣
|
||||
# ║ SLRU 50 │ 41.44 % │ 5,292,456 │ 3,099,112 │ 3,099,062 ║
|
||||
# ╟────────────────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ SLRU 100 │ 52.52 % │ 5,292,456 │ 2,513,049 │ 2,512,949 ║
|
||||
# ╟────────────────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ SLRU 200 │ 60.42 % │ 5,292,456 │ 2,094,936 │ 2,094,736 ║
|
||||
# ╟────────────────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ SLRU 500 │ 70.02 % │ 5,292,456 │ 1,586,665 │ 1,586,165 ║
|
||||
# ╠════════════════════╪═════════╪═══════════╪═════════════╪══════════════╣
|
||||
# ║ S4LRU 50 │ 39.87 % │ 5,292,456 │ 3,182,347 │ 3,182,307 ║
|
||||
# ╟────────────────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ S4LRU 100 │ 54.30 % │ 5,292,456 │ 2,418,459 │ 2,418,359 ║
|
||||
# ╟────────────────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ S4LRU 200 │ 63.50 % │ 5,292,456 │ 1,931,759 │ 1,931,559 ║
|
||||
# ╟────────────────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ S4LRU 500 │ 70.68 % │ 5,292,456 │ 1,551,818 │ 1,551,318 ║
|
||||
# ╠════════════════════╪═════════╪═══════════╪═════════════╪══════════════╣
|
||||
# ║ MRU 50 │ 22.23 % │ 5,292,456 │ 4,116,089 │ 4,116,039 ║
|
||||
# ╟────────────────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ MRU 100 │ 22.36 % │ 5,292,456 │ 4,109,089 │ 4,108,989 ║
|
||||
# ╟────────────────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ MRU 200 │ 22.68 % │ 5,292,456 │ 4,092,384 │ 4,092,184 ║
|
||||
# ╟────────────────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ MRU 500 │ 23.53 % │ 5,292,456 │ 4,046,928 │ 4,046,428 ║
|
||||
# ╠════════════════════╪═════════╪═══════════╪═════════════╪══════════════╣
|
||||
# ║ LFU 50 │ 35.92 % │ 5,292,456 │ 3,391,594 │ 3,391,544 ║
|
||||
# ╟────────────────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ LFU 100 │ 42.52 % │ 5,292,456 │ 3,041,915 │ 3,041,815 ║
|
||||
# ╟────────────────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ LFU 200 │ 48.42 % │ 5,292,456 │ 2,729,711 │ 2,729,511 ║
|
||||
# ╟────────────────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ LFU 500 │ 53.57 % │ 5,292,456 │ 2,457,445 │ 2,456,945 ║
|
||||
# ╠════════════════════╪═════════╪═══════════╪═════════════╪══════════════╣
|
||||
# ║ LFUDA 50 │ 46.11 % │ 5,292,456 │ 2,851,965 │ 2,851,915 ║
|
||||
# ╟────────────────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ LFUDA 100 │ 55.62 % │ 5,292,456 │ 2,348,665 │ 2,348,565 ║
|
||||
# ╟────────────────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ LFUDA 200 │ 64.83 % │ 5,292,456 │ 1,861,307 │ 1,861,107 ║
|
||||
# ╟────────────────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ LFUDA 500 │ 71.38 % │ 5,292,456 │ 1,514,631 │ 1,514,131 ║
|
||||
# ╠════════════════════╪═════════╪═══════════╪═════════════╪══════════════╣
|
||||
# ║ LRU/FS/SLRU 50 │ 34.91 % │ 5,292,456 │ 3,444,873 │ 3,444,823 ║
|
||||
# ╟────────────────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ LRU/FS/SLRU 100 │ 45.39 % │ 5,292,456 │ 2,890,305 │ 2,890,205 ║
|
||||
# ╟────────────────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ LRU/FS/SLRU 200 │ 52.07 % │ 5,292,456 │ 2,536,639 │ 2,536,439 ║
|
||||
# ╟────────────────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ LRU/FS/SLRU 500 │ 65.37 % │ 5,292,456 │ 1,832,718 │ 1,832,218 ║
|
||||
# ╠════════════════════╪═════════╪═══════════╪═════════════╪══════════════╣
|
||||
# ║ LRU/FS/SLRU/HC 50 │ 46.11 % │ 5,292,456 │ 2,852,272 │ 2,852,222 ║
|
||||
# ╟────────────────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ LRU/FS/SLRU/HC 100 │ 55.86 % │ 5,292,456 │ 2,336,245 │ 2,336,145 ║
|
||||
# ╟────────────────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ LRU/FS/SLRU/HC 200 │ 65.50 % │ 5,292,456 │ 1,826,070 │ 1,825,870 ║
|
||||
# ╟────────────────────┼─────────┼───────────┼─────────────┼──────────────╢
|
||||
# ║ LRU/FS/SLRU/HC 500 │ 71.77 % │ 5,292,456 │ 1,493,991 │ 1,493,491 ║
|
||||
# ╚════════════════════╧═════════╧═══════════╧═════════════╧══════════════╝
|
||||
#
|
||||
|
||||
lirs2-traces="lirs2-traces"
|
||||
|
|
@ -274,6 +290,62 @@ akka.cluster.sharding {
|
|||
pattern = lirs2-w106
|
||||
strategy = lfuda-500
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU 50"
|
||||
shards = 5
|
||||
regions = 1
|
||||
pattern = lirs2-w106
|
||||
strategy = lru-fs-slru-50
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU 100"
|
||||
shards = 5
|
||||
regions = 1
|
||||
pattern = lirs2-w106
|
||||
strategy = lru-fs-slru-100
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU 200"
|
||||
shards = 5
|
||||
regions = 1
|
||||
pattern = lirs2-w106
|
||||
strategy = lru-fs-slru-200
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU 500"
|
||||
shards = 5
|
||||
regions = 1
|
||||
pattern = lirs2-w106
|
||||
strategy = lru-fs-slru-500
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU/HC 50"
|
||||
shards = 5
|
||||
regions = 1
|
||||
pattern = lirs2-w106
|
||||
strategy = lru-fs-slru-hc-50
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU/HC 100"
|
||||
shards = 5
|
||||
regions = 1
|
||||
pattern = lirs2-w106
|
||||
strategy = lru-fs-slru-hc-100
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU/HC 200"
|
||||
shards = 5
|
||||
regions = 1
|
||||
pattern = lirs2-w106
|
||||
strategy = lru-fs-slru-hc-200
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU/HC 500"
|
||||
shards = 5
|
||||
regions = 1
|
||||
pattern = lirs2-w106
|
||||
strategy = lru-fs-slru-hc-500
|
||||
},
|
||||
]
|
||||
|
||||
print-detailed-stats = true
|
||||
|
|
@ -505,5 +577,62 @@ akka.cluster.sharding {
|
|||
dynamic-aging = on
|
||||
}
|
||||
}
|
||||
|
||||
lru-fs-slru {
|
||||
strategy = composite
|
||||
composite {
|
||||
admission {
|
||||
window.strategy = least-recently-used
|
||||
filter = frequency-sketch
|
||||
optimizer = none
|
||||
}
|
||||
main {
|
||||
strategy = least-recently-used
|
||||
least-recently-used {
|
||||
segmented {
|
||||
levels = 2
|
||||
proportions = [0.2, 0.8]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lru-fs-slru-50 = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru} {
|
||||
composite.per-region-limit = 50
|
||||
}
|
||||
|
||||
lru-fs-slru-100 = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru} {
|
||||
composite.per-region-limit = 100
|
||||
}
|
||||
|
||||
lru-fs-slru-200 = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru} {
|
||||
composite.per-region-limit = 200
|
||||
}
|
||||
|
||||
lru-fs-slru-500 = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru} {
|
||||
composite.per-region-limit = 500
|
||||
}
|
||||
|
||||
lru-fs-slru-hc = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru} {
|
||||
composite.admission.optimizer = hill-climbing
|
||||
}
|
||||
|
||||
lru-fs-slru-hc-50 = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru-hc} {
|
||||
composite.per-region-limit = 50
|
||||
}
|
||||
|
||||
lru-fs-slru-hc-100 = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru-hc} {
|
||||
composite.per-region-limit = 100
|
||||
}
|
||||
|
||||
lru-fs-slru-hc-200 = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru-hc} {
|
||||
composite.per-region-limit = 200
|
||||
}
|
||||
|
||||
lru-fs-slru-hc-500 = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru-hc} {
|
||||
composite.per-region-limit = 500
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,8 +19,34 @@ akka.cluster.sharding {
|
|||
}
|
||||
}
|
||||
least-frequently-used {
|
||||
per-region-limit = 100000
|
||||
dynamic-aging = off
|
||||
}
|
||||
composite {
|
||||
main.strategy = least-recently-used
|
||||
admission {
|
||||
window {
|
||||
proportion = 0.01
|
||||
minimum-proportion = 0.01
|
||||
maximum-proportion = 1.0
|
||||
strategy = least-recently-used
|
||||
}
|
||||
filter = frequency-sketch
|
||||
frequency-sketch {
|
||||
depth = 4
|
||||
counter-bits = 4
|
||||
width-multiplier = 4
|
||||
reset-multiplier = 10
|
||||
}
|
||||
optimizer = hill-climbing
|
||||
hill-climbing {
|
||||
adjust-multiplier = 10
|
||||
initial-step = 0.0625
|
||||
restart-threshold = 0.05
|
||||
step-decay = 0.98
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pattern-defaults {
|
||||
|
|
|
|||
|
|
@ -3,13 +3,17 @@
|
|||
#
|
||||
# > akka-cluster-sharding/Test/runMain akka.cluster.sharding.passivation.simulator.Simulator synthetic-loop
|
||||
#
|
||||
# ╔══════════╤═════════╤════════════╤═════════════╤══════════════╗
|
||||
# ║ Run │ Active │ Accesses │ Activations │ Passivations ║
|
||||
# ╠══════════╪═════════╪════════════╪═════════════╪══════════════╣
|
||||
# ║ LRU 500k │ 0.00 % │ 10,000,000 │ 10,000,000 │ 9,500,000 ║
|
||||
# ╟──────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ MRU 500k │ 45.00 % │ 10,000,000 │ 5,500,000 │ 5,000,000 ║
|
||||
# ╚══════════╧═════════╧════════════╧═════════════╧══════════════╝
|
||||
# ╔═════════════════════╤═════════╤════════════╤═════════════╤══════════════╗
|
||||
# ║ Run │ Active │ Accesses │ Activations │ Passivations ║
|
||||
# ╠═════════════════════╪═════════╪════════════╪═════════════╪══════════════╣
|
||||
# ║ LRU 500k │ 0.00 % │ 10,000,000 │ 10,000,000 │ 9,500,000 ║
|
||||
# ╟─────────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ MRU 500k │ 45.00 % │ 10,000,000 │ 5,500,000 │ 5,000,000 ║
|
||||
# ╟─────────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LRU/FS/SLRU 500k │ 44.24 % │ 10,000,000 │ 5,576,284 │ 5,076,284 ║
|
||||
# ╟─────────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LRU/FS/SLRU/HC 500k │ 44.24 % │ 10,000,000 │ 5,576,284 │ 5,076,284 ║
|
||||
# ╚═════════════════════╧═════════╧════════════╧═════════════╧══════════════╝
|
||||
#
|
||||
|
||||
akka.cluster.sharding {
|
||||
|
|
@ -28,7 +32,21 @@ akka.cluster.sharding {
|
|||
regions = 10
|
||||
pattern = loop-1M
|
||||
strategy = mru-50k
|
||||
}
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU 500k"
|
||||
shards = 100
|
||||
regions = 10
|
||||
pattern = loop-1M
|
||||
strategy = lru-fs-slru-50k
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU/HC 500k"
|
||||
shards = 100
|
||||
regions = 10
|
||||
pattern = loop-1M
|
||||
strategy = lru-fs-slru-hc-50k
|
||||
},
|
||||
]
|
||||
|
||||
print-detailed-stats = true
|
||||
|
|
@ -64,5 +82,38 @@ akka.cluster.sharding {
|
|||
per-region-limit = 50000
|
||||
}
|
||||
}
|
||||
|
||||
lru-fs-slru {
|
||||
strategy = composite
|
||||
composite {
|
||||
admission {
|
||||
window.strategy = least-recently-used
|
||||
filter = frequency-sketch
|
||||
optimizer = none
|
||||
}
|
||||
main {
|
||||
strategy = least-recently-used
|
||||
least-recently-used {
|
||||
segmented {
|
||||
levels = 2
|
||||
proportions = [0.2, 0.8]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lru-fs-slru-50k = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru} {
|
||||
composite.per-region-limit = 50000
|
||||
}
|
||||
|
||||
lru-fs-slru-hc = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru} {
|
||||
composite.admission.optimizer = hill-climbing
|
||||
}
|
||||
|
||||
lru-fs-slru-hc-50k = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru-hc} {
|
||||
composite.per-region-limit = 50000
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,110 +3,182 @@
|
|||
#
|
||||
# > akka-cluster-sharding/Test/runMain akka.cluster.sharding.passivation.simulator.Simulator synthetic-zipfian
|
||||
#
|
||||
# Zipfian:
|
||||
#
|
||||
# ╔════════════════════╤═════════╤════════════╤═════════════╤══════════════╗
|
||||
# ║ Run │ Active │ Accesses │ Activations │ Passivations ║
|
||||
# ╠════════════════════╪═════════╪════════════╪═════════════╪══════════════╣
|
||||
# ║ OPT 10k │ 60.36 % │ 50,000,000 │ 19,818,336 │ 19,808,336 ║
|
||||
# ╟────────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LRU 10k │ 46.99 % │ 50,000,000 │ 26,504,477 │ 26,494,477 ║
|
||||
# ╟────────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ SLRU 10k │ 55.23 % │ 50,000,000 │ 22,384,620 │ 22,374,620 ║
|
||||
# ╟────────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ S4LRU 10k │ 54.94 % │ 50,000,000 │ 22,532,034 │ 22,522,034 ║
|
||||
# ╟────────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ MRU 10k │ 15.89 % │ 50,000,000 │ 42,054,589 │ 42,044,589 ║
|
||||
# ╟────────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LFU 10k │ 55.41 % │ 50,000,000 │ 22,292,520 │ 22,282,520 ║
|
||||
# ╟────────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LFUDA 10k │ 52.15 % │ 50,000,000 │ 23,926,057 │ 23,916,057 ║
|
||||
# ╟────────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LRU/FS/SLRU 10k │ 55.67 % │ 50,000,000 │ 22,167,106 │ 22,157,106 ║
|
||||
# ╟────────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LRU/FS/SLRU/HC 10k │ 54.43 % │ 50,000,000 │ 22,785,290 │ 22,775,290 ║
|
||||
# ╚════════════════════╧═════════╧════════════╧═════════════╧══════════════╝
|
||||
#
|
||||
# Scrambled Zipfian:
|
||||
#
|
||||
# ╔════════════╤═════════╤════════════╤═════════════╤══════════════╗
|
||||
# ║ Run │ Active │ Accesses │ Activations │ Passivations ║
|
||||
# ╠════════════╪═════════╪════════════╪═════════════╪══════════════╣
|
||||
# ║ OPT 100k │ 53.75 % │ 50,000,000 │ 23,125,433 │ 23,025,433 ║
|
||||
# ╟────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LRU 100k │ 40.47 % │ 50,000,000 │ 29,764,380 │ 29,664,380 ║
|
||||
# ╟────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ SLRU 100k │ 47.14 % │ 50,000,000 │ 26,428,026 │ 26,328,026 ║
|
||||
# ╟────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ S4LRU 100k │ 47.08 % │ 50,000,000 │ 26,458,377 │ 26,358,377 ║
|
||||
# ╟────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ MRU 100k │ 10.08 % │ 50,000,000 │ 44,960,042 │ 44,860,042 ║
|
||||
# ╟────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LFU 100k │ 46.82 % │ 50,000,000 │ 26,589,475 │ 26,489,475 ║
|
||||
# ╟────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LFUDA 100k │ 43.66 % │ 50,000,000 │ 28,169,941 │ 28,069,941 ║
|
||||
# ╚════════════╧═════════╧════════════╧═════════════╧══════════════╝
|
||||
# ╔════════════════════╤═════════╤════════════╤═════════════╤══════════════╗
|
||||
# ║ Run │ Active │ Accesses │ Activations │ Passivations ║
|
||||
# ╠════════════════════╪═════════╪════════════╪═════════════╪══════════════╣
|
||||
# ║ OPT 10k │ 41.84 % │ 50,000,000 │ 29,079,442 │ 29,069,442 ║
|
||||
# ╟────────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LRU 10k │ 29.79 % │ 50,000,000 │ 35,105,304 │ 35,095,304 ║
|
||||
# ╟────────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ SLRU 10k │ 37.81 % │ 50,000,000 │ 31,095,778 │ 31,085,778 ║
|
||||
# ╟────────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ S4LRU 10k │ 37.58 % │ 50,000,000 │ 31,208,317 │ 31,198,317 ║
|
||||
# ╟────────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ MRU 10k │ 9.04 % │ 50,000,000 │ 45,479,628 │ 45,469,628 ║
|
||||
# ╟────────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LFU 10k │ 37.82 % │ 50,000,000 │ 31,088,819 │ 31,078,819 ║
|
||||
# ╟────────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LFUDA 10k │ 33.80 % │ 50,000,000 │ 33,098,270 │ 33,088,270 ║
|
||||
# ╟────────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LRU/FS/SLRU 10k │ 38.00 % │ 50,000,000 │ 30,997,711 │ 30,987,711 ║
|
||||
# ╟────────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LRU/FS/SLRU/HC 10k │ 36.98 % │ 50,000,000 │ 31,510,604 │ 31,500,604 ║
|
||||
# ╚════════════════════╧═════════╧════════════╧═════════════╧══════════════╝
|
||||
#
|
||||
# Shifting Scrambled Zipfian:
|
||||
#
|
||||
# ╔════════════╤═════════╤════════════╤═════════════╤══════════════╗
|
||||
# ║ Run │ Active │ Accesses │ Activations │ Passivations ║
|
||||
# ╠════════════╪═════════╪════════════╪═════════════╪══════════════╣
|
||||
# ║ OPT 100k │ 32.31 % │ 50,000,000 │ 33,846,785 │ 33,746,785 ║
|
||||
# ╟────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LRU 100k │ 22.50 % │ 50,000,000 │ 38,749,623 │ 38,649,623 ║
|
||||
# ╟────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ SLRU 100k │ 22.63 % │ 50,000,000 │ 38,682,890 │ 38,582,890 ║
|
||||
# ╟────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ S4LRU 100k │ 22.58 % │ 50,000,000 │ 38,711,319 │ 38,611,319 ║
|
||||
# ╟────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ MRU 100k │ 9.45 % │ 50,000,000 │ 45,276,420 │ 45,176,420 ║
|
||||
# ╟────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LFU 100k │ 13.23 % │ 50,000,000 │ 43,385,876 │ 43,285,876 ║
|
||||
# ╟────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LFUDA 100k │ 22.52 % │ 50,000,000 │ 38,739,017 │ 38,639,017 ║
|
||||
# ╚════════════╧═════════╧════════════╧═════════════╧══════════════╝
|
||||
# ╔════════════════════╤═════════╤════════════╤═════════════╤══════════════╗
|
||||
# ║ Run │ Active │ Accesses │ Activations │ Passivations ║
|
||||
# ╠════════════════════╪═════════╪════════════╪═════════════╪══════════════╣
|
||||
# ║ OPT 10k │ 24.98 % │ 50,000,000 │ 37,510,100 │ 37,500,100 ║
|
||||
# ╟────────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LRU 10k │ 21.86 % │ 50,000,000 │ 39,072,007 │ 39,062,007 ║
|
||||
# ╟────────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ SLRU 10k │ 21.18 % │ 50,000,000 │ 39,410,297 │ 39,400,297 ║
|
||||
# ╟────────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ S4LRU 10k │ 21.47 % │ 50,000,000 │ 39,265,652 │ 39,255,652 ║
|
||||
# ╟────────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ MRU 10k │ 8.60 % │ 50,000,000 │ 45,699,342 │ 45,689,342 ║
|
||||
# ╟────────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LFU 10k │ 9.19 % │ 50,000,000 │ 45,404,024 │ 45,394,024 ║
|
||||
# ╟────────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LFUDA 10k │ 21.84 % │ 50,000,000 │ 39,077,569 │ 39,067,569 ║
|
||||
# ╟────────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LRU/FS/SLRU 10k │ 16.99 % │ 50,000,000 │ 41,503,020 │ 41,493,020 ║
|
||||
# ╟────────────────────┼─────────┼────────────┼─────────────┼──────────────╢
|
||||
# ║ LRU/FS/SLRU/HC 10k │ 21.39 % │ 50,000,000 │ 39,306,616 │ 39,296,616 ║
|
||||
# ╚════════════════════╧═════════╧════════════╧═════════════╧══════════════╝
|
||||
#
|
||||
|
||||
akka.cluster.sharding {
|
||||
passivation.simulator {
|
||||
runs = [
|
||||
{
|
||||
name = "OPT 100k"
|
||||
name = "OPT 10k"
|
||||
shards = 100
|
||||
regions = 10
|
||||
# pattern = zipfian
|
||||
pattern = scrambled-zipfian
|
||||
# pattern = shifting-scrambled-zipfian
|
||||
strategy = optimal-10k
|
||||
strategy = optimal-1k
|
||||
},
|
||||
{
|
||||
name = "LRU 100k"
|
||||
name = "LRU 10k"
|
||||
shards = 100
|
||||
regions = 10
|
||||
# pattern = zipfian
|
||||
pattern = scrambled-zipfian
|
||||
# pattern = shifting-scrambled-zipfian
|
||||
strategy = lru-10k
|
||||
strategy = lru-1k
|
||||
},
|
||||
{
|
||||
name = "SLRU 100k"
|
||||
name = "SLRU 10k"
|
||||
shards = 100
|
||||
regions = 10
|
||||
# pattern = zipfian
|
||||
pattern = scrambled-zipfian
|
||||
# pattern = shifting-scrambled-zipfian
|
||||
strategy = slru-10k
|
||||
strategy = slru-1k
|
||||
},
|
||||
{
|
||||
name = "S4LRU 100k"
|
||||
name = "S4LRU 10k"
|
||||
shards = 100
|
||||
regions = 10
|
||||
# pattern = zipfian
|
||||
pattern = scrambled-zipfian
|
||||
# pattern = shifting-scrambled-zipfian
|
||||
strategy = s4lru-10k
|
||||
strategy = s4lru-1k
|
||||
},
|
||||
{
|
||||
name = "MRU 100k"
|
||||
name = "MRU 10k"
|
||||
shards = 100
|
||||
regions = 10
|
||||
# pattern = zipfian
|
||||
pattern = scrambled-zipfian
|
||||
# pattern = shifting-scrambled-zipfian
|
||||
strategy = mru-10k
|
||||
strategy = mru-1k
|
||||
},
|
||||
{
|
||||
name = "LFU 100k"
|
||||
name = "LFU 10k"
|
||||
shards = 100
|
||||
regions = 10
|
||||
# pattern = zipfian
|
||||
pattern = scrambled-zipfian
|
||||
# pattern = shifting-scrambled-zipfian
|
||||
strategy = lfu-10k
|
||||
strategy = lfu-1k
|
||||
},
|
||||
{
|
||||
name = "LFUDA 100k"
|
||||
name = "LFUDA 10k"
|
||||
shards = 100
|
||||
regions = 10
|
||||
# pattern = zipfian
|
||||
pattern = scrambled-zipfian
|
||||
# pattern = shifting-scrambled-zipfian
|
||||
strategy = lfuda-10k
|
||||
strategy = lfuda-1k
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU 10k"
|
||||
shards = 100
|
||||
regions = 10
|
||||
# pattern = zipfian
|
||||
pattern = scrambled-zipfian
|
||||
# pattern = shifting-scrambled-zipfian
|
||||
strategy = lru-fs-slru-1k
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU/HC 10k"
|
||||
shards = 100
|
||||
regions = 10
|
||||
# pattern = zipfian
|
||||
pattern = scrambled-zipfian
|
||||
# pattern = shifting-scrambled-zipfian
|
||||
strategy = lru-fs-slru-hc-1k
|
||||
},
|
||||
]
|
||||
|
||||
print-detailed-stats = true
|
||||
|
||||
# zipfian distribution
|
||||
# generate 50M events over 10M ids
|
||||
zipfian {
|
||||
pattern = synthetic
|
||||
synthetic {
|
||||
events = 50000000
|
||||
generator = zipfian
|
||||
zipfian {
|
||||
min = 1
|
||||
max = 10000000
|
||||
scrambled = off
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# scrambled zipfian distribution
|
||||
# generate 50M events over 10M ids
|
||||
scrambled-zipfian {
|
||||
|
|
@ -138,30 +210,30 @@ akka.cluster.sharding {
|
|||
}
|
||||
}
|
||||
|
||||
# Optimal (clairvoyant) strategy with 10k limit in each of 10 regions
|
||||
# total limit across cluster of 100k (1% of id space)
|
||||
optimal-10k {
|
||||
# Optimal (clairvoyant) strategy with 1k limit in each of 10 regions
|
||||
# total limit across cluster of 10k (0.1% of id space)
|
||||
optimal-1k {
|
||||
strategy = optimal
|
||||
optimal {
|
||||
per-region-limit = 10000
|
||||
per-region-limit = 1000
|
||||
}
|
||||
}
|
||||
|
||||
# LRU strategy with 10k limit in each of 10 regions
|
||||
# total limit across cluster of 100k (1% of id space)
|
||||
lru-10k {
|
||||
# LRU strategy with 1k limit in each of 10 regions
|
||||
# total limit across cluster of 10k (0.1% of id space)
|
||||
lru-1k {
|
||||
strategy = least-recently-used
|
||||
least-recently-used {
|
||||
per-region-limit = 10000
|
||||
per-region-limit = 1000
|
||||
}
|
||||
}
|
||||
|
||||
# SLRU strategy (segmented 80% protected) with 10k limit in each of 10 regions
|
||||
# total limit across cluster of 100k (1% of id space)
|
||||
slru-10k {
|
||||
# SLRU strategy (segmented 80% protected) with 1k limit in each of 10 regions
|
||||
# total limit across cluster of 10k (0.1% of id space)
|
||||
slru-1k {
|
||||
strategy = least-recently-used
|
||||
least-recently-used {
|
||||
per-region-limit = 10000
|
||||
per-region-limit = 1000
|
||||
segmented {
|
||||
levels = 2
|
||||
proportions = [0.2, 0.8]
|
||||
|
|
@ -169,42 +241,78 @@ akka.cluster.sharding {
|
|||
}
|
||||
}
|
||||
|
||||
# S4LRU strategy (segmented 4 levels) with 10k limit in each of 10 regions
|
||||
# total limit across cluster of 100k (1% of id space)
|
||||
s4lru-10k {
|
||||
# S4LRU strategy (segmented 4 levels) with 1k limit in each of 10 regions
|
||||
# total limit across cluster of 10k (0.1% of id space)
|
||||
s4lru-1k {
|
||||
strategy = least-recently-used
|
||||
least-recently-used {
|
||||
per-region-limit = 10000
|
||||
per-region-limit = 1000
|
||||
segmented.levels = 4
|
||||
}
|
||||
}
|
||||
|
||||
# MRU strategy with 10k limit in each of 10 regions
|
||||
# total limit across cluster of 100k (1% of id space)
|
||||
mru-10k {
|
||||
# MRU strategy with 1k limit in each of 10 regions
|
||||
# total limit across cluster of 10k (0.1% of id space)
|
||||
mru-1k {
|
||||
strategy = most-recently-used
|
||||
most-recently-used {
|
||||
per-region-limit = 10000
|
||||
per-region-limit = 1000
|
||||
}
|
||||
}
|
||||
|
||||
# LFU strategy with 10k limit in each of 10 regions
|
||||
# total limit across cluster of 100k (1% of id space)
|
||||
lfu-10k {
|
||||
# LFU strategy with 1k limit in each of 10 regions
|
||||
# total limit across cluster of 10k (0.1% of id space)
|
||||
lfu-1k {
|
||||
strategy = least-frequently-used
|
||||
least-frequently-used {
|
||||
per-region-limit = 10000
|
||||
per-region-limit = 1000
|
||||
}
|
||||
}
|
||||
|
||||
# LFUDA strategy (dynamic aging) with 10k limit in each of 10 regions
|
||||
# total limit across cluster of 100k (1% of id space)
|
||||
lfuda-10k {
|
||||
# LFUDA strategy (dynamic aging) with 1k limit in each of 10 regions
|
||||
# total limit across cluster of 10k (0.1% of id space)
|
||||
lfuda-1k {
|
||||
strategy = least-frequently-used
|
||||
least-frequently-used {
|
||||
per-region-limit = 10000
|
||||
per-region-limit = 1000
|
||||
dynamic-aging = on
|
||||
}
|
||||
}
|
||||
|
||||
# Window-TinyLFU strategy with 1k limit in each of 10 regions
|
||||
# total limit across cluster of 10k (0.1% of id space)
|
||||
lru-fs-slru {
|
||||
strategy = composite
|
||||
composite {
|
||||
admission {
|
||||
window.strategy = least-recently-used
|
||||
filter = frequency-sketch
|
||||
optimizer = none
|
||||
}
|
||||
main {
|
||||
strategy = least-recently-used
|
||||
least-recently-used {
|
||||
segmented {
|
||||
levels = 2
|
||||
proportions = [0.2, 0.8]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lru-fs-slru-1k = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru} {
|
||||
composite.per-region-limit = 1000
|
||||
}
|
||||
|
||||
# Adaptive (hill climbing) Window-TinyLFU strategy
|
||||
lru-fs-slru-hc = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru} {
|
||||
composite.admission.optimizer = hill-climbing
|
||||
}
|
||||
|
||||
lru-fs-slru-hc-1k = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru-hc} {
|
||||
composite.per-region-limit = 1000
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,51 +5,63 @@
|
|||
#
|
||||
# > akka-cluster-sharding/Test/runMain akka.cluster.sharding.passivation.simulator.Simulator text-moby-dick
|
||||
#
|
||||
# ╔═══════════╤═════════╤══════════╤═════════════╤══════════════╗
|
||||
# ║ Run │ Active │ Accesses │ Activations │ Passivations ║
|
||||
# ╠═══════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ OPT 25 │ 45.52 % │ 216,904 │ 118,161 │ 118,136 ║
|
||||
# ╟───────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ OPT 50 │ 54.52 % │ 216,904 │ 98,658 │ 98,608 ║
|
||||
# ╟───────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ OPT 100 │ 62.62 % │ 216,904 │ 81,073 │ 80,973 ║
|
||||
# ╠═══════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ LRU 25 │ 21.84 % │ 216,904 │ 169,542 │ 169,517 ║
|
||||
# ╟───────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LRU 50 │ 32.48 % │ 216,904 │ 146,444 │ 146,394 ║
|
||||
# ╟───────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LRU 100 │ 43.41 % │ 216,904 │ 122,750 │ 122,650 ║
|
||||
# ╠═══════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ SLRU 25 │ 30.22 % │ 216,904 │ 151,349 │ 151,324 ║
|
||||
# ╟───────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ SLRU 50 │ 40.14 % │ 216,904 │ 129,845 │ 129,795 ║
|
||||
# ╟───────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ SLRU 100 │ 50.10 % │ 216,904 │ 108,241 │ 108,141 ║
|
||||
# ╠═══════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ S4LRU 25 │ 30.19 % │ 216,904 │ 151,422 │ 151,398 ║
|
||||
# ╟───────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ S4LRU 50 │ 40.15 % │ 216,904 │ 129,816 │ 129,768 ║
|
||||
# ╟───────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ S4LRU 100 │ 50.53 % │ 216,904 │ 107,304 │ 107,204 ║
|
||||
# ╠═══════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ MRU 25 │ 0.30 % │ 216,904 │ 216,250 │ 216,225 ║
|
||||
# ╟───────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ MRU 50 │ 0.46 % │ 216,904 │ 215,899 │ 215,849 ║
|
||||
# ╟───────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ MRU 100 │ 0.71 % │ 216,904 │ 215,359 │ 215,259 ║
|
||||
# ╠═══════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ LFU 25 │ 24.55 % │ 216,904 │ 163,651 │ 163,626 ║
|
||||
# ╟───────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LFU 50 │ 33.91 % │ 216,904 │ 143,345 │ 143,295 ║
|
||||
# ╟───────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LFU 100 │ 43.58 % │ 216,904 │ 122,378 │ 122,278 ║
|
||||
# ╠═══════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ LFUDA 25 │ 30.80 % │ 216,904 │ 150,106 │ 150,081 ║
|
||||
# ╟───────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LFUDA 50 │ 40.90 % │ 216,904 │ 128,180 │ 128,130 ║
|
||||
# ╟───────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LFUDA 100 │ 50.79 % │ 216,904 │ 106,731 │ 106,631 ║
|
||||
# ╚═══════════╧═════════╧══════════╧═════════════╧══════════════╝
|
||||
# ╔════════════════════╤═════════╤══════════╤═════════════╤══════════════╗
|
||||
# ║ Run │ Active │ Accesses │ Activations │ Passivations ║
|
||||
# ╠════════════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ OPT 25 │ 45.52 % │ 216,904 │ 118,161 │ 118,136 ║
|
||||
# ╟────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ OPT 50 │ 54.52 % │ 216,904 │ 98,658 │ 98,608 ║
|
||||
# ╟────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ OPT 100 │ 62.62 % │ 216,904 │ 81,073 │ 80,973 ║
|
||||
# ╠════════════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ LRU 25 │ 21.84 % │ 216,904 │ 169,542 │ 169,517 ║
|
||||
# ╟────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LRU 50 │ 32.48 % │ 216,904 │ 146,444 │ 146,394 ║
|
||||
# ╟────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LRU 100 │ 43.41 % │ 216,904 │ 122,750 │ 122,650 ║
|
||||
# ╠════════════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ SLRU 25 │ 30.22 % │ 216,904 │ 151,349 │ 151,324 ║
|
||||
# ╟────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ SLRU 50 │ 40.14 % │ 216,904 │ 129,845 │ 129,795 ║
|
||||
# ╟────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ SLRU 100 │ 50.10 % │ 216,904 │ 108,241 │ 108,141 ║
|
||||
# ╠════════════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ S4LRU 25 │ 30.64 % │ 216,904 │ 150,448 │ 150,423 ║
|
||||
# ╟────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ S4LRU 50 │ 40.66 % │ 216,904 │ 128,707 │ 128,657 ║
|
||||
# ╟────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ S4LRU 100 │ 50.53 % │ 216,904 │ 107,304 │ 107,204 ║
|
||||
# ╠════════════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ MRU 25 │ 0.30 % │ 216,904 │ 216,250 │ 216,225 ║
|
||||
# ╟────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ MRU 50 │ 0.46 % │ 216,904 │ 215,899 │ 215,849 ║
|
||||
# ╟────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ MRU 100 │ 0.71 % │ 216,904 │ 215,359 │ 215,259 ║
|
||||
# ╠════════════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ LFU 25 │ 24.55 % │ 216,904 │ 163,651 │ 163,626 ║
|
||||
# ╟────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LFU 50 │ 33.91 % │ 216,904 │ 143,345 │ 143,295 ║
|
||||
# ╟────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LFU 100 │ 43.58 % │ 216,904 │ 122,378 │ 122,278 ║
|
||||
# ╠════════════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ LFUDA 25 │ 30.80 % │ 216,904 │ 150,106 │ 150,081 ║
|
||||
# ╟────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LFUDA 50 │ 40.90 % │ 216,904 │ 128,180 │ 128,130 ║
|
||||
# ╟────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LFUDA 100 │ 50.79 % │ 216,904 │ 106,731 │ 106,631 ║
|
||||
# ╠════════════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ LRU/FS/SLRU 25 │ 32.92 % │ 216,904 │ 145,499 │ 145,474 ║
|
||||
# ╟────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LRU/FS/SLRU 50 │ 42.10 % │ 216,904 │ 125,597 │ 125,547 ║
|
||||
# ╟────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LRU/FS/SLRU 100 │ 51.24 % │ 216,904 │ 105,756 │ 105,656 ║
|
||||
# ╠════════════════════╪═════════╪══════════╪═════════════╪══════════════╣
|
||||
# ║ LRU/FS/SLRU/HC 25 │ 30.45 % │ 216,904 │ 150,867 │ 150,842 ║
|
||||
# ╟────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LRU/FS/SLRU/HC 50 │ 41.40 % │ 216,904 │ 127,098 │ 127,048 ║
|
||||
# ╟────────────────────┼─────────┼──────────┼─────────────┼──────────────╢
|
||||
# ║ LRU/FS/SLRU/HC 100 │ 50.97 % │ 216,904 │ 106,345 │ 106,245 ║
|
||||
# ╚════════════════════╧═════════╧══════════╧═════════════╧══════════════╝
|
||||
#
|
||||
|
||||
text-traces="text-traces"
|
||||
|
|
@ -205,6 +217,48 @@ akka.cluster.sharding {
|
|||
pattern = moby-dick
|
||||
strategy = lfuda-100
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU 25"
|
||||
shards = 1
|
||||
regions = 1
|
||||
pattern = moby-dick
|
||||
strategy = lru-fs-slru-25
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU 50"
|
||||
shards = 1
|
||||
regions = 1
|
||||
pattern = moby-dick
|
||||
strategy = lru-fs-slru-50
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU 100"
|
||||
shards = 1
|
||||
regions = 1
|
||||
pattern = moby-dick
|
||||
strategy = lru-fs-slru-100
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU/HC 25"
|
||||
shards = 1
|
||||
regions = 1
|
||||
pattern = moby-dick
|
||||
strategy = lru-fs-slru-hc-25
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU/HC 50"
|
||||
shards = 1
|
||||
regions = 1
|
||||
pattern = moby-dick
|
||||
strategy = lru-fs-slru-hc-50
|
||||
},
|
||||
{
|
||||
name = "LRU/FS/SLRU/HC 100"
|
||||
shards = 1
|
||||
regions = 1
|
||||
pattern = moby-dick
|
||||
strategy = lru-fs-slru-hc-100
|
||||
},
|
||||
]
|
||||
|
||||
# Moby Dick text as a trace
|
||||
|
|
@ -380,5 +434,54 @@ akka.cluster.sharding {
|
|||
dynamic-aging = on
|
||||
}
|
||||
}
|
||||
|
||||
lru-fs-slru {
|
||||
strategy = composite
|
||||
composite {
|
||||
admission {
|
||||
window.strategy = least-recently-used
|
||||
filter = frequency-sketch
|
||||
optimizer = none
|
||||
}
|
||||
main {
|
||||
strategy = least-recently-used
|
||||
least-recently-used {
|
||||
segmented {
|
||||
levels = 2
|
||||
proportions = [0.2, 0.8]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lru-fs-slru-25 = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru} {
|
||||
composite.per-region-limit = 25
|
||||
}
|
||||
|
||||
lru-fs-slru-50 = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru} {
|
||||
composite.per-region-limit = 50
|
||||
}
|
||||
|
||||
lru-fs-slru-100 = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru} {
|
||||
composite.per-region-limit = 100
|
||||
}
|
||||
|
||||
lru-fs-slru-hc = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru} {
|
||||
composite.admission.optimizer = hill-climbing
|
||||
}
|
||||
|
||||
lru-fs-slru-hc-25 = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru-hc} {
|
||||
composite.per-region-limit = 25
|
||||
}
|
||||
|
||||
lru-fs-slru-hc-50 = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru-hc} {
|
||||
composite.per-region-limit = 50
|
||||
}
|
||||
|
||||
lru-fs-slru-hc-100 = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru-hc} {
|
||||
composite.per-region-limit = 100
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,21 +13,25 @@
|
|||
#
|
||||
# > akka-cluster-sharding/Test/runMain akka.cluster.sharding.passivation.simulator.Simulator wikipedia-trace-2018
|
||||
#
|
||||
# ╔════════════╤═════════╤═══════════════╤═══════════════╤═══════════════╗
|
||||
# ║ Run │ Active │ Accesses │ Activations │ Passivations ║
|
||||
# ╠════════════╪═════════╪═══════════════╪═══════════════╪═══════════════╣
|
||||
# ║ LRU 100k │ 53.48 % │ 2,800,000,000 │ 1,302,519,161 │ 1,302,419,161 ║
|
||||
# ╟────────────┼─────────┼───────────────┼───────────────┼───────────────╢
|
||||
# ║ SLRU 100k │ 60.89 % │ 2,800,000,000 │ 1,095,063,465 │ 1,094,963,465 ║
|
||||
# ╟────────────┼─────────┼───────────────┼───────────────┼───────────────╢
|
||||
# ║ S4LRU 100k │ 60.66 % │ 2,800,000,000 │ 1,101,617,318 │ 1,101,517,318 ║
|
||||
# ╟────────────┼─────────┼───────────────┼───────────────┼───────────────╢
|
||||
# ║ MRU 100k │ 5.70 % │ 2,800,000,000 │ 2,640,279,048 │ 2,640,179,048 ║
|
||||
# ╟────────────┼─────────┼───────────────┼───────────────┼───────────────╢
|
||||
# ║ LFU 100k │ 58.17 % │ 2,800,000,000 │ 1,171,104,161 │ 1,171,004,161 ║
|
||||
# ╟────────────┼─────────┼───────────────┼───────────────┼───────────────╢
|
||||
# ║ LFUDA 100k │ 60.01 % │ 2,800,000,000 │ 1,119,687,614 │ 1,119,587,614 ║
|
||||
# ╚════════════╧═════════╧═══════════════╧═══════════════╧═══════════════╝
|
||||
# ╔═════════════════════╤═════════╤═══════════════╤═══════════════╤═══════════════╗
|
||||
# ║ Run │ Active │ Accesses │ Activations │ Passivations ║
|
||||
# ╠═════════════════════╪═════════╪═══════════════╪═══════════════╪═══════════════╣
|
||||
# ║ LRU 100k │ 53.48 % │ 2,800,000,000 │ 1,302,519,161 │ 1,302,419,161 ║
|
||||
# ╟─────────────────────┼─────────┼───────────────┼───────────────┼───────────────╢
|
||||
# ║ SLRU 100k │ 60.89 % │ 2,800,000,000 │ 1,095,063,465 │ 1,094,963,465 ║
|
||||
# ╟─────────────────────┼─────────┼───────────────┼───────────────┼───────────────╢
|
||||
# ║ S4LRU 100k │ 60.66 % │ 2,800,000,000 │ 1,101,617,318 │ 1,101,517,318 ║
|
||||
# ╟─────────────────────┼─────────┼───────────────┼───────────────┼───────────────╢
|
||||
# ║ MRU 100k │ 5.70 % │ 2,800,000,000 │ 2,640,279,048 │ 2,640,179,048 ║
|
||||
# ╟─────────────────────┼─────────┼───────────────┼───────────────┼───────────────╢
|
||||
# ║ LFU 100k │ 58.17 % │ 2,800,000,000 │ 1,171,104,161 │ 1,171,004,161 ║
|
||||
# ╟─────────────────────┼─────────┼───────────────┼───────────────┼───────────────╢
|
||||
# ║ LFUDA 100k │ 60.01 % │ 2,800,000,000 │ 1,119,687,614 │ 1,119,587,614 ║
|
||||
# ╟─────────────────────┼─────────┼───────────────┼───────────────┼───────────────╢
|
||||
# ║ LRU/FS/SLRU 100k │ 61.81 % │ 2,800,000,000 │ 1,069,272,588 │ 1,069,172,588 ║
|
||||
# ╟─────────────────────┼─────────┼───────────────┼───────────────┼───────────────╢
|
||||
# ║ LRU/FS/SLRU/HC 100k │ 60.54 % │ 2,800,000,000 │ 1,104,800,099 │ 1,104,700,099 ║
|
||||
# ╚═════════════════════╧═════════╧═══════════════╧═══════════════╧═══════════════╝
|
||||
#
|
||||
|
||||
wiki-traces="wiki-traces"
|
||||
|
|
@ -36,47 +40,61 @@ wiki-traces=${?WIKI_TRACES}
|
|||
akka.cluster.sharding {
|
||||
passivation.simulator {
|
||||
runs = [
|
||||
# {
|
||||
# name = "LRU 100k"
|
||||
# shards = 100
|
||||
# regions = 10
|
||||
# pattern = wiki-2018
|
||||
# strategy = lru-10k
|
||||
# },
|
||||
# {
|
||||
# name = "SLRU 100k"
|
||||
# shards = 100
|
||||
# regions = 10
|
||||
# pattern = wiki-2018
|
||||
# strategy = slru-10k
|
||||
# },
|
||||
# {
|
||||
# name = "S4LRU 100k"
|
||||
# shards = 100
|
||||
# regions = 10
|
||||
# pattern = wiki-2018
|
||||
# strategy = s4lru-10k
|
||||
# },
|
||||
# {
|
||||
# name = "MRU 100k"
|
||||
# shards = 100
|
||||
# regions = 10
|
||||
# pattern = wiki-2018
|
||||
# strategy = mru-10k
|
||||
# },
|
||||
# {
|
||||
# name = "LFU 100k"
|
||||
# shards = 100
|
||||
# regions = 10
|
||||
# pattern = wiki-2018
|
||||
# strategy = lfu-10k
|
||||
# },
|
||||
# {
|
||||
# name = "LFUDA 100k"
|
||||
# shards = 100
|
||||
# regions = 10
|
||||
# pattern = wiki-2018
|
||||
# strategy = lfuda-10k
|
||||
# },
|
||||
{
|
||||
name = "LRU 100k"
|
||||
name = "LRU/FS/SLRU 100k"
|
||||
shards = 100
|
||||
regions = 10
|
||||
pattern = wiki-2018
|
||||
strategy = lru-10k
|
||||
strategy = lru-fs-slru-10k
|
||||
},
|
||||
{
|
||||
name = "SLRU 100k"
|
||||
name = "LRU/FS/SLRU/HC 100k"
|
||||
shards = 100
|
||||
regions = 10
|
||||
pattern = wiki-2018
|
||||
strategy = slru-10k
|
||||
},
|
||||
{
|
||||
name = "S4LRU 100k"
|
||||
shards = 100
|
||||
regions = 10
|
||||
pattern = wiki-2018
|
||||
strategy = s4lru-10k
|
||||
},
|
||||
{
|
||||
name = "MRU 100k"
|
||||
shards = 100
|
||||
regions = 10
|
||||
pattern = wiki-2018
|
||||
strategy = mru-10k
|
||||
},
|
||||
{
|
||||
name = "LFU 100k"
|
||||
shards = 100
|
||||
regions = 10
|
||||
pattern = wiki-2018
|
||||
strategy = lfu-10k
|
||||
},
|
||||
{
|
||||
name = "LFUDA 100k"
|
||||
shards = 100
|
||||
regions = 10
|
||||
pattern = wiki-2018
|
||||
strategy = lfuda-10k
|
||||
strategy = lru-fs-slru-hc-10k
|
||||
},
|
||||
]
|
||||
|
||||
|
|
@ -137,5 +155,38 @@ akka.cluster.sharding {
|
|||
dynamic-aging = on
|
||||
}
|
||||
}
|
||||
|
||||
lru-fs-slru {
|
||||
strategy = composite
|
||||
composite {
|
||||
admission {
|
||||
window.strategy = least-recently-used
|
||||
filter = frequency-sketch
|
||||
optimizer = none
|
||||
}
|
||||
main {
|
||||
strategy = least-recently-used
|
||||
least-recently-used {
|
||||
segmented {
|
||||
levels = 2
|
||||
proportions = [0.2, 0.8]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lru-fs-slru-10k = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru} {
|
||||
composite.per-region-limit = 10000
|
||||
}
|
||||
|
||||
lru-fs-slru-hc = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru} {
|
||||
composite.admission.optimizer = hill-climbing
|
||||
}
|
||||
|
||||
lru-fs-slru-hc-10k = ${akka.cluster.sharding.passivation.simulator.lru-fs-slru-hc} {
|
||||
composite.per-region-limit = 10000
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,9 +84,22 @@ class ClusterShardingSettingsSpec extends AnyWordSpec with Matchers {
|
|||
strategy = default-strategy
|
||||
}
|
||||
#passivation-new-default-strategy
|
||||
""").passivationStrategy shouldBe ClusterShardingSettings.LeastRecentlyUsedPassivationStrategy(
|
||||
""").passivationStrategy shouldBe ClusterShardingSettings.CompositePassivationStrategy(
|
||||
limit = 100000,
|
||||
segmented = List(0.2, 0.8),
|
||||
mainStrategy = ClusterShardingSettings
|
||||
.LeastRecentlyUsedPassivationStrategy(limit = 0, segmented = List(0.2, 0.8), idle = None),
|
||||
windowStrategy =
|
||||
ClusterShardingSettings.LeastRecentlyUsedPassivationStrategy(limit = 0, segmented = Nil, idle = None),
|
||||
initialWindowProportion = 0.01,
|
||||
minimumWindowProportion = 0.01,
|
||||
maximumWindowProportion = 1.0,
|
||||
windowOptimizer = ClusterShardingSettings.CompositePassivationStrategy.HillClimbingAdmissionOptimizer(
|
||||
adjustMultiplier = 10.0,
|
||||
initialStep = 0.0625,
|
||||
restartThreshold = 0.05,
|
||||
stepDecay = 0.98),
|
||||
admissionFilter = ClusterShardingSettings.CompositePassivationStrategy
|
||||
.FrequencySketchAdmissionFilter(widthMultiplier = 4, resetMultiplier = 10.0, depth = 4, counterBits = 4),
|
||||
idle = None)
|
||||
}
|
||||
|
||||
|
|
@ -100,9 +113,22 @@ class ClusterShardingSettingsSpec extends AnyWordSpec with Matchers {
|
|||
}
|
||||
}
|
||||
#passivation-new-default-strategy-configured
|
||||
""").passivationStrategy shouldBe ClusterShardingSettings.LeastRecentlyUsedPassivationStrategy(
|
||||
""").passivationStrategy shouldBe ClusterShardingSettings.CompositePassivationStrategy(
|
||||
limit = 1000000,
|
||||
segmented = List(0.2, 0.8),
|
||||
mainStrategy = ClusterShardingSettings
|
||||
.LeastRecentlyUsedPassivationStrategy(limit = 0, segmented = List(0.2, 0.8), idle = None),
|
||||
windowStrategy =
|
||||
ClusterShardingSettings.LeastRecentlyUsedPassivationStrategy(limit = 0, segmented = Nil, idle = None),
|
||||
initialWindowProportion = 0.01,
|
||||
minimumWindowProportion = 0.01,
|
||||
maximumWindowProportion = 1.0,
|
||||
windowOptimizer = ClusterShardingSettings.CompositePassivationStrategy.HillClimbingAdmissionOptimizer(
|
||||
adjustMultiplier = 10.0,
|
||||
initialStep = 0.0625,
|
||||
restartThreshold = 0.05,
|
||||
stepDecay = 0.98),
|
||||
admissionFilter = ClusterShardingSettings.CompositePassivationStrategy
|
||||
.FrequencySketchAdmissionFilter(widthMultiplier = 4, resetMultiplier = 10.0, depth = 4, counterBits = 4),
|
||||
idle = None)
|
||||
}
|
||||
|
||||
|
|
@ -116,9 +142,22 @@ class ClusterShardingSettingsSpec extends AnyWordSpec with Matchers {
|
|||
}
|
||||
}
|
||||
#passivation-new-default-strategy-with-idle
|
||||
""").passivationStrategy shouldBe ClusterShardingSettings.LeastRecentlyUsedPassivationStrategy(
|
||||
""").passivationStrategy shouldBe ClusterShardingSettings.CompositePassivationStrategy(
|
||||
limit = 100000,
|
||||
segmented = List(0.2, 0.8),
|
||||
mainStrategy = ClusterShardingSettings
|
||||
.LeastRecentlyUsedPassivationStrategy(limit = 0, segmented = List(0.2, 0.8), idle = None),
|
||||
windowStrategy =
|
||||
ClusterShardingSettings.LeastRecentlyUsedPassivationStrategy(limit = 0, segmented = Nil, idle = None),
|
||||
initialWindowProportion = 0.01,
|
||||
minimumWindowProportion = 0.01,
|
||||
maximumWindowProportion = 1.0,
|
||||
windowOptimizer = ClusterShardingSettings.CompositePassivationStrategy.HillClimbingAdmissionOptimizer(
|
||||
adjustMultiplier = 10.0,
|
||||
initialStep = 0.0625,
|
||||
restartThreshold = 0.05,
|
||||
stepDecay = 0.98),
|
||||
admissionFilter = ClusterShardingSettings.CompositePassivationStrategy
|
||||
.FrequencySketchAdmissionFilter(widthMultiplier = 4, resetMultiplier = 10.0, depth = 4, counterBits = 4),
|
||||
idle = Some(ClusterShardingSettings.IdlePassivationStrategy(timeout = 30.minutes, interval = 15.minutes)))
|
||||
}
|
||||
|
||||
|
|
@ -389,6 +428,356 @@ class ClusterShardingSettingsSpec extends AnyWordSpec with Matchers {
|
|||
idle = None)
|
||||
}
|
||||
|
||||
"allow passivation strategy admission window policy to be configured (via config)" in {
|
||||
settings("""
|
||||
#admission-window-policy
|
||||
akka.cluster.sharding.passivation {
|
||||
strategy = custom-strategy-with-admission-window
|
||||
custom-strategy-with-admission-window {
|
||||
active-entity-limit = 1000000
|
||||
admission.window.policy = least-recently-used
|
||||
replacement.policy = least-frequently-used
|
||||
}
|
||||
}
|
||||
#admission-window-policy
|
||||
""").passivationStrategy shouldBe ClusterShardingSettings.CompositePassivationStrategy(
|
||||
limit = 1000000,
|
||||
mainStrategy =
|
||||
ClusterShardingSettings.LeastFrequentlyUsedPassivationStrategy(limit = 0, dynamicAging = false, idle = None),
|
||||
windowStrategy =
|
||||
ClusterShardingSettings.LeastRecentlyUsedPassivationStrategy(limit = 0, segmented = Nil, idle = None),
|
||||
initialWindowProportion = 0.01,
|
||||
minimumWindowProportion = 0.01,
|
||||
maximumWindowProportion = 1.0,
|
||||
windowOptimizer = ClusterShardingSettings.CompositePassivationStrategy.NoAdmissionOptimizer,
|
||||
admissionFilter = ClusterShardingSettings.CompositePassivationStrategy.AlwaysAdmissionFilter,
|
||||
idle = None)
|
||||
}
|
||||
|
||||
"allow passivation strategy admission window proportion to be configured (via config)" in {
|
||||
settings("""
|
||||
#admission-window-proportion
|
||||
akka.cluster.sharding.passivation {
|
||||
strategy = custom-strategy-with-admission-window
|
||||
custom-strategy-with-admission-window {
|
||||
active-entity-limit = 1000000
|
||||
admission.window {
|
||||
policy = least-recently-used
|
||||
proportion = 0.1 # 10%
|
||||
}
|
||||
replacement.policy = least-frequently-used
|
||||
}
|
||||
}
|
||||
#admission-window-proportion
|
||||
""").passivationStrategy shouldBe ClusterShardingSettings.CompositePassivationStrategy(
|
||||
limit = 1000000,
|
||||
mainStrategy =
|
||||
ClusterShardingSettings.LeastFrequentlyUsedPassivationStrategy(limit = 0, dynamicAging = false, idle = None),
|
||||
windowStrategy =
|
||||
ClusterShardingSettings.LeastRecentlyUsedPassivationStrategy(limit = 0, segmented = Nil, idle = None),
|
||||
initialWindowProportion = 0.1,
|
||||
minimumWindowProportion = 0.01,
|
||||
maximumWindowProportion = 1.0,
|
||||
windowOptimizer = ClusterShardingSettings.CompositePassivationStrategy.NoAdmissionOptimizer,
|
||||
admissionFilter = ClusterShardingSettings.CompositePassivationStrategy.AlwaysAdmissionFilter,
|
||||
idle = None)
|
||||
}
|
||||
|
||||
"allow passivation strategy admission window optimizer to be configured (via config)" in {
|
||||
settings("""
|
||||
#admission-window-optimizer
|
||||
akka.cluster.sharding.passivation {
|
||||
strategy = custom-strategy-with-admission-window
|
||||
custom-strategy-with-admission-window {
|
||||
active-entity-limit = 1000000
|
||||
admission.window {
|
||||
policy = least-recently-used
|
||||
optimizer = hill-climbing
|
||||
}
|
||||
replacement.policy = least-frequently-used
|
||||
}
|
||||
}
|
||||
#admission-window-optimizer
|
||||
""").passivationStrategy shouldBe ClusterShardingSettings.CompositePassivationStrategy(
|
||||
limit = 1000000,
|
||||
mainStrategy =
|
||||
ClusterShardingSettings.LeastFrequentlyUsedPassivationStrategy(limit = 0, dynamicAging = false, idle = None),
|
||||
windowStrategy =
|
||||
ClusterShardingSettings.LeastRecentlyUsedPassivationStrategy(limit = 0, segmented = Nil, idle = None),
|
||||
initialWindowProportion = 0.01,
|
||||
minimumWindowProportion = 0.01,
|
||||
maximumWindowProportion = 1.0,
|
||||
windowOptimizer = ClusterShardingSettings.CompositePassivationStrategy.HillClimbingAdmissionOptimizer(
|
||||
adjustMultiplier = 10.0,
|
||||
initialStep = 0.0625,
|
||||
restartThreshold = 0.05,
|
||||
stepDecay = 0.98),
|
||||
admissionFilter = ClusterShardingSettings.CompositePassivationStrategy.AlwaysAdmissionFilter,
|
||||
idle = None)
|
||||
}
|
||||
|
||||
"allow passivation strategy admission to be configured (via config)" in {
|
||||
settings("""
|
||||
#admission-policy
|
||||
akka.cluster.sharding.passivation {
|
||||
strategy = custom-strategy-with-admission
|
||||
custom-strategy-with-admission {
|
||||
active-entity-limit = 1000000
|
||||
admission {
|
||||
window {
|
||||
policy = least-recently-used
|
||||
optimizer = hill-climbing
|
||||
}
|
||||
filter = frequency-sketch
|
||||
}
|
||||
replacement {
|
||||
policy = least-recently-used
|
||||
least-recently-used {
|
||||
segmented {
|
||||
levels = 2
|
||||
proportions = [0.2, 0.8]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#admission-policy
|
||||
""").passivationStrategy shouldBe ClusterShardingSettings.CompositePassivationStrategy(
|
||||
limit = 1000000,
|
||||
mainStrategy = ClusterShardingSettings
|
||||
.LeastRecentlyUsedPassivationStrategy(limit = 0, segmented = List(0.2, 0.8), idle = None),
|
||||
windowStrategy =
|
||||
ClusterShardingSettings.LeastRecentlyUsedPassivationStrategy(limit = 0, segmented = Nil, idle = None),
|
||||
initialWindowProportion = 0.01,
|
||||
minimumWindowProportion = 0.01,
|
||||
maximumWindowProportion = 1.0,
|
||||
windowOptimizer = ClusterShardingSettings.CompositePassivationStrategy.HillClimbingAdmissionOptimizer(
|
||||
adjustMultiplier = 10.0,
|
||||
initialStep = 0.0625,
|
||||
restartThreshold = 0.05,
|
||||
stepDecay = 0.98),
|
||||
admissionFilter = ClusterShardingSettings.CompositePassivationStrategy
|
||||
.FrequencySketchAdmissionFilter(widthMultiplier = 4, resetMultiplier = 10.0, depth = 4, counterBits = 4),
|
||||
idle = None)
|
||||
}
|
||||
|
||||
"allow passivation strategy admission parameters to be tuned (via config)" in {
|
||||
settings("""
|
||||
akka.cluster.sharding.passivation {
|
||||
strategy = custom-strategy-with-admission
|
||||
custom-strategy-with-admission {
|
||||
active-entity-limit = 1000000
|
||||
admission {
|
||||
window {
|
||||
policy = least-recently-used
|
||||
proportion = 0.1
|
||||
minimum-proportion = 0.05
|
||||
maximum-proportion = 0.50
|
||||
optimizer = hill-climbing
|
||||
hill-climbing {
|
||||
adjust-multiplier = 5
|
||||
initial-step = 0.05
|
||||
restart-threshold = 0.025
|
||||
step-decay = 0.95
|
||||
}
|
||||
}
|
||||
filter = frequency-sketch
|
||||
frequency-sketch {
|
||||
depth = 3
|
||||
counter-bits = 8
|
||||
width-multiplier = 2
|
||||
reset-multiplier = 50.0
|
||||
}
|
||||
}
|
||||
replacement {
|
||||
policy = least-recently-used
|
||||
least-recently-used {
|
||||
segmented {
|
||||
levels = 2
|
||||
proportions = [0.2, 0.8]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
""").passivationStrategy shouldBe ClusterShardingSettings.CompositePassivationStrategy(
|
||||
limit = 1000000,
|
||||
mainStrategy = ClusterShardingSettings
|
||||
.LeastRecentlyUsedPassivationStrategy(limit = 0, segmented = List(0.2, 0.8), idle = None),
|
||||
windowStrategy =
|
||||
ClusterShardingSettings.LeastRecentlyUsedPassivationStrategy(limit = 0, segmented = Nil, idle = None),
|
||||
initialWindowProportion = 0.1,
|
||||
minimumWindowProportion = 0.05,
|
||||
maximumWindowProportion = 0.5,
|
||||
windowOptimizer = ClusterShardingSettings.CompositePassivationStrategy.HillClimbingAdmissionOptimizer(
|
||||
adjustMultiplier = 5.0,
|
||||
initialStep = 0.05,
|
||||
restartThreshold = 0.025,
|
||||
stepDecay = 0.95),
|
||||
admissionFilter = ClusterShardingSettings.CompositePassivationStrategy
|
||||
.FrequencySketchAdmissionFilter(widthMultiplier = 2, resetMultiplier = 50.0, depth = 3, counterBits = 8),
|
||||
idle = None)
|
||||
}
|
||||
|
||||
"allow passivation strategy admission to be configured (via factory method)" in {
|
||||
defaultSettings
|
||||
.withPassivationStrategy(
|
||||
ClusterShardingSettings.PassivationStrategySettings.defaults
|
||||
.withActiveEntityLimit(42000)
|
||||
.withAdmission(ClusterShardingSettings.PassivationStrategySettings.AdmissionSettings.defaults
|
||||
.withWindow(ClusterShardingSettings.PassivationStrategySettings.AdmissionSettings.WindowSettings.defaults
|
||||
.withPolicy(ClusterShardingSettings.PassivationStrategySettings.LeastRecentlyUsedSettings.defaults)
|
||||
.withOptimizer(
|
||||
ClusterShardingSettings.PassivationStrategySettings.AdmissionSettings.HillClimbingSettings.defaults))
|
||||
.withFilter(
|
||||
ClusterShardingSettings.PassivationStrategySettings.AdmissionSettings.FrequencySketchSettings.defaults))
|
||||
.withReplacementPolicy(
|
||||
ClusterShardingSettings.PassivationStrategySettings.LeastRecentlyUsedSettings.defaults
|
||||
.withSegmented(proportions = List(0.2, 0.8))))
|
||||
.passivationStrategy shouldBe ClusterShardingSettings.CompositePassivationStrategy(
|
||||
limit = 42000,
|
||||
mainStrategy = ClusterShardingSettings
|
||||
.LeastRecentlyUsedPassivationStrategy(limit = 0, segmented = List(0.2, 0.8), idle = None),
|
||||
windowStrategy =
|
||||
ClusterShardingSettings.LeastRecentlyUsedPassivationStrategy(limit = 0, segmented = Nil, idle = None),
|
||||
initialWindowProportion = 0.01,
|
||||
minimumWindowProportion = 0.01,
|
||||
maximumWindowProportion = 1.0,
|
||||
windowOptimizer = ClusterShardingSettings.CompositePassivationStrategy.HillClimbingAdmissionOptimizer(
|
||||
adjustMultiplier = 10.0,
|
||||
initialStep = 0.0625,
|
||||
restartThreshold = 0.05,
|
||||
stepDecay = 0.98),
|
||||
admissionFilter = ClusterShardingSettings.CompositePassivationStrategy
|
||||
.FrequencySketchAdmissionFilter(widthMultiplier = 4, resetMultiplier = 10.0, depth = 4, counterBits = 4),
|
||||
idle = None)
|
||||
}
|
||||
|
||||
"allow passivation strategy admission settings to be tuned (via factory method)" in {
|
||||
defaultSettings
|
||||
.withPassivationStrategy(
|
||||
ClusterShardingSettings.PassivationStrategySettings.defaults
|
||||
.withActiveEntityLimit(42000)
|
||||
.withAdmission(ClusterShardingSettings.PassivationStrategySettings.AdmissionSettings.defaults
|
||||
.withWindow(
|
||||
ClusterShardingSettings.PassivationStrategySettings.AdmissionSettings.WindowSettings.defaults
|
||||
.withPolicy(ClusterShardingSettings.PassivationStrategySettings.LeastRecentlyUsedSettings.defaults)
|
||||
.withInitialProportion(0.1)
|
||||
.withMinimumProportion(0.05)
|
||||
.withMaximumProportion(0.5)
|
||||
.withOptimizer(
|
||||
ClusterShardingSettings.PassivationStrategySettings.AdmissionSettings.HillClimbingSettings.defaults
|
||||
.withAdjustMultiplier(5)
|
||||
.withInitialStep(0.05)
|
||||
.withRestartThreshold(0.025)
|
||||
.withStepDecay(0.95)))
|
||||
.withFilter(
|
||||
ClusterShardingSettings.PassivationStrategySettings.AdmissionSettings.FrequencySketchSettings.defaults
|
||||
.withDepth(3)
|
||||
.withCounterBits(8)
|
||||
.withWidthMultiplier(2)
|
||||
.withResetMultiplier(50)))
|
||||
.withReplacementPolicy(
|
||||
ClusterShardingSettings.PassivationStrategySettings.LeastRecentlyUsedSettings.defaults
|
||||
.withSegmented(proportions = List(0.2, 0.8))))
|
||||
.passivationStrategy shouldBe ClusterShardingSettings.CompositePassivationStrategy(
|
||||
limit = 42000,
|
||||
mainStrategy = ClusterShardingSettings
|
||||
.LeastRecentlyUsedPassivationStrategy(limit = 0, segmented = List(0.2, 0.8), idle = None),
|
||||
windowStrategy =
|
||||
ClusterShardingSettings.LeastRecentlyUsedPassivationStrategy(limit = 0, segmented = Nil, idle = None),
|
||||
initialWindowProportion = 0.1,
|
||||
minimumWindowProportion = 0.05,
|
||||
maximumWindowProportion = 0.5,
|
||||
windowOptimizer = ClusterShardingSettings.CompositePassivationStrategy.HillClimbingAdmissionOptimizer(
|
||||
adjustMultiplier = 5.0,
|
||||
initialStep = 0.05,
|
||||
restartThreshold = 0.025,
|
||||
stepDecay = 0.95),
|
||||
admissionFilter = ClusterShardingSettings.CompositePassivationStrategy
|
||||
.FrequencySketchAdmissionFilter(widthMultiplier = 2, resetMultiplier = 50.0, depth = 3, counterBits = 8),
|
||||
idle = None)
|
||||
}
|
||||
|
||||
"allow passivation strategy with admission and idle timeout to be configured (via config)" in {
|
||||
settings("""
|
||||
akka.cluster.sharding.passivation {
|
||||
strategy = custom-strategy-with-admission
|
||||
custom-strategy-with-admission {
|
||||
active-entity-limit = 1000000
|
||||
admission {
|
||||
window {
|
||||
policy = least-recently-used
|
||||
optimizer = hill-climbing
|
||||
}
|
||||
filter = frequency-sketch
|
||||
}
|
||||
replacement {
|
||||
policy = least-recently-used
|
||||
least-recently-used {
|
||||
segmented {
|
||||
levels = 2
|
||||
proportions = [0.2, 0.8]
|
||||
}
|
||||
}
|
||||
}
|
||||
idle-entity.timeout = 30.minutes
|
||||
}
|
||||
}
|
||||
""").passivationStrategy shouldBe ClusterShardingSettings.CompositePassivationStrategy(
|
||||
limit = 1000000,
|
||||
mainStrategy = ClusterShardingSettings
|
||||
.LeastRecentlyUsedPassivationStrategy(limit = 0, segmented = List(0.2, 0.8), idle = None),
|
||||
windowStrategy =
|
||||
ClusterShardingSettings.LeastRecentlyUsedPassivationStrategy(limit = 0, segmented = Nil, idle = None),
|
||||
initialWindowProportion = 0.01,
|
||||
minimumWindowProportion = 0.01,
|
||||
maximumWindowProportion = 1.0,
|
||||
windowOptimizer = ClusterShardingSettings.CompositePassivationStrategy.HillClimbingAdmissionOptimizer(
|
||||
adjustMultiplier = 10.0,
|
||||
initialStep = 0.0625,
|
||||
restartThreshold = 0.05,
|
||||
stepDecay = 0.98),
|
||||
admissionFilter = ClusterShardingSettings.CompositePassivationStrategy
|
||||
.FrequencySketchAdmissionFilter(widthMultiplier = 4, resetMultiplier = 10.0, depth = 4, counterBits = 4),
|
||||
idle = Some(ClusterShardingSettings.IdlePassivationStrategy(timeout = 30.minutes, interval = 15.minutes)))
|
||||
}
|
||||
|
||||
"allow passivation strategy with admission and idle timeout to be configured (via factory method)" in {
|
||||
defaultSettings
|
||||
.withPassivationStrategy(
|
||||
ClusterShardingSettings.PassivationStrategySettings.defaults
|
||||
.withActiveEntityLimit(42000)
|
||||
.withAdmission(ClusterShardingSettings.PassivationStrategySettings.AdmissionSettings.defaults
|
||||
.withWindow(ClusterShardingSettings.PassivationStrategySettings.AdmissionSettings.WindowSettings.defaults
|
||||
.withPolicy(ClusterShardingSettings.PassivationStrategySettings.LeastRecentlyUsedSettings.defaults)
|
||||
.withOptimizer(
|
||||
ClusterShardingSettings.PassivationStrategySettings.AdmissionSettings.HillClimbingSettings.defaults))
|
||||
.withFilter(
|
||||
ClusterShardingSettings.PassivationStrategySettings.AdmissionSettings.FrequencySketchSettings.defaults))
|
||||
.withReplacementPolicy(
|
||||
ClusterShardingSettings.PassivationStrategySettings.LeastRecentlyUsedSettings.defaults.withSegmented(
|
||||
proportions = List(0.2, 0.8)))
|
||||
.withIdleEntityPassivation(timeout = 42.minutes))
|
||||
.passivationStrategy shouldBe ClusterShardingSettings.CompositePassivationStrategy(
|
||||
limit = 42000,
|
||||
mainStrategy = ClusterShardingSettings
|
||||
.LeastRecentlyUsedPassivationStrategy(limit = 0, segmented = List(0.2, 0.8), idle = None),
|
||||
windowStrategy =
|
||||
ClusterShardingSettings.LeastRecentlyUsedPassivationStrategy(limit = 0, segmented = Nil, idle = None),
|
||||
initialWindowProportion = 0.01,
|
||||
minimumWindowProportion = 0.01,
|
||||
maximumWindowProportion = 1.0,
|
||||
windowOptimizer = ClusterShardingSettings.CompositePassivationStrategy.HillClimbingAdmissionOptimizer(
|
||||
adjustMultiplier = 10.0,
|
||||
initialStep = 0.0625,
|
||||
restartThreshold = 0.05,
|
||||
stepDecay = 0.98),
|
||||
admissionFilter = ClusterShardingSettings.CompositePassivationStrategy
|
||||
.FrequencySketchAdmissionFilter(widthMultiplier = 4, resetMultiplier = 10.0, depth = 4, counterBits = 4),
|
||||
idle = Some(ClusterShardingSettings.IdlePassivationStrategy(timeout = 42.minutes, interval = 21.minutes)))
|
||||
}
|
||||
|
||||
"disable automatic passivation if `remember-entities` is enabled (via config)" in {
|
||||
settings("""
|
||||
akka.cluster.sharding.remember-entities = on
|
||||
|
|
|
|||
|
|
@ -0,0 +1,479 @@
|
|||
/*
|
||||
* Copyright (C) 2009-2022 Lightbend Inc. <https://www.lightbend.com>
|
||||
*/
|
||||
|
||||
package akka.cluster.sharding.passivation
|
||||
|
||||
import akka.cluster.sharding.ShardRegion
|
||||
import com.typesafe.config.Config
|
||||
import com.typesafe.config.ConfigFactory
|
||||
|
||||
import scala.concurrent.duration._
|
||||
|
||||
object CompositeSpec {
|
||||
|
||||
val admissionWindowAndFilterConfig: Config = ConfigFactory.parseString("""
|
||||
akka.cluster.sharding {
|
||||
passivation {
|
||||
strategy = lru-fs-slru
|
||||
lru-fs-slru {
|
||||
active-entity-limit = 20
|
||||
admission {
|
||||
window {
|
||||
policy = least-recently-used
|
||||
proportion = 0.2
|
||||
optimizer = none
|
||||
}
|
||||
filter = frequency-sketch
|
||||
}
|
||||
replacement {
|
||||
policy = least-recently-used
|
||||
least-recently-used {
|
||||
segmented {
|
||||
levels = 2
|
||||
proportions = [0.25, 0.75]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
""").withFallback(EntityPassivationSpec.config)
|
||||
|
||||
val admissionFilterNoWindowConfig: Config = ConfigFactory.parseString("""
|
||||
akka.cluster.sharding {
|
||||
passivation {
|
||||
strategy = fs-lru
|
||||
fs-lru {
|
||||
active-entity-limit = 10
|
||||
admission {
|
||||
window.policy = none
|
||||
filter = frequency-sketch
|
||||
}
|
||||
replacement.policy = least-recently-used
|
||||
}
|
||||
}
|
||||
}
|
||||
""").withFallback(EntityPassivationSpec.config)
|
||||
|
||||
val adaptiveWindowConfig: Config = ConfigFactory.parseString("""
|
||||
akka.cluster.sharding {
|
||||
passivation {
|
||||
strategy = lru-fs-lru-hc
|
||||
lru-fs-lru-hc {
|
||||
active-entity-limit = 10
|
||||
admission {
|
||||
window {
|
||||
policy = least-recently-used
|
||||
proportion = 0.1
|
||||
minimum-proportion = 0.1
|
||||
maximum-proportion = 1.0
|
||||
optimizer = hill-climbing
|
||||
hill-climbing {
|
||||
adjust-multiplier = 2
|
||||
initial-step = 0.4 # big step for testing
|
||||
restart-threshold = 0.8 # high threshold for testing
|
||||
step-decay = 0.5 # fast decay for testing
|
||||
}
|
||||
}
|
||||
filter = frequency-sketch
|
||||
frequency-sketch {
|
||||
reset-multiplier = 100
|
||||
}
|
||||
}
|
||||
replacement.policy = least-recently-used
|
||||
}
|
||||
}
|
||||
}
|
||||
""").withFallback(EntityPassivationSpec.config)
|
||||
|
||||
val idleConfig: Config = ConfigFactory.parseString("""
|
||||
akka.cluster.sharding {
|
||||
passivation {
|
||||
strategy = default-strategy
|
||||
default-strategy {
|
||||
active-entity-limit = 3
|
||||
idle-entity.timeout = 1s
|
||||
}
|
||||
}
|
||||
}
|
||||
""").withFallback(EntityPassivationSpec.config)
|
||||
}
|
||||
|
||||
class AdmissionWindowAndFilterSpec
|
||||
extends AbstractEntityPassivationSpec(CompositeSpec.admissionWindowAndFilterConfig, expectedEntities = 41) {
|
||||
|
||||
import EntityPassivationSpec.Entity.Envelope
|
||||
import EntityPassivationSpec.Entity.Stop
|
||||
|
||||
"Passivation of entities with composite LRU/FS/SLRU strategy" must {
|
||||
"passivate the least recently or frequently used entities when the per-shard entity limit is reached" in {
|
||||
val region = start()
|
||||
|
||||
// only one active shard at first
|
||||
// entities move through the LRU window before moving to main
|
||||
// candidate entities from window passivated due to admission filter (and same frequency)
|
||||
// entities are only accessed once (so all in lowest segment)
|
||||
for (id <- 1 to 40) {
|
||||
region ! Envelope(shard = 1, id = id, message = "A")
|
||||
expectReceived(id = id, message = "A")
|
||||
if (id > 20) expectReceived(id = id - 4, message = Stop)
|
||||
}
|
||||
|
||||
// shard 1: window: 37-40, main level 0: 1-16, main level 1: empty
|
||||
expectState(region)(1 -> ((1 to 16) ++ (37 to 40)))
|
||||
|
||||
// increase the frequency of the entities in the main area
|
||||
// accessing entities a second time moves them to the higher "protected" segment in main area
|
||||
// when the limit for higher segment is reached, entities are demoted to lower "probationary" segment
|
||||
// any activated entities will passivate candidates from the window (which have lower frequency)
|
||||
for (id <- 1 to 20) {
|
||||
region ! Envelope(shard = 1, id = id, message = "B")
|
||||
expectReceived(id = id, message = "B")
|
||||
if (id > 16) expectReceived(id = id + 20, message = Stop)
|
||||
}
|
||||
|
||||
// shard 1: window: 17-20, main level 0: 1-4, level 1: 5-16
|
||||
expectState(region)(1 -> (1 to 20))
|
||||
|
||||
// cycle through the entities in the window to increase their counts in the frequency sketch
|
||||
for (id <- 17 to 20; _ <- 1 to 5) {
|
||||
region ! Envelope(shard = 1, id = id, message = "C")
|
||||
expectReceived(id = id, message = "C")
|
||||
}
|
||||
|
||||
// shard 1: window: 17-20, main level 0: 1-4, level 1: 5-16
|
||||
expectState(region)(1 -> (1 to 20))
|
||||
|
||||
// activating new entities will promote candidates from the window to main (higher frequencies now)
|
||||
for (id <- 21 to 24) {
|
||||
region ! Envelope(shard = 1, id = id, message = "D")
|
||||
expectReceived(id = id, message = "D")
|
||||
expectReceived(id = id - 20, message = Stop)
|
||||
}
|
||||
|
||||
// shard 1: window: 21-24, main level 0: 17-20, level 1: 5-16
|
||||
expectState(region)(1 -> (5 to 24))
|
||||
|
||||
// activating more new entities will passivate candidates from the window (lower frequencies than main)
|
||||
for (id <- 25 to 28) {
|
||||
region ! Envelope(shard = 1, id = id, message = "E")
|
||||
expectReceived(id = id, message = "E")
|
||||
expectReceived(id = id - 4, message = Stop)
|
||||
}
|
||||
|
||||
// shard 1: window: 25-28, main level 0: 17-20, level 1: 5-16
|
||||
expectState(region)(1 -> ((5 to 20) ++ (25 to 28)))
|
||||
|
||||
// activating a second shard will divide the per-shard limit in two, passivating half of the first shard
|
||||
region ! Envelope(shard = 2, id = 41, message = "F")
|
||||
expectReceived(id = 41, message = "F")
|
||||
for (id <- List(25, 26, 17, 18, 19, 20, 5, 6, 7, 8)) {
|
||||
expectReceived(id = id, message = Stop)
|
||||
}
|
||||
|
||||
// shard 1: window: 27-28, main level 0: 9-10, level 1: 11-16
|
||||
// shard 2: window: 41, main level 0: empty, level 1: empty
|
||||
expectState(region)(1 -> ((9 to 16) ++ (27 to 28)), 2 -> Set(41))
|
||||
|
||||
// ids 17 and 18 still have higher frequencies, will be promoted through to main from window
|
||||
for (id <- 17 to 20) {
|
||||
region ! Envelope(shard = 1, id = id, message = "G")
|
||||
expectReceived(id = id, message = "G")
|
||||
if (id == 17) expectReceived(id = 27, message = Stop)
|
||||
if (id == 18) expectReceived(id = 28, message = Stop)
|
||||
if (id == 19) expectReceived(id = 9, message = Stop)
|
||||
if (id == 20) expectReceived(id = 10, message = Stop)
|
||||
}
|
||||
|
||||
// shard 1: window: 19-20, main level 0: 17-18, level 1: 11-16
|
||||
// shard 2: window: 41, main level 0: empty, level 1: empty
|
||||
expectState(region)(1 -> (11 to 20), 2 -> Set(41))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AdmissionFilterNoWindowSpec
|
||||
extends AbstractEntityPassivationSpec(CompositeSpec.admissionFilterNoWindowConfig, expectedEntities = 21) {
|
||||
|
||||
import EntityPassivationSpec.Entity.Envelope
|
||||
import EntityPassivationSpec.Entity.Stop
|
||||
|
||||
"Passivation of entities with composite (no window) FS/LRU strategy" must {
|
||||
"passivate the least recently or frequently used entities when the per-shard entity limit is reached" in {
|
||||
val region = start()
|
||||
|
||||
// only one active shard at first
|
||||
// as entities have same frequency, when limit is reached the candidate entities (11-20) are not admitted to main
|
||||
for (id <- 1 to 20) {
|
||||
region ! Envelope(shard = 1, id = id, message = "A")
|
||||
expectReceived(id = id, message = "A")
|
||||
if (id > 10) expectReceived(id = id, message = Stop)
|
||||
}
|
||||
|
||||
// shard 1: 1-10
|
||||
expectState(region)(1 -> (1 to 10))
|
||||
|
||||
// entities 11-20 on second access, so admitted to main, replacing current entities
|
||||
// cycle through multiple times to increase frequency counts
|
||||
for (id <- 11 to 20; i <- 1 to 5) {
|
||||
region ! Envelope(shard = 1, id = id, message = "B")
|
||||
expectReceived(id = id, message = "B")
|
||||
if (i == 1) expectReceived(id = id - 10, message = Stop)
|
||||
}
|
||||
|
||||
// shard 1: 11-20
|
||||
expectState(region)(1 -> (11 to 20))
|
||||
|
||||
// entities 1-10 on second and third access, but not admitted to main as lower frequency
|
||||
for (id <- 1 to 10; _ <- 1 to 2) {
|
||||
region ! Envelope(shard = 1, id = id, message = "C")
|
||||
expectReceived(id = id, message = "C")
|
||||
expectReceived(id = id, message = Stop)
|
||||
}
|
||||
|
||||
// activating a second shard will divide the per-shard limit in two, passivating half of the first shard
|
||||
region ! Envelope(shard = 2, id = 21, message = "D")
|
||||
expectReceived(id = 21, message = "D")
|
||||
for (id <- 11 to 15) {
|
||||
expectReceived(id = id, message = Stop)
|
||||
}
|
||||
|
||||
// shard 1: 16-20, shard 2: 21
|
||||
expectState(region)(1 -> (16 to 20), 2 -> Set(21))
|
||||
|
||||
// frequency sketch is recreated on limit changes, so all frequencies are 0 again
|
||||
// candidate entities will replace old entities, but then retain their position
|
||||
for (id <- 1 to 10) {
|
||||
region ! Envelope(shard = 1, id = id, message = "E")
|
||||
expectReceived(id = id, message = "E")
|
||||
if (id <= 5) expectReceived(id = id + 15, message = Stop)
|
||||
}
|
||||
|
||||
// shard 1: 16-20, shard 2: 21
|
||||
expectState(region)(1 -> (1 to 5), 2 -> Set(21))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AdaptiveAdmissionWindowSpec
|
||||
extends AbstractEntityPassivationSpec(CompositeSpec.adaptiveWindowConfig, expectedEntities = 70) {
|
||||
|
||||
import EntityPassivationSpec.Entity.Envelope
|
||||
import EntityPassivationSpec.Entity.Stop
|
||||
|
||||
"Passivation of entities with composite LRU/FS/LRU/HC strategy" must {
|
||||
"adjust the admission window size when optimizing with hill-climbing algorithm" in {
|
||||
val region = start()
|
||||
|
||||
// fill admission window and main areas
|
||||
// increase frequency counts for entities 1-10
|
||||
for (id <- 1 to 10; i <- 1 to 10) {
|
||||
region ! Envelope(shard = 1, id = id, message = s"A$i")
|
||||
expectReceived(id = id, message = s"A$i")
|
||||
}
|
||||
|
||||
expectState(region)(1 -> (1 to 10))
|
||||
|
||||
// window = [10], main = [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
// window limit is currently 1 (window proportion of 0.1)
|
||||
// these entities will be passivated as they have lower frequencies
|
||||
// given drop in active rate the adjustment direction flips to increased (for next step)
|
||||
// so that window proportion is increased by step of 0.4 (to window limit of 5) on next cycle
|
||||
for (i <- 1 to 4; id <- 11 to 20) {
|
||||
region ! Envelope(shard = 1, id = id, message = s"B$i")
|
||||
expectReceived(id = id, message = s"B$i")
|
||||
val passivated = if (id == 11 && i > 1) 20 else id - 1
|
||||
expectReceived(id = passivated, message = Stop)
|
||||
}
|
||||
|
||||
expectState(region)(1 -> ((1 to 9) ++ Set(20)))
|
||||
|
||||
// window = [20, 1, 2, 3, 4], main = [5, 6, 7, 8, 9]
|
||||
// window limit is currently 5 (window proportion of 0.5), direction is increasing
|
||||
// continue to maintain positive active rate delta to increase window by decayed step of 0.2
|
||||
for (id <- 21 to 30; i <- 1 to 2) {
|
||||
region ! Envelope(shard = 1, id = id, message = s"C$i")
|
||||
expectReceived(id = id, message = s"C$i")
|
||||
if (i == 1) {
|
||||
val passivated = id match {
|
||||
case 21 => 20 // in window from previous loop
|
||||
case x if x <= 25 => x - 21 // demoted from main
|
||||
case x => x - 5 // window size
|
||||
}
|
||||
expectReceived(id = passivated, message = Stop)
|
||||
}
|
||||
}
|
||||
|
||||
expectState(region)(1 -> ((5 to 9) ++ (26 to 30)))
|
||||
|
||||
// window = [26, 27, 28, 29, 30, 5, 6], main = [7, 8, 9]
|
||||
// window proportion is currently 0.7, direction is increasing
|
||||
// continue to maintain positive active rate delta to increase window by decayed step of 0.1
|
||||
// increase to high active rate to trigger subsequent restart on delta over threshold
|
||||
for (id <- 21 to 24; i <- 1 to 5) {
|
||||
region ! Envelope(shard = 1, id = id, message = s"D$i")
|
||||
expectReceived(id = id, message = s"D$i")
|
||||
if (i == 1) expectReceived(id = id + 5, message = Stop)
|
||||
}
|
||||
|
||||
expectState(region)(1 -> ((5 to 9) ++ (21 to 24) ++ Set(30)))
|
||||
|
||||
// window = [30, 5, 6, 21, 22, 23, 24, 7], main = [8, 9]
|
||||
// window proportion is currently 0.8, direction is increasing
|
||||
// drop the active rate to zero to trigger a direction change (decrease of 0.05 to window of 7)
|
||||
// and hill-climbing restart triggered for next step (change is over restart threshold)
|
||||
for (i <- 1 to 2; id <- 31 to 40) {
|
||||
region ! Envelope(shard = 1, id = id, message = s"E$i")
|
||||
expectReceived(id = id, message = s"E$i")
|
||||
val previousWindow = IndexedSeq(30, 5, 6, 21, 22, 23, 24, 7)
|
||||
val passivated = {
|
||||
if (i == 1 && id <= 38) previousWindow(id - 31)
|
||||
else if (id <= 38) id + 2
|
||||
else id - 8 // window size
|
||||
}
|
||||
expectReceived(id = passivated, message = Stop)
|
||||
}
|
||||
|
||||
expectState(region)(1 -> ((8 to 9) ++ (33 to 40)))
|
||||
|
||||
// window = [34, 35, 36, 37, 38, 39, 40], main = [8, 9, 33]
|
||||
// window proportion is currently 0.7, direction is decreasing and restarted at initial step
|
||||
// stable or increasing active rate will keep decreasing window now (step of -0.4)
|
||||
for (id <- 41 to 50; i <- 1 to 2) {
|
||||
region ! Envelope(shard = 1, id = id, message = s"F$i")
|
||||
expectReceived(id = id, message = s"F$i")
|
||||
if (i == 1) expectReceived(id = id - 7 /* window size */, message = Stop)
|
||||
}
|
||||
|
||||
expectState(region)(1 -> ((8 to 9) ++ Set(33) ++ (44 to 50)))
|
||||
|
||||
// window = [48, 49, 50], main = [8, 9, 33, 44, 45, 46, 47]
|
||||
// window proportion is currently 0.3, direction is decreasing, with next step decayed to -0.2
|
||||
for (id <- 51 to 60; i <- 1 to 2) {
|
||||
region ! Envelope(shard = 1, id = id, message = s"G$i")
|
||||
expectReceived(id = id, message = s"G$i")
|
||||
if (i == 1) expectReceived(id = id - 3 /* window size */, message = Stop)
|
||||
}
|
||||
|
||||
expectState(region)(1 -> (Set(60) ++ Set(8, 9, 33, 44, 45, 46, 47, 58, 59)))
|
||||
|
||||
// window = [60], main = [8, 9, 33, 44, 45, 46, 47, 58, 59]
|
||||
// window proportion is currently 0.1, direction is decreasing, with next step decayed to -0.1
|
||||
for (id <- 61 to 70) {
|
||||
region ! Envelope(shard = 1, id = id, message = s"H")
|
||||
expectReceived(id = id, message = s"H")
|
||||
expectReceived(id = id - 1 /* window size */, message = Stop)
|
||||
}
|
||||
|
||||
expectState(region)(1 -> (Set(70) ++ Set(8, 9, 33, 44, 45, 46, 47, 58, 59)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CompositeWithIdleSpec extends AbstractEntityPassivationSpec(CompositeSpec.idleConfig, expectedEntities = 3) {
|
||||
|
||||
import EntityPassivationSpec.Entity.Envelope
|
||||
import EntityPassivationSpec.Entity.Stop
|
||||
|
||||
"Passivation of idle entities with least recently used strategy" must {
|
||||
"passivate entities when they haven't seen messages for the configured timeout" in {
|
||||
val region = start()
|
||||
|
||||
val lastSendNanoTime1 = System.nanoTime()
|
||||
region ! Envelope(shard = 1, id = 1, message = "A")
|
||||
region ! Envelope(shard = 1, id = 2, message = "B")
|
||||
|
||||
// keep entity 3 active to prevent idle passivation
|
||||
region ! Envelope(shard = 1, id = 3, message = "C")
|
||||
Thread.sleep((configuredIdleTimeout / 2).toMillis)
|
||||
region ! Envelope(shard = 1, id = 3, message = "D")
|
||||
Thread.sleep((configuredIdleTimeout / 2).toMillis)
|
||||
region ! Envelope(shard = 1, id = 3, message = "E")
|
||||
Thread.sleep((configuredIdleTimeout / 2).toMillis)
|
||||
val lastSendNanoTime2 = System.nanoTime()
|
||||
region ! Envelope(shard = 1, id = 3, message = "F")
|
||||
|
||||
expectReceived(id = 1, message = "A")
|
||||
expectReceived(id = 2, message = "B")
|
||||
expectReceived(id = 3, message = "C")
|
||||
expectReceived(id = 3, message = "D")
|
||||
expectReceived(id = 3, message = "E")
|
||||
expectReceived(id = 3, message = "F")
|
||||
val passivate1 = expectReceived(id = 1, message = Stop)
|
||||
val passivate2 = expectReceived(id = 2, message = Stop)
|
||||
val passivate3 = expectReceived(id = 3, message = Stop, within = configuredIdleTimeout * 2)
|
||||
|
||||
// note: touched timestamps are when the shard receives the message, not the entity itself
|
||||
// so look at the time from before sending the last message until receiving the passivate message
|
||||
(passivate1.nanoTime - lastSendNanoTime1).nanos should be > configuredIdleTimeout
|
||||
(passivate2.nanoTime - lastSendNanoTime1).nanos should be > configuredIdleTimeout
|
||||
(passivate3.nanoTime - lastSendNanoTime2).nanos should be > configuredIdleTimeout
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CompositeLimitAdjustmentSpec
|
||||
extends AbstractEntityPassivationSpec(CompositeSpec.admissionWindowAndFilterConfig, expectedEntities = 41) {
|
||||
|
||||
import EntityPassivationSpec.Entity.Envelope
|
||||
import EntityPassivationSpec.Entity.Stop
|
||||
|
||||
"Passivation of least recently used entities" must {
|
||||
"adjust per-shard entity limits when the per-region limit is dynamically adjusted" in {
|
||||
val region = start()
|
||||
|
||||
// only one active shard at first, initial per-shard limit of 20
|
||||
// entities move through the LRU window before moving to main
|
||||
// candidate entities from window passivated due to admission filter (and same frequency)
|
||||
for (id <- 1 to 40) {
|
||||
region ! Envelope(shard = 1, id = id, message = "A")
|
||||
expectReceived(id = id, message = "A")
|
||||
if (id > 20) expectReceived(id = id - 4, message = Stop)
|
||||
}
|
||||
|
||||
expectState(region)(1 -> ((1 to 16) ++ (37 to 40)))
|
||||
|
||||
// activating a second shard will divide the per-shard limit in two, passivating half of the first shard
|
||||
region ! Envelope(shard = 2, id = 41, message = "B")
|
||||
expectReceived(id = 41, message = "B")
|
||||
for (id <- List(37, 38) ++ (1 to 8)) {
|
||||
expectReceived(id = id, message = Stop)
|
||||
}
|
||||
|
||||
expectState(region)(1 -> ((9 to 16) ++ (39 to 40)), 2 -> Set(41))
|
||||
|
||||
// reduce the per-region limit from 20 to 10, per-shard limit becomes 5
|
||||
region ! ShardRegion.SetActiveEntityLimit(10)
|
||||
for (id <- 39 +: (9 to 12)) { // passivate entities over new limit
|
||||
expectReceived(id = id, message = Stop)
|
||||
}
|
||||
|
||||
expectState(region)(1 -> ((13 to 16) ++ Set(40)), 2 -> Set(41))
|
||||
|
||||
// note: frequency sketch is recreated when limit changes, all frequency counts are 0 again
|
||||
for (id <- 1 to 10) {
|
||||
region ! Envelope(shard = 1, id = id, message = "C")
|
||||
expectReceived(id = id, message = "C")
|
||||
val passivated = if (id == 1) 40 else if (id <= 5) id + 11 else id - 1
|
||||
expectReceived(id = passivated, message = Stop)
|
||||
}
|
||||
|
||||
expectState(region)(1 -> ((1 to 4) ++ Set(10)), 2 -> Set(41))
|
||||
|
||||
// increase the per-region limit from 10 to 30, per-shard limit becomes 15
|
||||
region ! ShardRegion.SetActiveEntityLimit(30)
|
||||
|
||||
// note: frequency sketch is recreated when limit changes, all frequency counts are 0 again
|
||||
for (id <- 1 to 20) {
|
||||
region ! Envelope(shard = 1, id = id, message = "D")
|
||||
expectReceived(id = id, message = "D")
|
||||
if (id > 15) { // start passivating window candidates at new higher limit of 15
|
||||
expectReceived(id = id - 3 /* new window size */, message = Stop)
|
||||
}
|
||||
}
|
||||
|
||||
expectState(region)(1 -> ((1 to 12) ++ (18 to 20)), 2 -> Set(41))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright (C) 2022 Lightbend Inc. <https://www.lightbend.com>
|
||||
*/
|
||||
|
||||
package akka.cluster.sharding.passivation
|
||||
|
||||
import akka.cluster.sharding.internal.HillClimbingAdmissionOptimizer
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import org.scalatest.wordspec.AnyWordSpec
|
||||
|
||||
class HillClimbingAdmissionOptimizerSpec extends AnyWordSpec with Matchers {
|
||||
|
||||
def create(
|
||||
initialLimit: Int = 5,
|
||||
adjustMultiplier: Double = 2.0,
|
||||
initialStep: Double = 0.01,
|
||||
restartThreshold: Double = 0.05,
|
||||
stepDecay: Double = 0.98): HillClimbingAdmissionOptimizer =
|
||||
new HillClimbingAdmissionOptimizer(initialLimit, adjustMultiplier, initialStep, restartThreshold, stepDecay)
|
||||
|
||||
"HillClimbingAdmissionOptimizer" must {
|
||||
|
||||
"start in decreasing direction" in {
|
||||
val optimizer = create(initialStep = 0.123)
|
||||
for (_ <- 1 to 10) optimizer.recordPassive()
|
||||
optimizer.calculateAdjustment() shouldBe -0.123
|
||||
}
|
||||
|
||||
"only adjust every 'adjust size' accesses" in {
|
||||
val optimizer = create()
|
||||
for (i <- 1 to 100) {
|
||||
optimizer.recordPassive()
|
||||
if (i % 10 == 0) optimizer.calculateAdjustment() should not be 0.0
|
||||
else optimizer.calculateAdjustment() shouldBe 0.0
|
||||
}
|
||||
}
|
||||
|
||||
"decay each step when active rate is under restart threshold" in {
|
||||
val step = 0.1
|
||||
val decay = 0.5
|
||||
val optimizer = create(initialStep = step, stepDecay = decay)
|
||||
for (i <- 1 to 100) {
|
||||
optimizer.recordPassive()
|
||||
if (i % 10 == 0) optimizer.calculateAdjustment() shouldBe math.pow(decay, i / 10 - 1) * -step
|
||||
}
|
||||
}
|
||||
|
||||
"restart when active rate is over restart threshold" in {
|
||||
val step = 0.1
|
||||
val decay = 0.5
|
||||
val optimizer = create(initialStep = step, stepDecay = decay)
|
||||
for (i <- 1 to 100) {
|
||||
// increase (and maintain) active rate after 40 accesses to trigger restart at 60 then decay again
|
||||
if (i > 40) optimizer.recordActive() else optimizer.recordPassive()
|
||||
if (i % 10 == 0) {
|
||||
val shift = if (i < 60) 1 else 6
|
||||
optimizer.calculateAdjustment() shouldBe math.pow(decay, i / 10 - shift) * -step
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"change direction when active rate drops" in {
|
||||
val optimizer = create()
|
||||
for (i <- 1 to 500) {
|
||||
// decrease active rate every 50 accesses to switch direction
|
||||
val activeRate = math.max(1, 10 - (i / 50))
|
||||
if (i % 10 < activeRate) optimizer.recordActive() else optimizer.recordPassive()
|
||||
if (i % 10 == 0) {
|
||||
// at 10-50 should be negative direction, at 60-100 should be positive direction, and so on
|
||||
val adjustment = optimizer.calculateAdjustment()
|
||||
if (((i - 1) / 50) % 2 == 0) adjustment should be < 0.0 else adjustment should be > 0.0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -144,6 +144,19 @@ object TraceFileReader {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read binary traces from R3 Corda traces.
|
||||
*/
|
||||
final class Corda(path: String) extends AccessPattern {
|
||||
override val isSynthetic = false
|
||||
|
||||
override def entityIds: Source[EntityId, NotUsed] =
|
||||
FileIO // binary file of longs
|
||||
.fromPath(Paths.get(path), chunkSize = 8)
|
||||
.map(bytes => bytes.toByteBuffer.getLong.toString)
|
||||
.mapMaterializedValue(_ => NotUsed)
|
||||
}
|
||||
|
||||
/**
|
||||
* Read traces provided with the "LIRS" (or "LIRS2") paper:
|
||||
* LIRS: An Efficient Low Inter-reference Recency Set Replacement Policy to Improve Buffer Cache Performance
|
||||
|
|
@ -179,3 +192,11 @@ object TraceFileReader {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
class JoinedAccessPatterns(patterns: Seq[AccessPattern]) extends AccessPattern {
|
||||
override def isSynthetic: Boolean =
|
||||
patterns.exists(_.isSynthetic)
|
||||
|
||||
override def entityIds: Source[EntityId, NotUsed] =
|
||||
patterns.map(_.entityIds).foldLeft(Source.empty[EntityId])(_.concat(_))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,20 +6,36 @@ package akka.cluster.sharding.passivation.simulator
|
|||
|
||||
import akka.NotUsed
|
||||
import akka.actor.ActorSystem
|
||||
import akka.cluster.sharding.internal.{
|
||||
EntityPassivationStrategy,
|
||||
LeastFrequentlyUsedEntityPassivationStrategy,
|
||||
LeastRecentlyUsedEntityPassivationStrategy,
|
||||
MostRecentlyUsedEntityPassivationStrategy,
|
||||
SegmentedLeastRecentlyUsedEntityPassivationStrategy
|
||||
}
|
||||
import akka.stream.scaladsl.{ Flow, Source }
|
||||
import akka.cluster.sharding.internal.ActiveEntities
|
||||
import akka.cluster.sharding.internal.AdmissionFilter
|
||||
import akka.cluster.sharding.internal.AdmissionOptimizer
|
||||
import akka.cluster.sharding.internal.AlwaysAdmissionFilter
|
||||
import akka.cluster.sharding.internal.CompositeEntityPassivationStrategy
|
||||
import akka.cluster.sharding.internal.DisabledEntityPassivationStrategy
|
||||
import akka.cluster.sharding.internal.EntityPassivationStrategy
|
||||
import akka.cluster.sharding.internal.FrequencySketchAdmissionFilter
|
||||
import akka.cluster.sharding.internal.HillClimbingAdmissionOptimizer
|
||||
import akka.cluster.sharding.internal.LeastFrequentlyUsedEntityPassivationStrategy
|
||||
import akka.cluster.sharding.internal.LeastFrequentlyUsedReplacementPolicy
|
||||
import akka.cluster.sharding.internal.LeastRecentlyUsedEntityPassivationStrategy
|
||||
import akka.cluster.sharding.internal.LeastRecentlyUsedReplacementPolicy
|
||||
import akka.cluster.sharding.internal.MostRecentlyUsedEntityPassivationStrategy
|
||||
import akka.cluster.sharding.internal.MostRecentlyUsedReplacementPolicy
|
||||
import akka.cluster.sharding.internal.NoActiveEntities
|
||||
import akka.cluster.sharding.internal.NoAdmissionOptimizer
|
||||
import akka.cluster.sharding.internal.SegmentedLeastRecentlyUsedEntityPassivationStrategy
|
||||
import akka.cluster.sharding.internal.SegmentedLeastRecentlyUsedReplacementPolicy
|
||||
import akka.stream.scaladsl.Flow
|
||||
import akka.stream.scaladsl.Source
|
||||
import akka.util.OptionVal
|
||||
import com.typesafe.config.ConfigFactory
|
||||
|
||||
import scala.collection.{ immutable, mutable }
|
||||
import scala.concurrent.{ ExecutionContext, Future }
|
||||
import scala.util.{ Failure, Success }
|
||||
import scala.collection.immutable
|
||||
import scala.collection.mutable
|
||||
import scala.concurrent.ExecutionContext
|
||||
import scala.concurrent.Future
|
||||
import scala.util.Failure
|
||||
import scala.util.Success
|
||||
|
||||
/**
|
||||
* Simulator for testing the efficiency of passivation strategies.
|
||||
|
|
@ -75,10 +91,10 @@ object Simulator {
|
|||
name = runSettings.name,
|
||||
numberOfShards = runSettings.shards,
|
||||
numberOfRegions = runSettings.regions,
|
||||
accessPattern = accessPattern(runSettings),
|
||||
accessPattern = accessPattern(runSettings.pattern),
|
||||
strategyCreator = strategyCreator(runSettings))
|
||||
|
||||
def accessPattern(runSettings: SimulatorSettings.RunSettings): AccessPattern = runSettings.pattern match {
|
||||
def accessPattern(patternSettings: SimulatorSettings.PatternSettings): AccessPattern = patternSettings match {
|
||||
case SimulatorSettings.PatternSettings.Synthetic(generator, events) =>
|
||||
generator match {
|
||||
case SimulatorSettings.PatternSettings.Synthetic.Sequence(start) =>
|
||||
|
|
@ -99,6 +115,7 @@ object Simulator {
|
|||
case SimulatorSettings.PatternSettings.Trace(path, format) =>
|
||||
format match {
|
||||
case "arc" => new TraceFileReader.Arc(path)
|
||||
case "corda" => new TraceFileReader.Corda(path)
|
||||
case "lirs" => new TraceFileReader.Lirs(path)
|
||||
case "lirs2" => new TraceFileReader.Lirs2(path)
|
||||
case "simple" => new TraceFileReader.Simple(path)
|
||||
|
|
@ -106,6 +123,8 @@ object Simulator {
|
|||
case "wikipedia" => new TraceFileReader.Wikipedia(path)
|
||||
case _ => sys.error(s"Unknown trace file format [$format]")
|
||||
}
|
||||
case SimulatorSettings.PatternSettings.Joined(patterns) =>
|
||||
new JoinedAccessPatterns(patterns.map(accessPattern))
|
||||
}
|
||||
|
||||
def strategyCreator(runSettings: SimulatorSettings.RunSettings): StrategyCreator =
|
||||
|
|
@ -118,6 +137,10 @@ object Simulator {
|
|||
new MostRecentlyUsedStrategyCreator(perRegionLimit)
|
||||
case SimulatorSettings.StrategySettings.LeastFrequentlyUsed(perRegionLimit, dynamicAging) =>
|
||||
new LeastFrequentlyUsedStrategyCreator(perRegionLimit, dynamicAging)
|
||||
case settings: SimulatorSettings.StrategySettings.Composite =>
|
||||
new CompositeStrategyCreator(settings)
|
||||
case SimulatorSettings.StrategySettings.NoStrategy =>
|
||||
DisabledStrategyCreator
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -296,6 +319,70 @@ object Simulator {
|
|||
new LeastFrequentlyUsedEntityPassivationStrategy(perRegionLimit, dynamicAging, idleCheck = None))
|
||||
}
|
||||
|
||||
final class CompositeStrategyCreator(settings: SimulatorSettings.StrategySettings.Composite)
|
||||
extends PassivationStrategyCreator {
|
||||
override def create(shardId: ShardId): SimulatedStrategy = {
|
||||
val main = activeEntities(settings.main)
|
||||
val window = activeEntities(settings.window)
|
||||
val initialWindowProportion = if (window eq NoActiveEntities) 0.0 else settings.initialWindowProportion
|
||||
val minimumWindowProportion = if (window eq NoActiveEntities) 0.0 else settings.minimumWindowProportion
|
||||
val maximumWindowProportion = if (window eq NoActiveEntities) 0.0 else settings.maximumWindowProportion
|
||||
val windowOptimizer =
|
||||
if (window eq NoActiveEntities) NoAdmissionOptimizer
|
||||
else admissionOptimizer(settings.perRegionLimit, settings.optimizer)
|
||||
val admission = admissionFilter(settings.perRegionLimit, settings.filter)
|
||||
new PassivationStrategy(
|
||||
new CompositeEntityPassivationStrategy(
|
||||
settings.perRegionLimit,
|
||||
window,
|
||||
initialWindowProportion,
|
||||
minimumWindowProportion,
|
||||
maximumWindowProportion,
|
||||
windowOptimizer,
|
||||
admission,
|
||||
main,
|
||||
idleCheck = None))
|
||||
}
|
||||
|
||||
private def activeEntities(strategySettings: SimulatorSettings.StrategySettings): ActiveEntities =
|
||||
strategySettings match {
|
||||
case SimulatorSettings.StrategySettings.LeastRecentlyUsed(perRegionLimit, segmented) if segmented.isEmpty =>
|
||||
new LeastRecentlyUsedReplacementPolicy(perRegionLimit)
|
||||
case SimulatorSettings.StrategySettings.LeastRecentlyUsed(perRegionLimit, segmented) =>
|
||||
new SegmentedLeastRecentlyUsedReplacementPolicy(perRegionLimit, segmented, idleEnabled = false)
|
||||
case SimulatorSettings.StrategySettings.MostRecentlyUsed(perRegionLimit) =>
|
||||
new MostRecentlyUsedReplacementPolicy(perRegionLimit)
|
||||
case SimulatorSettings.StrategySettings.LeastFrequentlyUsed(perRegionLimit, dynamicAging) =>
|
||||
new LeastFrequentlyUsedReplacementPolicy(perRegionLimit, dynamicAging, idleEnabled = false)
|
||||
case _ => NoActiveEntities
|
||||
}
|
||||
|
||||
private def admissionOptimizer(
|
||||
capacity: Int,
|
||||
optimizerSettings: SimulatorSettings.StrategySettings.AdmissionOptimizerSettings): AdmissionOptimizer =
|
||||
optimizerSettings match {
|
||||
case SimulatorSettings.StrategySettings.AdmissionOptimizerSettings.NoOptimizer => NoAdmissionOptimizer
|
||||
case SimulatorSettings.StrategySettings.AdmissionOptimizerSettings
|
||||
.HillClimbingOptimizer(adjustMultiplier, initialStep, restartThreshold, stepDecay) =>
|
||||
new HillClimbingAdmissionOptimizer(capacity, adjustMultiplier, initialStep, restartThreshold, stepDecay)
|
||||
}
|
||||
|
||||
private def admissionFilter(
|
||||
capacity: Int,
|
||||
filterSettings: SimulatorSettings.StrategySettings.AdmissionFilterSettings): AdmissionFilter =
|
||||
filterSettings match {
|
||||
case SimulatorSettings.StrategySettings.AdmissionFilterSettings.NoFilter => AlwaysAdmissionFilter
|
||||
case SimulatorSettings.StrategySettings.AdmissionFilterSettings
|
||||
.FrequencySketchFilter(widthMultiplier, resetMultiplier, depth, counterBits) =>
|
||||
FrequencySketchAdmissionFilter(capacity, widthMultiplier, resetMultiplier, depth, counterBits)
|
||||
}
|
||||
}
|
||||
|
||||
object DisabledStrategyCreator extends PassivationStrategyCreator {
|
||||
override def create(shardId: ShardId): SimulatedStrategy =
|
||||
new PassivationStrategy(DisabledEntityPassivationStrategy)
|
||||
}
|
||||
|
||||
// Clairvoyant passivation strategy using Bélády's algorithm.
|
||||
// Record virtual access times per entity id on a first pass through the access pattern,
|
||||
// to passivate entities that will not be accessed again for the furthest time in the future.
|
||||
|
|
|
|||
|
|
@ -49,9 +49,40 @@ object SimulatorSettings {
|
|||
final case class LeastRecentlyUsed(perRegionLimit: Int, segmented: immutable.Seq[Double]) extends StrategySettings
|
||||
final case class MostRecentlyUsed(perRegionLimit: Int) extends StrategySettings
|
||||
final case class LeastFrequentlyUsed(perRegionLimit: Int, dynamicAging: Boolean) extends StrategySettings
|
||||
case object NoStrategy extends StrategySettings
|
||||
|
||||
final case class Composite(
|
||||
perRegionLimit: Int,
|
||||
main: StrategySettings,
|
||||
window: StrategySettings,
|
||||
initialWindowProportion: Double,
|
||||
minimumWindowProportion: Double,
|
||||
maximumWindowProportion: Double,
|
||||
filter: AdmissionFilterSettings,
|
||||
optimizer: AdmissionOptimizerSettings)
|
||||
extends StrategySettings
|
||||
|
||||
def apply(simulatorConfig: Config, strategy: String): StrategySettings = {
|
||||
val config = simulatorConfig.getConfig(strategy).withFallback(simulatorConfig.getConfig("strategy-defaults"))
|
||||
val config = simulatorConfig.getConfig(strategy)
|
||||
val fallbackConfig = simulatorConfig.getConfig("strategy-defaults")
|
||||
lowerCase(config.getString("strategy")) match {
|
||||
case "composite" =>
|
||||
val compositeConfig = config.getConfig("composite").withFallback(fallbackConfig.getConfig("composite"))
|
||||
Composite(
|
||||
compositeConfig.getInt("per-region-limit"),
|
||||
settings(compositeConfig.getConfig("main"), fallbackConfig),
|
||||
settings(compositeConfig.getConfig("admission.window"), fallbackConfig),
|
||||
compositeConfig.getDouble("admission.window.proportion"),
|
||||
compositeConfig.getDouble("admission.window.minimum-proportion"),
|
||||
compositeConfig.getDouble("admission.window.maximum-proportion"),
|
||||
AdmissionFilterSettings(compositeConfig),
|
||||
AdmissionOptimizerSettings(compositeConfig))
|
||||
case _ => settings(config, fallbackConfig)
|
||||
}
|
||||
}
|
||||
|
||||
private def settings(strategyConfig: Config, fallbackConfig: Config): StrategySettings = {
|
||||
val config = strategyConfig.withFallback(fallbackConfig)
|
||||
lowerCase(config.getString("strategy")) match {
|
||||
case "optimal" => Optimal(config.getInt("optimal.per-region-limit"))
|
||||
case "least-recently-used" =>
|
||||
|
|
@ -70,7 +101,55 @@ object SimulatorSettings {
|
|||
LeastFrequentlyUsed(
|
||||
config.getInt("least-frequently-used.per-region-limit"),
|
||||
config.getBoolean("least-frequently-used.dynamic-aging"))
|
||||
case _ => sys.error(s"Unknown strategy for [$strategy]")
|
||||
case _ => NoStrategy
|
||||
}
|
||||
}
|
||||
|
||||
sealed trait AdmissionFilterSettings
|
||||
|
||||
object AdmissionFilterSettings {
|
||||
object NoFilter extends AdmissionFilterSettings
|
||||
final case class FrequencySketchFilter(
|
||||
widthMultiplier: Int,
|
||||
resetMultiplier: Double,
|
||||
depth: Int,
|
||||
counterBits: Int)
|
||||
extends AdmissionFilterSettings
|
||||
|
||||
def apply(config: Config): AdmissionFilterSettings = {
|
||||
lowerCase(config.getString("admission.filter")) match {
|
||||
case "frequency-sketch" =>
|
||||
FrequencySketchFilter(
|
||||
config.getInt("admission.frequency-sketch.width-multiplier"),
|
||||
config.getDouble("admission.frequency-sketch.reset-multiplier"),
|
||||
config.getInt("admission.frequency-sketch.depth"),
|
||||
config.getInt("admission.frequency-sketch.counter-bits"))
|
||||
case _ => NoFilter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sealed trait AdmissionOptimizerSettings
|
||||
|
||||
object AdmissionOptimizerSettings {
|
||||
object NoOptimizer extends AdmissionOptimizerSettings
|
||||
final case class HillClimbingOptimizer(
|
||||
adjustMultiplier: Double,
|
||||
initialStep: Double,
|
||||
restartThreshold: Double,
|
||||
stepDecay: Double)
|
||||
extends AdmissionOptimizerSettings
|
||||
|
||||
def apply(config: Config): AdmissionOptimizerSettings = {
|
||||
lowerCase(config.getString("admission.optimizer")) match {
|
||||
case "hill-climbing" =>
|
||||
HillClimbingOptimizer(
|
||||
config.getDouble("admission.hill-climbing.adjust-multiplier"),
|
||||
config.getDouble("admission.hill-climbing.initial-step"),
|
||||
config.getDouble("admission.hill-climbing.restart-threshold"),
|
||||
config.getDouble("admission.hill-climbing.step-decay"))
|
||||
case _ => NoOptimizer
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -141,11 +220,21 @@ object SimulatorSettings {
|
|||
}
|
||||
}
|
||||
|
||||
final case class Joined(patterns: Seq[PatternSettings]) extends PatternSettings
|
||||
|
||||
object Joined {
|
||||
def apply(simulatorConfig: Config, patternConfig: Config): Joined = {
|
||||
val patterns = patternConfig.getStringList("joined").asScala.toSeq
|
||||
Joined(patterns.map(pattern => PatternSettings(simulatorConfig, pattern)))
|
||||
}
|
||||
}
|
||||
|
||||
def apply(simulatorConfig: Config, pattern: String): PatternSettings = {
|
||||
val config = simulatorConfig.getConfig(pattern).withFallback(simulatorConfig.getConfig("pattern-defaults"))
|
||||
lowerCase(config.getString("pattern")) match {
|
||||
case "synthetic" => Synthetic(config)
|
||||
case "trace" => Trace(config)
|
||||
case "joined" => Joined(simulatorConfig, config)
|
||||
case _ => sys.error(s"Unknown pattern for [$pattern]")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -337,8 +337,13 @@ Cluster Sharding, can be enabled with configuration:
|
|||
|
||||
@@snip [passivation new default strategy](/akka-cluster-sharding/src/test/scala/akka/cluster/sharding/ClusterShardingSettingsSpec.scala) { #passivation-new-default-strategy type=conf }
|
||||
|
||||
This default strategy uses a [segmented least recently used policy](#segmented-least-recently-used-policy). The active
|
||||
entity limit can be configured:
|
||||
This default strategy uses a [composite passivation strategy](#composite-passivation-strategies) which combines
|
||||
recency-based and frequency-based tracking: the main area is configured with a [segmented least recently used
|
||||
policy](#segmented-least-recently-used-policy) with a frequency-biased [admission filter](#admission-filter), fronted
|
||||
by a recency-biased [admission window](#admission-window-policy) with [adaptive sizing](#admission-window-optimizer)
|
||||
enabled.
|
||||
|
||||
The active entity limit for the default strategy can be configured:
|
||||
|
||||
@@snip [passivation new default strategy configured](/akka-cluster-sharding/src/test/scala/akka/cluster/sharding/ClusterShardingSettingsSpec.scala) { #passivation-new-default-strategy-configured type=conf }
|
||||
|
||||
|
|
@ -456,6 +461,63 @@ Configure dynamic aging with the least frequently used policy:
|
|||
|
||||
Or using custom `ClusterShardingSettings.PassivationStrategySettings.LeastFrequentlyUsedSettings`.
|
||||
|
||||
### Composite passivation strategies
|
||||
|
||||
Passivation strategies can be combined using an admission window and admission filter. The admission window tracks
|
||||
newly activated entities. Entities are replaced in the admission window using one of the replacement policies, such as
|
||||
the least recently used replacement policy. When an entity is replaced in the window area it has an opportunity to
|
||||
enter the main entity tracking area, based on the admission filter. The admission filter determines whether an entity
|
||||
that has left the window area should be admitted into the main area, or otherwise be passivated. A frequency sketch is
|
||||
the default admission filter and estimates the access frequency of entities over the lifespan of the cluster sharding
|
||||
node, selecting the entity that is estimated to be accessed more frequently. Composite passivation strategies with an
|
||||
admission window and admission filter are implementing the _Window-TinyLFU_ caching algorithm.
|
||||
|
||||
#### Admission window policy
|
||||
|
||||
The admission window tracks newly activated entities. When an entity is replaced in the window area, it has an
|
||||
opportunity to enter the main entity tracking area, based on the [admission filter](#admission-filter). The admission
|
||||
window can be enabled by selecting a policy (while the regular replacement policy is for the main area):
|
||||
|
||||
@@snip [admission window policy](/akka-cluster-sharding/src/test/scala/akka/cluster/sharding/ClusterShardingSettingsSpec.scala) { #admission-window-policy type=conf }
|
||||
|
||||
The proportion of the active entity limit used for the admission window can be configured (the default is 1%):
|
||||
|
||||
@@snip [admission window proportion](/akka-cluster-sharding/src/test/scala/akka/cluster/sharding/ClusterShardingSettingsSpec.scala) { #admission-window-proportion type=conf }
|
||||
|
||||
The proportion for the admission window can also be adapted and optimized dynamically, by enabling an [admission window
|
||||
optimizer](#admission-window-optimizer).
|
||||
|
||||
#### Admission window optimizer
|
||||
|
||||
The proportion of the active entity limit used for the admission window can be adapted dynamically using an optimizer.
|
||||
The window area will usually retain entities that are accessed again in a short time (recency-biased), while the main
|
||||
area can track entities that are accessed more frequently over longer times (frequency-biased). If access patterns for
|
||||
entities are changeable, then the adaptive sizing of the window allows the passivation strategy to adapt between
|
||||
recency-biased and frequency-biased workloads.
|
||||
|
||||
The optimizer currently available uses a simple hill-climbing algorithm, which searches for a window proportion that
|
||||
provides an optimal active rate (where entities are already active when accessed, the _cache hit rate_). Enable
|
||||
adaptive window sizing by configuring the `hill-climbing` window optimizer:
|
||||
|
||||
@@snip [admission window optimizer](/akka-cluster-sharding/src/test/scala/akka/cluster/sharding/ClusterShardingSettingsSpec.scala) { #admission-window-optimizer type=conf }
|
||||
|
||||
See the `reference.conf` for parameters that can be tuned for the hill climbing admission window optimizer.
|
||||
|
||||
#### Admission filter
|
||||
|
||||
An admission filter can be enabled, which determines whether an entity that has left the window area (or a newly
|
||||
activated entity if there is no admission window) should be admitted into the main entity tracking area, or otherwise
|
||||
be passivated. If no admission filter is configured, then entities will always be admitted into the main area.
|
||||
|
||||
A frequency sketch is the default admission filter and estimates the access frequency of entities over the lifespan of
|
||||
the cluster sharding node, selecting the entity that is estimated to be accessed more frequently. The frequency sketch
|
||||
automatically ages entries, using the approach from the _TinyLFU_ cache admission algorithm. Enable an admission filter
|
||||
by configuring the `frequency-sketch` admission filter:
|
||||
|
||||
@@snip [admission policy](/akka-cluster-sharding/src/test/scala/akka/cluster/sharding/ClusterShardingSettingsSpec.scala) { #admission-policy type=conf }
|
||||
|
||||
See the `reference.conf` for parameters that can be tuned for the frequency sketch admission filter.
|
||||
|
||||
|
||||
## Sharding State
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue