Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Ok so I was chatting about this with someone and decided to test this more. As far as I can tell, the performance of <code>as</code> and <code>is</code> are both very good, compared to testing your own member or function to store type information.</p> <p>I used <code>Stopwatch</code>, which I just learned may not be the most reliable approach, so I also tried <code>UtcNow</code>. Later, I also tried Processor time approach which seems similar to <code>UtcNow</code> including unpredictable create times. I also tried making the base class non-abstract with no virtuals but it didn't seem to have a significant effect.</p> <p>I ran this on a Quad Q6600 with 16GB RAM. Even with 50mil iterations, the numbers still bounce around +/- 50 or so millisec so I wouldn't read too much into the minor differences.</p> <p>It was interesting to see that x64 created faster but executed as/is slower than x86</p> <p><strong>x64 Release Mode:</strong> <br /> Stopwatch: <br /> As: 561ms<br /> Is: 597ms<br /> Base property: 539ms<br /> Base field: 555ms<br /> Base RO field: 552ms<br /> Virtual GetEnumType() test: 556ms<br /> Virtual IsB() test: 588ms<br /> Create Time : 10416ms<br /></p> <p>UtcNow: <br /> As: 499ms<br /> Is: 532ms<br /> Base property: 479ms<br /> Base field: 502ms<br /> Base RO field: 491ms<br /> Virtual GetEnumType(): 502ms<br /> Virtual bool IsB(): 522ms<br /> Create Time : 285ms (This number seems unreliable with UtcNow. I also get 109ms and 806ms.) <br /></p> <p><strong>x86 Release Mode:</strong><br /> Stopwatch: <br /> As: 391ms<br /> Is: 423ms<br /> Base property: 369ms<br /> Base field: 321ms<br /> Base RO field: 339ms<br /> Virtual GetEnumType() test: 361ms<br /> Virtual IsB() test: 365ms<br /> Create Time : 14106ms<br /></p> <p>UtcNow: <br /> As: 348ms<br /> Is: 375ms<br /> Base property: 329ms<br /> Base field: 286ms<br /> Base RO field: 309ms<br /> Virtual GetEnumType(): 321ms<br /> Virtual bool IsB(): 332ms<br /> Create Time : 544ms (This number seems unreliable with UtcNow.)<br /></p> <p>Here's most of the code:</p> <pre><code> static readonly int iterations = 50000000; void IsTest() { Process.GetCurrentProcess().ProcessorAffinity = (IntPtr)1; MyBaseClass[] bases = new MyBaseClass[iterations]; bool[] results1 = new bool[iterations]; Stopwatch createTime = new Stopwatch(); createTime.Start(); DateTime createStart = DateTime.UtcNow; for (int i = 0; i &lt; iterations; i++) { if (i % 2 == 0) bases[i] = new MyClassA(); else bases[i] = new MyClassB(); } DateTime createStop = DateTime.UtcNow; createTime.Stop(); Stopwatch isTimer = new Stopwatch(); isTimer.Start(); DateTime isStart = DateTime.UtcNow; for (int i = 0; i &lt; iterations; i++) { results1[i] = bases[i] is MyClassB; } DateTime isStop = DateTime.UtcNow; isTimer.Stop(); CheckResults(ref results1); Stopwatch asTimer = new Stopwatch(); asTimer.Start(); DateTime asStart = DateTime.UtcNow; for (int i = 0; i &lt; iterations; i++) { results1[i] = bases[i] as MyClassB != null; } DateTime asStop = DateTime.UtcNow; asTimer.Stop(); CheckResults(ref results1); Stopwatch baseMemberTime = new Stopwatch(); baseMemberTime.Start(); DateTime baseStart = DateTime.UtcNow; for (int i = 0; i &lt; iterations; i++) { results1[i] = bases[i].ClassType == MyBaseClass.ClassTypeEnum.B; } DateTime baseStop = DateTime.UtcNow; baseMemberTime.Stop(); CheckResults(ref results1); Stopwatch baseFieldTime = new Stopwatch(); baseFieldTime.Start(); DateTime baseFieldStart = DateTime.UtcNow; for (int i = 0; i &lt; iterations; i++) { results1[i] = bases[i].ClassTypeField == MyBaseClass.ClassTypeEnum.B; } DateTime baseFieldStop = DateTime.UtcNow; baseFieldTime.Stop(); CheckResults(ref results1); Stopwatch baseROFieldTime = new Stopwatch(); baseROFieldTime.Start(); DateTime baseROFieldStart = DateTime.UtcNow; for (int i = 0; i &lt; iterations; i++) { results1[i] = bases[i].ClassTypeField == MyBaseClass.ClassTypeEnum.B; } DateTime baseROFieldStop = DateTime.UtcNow; baseROFieldTime.Stop(); CheckResults(ref results1); Stopwatch virtMethTime = new Stopwatch(); virtMethTime.Start(); DateTime virtStart = DateTime.UtcNow; for (int i = 0; i &lt; iterations; i++) { results1[i] = bases[i].GetClassType() == MyBaseClass.ClassTypeEnum.B; } DateTime virtStop = DateTime.UtcNow; virtMethTime.Stop(); CheckResults(ref results1); Stopwatch virtMethBoolTime = new Stopwatch(); virtMethBoolTime.Start(); DateTime virtBoolStart = DateTime.UtcNow; for (int i = 0; i &lt; iterations; i++) { results1[i] = bases[i].IsB(); } DateTime virtBoolStop = DateTime.UtcNow; virtMethBoolTime.Stop(); CheckResults(ref results1); asdf.Text += "Stopwatch: " + Environment.NewLine + "As: " + asTimer.ElapsedMilliseconds + "ms" + Environment.NewLine +"Is: " + isTimer.ElapsedMilliseconds + "ms" + Environment.NewLine + "Base property: " + baseMemberTime.ElapsedMilliseconds + "ms" + Environment.NewLine + "Base field: " + baseFieldTime.ElapsedMilliseconds + "ms" + Environment.NewLine + "Base RO field: " + baseROFieldTime.ElapsedMilliseconds + "ms" + Environment.NewLine + "Virtual GetEnumType() test: " + virtMethTime.ElapsedMilliseconds + "ms" + Environment.NewLine + "Virtual IsB() test: " + virtMethBoolTime.ElapsedMilliseconds + "ms" + Environment.NewLine + "Create Time : " + createTime.ElapsedMilliseconds + "ms" + Environment.NewLine + Environment.NewLine+"UtcNow: " + Environment.NewLine + "As: " + (asStop - asStart).Milliseconds + "ms" + Environment.NewLine + "Is: " + (isStop - isStart).Milliseconds + "ms" + Environment.NewLine + "Base property: " + (baseStop - baseStart).Milliseconds + "ms" + Environment.NewLine + "Base field: " + (baseFieldStop - baseFieldStart).Milliseconds + "ms" + Environment.NewLine + "Base RO field: " + (baseROFieldStop - baseROFieldStart).Milliseconds + "ms" + Environment.NewLine + "Virtual GetEnumType(): " + (virtStop - virtStart).Milliseconds + "ms" + Environment.NewLine + "Virtual bool IsB(): " + (virtBoolStop - virtBoolStart).Milliseconds + "ms" + Environment.NewLine + "Create Time : " + (createStop-createStart).Milliseconds + "ms" + Environment.NewLine; } } abstract class MyBaseClass { public enum ClassTypeEnum { A, B } public ClassTypeEnum ClassType { get; protected set; } public ClassTypeEnum ClassTypeField; public readonly ClassTypeEnum ClassTypeReadonlyField; public abstract ClassTypeEnum GetClassType(); public abstract bool IsB(); protected MyBaseClass(ClassTypeEnum kind) { ClassTypeReadonlyField = kind; } } class MyClassA : MyBaseClass { public override bool IsB() { return false; } public override ClassTypeEnum GetClassType() { return ClassTypeEnum.A; } public MyClassA() : base(MyBaseClass.ClassTypeEnum.A) { ClassType = MyBaseClass.ClassTypeEnum.A; ClassTypeField = MyBaseClass.ClassTypeEnum.A; } } class MyClassB : MyBaseClass { public override bool IsB() { return true; } public override ClassTypeEnum GetClassType() { return ClassTypeEnum.B; } public MyClassB() : base(MyBaseClass.ClassTypeEnum.B) { ClassType = MyBaseClass.ClassTypeEnum.B; ClassTypeField = MyBaseClass.ClassTypeEnum.B; } } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload