Skip to content

Instantly share code, notes, and snippets.

@Pzixel
Created April 19, 2019 19:37
Show Gist options
  • Save Pzixel/e05d220629bb30a9a1746822cfa3ed27 to your computer and use it in GitHub Desktop.
Save Pzixel/e05d220629bb30a9a1746822cfa3ed27 to your computer and use it in GitHub Desktop.
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Security.Cryptography;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
namespace ConsoleApp7
{
[CoreJob]
[RPlotExporter, RankColumn]
public class EnumTryParse
{
private SHA256 sha256 = SHA256.Create();
private MD5 md5 = MD5.Create();
private string[] data;
[Params(1000, 10000)]
public int N;
[GlobalSetup]
public void Setup()
{
string[] variants = Enum.GetNames(typeof(Foo)).Concat(new[]
{
"111111111111111111111111111111",
"222222222222222222222222222222",
"333333333333333333333333333333",
"444444444444444444444444444444",
"555555555555555555555555555555",
"666666666666666666666666666666",
"777777777777777777777777777777",
"888888888888888888888888888888",
"999999999999999999999999999999",
}).ToArray();
Shuffle(variants);
data = Enumerable.Range(1, N).Select(i => variants[i % variants.Length]).ToArray();
}
static void Shuffle<T>(T[] a)
{
Random rand = new Random();
for (int i = a.Length - 1; i > 0; i--)
{
int j = rand.Next(0, i + 1);
T tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
}
[Benchmark]
public bool[] EnumParse() => data.Select(x => Enum.TryParse(typeof(Foo), x, out _)).ToArray();
[Benchmark]
public Foo?[] ExprParse() => data.Select(EnumHelper.TryParse<Foo>).ToArray();
}
public enum Foo
{
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = 1,
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb = 2,
cccccccccccccccccccccccccccccc = 3,
dddddddddddddddddddddddddddddd = 4,
eeeeeeeeeeeeeeeeeeeeeeeeeeeeee = 5,
ffffffffffffffffffffffffffffff = 6,
gggggggggggggggggggggggggggggg = 7,
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhh = 8,
iiiiiiiiiiiiiiiiiiiiiiiiiiiiii = 9,
jjjjjjjjjjjjjjjjjjjjjjjjjjjjjj = 10,
kkkkkkkkkkkkkkkkkkkkkkkkkkkkkk = 11,
llllllllllllllllllllllllllllll = 12,
mmmmmmmmmmmmmmmmmmmmmmmmmmmmmm = 13,
nnnnnnnnnnnnnnnnnnnnnnnnnnnnnn = 14,
oooooooooooooooooooooooooooooo = 15,
pppppppppppppppppppppppppppppp = 16,
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqq = 17,
rrrrrrrrrrrrrrrrrrrrrrrrrrrrrr = 18,
ssssssssssssssssssssssssssssss = 19,
tttttttttttttttttttttttttttttt = 20,
uuuuuuuuuuuuuuuuuuuuuuuuuuuuuu = 21,
vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv = 22,
wwwwwwwwwwwwwwwwwwwwwwwwwwwwww = 23,
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx = 24,
yyyyyyyyyyyyyyyyyyyyyyyyyyyyyy = 25,
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz = 26,
}
class Program
{
static void Main(string[] args)
{
var summary = BenchmarkRunner.Run<EnumTryParse>();
}
}
class EnumHelper
{
private static class FnHolder<T> where T : struct, Enum
{
public static Func<string, T?> TryParseImpl = GetTryParse();
private static Func<string, T?> GetTryParse()
{
var parameter = Expression.Parameter(typeof(string));
var label = Expression.Label();
var result = Expression.Variable(typeof(T?));
var members = Enum.GetNames(typeof(T));
var ctor = result.Type.GetConstructor(new[] { typeof(T) });
var switchCases = members.Select(m => Expression.SwitchCase(
Expression.Block(
Expression.Assign(result, Expression.New(ctor, Expression.Constant(Enum.Parse(typeof(T), m)))),
Expression.Break(label)),
Expression.Constant(m)
)).ToArray();
SwitchExpression switchExpr =
Expression.Switch(
parameter,
Expression.Block(
Expression.Assign(result, Expression.Default(typeof(T?))),
Expression.Break(label)),
switchCases
);
var lambda = Expression.Lambda<Func<string, T?>>(Expression.Block(new[] { result }, switchExpr, Expression.Label(label), result), parameter);
return lambda.Compile();
}
}
public static T? TryParse<T>(string value) where T : struct, Enum => FnHolder<T>.TryParseImpl(value);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment