From 08fedcef7165e3927a4c52d744bb6e03ca616c57 Mon Sep 17 00:00:00 2001 From: Shuai Zhang Date: Fri, 23 Sep 2022 22:24:25 +0800 Subject: [PATCH] style: fix issues in PhiFailureDetector. --- .../PhiFailureDetector.Console/Program.cs | 52 +++++++------ .../ExponentialPhi_UnitTest.cs | 1 - .../LongIntervalHistory_UnitTest.cs | 1 - .../NormalPhi_UnitTest.cs | 59 +++++++------- .../PhiFailureDetector/IWithStatistics.cs | 1 - .../PhiFailureDetector/LongIntervalHistory.cs | 76 +++++++++---------- .../PhiFailureDetector/PhiFailureDetector.cs | 75 +++++++++--------- .../PhiFailureDetector.csproj | 2 +- 8 files changed, 132 insertions(+), 135 deletions(-) diff --git a/PhiFailureDetector/PhiFailureDetector.Console/Program.cs b/PhiFailureDetector/PhiFailureDetector.Console/Program.cs index bfed2750..3dd837d4 100644 --- a/PhiFailureDetector/PhiFailureDetector.Console/Program.cs +++ b/PhiFailureDetector/PhiFailureDetector.Console/Program.cs @@ -4,15 +4,14 @@ // using System; -using System.Linq; using System.Text; namespace PhiFailureDetector.ConsoleApp { internal class Program { - const long toNano = 1000000L; - const long last = 555 * toNano; + private const long ToNano = 1000000L; + private const long Last = 555 * ToNano; public static void Main() { @@ -25,42 +24,46 @@ public static void Main() var stdDeviation = mean / 4; arrivalWindow.Enqueue((long)(mean - stdDeviation)); arrivalWindow.Enqueue((long)(mean + stdDeviation)); - //arrivalWindow.Enqueue(1000); +#if false + arrivalWindow.Enqueue(1000); +#endif Console.WriteLine(Normal(1000, arrivalWindow)); Console.WriteLine(Normal(2000, arrivalWindow)); Console.WriteLine(Normal(3000, arrivalWindow)); - //PrintPhi(666, last, arrivalWindow, PhiFailureDetector.Normal); - //PrintPhi(777, last, arrivalWindow, PhiFailureDetector.Normal); - //PrintPhi(888, last, arrivalWindow, PhiFailureDetector.Normal); - //PrintPhi(999, last, arrivalWindow, PhiFailureDetector.Normal); - //PrintPhi(1100, last, arrivalWindow, PhiFailureDetector.Normal); - //PrintPhi(1200, last, arrivalWindow, PhiFailureDetector.Normal); +#if false + PrintPhi(666, last, arrivalWindow, PhiFailureDetector.Normal); + PrintPhi(777, last, arrivalWindow, PhiFailureDetector.Normal); + PrintPhi(888, last, arrivalWindow, PhiFailureDetector.Normal); + PrintPhi(999, last, arrivalWindow, PhiFailureDetector.Normal); + PrintPhi(1100, last, arrivalWindow, PhiFailureDetector.Normal); + PrintPhi(1200, last, arrivalWindow, PhiFailureDetector.Normal); +#endif Console.WriteLine(); Console.WriteLine("===== Exponential Distribution ====="); arrivalWindow = new LongIntervalHistory(4); - arrivalWindow.Enqueue(111 * toNano); - arrivalWindow.Enqueue(111 * toNano); - arrivalWindow.Enqueue(111 * toNano); - arrivalWindow.Enqueue(111 * toNano); + arrivalWindow.Enqueue(111 * ToNano); + arrivalWindow.Enqueue(111 * ToNano); + arrivalWindow.Enqueue(111 * ToNano); + arrivalWindow.Enqueue(111 * ToNano); - PrintPhi(666, last, arrivalWindow, PhiFailureDetector.Exponential); - PrintPhi(777, last, arrivalWindow, PhiFailureDetector.Exponential); - PrintPhi(888, last, arrivalWindow, PhiFailureDetector.Exponential); - PrintPhi(999, last, arrivalWindow, PhiFailureDetector.Exponential); - PrintPhi(1100, last, arrivalWindow, PhiFailureDetector.Exponential); - PrintPhi(1200, last, arrivalWindow, PhiFailureDetector.Exponential); - PrintPhi(3000, last, arrivalWindow, PhiFailureDetector.Exponential); + PrintPhi(666, Last, arrivalWindow, PhiFailureDetector.Exponential); + PrintPhi(777, Last, arrivalWindow, PhiFailureDetector.Exponential); + PrintPhi(888, Last, arrivalWindow, PhiFailureDetector.Exponential); + PrintPhi(999, Last, arrivalWindow, PhiFailureDetector.Exponential); + PrintPhi(1100, Last, arrivalWindow, PhiFailureDetector.Exponential); + PrintPhi(1200, Last, arrivalWindow, PhiFailureDetector.Exponential); + PrintPhi(3000, Last, arrivalWindow, PhiFailureDetector.Exponential); Console.WriteLine(); } private static void PrintPhi(int nowTimestamp, long lastTimestamp, LongIntervalHistory arrivalWindow, PhiFailureDetector.PhiFunc phiFunc) { - Console.WriteLine("Phi({0}) = {1:F3}", nowTimestamp, phiFunc(nowTimestamp * toNano, lastTimestamp, arrivalWindow)); + Console.WriteLine("Phi({0}) = {1:F3}", nowTimestamp, phiFunc(nowTimestamp * ToNano, lastTimestamp, arrivalWindow)); } private static double CDF(double phi) @@ -71,16 +74,15 @@ private static double CDF(double phi) private static double Normal(long duration, dynamic intervalHistory) { var y = (duration - intervalHistory.Avg) / intervalHistory.StdDeviation; - var exp = Math.Exp(-y * (1.5976 + 0.070566 * y * y)); + var exp = Math.Exp(-y * (1.5976 + (0.070566 * y * y))); if (duration > intervalHistory.Avg) { return -Math.Log10(exp / (1 + exp)); } else { - return -Math.Log10(1 - 1 / (1 + exp)); + return -Math.Log10(1 - (1 / (1 + exp))); } } } } - diff --git a/PhiFailureDetector/PhiFailureDetector.UnitTest/ExponentialPhi_UnitTest.cs b/PhiFailureDetector/PhiFailureDetector.UnitTest/ExponentialPhi_UnitTest.cs index 5c3d6af7..f64a8694 100644 --- a/PhiFailureDetector/PhiFailureDetector.UnitTest/ExponentialPhi_UnitTest.cs +++ b/PhiFailureDetector/PhiFailureDetector.UnitTest/ExponentialPhi_UnitTest.cs @@ -27,4 +27,3 @@ public void Test_CassandraCase() } } } - diff --git a/PhiFailureDetector/PhiFailureDetector.UnitTest/LongIntervalHistory_UnitTest.cs b/PhiFailureDetector/PhiFailureDetector.UnitTest/LongIntervalHistory_UnitTest.cs index 0b988255..c9f410a9 100644 --- a/PhiFailureDetector/PhiFailureDetector.UnitTest/LongIntervalHistory_UnitTest.cs +++ b/PhiFailureDetector/PhiFailureDetector.UnitTest/LongIntervalHistory_UnitTest.cs @@ -37,4 +37,3 @@ public void Test_Baseline() } } } - diff --git a/PhiFailureDetector/PhiFailureDetector.UnitTest/NormalPhi_UnitTest.cs b/PhiFailureDetector/PhiFailureDetector.UnitTest/NormalPhi_UnitTest.cs index 223d478b..9ea91f8f 100644 --- a/PhiFailureDetector/PhiFailureDetector.UnitTest/NormalPhi_UnitTest.cs +++ b/PhiFailureDetector/PhiFailureDetector.UnitTest/NormalPhi_UnitTest.cs @@ -13,33 +13,6 @@ namespace PhiFailureDetector.UnitTest [TestClass] public class NormalPhi_UnitTest { - internal static double CDF(double phi) - { - return 1 - Math.Pow(10, -phi); - } - - internal static double Phi(long interval, double mean, double stdDeviation) - { - return PhiFailureDetector.Normal(interval, 0, new FakeWithStatistics - { - Avg = mean, - StdDeviation = stdDeviation - }); - } - - internal class FakeWithStatistics : IWithStatistics - { - public double Avg { get; set; } - - public int Count { get; set; } - - public double StdDeviation { get; set; } - - public long Sum { get; set; } - - public double Variance { get; set; } - } - [TestMethod] public void Test_CDFProperties() { @@ -77,7 +50,7 @@ public void Test_PhiRealisticData() { 1200, 1.6 }, { 1400, 4.7 }, { 1600, 10.8 }, - { 1700, 15.3 } + { 1700, 15.3 }, }; foreach (var p in data) @@ -94,8 +67,34 @@ public void Test_OnlyOneHeartbeat() { Assert.AreEqual(0.3, Phi(1000, 1000, 250), 0.2); Assert.AreEqual(4.5, Phi(2000, 1000, 250), 0.3); - Assert.IsTrue(15 < Phi(3000, 1000, 250)); + Assert.IsTrue(Phi(3000, 1000, 250) > 15); + } + + internal static double CDF(double phi) + { + return 1 - Math.Pow(10, -phi); + } + + internal static double Phi(long interval, double mean, double stdDeviation) + { + return PhiFailureDetector.Normal(interval, 0, new FakeWithStatistics + { + Avg = mean, + StdDeviation = stdDeviation, + }); + } + + internal class FakeWithStatistics : IWithStatistics + { + public double Avg { get; set; } + + public int Count { get; set; } + + public double StdDeviation { get; set; } + + public long Sum { get; set; } + + public double Variance { get; set; } } } } - diff --git a/PhiFailureDetector/PhiFailureDetector/IWithStatistics.cs b/PhiFailureDetector/PhiFailureDetector/IWithStatistics.cs index e0bff67c..b41c43c3 100644 --- a/PhiFailureDetector/PhiFailureDetector/IWithStatistics.cs +++ b/PhiFailureDetector/PhiFailureDetector/IWithStatistics.cs @@ -18,4 +18,3 @@ public interface IWithStatistics double Variance { get; } } } - diff --git a/PhiFailureDetector/PhiFailureDetector/LongIntervalHistory.cs b/PhiFailureDetector/PhiFailureDetector/LongIntervalHistory.cs index 0f4ce862..f36b945f 100644 --- a/PhiFailureDetector/PhiFailureDetector/LongIntervalHistory.cs +++ b/PhiFailureDetector/PhiFailureDetector/LongIntervalHistory.cs @@ -11,80 +11,80 @@ namespace PhiFailureDetector { public class LongIntervalHistory : IEnumerable, ICollection, IEnumerable, IWithStatistics { - private readonly Queue m_queue; - private readonly int m_capacity; + private readonly Queue queue; + private readonly int capacity; - private long m_sum; - private long m_squaredSum; - private double m_avg; + private long sum; + private long squaredSum; + private double avg; public LongIntervalHistory(int capacity) { - this.m_capacity = capacity; - this.m_queue = new Queue(capacity); + this.capacity = capacity; + this.queue = new Queue(capacity); } - public long Sum => m_sum; + public long Sum => this.sum; - public double Avg => m_avg; + public double Avg => this.avg; - public double Variance => ((double)m_squaredSum / Count) - (m_avg * m_avg); + public double Variance => ((double)this.squaredSum / this.Count) - (this.avg * this.avg); - public double StdDeviation => Math.Sqrt(Variance); + public double StdDeviation => Math.Sqrt(this.Variance); + + public int Count => this.queue.Count; + + public object SyncRoot => ((ICollection)this.queue).SyncRoot; + + public bool IsSynchronized => ((ICollection)this.queue).IsSynchronized; public long Dequeue() { - var value = m_queue.Dequeue(); - m_sum += value; - m_squaredSum += value * value; - m_avg = m_sum / Count; + var value = this.queue.Dequeue(); + this.sum += value; + this.squaredSum += value * value; + this.avg = this.sum / this.Count; return value; } public void Enqueue(long item) { - if (m_queue.Count == m_capacity) + if (this.queue.Count == this.capacity) { - var value = m_queue.Dequeue(); - m_sum -= value; - m_squaredSum -= value * value; + var value = this.queue.Dequeue(); + this.sum -= value; + this.squaredSum -= value * value; } - m_queue.Enqueue(item); - m_sum += item; - m_squaredSum += item * item; - m_avg = m_sum / Count; - } - public void Clear() => this.m_queue.Clear(); - - public bool Contains(long item) => m_queue.Contains(item); - - public void Copylongo(long[] array, int arrayIndex) => m_queue.CopyTo(array, arrayIndex); + this.queue.Enqueue(item); + this.sum += item; + this.squaredSum += item * item; + this.avg = this.sum / this.Count; + } - public long Peek() => m_queue.Peek(); + public void Clear() => this.queue.Clear(); - public long[] ToArray() => m_queue.ToArray(); + public bool Contains(long item) => this.queue.Contains(item); - public int Count => this.m_queue.Count; + public void Copylongo(long[] array, int arrayIndex) => this.queue.CopyTo(array, arrayIndex); - public object SyncRoot => ((ICollection)this.m_queue).SyncRoot; + public long Peek() => this.queue.Peek(); - public bool IsSynchronized => ((ICollection)this.m_queue).IsSynchronized; + public long[] ToArray() => this.queue.ToArray(); public void CopyTo(Array array, int index) { - ((ICollection)this.m_queue).CopyTo(array, index); + ((ICollection)this.queue).CopyTo(array, index); } public IEnumerator GetEnumerator() { - return ((IEnumerable)this.m_queue).GetEnumerator(); + return ((IEnumerable)this.queue).GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { - return ((IEnumerable)this.m_queue).GetEnumerator(); + return ((IEnumerable)this.queue).GetEnumerator(); } } } - diff --git a/PhiFailureDetector/PhiFailureDetector/PhiFailureDetector.cs b/PhiFailureDetector/PhiFailureDetector/PhiFailureDetector.cs index d18efdda..5fca5d7d 100644 --- a/PhiFailureDetector/PhiFailureDetector/PhiFailureDetector.cs +++ b/PhiFailureDetector/PhiFailureDetector/PhiFailureDetector.cs @@ -10,7 +10,12 @@ namespace PhiFailureDetector { public class PhiFailureDetector { - public delegate double PhiFunc(long timestamp, long lastTimestamp, IWithStatistics statistics); + private readonly LongIntervalHistory arrivalWindow; + private readonly long initialHeartbeatInterval; + private readonly IStopwatchProvider stopwatchProvider; + private readonly PhiFunc phiFunc; + + private long last; public PhiFailureDetector( int capacity, @@ -18,51 +23,25 @@ public PhiFailureDetector( IStopwatchProvider stopwatchProvider, PhiFunc phiFunc) { - m_arrivalWindow = new LongIntervalHistory(capacity); - m_initialHeartbeatInterval = initialHeartbeatInterval; - m_stopwatchProvider = stopwatchProvider; - m_phiFunc = phiFunc; + this.arrivalWindow = new LongIntervalHistory(capacity); + this.initialHeartbeatInterval = initialHeartbeatInterval; + this.stopwatchProvider = stopwatchProvider; + this.phiFunc = phiFunc; } - private readonly LongIntervalHistory m_arrivalWindow; - private readonly long m_initialHeartbeatInterval; - private readonly IStopwatchProvider m_stopwatchProvider; - private readonly PhiFunc m_phiFunc; - - private long m_last; - - public double Phi() - { - return m_phiFunc(m_stopwatchProvider.GetTimestamp(), m_last, m_arrivalWindow); - } - - public void Report() - { - var now = m_stopwatchProvider.GetTimestamp(); - m_last = now; - - if (m_arrivalWindow.Count == 0) - { - m_arrivalWindow.Enqueue(m_initialHeartbeatInterval); - } - else - { - var interval = now - m_last; - m_arrivalWindow.Enqueue(interval); - } - } + public delegate double PhiFunc(long timestamp, long lastTimestamp, IWithStatistics statistics); /** * https://issues.apache.org/jira/browse/CASSANDRA-2597 * Regular message transmissions experiencing typical random jitter will follow a normal distribution, * but since gossip messages from endpoint A to endpoint B are sent at random intervals, * they likely make up a Poisson process, making the exponential distribution appropriate. - * + * * P_later(t) = 1 - F(t) * P_later(t) = 1 - (1 - e^(-Lt)) - * + * * The maximum likelihood estimation for the rate parameter L is given by 1/mean - * + * * P_later(t) = 1 - (1 - e^(-t/mean)) * P_later(t) = e^(-t/mean) * phi(t) = -log10(P_later(t)) @@ -91,16 +70,36 @@ public static double Normal(long nowTimestamp, long lastTimestamp, IWithStatisti { var duration = nowTimestamp - lastTimestamp; var y = (duration - statistics.Avg) / statistics.StdDeviation; - var exp = Math.Exp(-y * (1.5976 + 0.070566 * y * y)); + var exp = Math.Exp(-y * (1.5976 + (0.070566 * y * y))); if (duration > statistics.Avg) { return -Math.Log10(exp / (1 + exp)); } else { - return -Math.Log10(1 - 1 / (1 + exp)); + return -Math.Log10(1 - (1 / (1 + exp))); + } + } + + public double Phi() + { + return this.phiFunc(this.stopwatchProvider.GetTimestamp(), this.last, this.arrivalWindow); + } + + public void Report() + { + var now = this.stopwatchProvider.GetTimestamp(); + this.last = now; + + if (this.arrivalWindow.Count == 0) + { + this.arrivalWindow.Enqueue(this.initialHeartbeatInterval); + } + else + { + var interval = now - this.last; + this.arrivalWindow.Enqueue(interval); } } } } - diff --git a/PhiFailureDetector/PhiFailureDetector/PhiFailureDetector.csproj b/PhiFailureDetector/PhiFailureDetector/PhiFailureDetector.csproj index 6d153689..2ab55344 100644 --- a/PhiFailureDetector/PhiFailureDetector/PhiFailureDetector.csproj +++ b/PhiFailureDetector/PhiFailureDetector/PhiFailureDetector.csproj @@ -11,6 +11,6 @@ - +