using System; | |
using System.Collections.Concurrent; | |
using System.Collections.Generic; | |
using System.Linq; | |
using BenchmarkDotNet.Attributes; | |
using BenchmarkDotNet.Running; | |
[CoreJob] | |
//[MemoryDiagnoser] | |
//[InProcess()] | |
public class Strings | |
{ | |
//For "find nearest" | |
private const int Entries = 20; | |
private const int StepSize = 60; | |
private static readonly int[] _acceptableSeconds = | |
Enumerable.Range(1, Entries).Select(seconds => seconds * StepSize).ToArray(); | |
private static readonly string[] _fuckYouImATrain = | |
_acceptableSeconds.Select(seconds => $"public,max-age={seconds},must-revalidate").ToArray(); | |
//For the dictionary lookup | |
private ConcurrentDictionary<int, string> LittleShopOfHorrors = new ConcurrentDictionary<int, string>(); | |
//For LastCache | |
private int _lastSeconds = 3600; | |
private string _lastHeader = "public,max-age=3600,must-revalidate"; | |
[Benchmark] | |
public string Literal() => "public,max-age=3600,must-revalidate"; | |
[Benchmark(Baseline = true)] | |
[ArgumentsSource(nameof(PassingInts))] | |
public string BlingString(int seconds) => $"public,max-age={seconds},must-revalidate"; | |
[Benchmark] | |
[ArgumentsSource(nameof(PassingInts))] | |
public string LookupDictionary(int seconds) => | |
LittleShopOfHorrors.GetOrAdd(seconds, s => $"public,max-age={s},must-revalidate"); | |
[Benchmark()] | |
[ArgumentsSource(nameof(PassingInts))] | |
public string LastCache(int seconds) | |
{ | |
if (_lastSeconds != seconds) | |
{ | |
_lastSeconds = seconds; | |
_lastHeader = $"public,max-age={seconds},must-revalidate"; | |
} | |
return _lastHeader; | |
} | |
[Benchmark] | |
[ArgumentsSource(nameof(PassingInts))] | |
public string FindNearest(int seconds) | |
{ | |
var idx = Array.BinarySearch(_acceptableSeconds, RoundToNearest(seconds, StepSize)); | |
if (idx > -1) | |
return _fuckYouImATrain[idx]; | |
return ~idx < Entries ? _fuckYouImATrain[~idx] : _fuckYouImATrain[Entries - 1]; | |
} | |
private static int RoundToNearest(int value, int step) => ((value + (step / 2)) / step) * step; | |
[Benchmark] | |
[ArgumentsSource(nameof(PassingEnums))] | |
public string LiteralByChoice(CacheLengths cacheLength) | |
{ | |
switch (cacheLength) | |
{ | |
case CacheLengths.Short: | |
return "public,max-age=60,must-revalidate"; | |
case CacheLengths.Medium: | |
return "public,max-age=3600,must-revalidate"; | |
case CacheLengths.Long: | |
return "public,max-age=86400,must-revalidate"; | |
default: | |
return "public,max-age=0"; | |
} | |
} | |
public IEnumerable<int> PassingInts() | |
{ | |
yield return 60; | |
yield return 60 * 60; | |
yield return 60 * 60 * 24; | |
} | |
public IEnumerable<CacheLengths> PassingEnums() | |
{ | |
yield return CacheLengths.Short; | |
yield return CacheLengths.Medium; | |
yield return CacheLengths.Long; | |
} | |
public enum CacheLengths | |
{ | |
Short = 60, | |
Medium = 60 * 60, | |
Long = 60 * 60 * 24 | |
} | |
} | |
public class Program | |
{ | |
public static void Main(string[] args) | |
{ | |
var summary = BenchmarkRunner.Run<Strings>(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment