Enum.HasFlagの速度
google先生が、Enum.HasFlagはBoxing/Unboxingが発生するので遅い、とおっしゃるので、速度を計ってみた。ついでに、Parallelも使ってみた。
for版
回 数 | bit演算 | HasFlag | 総検査時間 |
---|---|---|---|
1,000,000 | 18 | 148 | 1,673 |
10,000,000 | 169 | 1,299 | 14,689 |
100,000,000 | 1,688 | 12,756 | 144,267 |
総じて、8倍くらいの時間がかかるようだ。
Parallelで回してみると、総検査時間が1/3くらいになる。
bit演算とHasFlagの速度比が、4倍くらいに縮まっているのは謎だが。
Parallel.For版
回 数 | bit演算 | HasFlag | 総検査時間 |
---|---|---|---|
1,000,000 | 14 | 55 | 696 |
10,000,000 | 106 | 492 | 5,552 |
100,000,000 | 835 | 3,501 | 47,213 |
for版のタスクマネージャ
Parallel.For版のタスクマネージャ
Parallelのほうが、CPUをまんべんなく使っているのがわかる。
namespace EnumHasFlagTest { [Flags] public enum TestFlag { A = 1, B = 2, C = 4, D = 8, } class Program { static long Meas(int count, Action func) { var sw = Stopwatch.StartNew(); for (int i = 0; i < count; i++) { func(); } return sw.ElapsedMilliseconds; } static void FuncBitComp() { var flags = TestFlag.B | TestFlag.D; var a1 = (flags & TestFlag.A) == TestFlag.A; var a2 = (flags & TestFlag.B) == TestFlag.B; var a3 = (flags & TestFlag.C) == TestFlag.C; var a4 = (flags & TestFlag.D) == TestFlag.D; } static void FuncHasFlag() { var flags = TestFlag.B | TestFlag.D; var a1 = flags.HasFlag(TestFlag.A); var a2 = flags.HasFlag(TestFlag.B); var a3 = flags.HasFlag(TestFlag.C); var a4 = flags.HasFlag(TestFlag.D); } static void Main(string[] args) { int count = 100000000; long a = 0, b = 0; var sw = Stopwatch.StartNew(); //// Parallel.For版 Parallel.For(0, 10, (x) => { a += Meas(count, FuncBitComp); b += Meas(count, FuncHasFlag); }); //// for版 //for(int i = 0; i < 10; i++) //{ // a += Meas(count, FuncBitComp); // b += Meas(count, FuncHasFlag); //} Console.WriteLine("{0}ms", sw.ElapsedMilliseconds); Console.WriteLine("BitComp={0}", a / 10); Console.WriteLine("HasFlag={0}", b / 10); Console.ReadLine(); } } }