diff --git a/BitFaster.Caching.HitRateAnalysis/BitFaster.Caching.HitRateAnalysis.csproj b/BitFaster.Caching.HitRateAnalysis/BitFaster.Caching.HitRateAnalysis.csproj index 43aa85f5..98c2c77c 100644 --- a/BitFaster.Caching.HitRateAnalysis/BitFaster.Caching.HitRateAnalysis.csproj +++ b/BitFaster.Caching.HitRateAnalysis/BitFaster.Caching.HitRateAnalysis.csproj @@ -1,4 +1,4 @@ - + Exe @@ -13,10 +13,14 @@ 1701;1702,CS8002 + + + + - + NU1701 diff --git a/BitFaster.Caching.HitRateAnalysis/Zipfian/Runner.cs b/BitFaster.Caching.HitRateAnalysis/Zipfian/Runner.cs index 82cf72ac..b9acc04d 100644 --- a/BitFaster.Caching.HitRateAnalysis/Zipfian/Runner.cs +++ b/BitFaster.Caching.HitRateAnalysis/Zipfian/Runner.cs @@ -5,6 +5,7 @@ using System.Text; using System.Threading.Tasks; using BitFaster.Caching.Lru; +using BitFaster.Caching.ThroughputAnalysis; using MathNet.Numerics; using MathNet.Numerics.Distributions; @@ -58,8 +59,7 @@ public static void Run() { Console.WriteLine($"Generating Zipfian distribution with {sampleCount} samples, s = {sValues[index]}, N = {n}"); var sw = Stopwatch.StartNew(); - zipdfDistribution[index] = new int[sampleCount]; - Zipf.Samples(zipdfDistribution[index], sValues[index], n); + zipdfDistribution[index] = FastZipf.Generate(new Random(666), sampleCount, sValues[index], n); Console.WriteLine($"Took {sw.Elapsed} for s = {sValues[index]}."); }); diff --git a/BitFaster.Caching.ThroughputAnalysis/FastZipf.cs b/BitFaster.Caching.ThroughputAnalysis/FastZipf.cs new file mode 100644 index 00000000..731fab80 --- /dev/null +++ b/BitFaster.Caching.ThroughputAnalysis/FastZipf.cs @@ -0,0 +1,54 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using MathNet.Numerics; + +namespace BitFaster.Caching.ThroughputAnalysis +{ + // produces the same output as MathNet.Numerics Zipf.Samples(random, samples[], s, n) + // but about 20x faster. + public class FastZipf + { + static Random srandom = new Random(666); + + public static int[] Generate(Random random, int sampleCount, double s, int n) + { + double[] num = new double[sampleCount]; + int[] samples = new int[sampleCount]; + + for (int i = 0; i < sampleCount; i++) + { + while (num[i] == 0.0) + { + num[i] = random.NextDouble(); + } + } + + double num2 = 1.0 / SpecialFunctions.GeneralHarmonic(n, s); + + Parallel.ForEach(Enumerable.Range(0, samples.Length), (x, j) => + { + double num3 = 0.0; + int i; + + for (i = 1; i <= n; i++) + { + num3 += num2 / Math.Pow(i, s); + if (num3 >= num[x]) + { + break; + } + } + + samples[x] = i; + }); + + return samples; + } + + public static int[] Generate(int sampleCount, double s, int n) + { + return Generate(srandom, sampleCount, s, n); + } + } +} diff --git a/BitFaster.Caching.ThroughputAnalysis/Program.cs b/BitFaster.Caching.ThroughputAnalysis/Program.cs index ec7c1f04..5a0bc06b 100644 --- a/BitFaster.Caching.ThroughputAnalysis/Program.cs +++ b/BitFaster.Caching.ThroughputAnalysis/Program.cs @@ -1,5 +1,9 @@ using System; +using System.ComponentModel.DataAnnotations; +using System.Diagnostics; using BitFaster.Caching.ThroughputAnalysis; +using Iced.Intel; +using MathNet.Numerics.Distributions; Host.PrintInfo(); diff --git a/BitFaster.Caching.ThroughputAnalysis/ThroughputBenchConfig.cs b/BitFaster.Caching.ThroughputAnalysis/ThroughputBenchConfig.cs index 7b6fcd2b..acc5943b 100644 --- a/BitFaster.Caching.ThroughputAnalysis/ThroughputBenchConfig.cs +++ b/BitFaster.Caching.ThroughputAnalysis/ThroughputBenchConfig.cs @@ -25,10 +25,7 @@ public ZipfConfig(int iterations, int sampleCount, double s, int n) { this.iterations = iterations; - Random random = new Random(666); - - samples = new int[sampleCount]; - Zipf.Samples(random, samples, s, n); + samples = FastZipf.Generate(sampleCount, s, n); } public int Iterations => iterations;