Created
May 15, 2019 06:57
-
-
Save arphox/4b7b8bb8ba2ee27909975254ae8e3fd3 to your computer and use it in GitHub Desktop.
Enum.HasFlag performance loss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Based on https://stackoverflow.com/q/7368652/4215389 | |
using System; | |
using System.Collections.Generic; | |
using System.Diagnostics; | |
using System.Linq; | |
namespace app | |
{ | |
public class Program | |
{ | |
[Flags] | |
public enum Test | |
{ | |
Flag1 = 1, | |
Flag2 = 2, | |
Flag3 = 4, | |
Flag4 = 8 | |
} | |
static int num = 0; | |
static Random rand; | |
static void Main(string[] args) | |
{ | |
int seed = (int)DateTime.UtcNow.Ticks; | |
var st1 = new SpeedTest(delegate | |
{ | |
Test t = Test.Flag1; | |
t |= (Test)rand.Next(1, 9); | |
if (t.HasFlag(Test.Flag4)) | |
num++; | |
}); | |
var st2 = new SpeedTest(delegate | |
{ | |
Test t = Test.Flag1; | |
t |= (Test)rand.Next(1, 9); | |
if (CustomHasFlag(t, Test.Flag4)) | |
num++; | |
}); | |
rand = new Random(seed); | |
st1.Test(); | |
rand = new Random(seed); | |
st2.Test(); | |
Console.WriteLine("Random to prevent optimizing out things {0}", num); | |
Console.WriteLine("HasFlag: {0}ms {1}ms {2}ms", st1.Min, st1.Average, st1.Max); | |
Console.WriteLine("Bitwise: {0}ms {1}ms {2}ms", st2.Min, st2.Average, st2.Max); | |
Console.ReadLine(); | |
} | |
static bool CustomHasFlag(Test flags, Test flag) | |
{ | |
return (flags & flag) != 0; | |
} | |
} | |
[DebuggerDisplay("Average = {Average}")] | |
class SpeedTest | |
{ | |
public int Iterations { get; set; } | |
public int Times { get; set; } | |
public List<Stopwatch> Watches { get; set; } | |
public Action Function { get; set; } | |
public long Min { get { return Watches.Min(s => s.ElapsedMilliseconds); } } | |
public long Max { get { return Watches.Max(s => s.ElapsedMilliseconds); } } | |
public double Average { get { return Watches.Average(s => s.ElapsedMilliseconds); } } | |
public SpeedTest(Action func) | |
{ | |
Times = 100; | |
Iterations = 1000000; | |
Function = func; | |
Watches = new List<Stopwatch>(); | |
} | |
public void Test() | |
{ | |
Watches.Clear(); | |
for (int i = 0; i < Times; i++) | |
{ | |
var sw = Stopwatch.StartNew(); | |
for (int o = 0; o < Iterations; o++) | |
{ | |
Function(); | |
} | |
sw.Stop(); | |
Watches.Add(sw); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Shared on Medium, don't delete!