diff --git a/src/Orleans.Runtime/Placement/Repartitioning/RebalancerCompatibleRule.cs b/src/Orleans.Runtime/Placement/Repartitioning/RebalancerCompatibleRule.cs index 6cb2c2ff8fe..ce26e5c12e6 100644 --- a/src/Orleans.Runtime/Placement/Repartitioning/RebalancerCompatibleRule.cs +++ b/src/Orleans.Runtime/Placement/Repartitioning/RebalancerCompatibleRule.cs @@ -29,7 +29,7 @@ internal class RebalancerCompatibleRule(IServiceProvider provider) : private readonly ISiloStatusOracle _oracle = provider.GetRequiredService(); private readonly IActivationRebalancer? _rebalancer = provider.GetService(); - public bool IsSatisfiedBy(uint imbalance) => imbalance <= _pairwiseImbalance; + public bool IsSatisfiedBy(uint imbalance) => imbalance <= Volatile.Read(ref _pairwiseImbalance); public void SiloStatusChangeNotification(SiloAddress silo, SiloStatus status) { @@ -37,16 +37,7 @@ public void SiloStatusChangeNotification(SiloAddress silo, SiloStatus status) { ref var statusRef = ref CollectionsMarshal.GetValueRefOrAddDefault(_silos, silo, out _); statusRef = status; - - var activeSilos = _silos.Count(s => s.Value == SiloStatus.Active); - var percentageOfBaseline = 100d / (1 + Math.Exp(0.07d * activeSilos - 4.8d)); - - if (percentageOfBaseline < 10d) percentageOfBaseline = 10d; - - var pairwiseImbalance = (uint)Math.Round(10.1d * percentageOfBaseline, 0); - var toleranceFactor = Math.Cos(Math.PI * _clusterImbalance / 2); // This will always be 1 if rebalancer is not registered. - - _pairwiseImbalance = (uint)Math.Max(pairwiseImbalance * toleranceFactor, 0); + UpdatePairwiseImbalance(); } } @@ -59,9 +50,23 @@ public void OnReport(RebalancingReport report) lock (_lock) { _clusterImbalance = report.ClusterImbalance; + UpdatePairwiseImbalance(); } } + private void UpdatePairwiseImbalance() + { + var activeSilos = _silos.Count(s => s.Value == SiloStatus.Active); + var percentageOfBaseline = 100d / (1 + Math.Exp(0.07d * activeSilos - 4.8d)); + + if (percentageOfBaseline < 10d) percentageOfBaseline = 10d; + + var pairwiseImbalance = (uint)Math.Round(10.1d * percentageOfBaseline, 0); + var toleranceFactor = Math.Cos(Math.PI * _clusterImbalance / 2); // This will always be 1 if rebalancer is not registered. + + _pairwiseImbalance = (uint)Math.Max(pairwiseImbalance * toleranceFactor, 0); + } + public Task OnStart(CancellationToken cancellationToken) { _oracle.SubscribeToSiloStatusEvents(this);