型の判別あれこれ
型の判別で早い方法はないものか調べてみた。
ソースと実行結果はドクソ長いので後に回して隔離。結果をまとめると、
IsTest 200 192 188 IsAssignableTest 1851 1829 1783 IsInstanceOfTest 764 802 825 IsSubclassOfTest 2947 2899 2857 EqualTest 125 122 120 EqualsTest 335 358 361 SwitchTest 212 228 223 DictionaryTest 245 169 172 DicIntPtrTest 167 167 177 DicArrayTest 136 132 140 CachedDicTest 131 129 143 CachedDicSwitchTest 148 146 157 CachedStringDicTest 189 191 192
3回繰り返してる。一回目はアセンブリのロードとか入っちゃってるっぽくて正確じゃないっぽい。
12個のクラスを判別するためにifを12回やってるけど、結局Typeの==が一番速い。継承関係とかないならこれで決まりだろう。Equalsは遅い。
isも演算子だけあって速い。継承関係も考慮する場合で事前に調べる型が分かってるならこれだろう。
Dictionaryもそこそこだが12個程度ではif連打の方が速いようだ。Dictionaryを使う場合KeyはTypeでいいみたいだ。
動的に継承関係も考慮して調べる場合に早い方法が見当たらない。IsInstanceOfTypeがインスタンスを持ってるならそこそこ速いようだ。
30個にしてみる。調べるのは見込みがありそうなのに絞ってみる。
IsTest 497 500 475 IsInstanceOfTest 1959 2024 2002 EqualTest 207 208 221 DictionaryTest 228 154 164 CachedDicSwitchTest 144 140 151
30個あるとif連打よりDictionaryがだいぶ速い。あとModule.GetTypeはモジュール内のクラスの数によってスピードが変わっているように見える
ソースと実行結果
using System; using System.Collections.Generic; using System.Linq; using System.Diagnostics; namespace TestModule { class Parent { } class Child1 : Parent { } class Child2 : Parent { } class Child3 : Parent { } class Child4 : Parent { } class Child5 : Child1 { } class Child6 : Child1 { } class Child7 : Child1 { } class Child8 : Child1 { } class Child9 : Child2 { } class Child10 : Child2 { } class Child11 : Child2 { } class Child12 : Child2 { } class Program { const int N = 12; Parent[] Generate() { var rand = new Random(); var module = typeof(Parent).Module; return Enumerable.Range(0,1000000) .Select( i => (Parent)Activator.CreateInstance( module.GetType("TestModule.Child" + (rand.Next(N) + 1)) ) ).ToArray(); } int[] IsTest(Parent[] parents) { int[] array = new int[N]; for (int i = 0; i < parents.Length; ++i) { var p = parents[i]; if (p is Child1) ++array[0]; if (p is Child2) ++array[1]; if (p is Child3) ++array[2]; if (p is Child4) ++array[3]; if (p is Child5) ++array[4]; if (p is Child6) ++array[5]; if (p is Child7) ++array[6]; if (p is Child8) ++array[7]; if (p is Child9) ++array[8]; if (p is Child10) ++array[9]; if (p is Child11) ++array[10]; if (p is Child12) ++array[11]; } return array; } int[] IsAssignableTest(Parent[] parents) { int[] array = new int[N]; for (int i = 0; i < parents.Length; ++i) { var p = parents[i].GetType(); if (typeof(Child1).IsAssignableFrom(p)) ++array[0]; if (typeof(Child2).IsAssignableFrom(p)) ++array[1]; if (typeof(Child3).IsAssignableFrom(p)) ++array[2]; if (typeof(Child4).IsAssignableFrom(p)) ++array[3]; if (typeof(Child5).IsAssignableFrom(p)) ++array[4]; if (typeof(Child6).IsAssignableFrom(p)) ++array[5]; if (typeof(Child7).IsAssignableFrom(p)) ++array[6]; if (typeof(Child8).IsAssignableFrom(p)) ++array[7]; if (typeof(Child9).IsAssignableFrom(p)) ++array[8]; if (typeof(Child10).IsAssignableFrom(p)) ++array[9]; if (typeof(Child11).IsAssignableFrom(p)) ++array[10]; if (typeof(Child12).IsAssignableFrom(p)) ++array[11]; } return array; } int[] IsInstanceOfTest(Parent[] parents) { int[] array = new int[N]; for (int i = 0; i < parents.Length; ++i) { var p = parents[i]; if (typeof(Child1).IsInstanceOfType(p)) ++array[0]; if (typeof(Child2).IsInstanceOfType(p)) ++array[1]; if (typeof(Child3).IsInstanceOfType(p)) ++array[2]; if (typeof(Child4).IsInstanceOfType(p)) ++array[3]; if (typeof(Child5).IsInstanceOfType(p)) ++array[4]; if (typeof(Child6).IsInstanceOfType(p)) ++array[5]; if (typeof(Child7).IsInstanceOfType(p)) ++array[6]; if (typeof(Child8).IsInstanceOfType(p)) ++array[7]; if (typeof(Child9).IsInstanceOfType(p)) ++array[8]; if (typeof(Child10).IsInstanceOfType(p)) ++array[9]; if (typeof(Child11).IsInstanceOfType(p)) ++array[10]; if (typeof(Child12).IsInstanceOfType(p)) ++array[11]; } return array; } int[] IsSubClassOfTest(Parent[] parents) { int[] array = new int[N]; for (int i = 0; i < parents.Length; ++i) { var p = parents[i].GetType(); if (p.IsSubclassOf(typeof(Child1))) ++array[0]; if (p.IsSubclassOf(typeof(Child2))) ++array[1]; if (p.IsSubclassOf(typeof(Child3))) ++array[2]; if (p.IsSubclassOf(typeof(Child4))) ++array[3]; if (p.IsSubclassOf(typeof(Child5))) ++array[4]; if (p.IsSubclassOf(typeof(Child6))) ++array[5]; if (p.IsSubclassOf(typeof(Child7))) ++array[6]; if (p.IsSubclassOf(typeof(Child8))) ++array[7]; if (p.IsSubclassOf(typeof(Child9))) ++array[8]; if (p.IsSubclassOf(typeof(Child10))) ++array[9]; if (p.IsSubclassOf(typeof(Child11))) ++array[10]; if (p.IsSubclassOf(typeof(Child12))) ++array[11]; } return array; } int[] EqualTest(Parent[] parents) { int[] array = new int[N]; for (int i = 0; i < parents.Length; ++i) { var p = parents[i].GetType(); if (typeof(Child1) == p) ++array[0]; if (typeof(Child2) == p) ++array[1]; if (typeof(Child3) == p) ++array[2]; if (typeof(Child4) == p) ++array[3]; if (typeof(Child5) == p) ++array[4]; if (typeof(Child6) == p) ++array[5]; if (typeof(Child7) == p) ++array[6]; if (typeof(Child8) == p) ++array[7]; if (typeof(Child9) == p) ++array[8]; if (typeof(Child10) == p) ++array[9]; if (typeof(Child11) == p) ++array[10]; if (typeof(Child12) == p) ++array[11]; } return array; } int[] EqualsTest(Parent[] parents) { int[] array = new int[N]; for (int i = 0; i < parents.Length; ++i) { var p = parents[i].GetType(); if (typeof(Child1).Equals(p)) ++array[0]; if (typeof(Child2).Equals(p)) ++array[1]; if (typeof(Child3).Equals(p)) ++array[2]; if (typeof(Child4).Equals(p)) ++array[3]; if (typeof(Child5).Equals(p)) ++array[4]; if (typeof(Child6).Equals(p)) ++array[5]; if (typeof(Child7).Equals(p)) ++array[6]; if (typeof(Child8).Equals(p)) ++array[7]; if (typeof(Child9).Equals(p)) ++array[8]; if (typeof(Child10).Equals(p)) ++array[9]; if (typeof(Child11).Equals(p)) ++array[10]; if (typeof(Child12).Equals(p)) ++array[11]; } return array; } int[] SwitchTest(Parent[] parents) { int[] array = new int[N]; for (int i = 0; i < parents.Length; ++i) { var n = parents[i].GetType().Name; switch (n) { case "Child1": ++array[0]; break; case "Child2": ++array[1]; break; case "Child3": ++array[2]; break; case "Child4": ++array[3]; break; case "Child5": ++array[4]; break; case "Child6": ++array[5]; break; case "Child7": ++array[6]; break; case "Child8": ++array[7]; break; case "Child9": ++array[8]; break; case "Child10": ++array[9]; break; case "Child11": ++array[10]; break; case "Child12": ++array[11]; break; } } return array; } int[] DictionaryTest(Parent[] parents) { var array = new int[N]; var d = new Dictionary<RuntimeTypeHandle, Action>(); d.Add(typeof(Child1).TypeHandle, () => ++array[0]); d.Add(typeof(Child2).TypeHandle, () => ++array[1]); d.Add(typeof(Child3).TypeHandle, () => ++array[2]); d.Add(typeof(Child4).TypeHandle, () => ++array[3]); d.Add(typeof(Child5).TypeHandle, () => ++array[4]); d.Add(typeof(Child6).TypeHandle, () => ++array[5]); d.Add(typeof(Child7).TypeHandle, () => ++array[6]); d.Add(typeof(Child8).TypeHandle, () => ++array[7]); d.Add(typeof(Child9).TypeHandle, () => ++array[8]); d.Add(typeof(Child10).TypeHandle, () => ++array[9]); d.Add(typeof(Child11).TypeHandle, () => ++array[10]); d.Add(typeof(Child12).TypeHandle, () => ++array[11]); for (int i = 0; i < parents.Length; ++i) { d[Type.GetTypeHandle(parents[i])](); } return array; } int[] DictionaryIntPtrTest(Parent[] parents) { var array = new int[N]; var d = new Dictionary<IntPtr, Action>(); d.Add(typeof(Child1).TypeHandle.Value, () => ++array[0]); d.Add(typeof(Child2).TypeHandle.Value, () => ++array[1]); d.Add(typeof(Child3).TypeHandle.Value, () => ++array[2]); d.Add(typeof(Child4).TypeHandle.Value, () => ++array[3]); d.Add(typeof(Child5).TypeHandle.Value, () => ++array[4]); d.Add(typeof(Child6).TypeHandle.Value, () => ++array[5]); d.Add(typeof(Child7).TypeHandle.Value, () => ++array[6]); d.Add(typeof(Child8).TypeHandle.Value, () => ++array[7]); d.Add(typeof(Child9).TypeHandle.Value, () => ++array[8]); d.Add(typeof(Child10).TypeHandle.Value, () => ++array[9]); d.Add(typeof(Child11).TypeHandle.Value, () => ++array[10]); d.Add(typeof(Child12).TypeHandle.Value, () => ++array[11]); for (int i = 0; i < parents.Length; ++i) { d[Type.GetTypeHandle(parents[i]).Value](); } return array; } int[] DictionaryArrayTest(Parent[] parents) { var array = new int[N]; var d = new Dictionary<RuntimeTypeHandle, int>(); d.Add(typeof(Child1).TypeHandle, 0); d.Add(typeof(Child2).TypeHandle, 1); d.Add(typeof(Child3).TypeHandle, 2); d.Add(typeof(Child4).TypeHandle, 3); d.Add(typeof(Child5).TypeHandle, 4); d.Add(typeof(Child6).TypeHandle, 5); d.Add(typeof(Child7).TypeHandle, 6); d.Add(typeof(Child8).TypeHandle, 7); d.Add(typeof(Child9).TypeHandle, 8); d.Add(typeof(Child10).TypeHandle, 9); d.Add(typeof(Child11).TypeHandle, 10); d.Add(typeof(Child12).TypeHandle, 11); for (int i = 0; i < parents.Length; ++i) { ++array[d[Type.GetTypeHandle(parents[i])]]; } return array; } int[] CachedDictionaryTest(Parent[] parents, Dictionary<RuntimeTypeHandle, int> d) { var array = new int[N]; for (int i = 0; i < parents.Length; ++i) { ++array[d[Type.GetTypeHandle(parents[i])]]; } return array; } int[] CachedDictionarySwitchTest(Parent[] parents, Dictionary<RuntimeTypeHandle, int> d) { var array = new int[N]; for (int i = 0; i < parents.Length; ++i) { var a = d[Type.GetTypeHandle(parents[i])]; switch (a) { case 0: ++array[0]; break; case 1: ++array[1]; break; case 2: ++array[2]; break; case 3: ++array[3]; break; case 4: ++array[4]; break; case 5: ++array[5]; break; case 6: ++array[6]; break; case 7: ++array[7]; break; case 8: ++array[8]; break; case 9: ++array[9]; break; case 10: ++array[10]; break; case 11: ++array[11]; break; } } return array; } int[] CachedStringDictionaryTest(Parent[] parents, Dictionary<string, int> d) { var array = new int[N]; for (int i = 0; i < parents.Length; ++i) { ++array[d[parents[i].GetType().Name]]; } return array; } void Do(Parent[] parents) { var sw = new Stopwatch(); sw.Reset(); sw.Start(); var isTest = IsTest(parents); sw.Stop(); Console.WriteLine("IsTest " + Tick(sw)); sw.Reset(); sw.Start(); var isAssignableTest = IsAssignableTest(parents); sw.Stop(); Console.WriteLine("IsAssignableTest " + Tick(sw)); sw.Reset(); sw.Start(); var isInstanceOfTest = IsInstanceOfTest(parents); sw.Stop(); Console.WriteLine("IsInstanceOfTest " + Tick(sw)); sw.Reset(); sw.Start(); var isSubclassOfTest = IsSubClassOfTest(parents); sw.Stop(); Console.WriteLine("IsSubclassOfTest " + Tick(sw)); sw.Reset(); sw.Start(); var equalTest = EqualTest(parents); sw.Stop(); Console.WriteLine("EqualTest " + Tick(sw)); sw.Reset(); sw.Start(); var equalsTest = EqualsTest(parents); sw.Stop(); Console.WriteLine("EqualsTest " + Tick(sw)); sw.Reset(); sw.Start(); var switchTest = SwitchTest(parents); sw.Stop(); Console.WriteLine("SwitchTest " + Tick(sw)); sw.Reset(); sw.Start(); var dicTest = DictionaryTest(parents); sw.Stop(); Console.WriteLine("DictionaryTest " + Tick(sw)); sw.Reset(); sw.Start(); var dicIntPtrTest = DictionaryIntPtrTest(parents); sw.Stop(); Console.WriteLine("DicIntPtrTest " + Tick(sw)); sw.Reset(); sw.Start(); var dicArrayTest = DictionaryArrayTest(parents); sw.Stop(); Console.WriteLine("DicArrayTest " + Tick(sw)); var d = new Dictionary<RuntimeTypeHandle, int>(); d.Add(typeof(Child1).TypeHandle, 0); d.Add(typeof(Child2).TypeHandle, 1); d.Add(typeof(Child3).TypeHandle, 2); d.Add(typeof(Child4).TypeHandle, 3); d.Add(typeof(Child5).TypeHandle, 4); d.Add(typeof(Child6).TypeHandle, 5); d.Add(typeof(Child7).TypeHandle, 6); d.Add(typeof(Child8).TypeHandle, 7); d.Add(typeof(Child9).TypeHandle, 8); d.Add(typeof(Child10).TypeHandle, 9); d.Add(typeof(Child11).TypeHandle, 10); d.Add(typeof(Child12).TypeHandle, 11); sw.Reset(); sw.Start(); var cachedTest = CachedDictionaryTest(parents,d); sw.Stop(); Console.WriteLine("CachedDicTest " + Tick(sw)); sw.Reset(); sw.Start(); var cachedDicSwitchTest = CachedDictionarySwitchTest(parents, d); sw.Stop(); Console.WriteLine("CachedDicSwitchTest " + Tick(sw)); var d2 = new Dictionary<string, int>(); d2.Add(typeof(Child1).Name, 0); d2.Add(typeof(Child2).Name, 1); d2.Add(typeof(Child3).Name, 2); d2.Add(typeof(Child4).Name, 3); d2.Add(typeof(Child5).Name, 4); d2.Add(typeof(Child6).Name, 5); d2.Add(typeof(Child7).Name, 6); d2.Add(typeof(Child8).Name, 7); d2.Add(typeof(Child9).Name, 8); d2.Add(typeof(Child10).Name, 9); d2.Add(typeof(Child11).Name, 10); d2.Add(typeof(Child12).Name, 11); sw.Reset(); sw.Start(); var cachedStringDicTest = CachedStringDictionaryTest(parents, d2); sw.Stop(); Console.WriteLine("CachedStringDicTest " + Tick(sw)); for (int i = 0; i < isTest.Length; ++i) { Console.WriteLine("{0} {1} {2} {3} {4} {5} {6} {7} {8} {9} {10} {11}", isTest[i], isAssignableTest[i], isInstanceOfTest[i], isSubclassOfTest[i],switchTest[i], dicTest[i], dicIntPtrTest[i], dicArrayTest[i], cachedTest[i], cachedStringDicTest[i], equalTest[i], equalsTest[i], cachedDicSwitchTest[i]); } } long Tick(Stopwatch sw) { return sw.ElapsedMilliseconds; } static void Main() { var p = new Program(); Stopwatch sw = new Stopwatch(); sw.Start(); var parents = p.Generate(); sw.Stop(); Console.WriteLine("Generate " + p.Tick(sw)); p.Do(parents); p.Do(parents); p.Do(parents); System.Windows.Forms.Application.Run(new Form1()); } } } Generate 13690 IsTest 200 IsAssignableTest 1851 IsInstanceOfTest 764 IsSubclassOfTest 2947 EqualTest 125 EqualsTest 335 SwitchTest 212 DictionaryTest 245 DicIntPtrTest 167 DicArrayTest 136 CachedDicTest 131 CachedDicSwitchTest 148 CachedStringDicTest 189 416466 416466 416466 332998 83468 83468 83468 83468 83468 83468 83468 83468 416291 416291 416291 332692 83599 83599 83599 83599 83599 83599 83599 83599 83665 83665 83665 0 83665 83665 83665 83665 83665 83665 83665 83665 83578 83578 83578 0 83578 83578 83578 83578 83578 83578 83578 83578 83253 83253 83253 0 83253 83253 83253 83253 83253 83253 83253 83253 83179 83179 83179 0 83179 83179 83179 83179 83179 83179 83179 83179 83200 83200 83200 0 83200 83200 83200 83200 83200 83200 83200 83200 83366 83366 83366 0 83366 83366 83366 83366 83366 83366 83366 83366 83486 83486 83486 0 83486 83486 83486 83486 83486 83486 83486 83486 82733 82733 82733 0 82733 82733 82733 82733 82733 82733 82733 82733 83211 83211 83211 0 83211 83211 83211 83211 83211 83211 83211 83211 83262 83262 83262 0 83262 83262 83262 83262 83262 83262 83262 83262 IsTest 192 IsAssignableTest 1829 IsInstanceOfTest 802 IsSubclassOfTest 2899 EqualTest 122 EqualsTest 358 SwitchTest 228 DictionaryTest 169 DicIntPtrTest 167 DicArrayTest 132 CachedDicTest 129 CachedDicSwitchTest 146 CachedStringDicTest 191 416466 416466 416466 332998 83468 83468 83468 83468 83468 83468 83468 83468 416291 416291 416291 332692 83599 83599 83599 83599 83599 83599 83599 83599 83665 83665 83665 0 83665 83665 83665 83665 83665 83665 83665 83665 83578 83578 83578 0 83578 83578 83578 83578 83578 83578 83578 83578 83253 83253 83253 0 83253 83253 83253 83253 83253 83253 83253 83253 83179 83179 83179 0 83179 83179 83179 83179 83179 83179 83179 83179 83200 83200 83200 0 83200 83200 83200 83200 83200 83200 83200 83200 83366 83366 83366 0 83366 83366 83366 83366 83366 83366 83366 83366 83486 83486 83486 0 83486 83486 83486 83486 83486 83486 83486 83486 82733 82733 82733 0 82733 82733 82733 82733 82733 82733 82733 82733 83211 83211 83211 0 83211 83211 83211 83211 83211 83211 83211 83211 83262 83262 83262 0 83262 83262 83262 83262 83262 83262 83262 83262 IsTest 188 スレッド 0x1c34c はコード 0 (0x0) で終了しました。 IsAssignableTest 1783 IsInstanceOfTest 825 IsSubclassOfTest 2857 EqualTest 120 EqualsTest 361 SwitchTest 223 DictionaryTest 172 DicIntPtrTest 177 DicArrayTest 140 CachedDicTest 143 CachedDicSwitchTest 157 CachedStringDicTest 192 416466 416466 416466 332998 83468 83468 83468 83468 83468 83468 83468 83468 416291 416291 416291 332692 83599 83599 83599 83599 83599 83599 83599 83599 83665 83665 83665 0 83665 83665 83665 83665 83665 83665 83665 83665 83578 83578 83578 0 83578 83578 83578 83578 83578 83578 83578 83578 83253 83253 83253 0 83253 83253 83253 83253 83253 83253 83253 83253 83179 83179 83179 0 83179 83179 83179 83179 83179 83179 83179 83179 83200 83200 83200 0 83200 83200 83200 83200 83200 83200 83200 83200 83366 83366 83366 0 83366 83366 83366 83366 83366 83366 83366 83366 83486 83486 83486 0 83486 83486 83486 83486 83486 83486 83486 83486 82733 82733 82733 0 82733 82733 82733 82733 82733 82733 82733 82733 83211 83211 83211 0 83211 83211 83211 83211 83211 83211 83211 83211 83262 83262 83262 0 83262 83262 83262 83262 83262 83262 83262 83262
30個版
using System; using System.Collections.Generic; using System.Linq; using System.Diagnostics; namespace TestModule2 { class Parent { } class Child1 : Parent { } class Child2 : Parent { } class Child3 : Parent { } class Child4 : Parent { } class Child5 : Child1 { } class Child6 : Child1 { } class Child7 : Child1 { } class Child8 : Child1 { } class Child9 : Child2 { } class Child10 : Child2 { } class Child11 : Child2 { } class Child12 : Child2 { } class Child13 : Child3 { } class Child14 : Child3 { } class Child15 : Child3 { } class Child16 : Child3 { } class Child17 : Child4 { } class Child18 : Child4 { } class Child19 : Child4 { } class Child20 : Child4 { } class Child21 : Child5 { } class Child22 : Child5 { } class Child23 : Child5 { } class Child24 : Child5 { } class Child25 : Child6 { } class Child26 : Child6 { } class Child27 : Child6 { } class Child28 : Child6 { } class Child29 : Child7 { } class Child30 : Child7 { } class Program2 { const int N = 30; Parent[] Generate() { var rand = new Random(); var module = typeof(Parent).Module; return Enumerable.Range(0,1000000) .Select( i => (Parent)Activator.CreateInstance( module.GetType("TestModule2.Child" + (rand.Next(N) + 1)) ) ).ToArray(); } int[] IsTest(Parent[] parents) { int[] array = new int[N]; for (int i = 0; i < parents.Length; ++i) { var p = parents[i]; if (p is Child1) ++array[0]; if (p is Child2) ++array[1]; if (p is Child3) ++array[2]; if (p is Child4) ++array[3]; if (p is Child5) ++array[4]; if (p is Child6) ++array[5]; if (p is Child7) ++array[6]; if (p is Child8) ++array[7]; if (p is Child9) ++array[8]; if (p is Child10) ++array[9]; if (p is Child11) ++array[10]; if (p is Child12) ++array[11]; if (p is Child13) ++array[12]; if (p is Child14) ++array[13]; if (p is Child15) ++array[14]; if (p is Child16) ++array[15]; if (p is Child17) ++array[16]; if (p is Child18) ++array[17]; if (p is Child19) ++array[18]; if (p is Child10) ++array[19]; if (p is Child21) ++array[20]; if (p is Child22) ++array[21]; if (p is Child23) ++array[22]; if (p is Child24) ++array[23]; if (p is Child25) ++array[24]; if (p is Child26) ++array[25]; if (p is Child27) ++array[26]; if (p is Child28) ++array[27]; if (p is Child29) ++array[28]; if (p is Child30) ++array[29]; } return array; } int[] IsInstanceOfTest(Parent[] parents) { int[] array = new int[N]; for (int i = 0; i < parents.Length; ++i) { var p = parents[i]; if (typeof(Child1).IsInstanceOfType(p)) ++array[0]; if (typeof(Child2).IsInstanceOfType(p)) ++array[1]; if (typeof(Child3).IsInstanceOfType(p)) ++array[2]; if (typeof(Child4).IsInstanceOfType(p)) ++array[3]; if (typeof(Child5).IsInstanceOfType(p)) ++array[4]; if (typeof(Child6).IsInstanceOfType(p)) ++array[5]; if (typeof(Child7).IsInstanceOfType(p)) ++array[6]; if (typeof(Child8).IsInstanceOfType(p)) ++array[7]; if (typeof(Child9).IsInstanceOfType(p)) ++array[8]; if (typeof(Child10).IsInstanceOfType(p)) ++array[9]; if (typeof(Child11).IsInstanceOfType(p)) ++array[10]; if (typeof(Child12).IsInstanceOfType(p)) ++array[11]; if (typeof(Child13).IsInstanceOfType(p)) ++array[12]; if (typeof(Child14).IsInstanceOfType(p)) ++array[13]; if (typeof(Child15).IsInstanceOfType(p)) ++array[14]; if (typeof(Child16).IsInstanceOfType(p)) ++array[15]; if (typeof(Child17).IsInstanceOfType(p)) ++array[16]; if (typeof(Child18).IsInstanceOfType(p)) ++array[17]; if (typeof(Child19).IsInstanceOfType(p)) ++array[18]; if (typeof(Child20).IsInstanceOfType(p)) ++array[19]; if (typeof(Child21).IsInstanceOfType(p)) ++array[20]; if (typeof(Child22).IsInstanceOfType(p)) ++array[21]; if (typeof(Child23).IsInstanceOfType(p)) ++array[22]; if (typeof(Child24).IsInstanceOfType(p)) ++array[23]; if (typeof(Child25).IsInstanceOfType(p)) ++array[24]; if (typeof(Child26).IsInstanceOfType(p)) ++array[25]; if (typeof(Child27).IsInstanceOfType(p)) ++array[26]; if (typeof(Child28).IsInstanceOfType(p)) ++array[27]; if (typeof(Child29).IsInstanceOfType(p)) ++array[28]; if (typeof(Child30).IsInstanceOfType(p)) ++array[29]; } return array; } int[] EqualTest(Parent[] parents) { int[] array = new int[N]; for (int i = 0; i < parents.Length; ++i) { var p = parents[i].GetType(); if (typeof(Child1) == p) ++array[0]; if (typeof(Child2) == p) ++array[1]; if (typeof(Child3) == p) ++array[2]; if (typeof(Child4) == p) ++array[3]; if (typeof(Child5) == p) ++array[4]; if (typeof(Child6) == p) ++array[5]; if (typeof(Child7) == p) ++array[6]; if (typeof(Child8) == p) ++array[7]; if (typeof(Child9) == p) ++array[8]; if (typeof(Child10) == p) ++array[9]; if (typeof(Child11) == p) ++array[10]; if (typeof(Child12) == p) ++array[11]; if (typeof(Child13) == p) ++array[12]; if (typeof(Child14) == p) ++array[13]; if (typeof(Child15) == p) ++array[14]; if (typeof(Child16) == p) ++array[15]; if (typeof(Child17) == p) ++array[16]; if (typeof(Child18) == p) ++array[17]; if (typeof(Child19) == p) ++array[18]; if (typeof(Child20) == p) ++array[19]; if (typeof(Child21) == p) ++array[20]; if (typeof(Child22) == p) ++array[21]; if (typeof(Child23) == p) ++array[22]; if (typeof(Child24) == p) ++array[23]; if (typeof(Child25) == p) ++array[24]; if (typeof(Child26) == p) ++array[25]; if (typeof(Child27) == p) ++array[26]; if (typeof(Child28) == p) ++array[27]; if (typeof(Child29) == p) ++array[28]; if (typeof(Child30) == p) ++array[29]; } return array; } int[] DictionaryTest(Parent[] parents) { var array = new int[N]; var d = new Dictionary<RuntimeTypeHandle, Action>(); d.Add(typeof(Child1).TypeHandle, () => ++array[0]); d.Add(typeof(Child2).TypeHandle, () => ++array[1]); d.Add(typeof(Child3).TypeHandle, () => ++array[2]); d.Add(typeof(Child4).TypeHandle, () => ++array[3]); d.Add(typeof(Child5).TypeHandle, () => ++array[4]); d.Add(typeof(Child6).TypeHandle, () => ++array[5]); d.Add(typeof(Child7).TypeHandle, () => ++array[6]); d.Add(typeof(Child8).TypeHandle, () => ++array[7]); d.Add(typeof(Child9).TypeHandle, () => ++array[8]); d.Add(typeof(Child10).TypeHandle, () => ++array[9]); d.Add(typeof(Child11).TypeHandle, () => ++array[10]); d.Add(typeof(Child12).TypeHandle, () => ++array[11]); d.Add(typeof(Child13).TypeHandle, () => ++array[12]); d.Add(typeof(Child14).TypeHandle, () => ++array[13]); d.Add(typeof(Child15).TypeHandle, () => ++array[14]); d.Add(typeof(Child16).TypeHandle, () => ++array[15]); d.Add(typeof(Child17).TypeHandle, () => ++array[16]); d.Add(typeof(Child18).TypeHandle, () => ++array[17]); d.Add(typeof(Child19).TypeHandle, () => ++array[18]); d.Add(typeof(Child20).TypeHandle, () => ++array[19]); d.Add(typeof(Child21).TypeHandle, () => ++array[20]); d.Add(typeof(Child22).TypeHandle, () => ++array[21]); d.Add(typeof(Child23).TypeHandle, () => ++array[22]); d.Add(typeof(Child24).TypeHandle, () => ++array[23]); d.Add(typeof(Child25).TypeHandle, () => ++array[24]); d.Add(typeof(Child26).TypeHandle, () => ++array[25]); d.Add(typeof(Child27).TypeHandle, () => ++array[26]); d.Add(typeof(Child28).TypeHandle, () => ++array[27]); d.Add(typeof(Child29).TypeHandle, () => ++array[28]); d.Add(typeof(Child30).TypeHandle, () => ++array[29]); for (int i = 0; i < parents.Length; ++i) { d[Type.GetTypeHandle(parents[i])](); } return array; } int[] CachedDictionarySwitchTest(Parent[] parents, Dictionary<RuntimeTypeHandle, int> d) { var array = new int[N]; for (int i = 0; i < parents.Length; ++i) { var a = d[Type.GetTypeHandle(parents[i])]; switch (a) { case 0: ++array[0]; break; case 1: ++array[1]; break; case 2: ++array[2]; break; case 3: ++array[3]; break; case 4: ++array[4]; break; case 5: ++array[5]; break; case 6: ++array[6]; break; case 7: ++array[7]; break; case 8: ++array[8]; break; case 9: ++array[9]; break; case 10: ++array[10]; break; case 11: ++array[11]; break; case 12: ++array[12]; break; case 13: ++array[13]; break; case 14: ++array[14]; break; case 15: ++array[15]; break; case 16: ++array[16]; break; case 17: ++array[17]; break; case 18: ++array[18]; break; case 19: ++array[19]; break; case 20: ++array[20]; break; case 21: ++array[21]; break; case 22: ++array[22]; break; case 23: ++array[23]; break; case 24: ++array[24]; break; case 25: ++array[25]; break; case 26: ++array[26]; break; case 27: ++array[27]; break; case 28: ++array[28]; break; case 29: ++array[29]; break; case 30: ++array[30]; break; } } return array; } void Do(Parent[] parents) { var sw = new Stopwatch(); sw.Reset(); sw.Start(); var isTest = IsTest(parents); sw.Stop(); Console.WriteLine("IsTest " + Tick(sw)); sw.Reset(); sw.Start(); var isInstanceOfTest = IsInstanceOfTest(parents); sw.Stop(); Console.WriteLine("IsInstanceOfTest " + Tick(sw)); sw.Reset(); sw.Start(); var equalTest = EqualTest(parents); sw.Stop(); Console.WriteLine("EqualTest " + Tick(sw)); sw.Reset(); sw.Start(); var dicTest = DictionaryTest(parents); sw.Stop(); Console.WriteLine("DictionaryTest " + Tick(sw)); var d = new Dictionary<RuntimeTypeHandle, int>(); d.Add(typeof(Child1).TypeHandle, 0); d.Add(typeof(Child2).TypeHandle, 1); d.Add(typeof(Child3).TypeHandle, 2); d.Add(typeof(Child4).TypeHandle, 3); d.Add(typeof(Child5).TypeHandle, 4); d.Add(typeof(Child6).TypeHandle, 5); d.Add(typeof(Child7).TypeHandle, 6); d.Add(typeof(Child8).TypeHandle, 7); d.Add(typeof(Child9).TypeHandle, 8); d.Add(typeof(Child10).TypeHandle, 9); d.Add(typeof(Child11).TypeHandle, 10); d.Add(typeof(Child12).TypeHandle, 11); d.Add(typeof(Child13).TypeHandle, 12); d.Add(typeof(Child14).TypeHandle, 13); d.Add(typeof(Child15).TypeHandle, 14); d.Add(typeof(Child16).TypeHandle, 15); d.Add(typeof(Child17).TypeHandle, 16); d.Add(typeof(Child18).TypeHandle, 17); d.Add(typeof(Child19).TypeHandle, 18); d.Add(typeof(Child20).TypeHandle, 19); d.Add(typeof(Child21).TypeHandle, 20); d.Add(typeof(Child22).TypeHandle, 21); d.Add(typeof(Child23).TypeHandle, 22); d.Add(typeof(Child24).TypeHandle, 23); d.Add(typeof(Child25).TypeHandle, 24); d.Add(typeof(Child26).TypeHandle, 25); d.Add(typeof(Child27).TypeHandle, 26); d.Add(typeof(Child28).TypeHandle, 27); d.Add(typeof(Child29).TypeHandle, 28); d.Add(typeof(Child30).TypeHandle, 29); sw.Reset(); sw.Start(); var cachedDicSwitchTest = CachedDictionarySwitchTest(parents, d); sw.Stop(); Console.WriteLine("CachedDicSwitchTest " + Tick(sw)); for (int i = 0; i < isTest.Length; ++i) { Console.WriteLine("{0} {1} {2} {3} {4}", isTest[i],isInstanceOfTest[i], dicTest[i], equalTest[i], cachedDicSwitchTest[i]); } } long Tick(Stopwatch sw) { return sw.ElapsedMilliseconds; } static void Main() { var p = new Program2(); Stopwatch sw = new Stopwatch(); sw.Start(); var parents = p.Generate(); sw.Stop(); Console.WriteLine("Generate " + p.Tick(sw)); p.Do(parents); p.Do(parents); p.Do(parents); System.Windows.Forms.Application.Run(new System.Windows.Forms.Form()); } } } Generate 23381 IsTest 497 IsInstanceOfTest 1959 EqualTest 207 DictionaryTest 228 CachedDicSwitchTest 144 499426 499426 33205 33205 33205 166155 166155 33245 33245 33245 167171 167171 33346 33346 33346 167248 167248 33541 33541 33541 166226 166226 33158 33158 33158 166204 166204 33149 33149 33149 100003 100003 33316 33316 33316 33788 33788 33788 33788 33788 32968 32968 32968 32968 32968 33299 33299 33299 33299 33299 33195 33195 33195 33195 33195 33448 33448 33448 33448 33448 33585 33585 33585 33585 33585 33434 33434 33434 33434 33434 33373 33373 33373 33373 33373 33433 33433 33433 33433 33433 33618 33618 33618 33618 33618 33424 33424 33424 33424 33424 33325 33325 33325 33325 33325 33299 33340 33340 33340 33340 33443 33443 33443 33443 33443 33167 33167 33167 33167 33167 33257 33257 33257 33257 33257 33201 33201 33201 33201 33201 33151 33151 33151 33151 33151 33426 33426 33426 33426 33426 33483 33483 33483 33483 33483 32995 32995 32995 32995 32995 33543 33543 33543 33543 33543 33144 33144 33144 33144 33144 IsTest 500 IsInstanceOfTest 2024 EqualTest 208 DictionaryTest 154 CachedDicSwitchTest 140 499426 499426 33205 33205 33205 166155 166155 33245 33245 33245 167171 167171 33346 33346 33346 167248 167248 33541 33541 33541 166226 166226 33158 33158 33158 166204 166204 33149 33149 33149 100003 100003 33316 33316 33316 33788 33788 33788 33788 33788 32968 32968 32968 32968 32968 33299 33299 33299 33299 33299 33195 33195 33195 33195 33195 33448 33448 33448 33448 33448 33585 33585 33585 33585 33585 33434 33434 33434 33434 33434 33373 33373 33373 33373 33373 33433 33433 33433 33433 33433 33618 33618 33618 33618 33618 33424 33424 33424 33424 33424 33325 33325 33325 33325 33325 33299 33340 33340 33340 33340 33443 33443 33443 33443 33443 33167 33167 33167 33167 33167 33257 33257 33257 33257 33257 33201 33201 33201 33201 33201 33151 33151 33151 33151 33151 33426 33426 33426 33426 33426 33483 33483 33483 33483 33483 32995 32995 32995 32995 32995 33543 33543 33543 33543 33543 33144 33144 33144 33144 33144 IsTest 475 IsInstanceOfTest 2002 EqualTest 221 DictionaryTest 164 CachedDicSwitchTest 151 499426 499426 33205 33205 33205 166155 166155 33245 33245 33245 167171 167171 33346 33346 33346 167248 167248 33541 33541 33541 166226 166226 33158 33158 33158 166204 166204 33149 33149 33149 100003 100003 33316 33316 33316 33788 33788 33788 33788 33788 32968 32968 32968 32968 32968 33299 33299 33299 33299 33299 33195 33195 33195 33195 33195 33448 33448 33448 33448 33448 33585 33585 33585 33585 33585 33434 33434 33434 33434 33434 33373 33373 33373 33373 33373 33433 33433 33433 33433 33433 33618 33618 33618 33618 33618 33424 33424 33424 33424 33424 33325 33325 33325 33325 33325 33299 33340 33340 33340 33340 33443 33443 33443 33443 33443 33167 33167 33167 33167 33167 33257 33257 33257 33257 33257 33201 33201 33201 33201 33201 33151 33151 33151 33151 33151 33426 33426 33426 33426 33426 33483 33483 33483 33483 33483 32995 32995 32995 32995 32995 33543 33543 33543 33543 33543 33144 33144 33144 33144 33144 スレッド 0x1d0ec はコード 0 (0x0) で終了しました。
|