Skip to content

Instantly share code, notes, and snippets.

@giggio
Last active January 27, 2016 17:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save giggio/a4a57e170c9d22d1fc35 to your computer and use it in GitHub Desktop.
Save giggio/a4a57e170c9d22d1fc35 to your computer and use it in GitHub Desktop.
C# Script testing "is" perf vs reflection

##Perf test comparing is, as and Reflection

You can run this by running csx aperf.csx. You need Visual Studio 2015 Update 1 or later, or the latest Roslyn bits, which are open source.

The IL is from a console project, as a csx file does not generate IL on disk. This is the Main method decompiled with ildasm.

using System.Diagnostics;
using static System.Console;
interface IFoo { }
interface BaseBase { }
interface Base : BaseBase { }
class Foo : Base, IFoo { }
struct Bar : IFoo { }
struct Baz : IFoo { }
BaseBase foo = new Foo();
IFoo bar = new Bar();
bool check;
var stopWatch = new Stopwatch();
var times = 10 * 1000 * 1000;
stopWatch.Start();
for (int i = 0; i < times; i++)
check = foo is Foo;
stopWatch.Stop();
WriteLine($"is Class: {stopWatch.Elapsed.TotalMilliseconds:n}");
stopWatch.Reset();
stopWatch.Start();
for (int i = 0; i < times; i++)
check = foo is Base;
stopWatch.Stop();
WriteLine($"is Class (no match): {stopWatch.Elapsed.TotalMilliseconds:n}");
stopWatch.Reset();
stopWatch.Start();
for (int i = 0; i < times; i++)
check = bar is Bar;
stopWatch.Stop();
WriteLine($"is Struct: {stopWatch.Elapsed.TotalMilliseconds:n}");
stopWatch.Reset();
stopWatch.Start();
for (int i = 0; i < times; i++)
check = bar is Baz;
stopWatch.Stop();
WriteLine($"is Struct (no match): {stopWatch.Elapsed.TotalMilliseconds:n}");
stopWatch.Reset();
stopWatch.Start();
for (int i = 0; i < times; i++)
check = foo is IFoo;
stopWatch.Stop();
WriteLine($"is interface: {stopWatch.Elapsed.TotalMilliseconds:n}");
stopWatch.Reset();
stopWatch.Start();
for (int i = 0; i < times; i++)
check = foo is ICollectData;
stopWatch.Stop();
WriteLine($"is interface (no match): {stopWatch.Elapsed.TotalMilliseconds:n}");
stopWatch.Reset();
Base node;
stopWatch.Start();
for (int i = 0; i < times; i++)
node = foo as Foo;
stopWatch.Stop();
WriteLine($"as Class: {stopWatch.Elapsed.TotalMilliseconds:n}");
stopWatch.Reset();
object o;
stopWatch.Start();
for (int i = 0; i < times; i++)
o = foo as ICollectData;
stopWatch.Stop();
WriteLine($"as interface (no match): {stopWatch.Elapsed.TotalMilliseconds:n}");
stopWatch.Reset();
stopWatch.Start();
for (int i = 0; i < times; i++)
check = typeof(Foo).IsAssignableFrom(foo.GetType());
stopWatch.Stop();
WriteLine($"IsAssignableFrom: {stopWatch.Elapsed.TotalMilliseconds:n}");
stopWatch.Reset();
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 855 (0x357)
.maxstack 2
.locals init ([0] class BaseBase foo,
[1] class IFoo bar,
[2] bool check,
[3] class [System]System.Diagnostics.Stopwatch stopWatch,
[4] int32 times,
[5] class Base node,
[6] object o,
[7] valuetype Bar V_7,
[8] int32 i,
[9] bool V_9,
[10] valuetype [mscorlib]System.TimeSpan V_10,
[11] int32 V_11,
[12] bool V_12,
[13] int32 V_13,
[14] bool V_14,
[15] int32 V_15,
[16] bool V_16,
[17] int32 V_17,
[18] bool V_18,
[19] int32 V_19,
[20] bool V_20,
[21] int32 V_21,
[22] bool V_22,
[23] int32 V_23,
[24] bool V_24,
[25] int32 V_25,
[26] bool V_26)
IL_0000: nop
IL_0001: newobj instance void Foo::.ctor()
IL_0006: stloc.0
IL_0007: ldloca.s V_7
IL_0009: initobj Bar
IL_000f: ldloc.s V_7
IL_0011: box Bar
IL_0016: stloc.1
IL_0017: newobj instance void [System]System.Diagnostics.Stopwatch::.ctor()
IL_001c: stloc.3
IL_001d: ldc.i4 0x989680
IL_0022: stloc.s times
IL_0024: ldloc.3
IL_0025: callvirt instance void [System]System.Diagnostics.Stopwatch::Start()
IL_002a: nop
IL_002b: ldc.i4.0
IL_002c: stloc.s i
IL_002e: br.s IL_0040
IL_0030: ldloc.0
IL_0031: isinst Foo
IL_0036: ldnull
IL_0037: cgt.un
IL_0039: stloc.2
IL_003a: ldloc.s i
IL_003c: ldc.i4.1
IL_003d: add
IL_003e: stloc.s i
IL_0040: ldloc.s i
IL_0042: ldloc.s times
IL_0044: clt
IL_0046: stloc.s V_9
IL_0048: ldloc.s V_9
IL_004a: brtrue.s IL_0030
IL_004c: ldloc.3
IL_004d: callvirt instance void [System]System.Diagnostics.Stopwatch::Stop()
IL_0052: nop
IL_0053: ldstr "is Class: {0:n}"
IL_0058: ldloc.3
IL_0059: callvirt instance valuetype [mscorlib]System.TimeSpan [System]System.Diagnostics.Stopwatch::get_Elapsed()
IL_005e: stloc.s V_10
IL_0060: ldloca.s V_10
IL_0062: call instance float64 [mscorlib]System.TimeSpan::get_TotalMilliseconds()
IL_0067: box [mscorlib]System.Double
IL_006c: call string [mscorlib]System.String::Format(string,
object)
IL_0071: call void [mscorlib]System.Console::WriteLine(string)
IL_0076: nop
IL_0077: ldloc.3
IL_0078: callvirt instance void [System]System.Diagnostics.Stopwatch::Reset()
IL_007d: nop
IL_007e: ldloc.3
IL_007f: callvirt instance void [System]System.Diagnostics.Stopwatch::Start()
IL_0084: nop
IL_0085: ldc.i4.0
IL_0086: stloc.s V_11
IL_0088: br.s IL_009a
IL_008a: ldloc.0
IL_008b: isinst Base
IL_0090: ldnull
IL_0091: cgt.un
IL_0093: stloc.2
IL_0094: ldloc.s V_11
IL_0096: ldc.i4.1
IL_0097: add
IL_0098: stloc.s V_11
IL_009a: ldloc.s V_11
IL_009c: ldloc.s times
IL_009e: clt
IL_00a0: stloc.s V_12
IL_00a2: ldloc.s V_12
IL_00a4: brtrue.s IL_008a
IL_00a6: ldloc.3
IL_00a7: callvirt instance void [System]System.Diagnostics.Stopwatch::Stop()
IL_00ac: nop
IL_00ad: ldstr "is Class (no match): {0:n}"
IL_00b2: ldloc.3
IL_00b3: callvirt instance valuetype [mscorlib]System.TimeSpan [System]System.Diagnostics.Stopwatch::get_Elapsed()
IL_00b8: stloc.s V_10
IL_00ba: ldloca.s V_10
IL_00bc: call instance float64 [mscorlib]System.TimeSpan::get_TotalMilliseconds()
IL_00c1: box [mscorlib]System.Double
IL_00c6: call string [mscorlib]System.String::Format(string,
object)
IL_00cb: call void [mscorlib]System.Console::WriteLine(string)
IL_00d0: nop
IL_00d1: ldloc.3
IL_00d2: callvirt instance void [System]System.Diagnostics.Stopwatch::Reset()
IL_00d7: nop
IL_00d8: ldloc.3
IL_00d9: callvirt instance void [System]System.Diagnostics.Stopwatch::Start()
IL_00de: nop
IL_00df: ldc.i4.0
IL_00e0: stloc.s V_13
IL_00e2: br.s IL_00f4
IL_00e4: ldloc.1
IL_00e5: isinst Bar
IL_00ea: ldnull
IL_00eb: cgt.un
IL_00ed: stloc.2
IL_00ee: ldloc.s V_13
IL_00f0: ldc.i4.1
IL_00f1: add
IL_00f2: stloc.s V_13
IL_00f4: ldloc.s V_13
IL_00f6: ldloc.s times
IL_00f8: clt
IL_00fa: stloc.s V_14
IL_00fc: ldloc.s V_14
IL_00fe: brtrue.s IL_00e4
IL_0100: ldloc.3
IL_0101: callvirt instance void [System]System.Diagnostics.Stopwatch::Stop()
IL_0106: nop
IL_0107: ldstr "is Struct: {0:n}"
IL_010c: ldloc.3
IL_010d: callvirt instance valuetype [mscorlib]System.TimeSpan [System]System.Diagnostics.Stopwatch::get_Elapsed()
IL_0112: stloc.s V_10
IL_0114: ldloca.s V_10
IL_0116: call instance float64 [mscorlib]System.TimeSpan::get_TotalMilliseconds()
IL_011b: box [mscorlib]System.Double
IL_0120: call string [mscorlib]System.String::Format(string,
object)
IL_0125: call void [mscorlib]System.Console::WriteLine(string)
IL_012a: nop
IL_012b: ldloc.3
IL_012c: callvirt instance void [System]System.Diagnostics.Stopwatch::Reset()
IL_0131: nop
IL_0132: ldloc.3
IL_0133: callvirt instance void [System]System.Diagnostics.Stopwatch::Start()
IL_0138: nop
IL_0139: ldc.i4.0
IL_013a: stloc.s V_15
IL_013c: br.s IL_014e
IL_013e: ldloc.1
IL_013f: isinst Baz
IL_0144: ldnull
IL_0145: cgt.un
IL_0147: stloc.2
IL_0148: ldloc.s V_15
IL_014a: ldc.i4.1
IL_014b: add
IL_014c: stloc.s V_15
IL_014e: ldloc.s V_15
IL_0150: ldloc.s times
IL_0152: clt
IL_0154: stloc.s V_16
IL_0156: ldloc.s V_16
IL_0158: brtrue.s IL_013e
IL_015a: ldloc.3
IL_015b: callvirt instance void [System]System.Diagnostics.Stopwatch::Stop()
IL_0160: nop
IL_0161: ldstr "is Struct (no match): {0:n}"
IL_0166: ldloc.3
IL_0167: callvirt instance valuetype [mscorlib]System.TimeSpan [System]System.Diagnostics.Stopwatch::get_Elapsed()
IL_016c: stloc.s V_10
IL_016e: ldloca.s V_10
IL_0170: call instance float64 [mscorlib]System.TimeSpan::get_TotalMilliseconds()
IL_0175: box [mscorlib]System.Double
IL_017a: call string [mscorlib]System.String::Format(string,
object)
IL_017f: call void [mscorlib]System.Console::WriteLine(string)
IL_0184: nop
IL_0185: ldloc.3
IL_0186: callvirt instance void [System]System.Diagnostics.Stopwatch::Reset()
IL_018b: nop
IL_018c: ldloc.3
IL_018d: callvirt instance void [System]System.Diagnostics.Stopwatch::Start()
IL_0192: nop
IL_0193: ldc.i4.0
IL_0194: stloc.s V_17
IL_0196: br.s IL_01a8
IL_0198: ldloc.0
IL_0199: isinst IFoo
IL_019e: ldnull
IL_019f: cgt.un
IL_01a1: stloc.2
IL_01a2: ldloc.s V_17
IL_01a4: ldc.i4.1
IL_01a5: add
IL_01a6: stloc.s V_17
IL_01a8: ldloc.s V_17
IL_01aa: ldloc.s times
IL_01ac: clt
IL_01ae: stloc.s V_18
IL_01b0: ldloc.s V_18
IL_01b2: brtrue.s IL_0198
IL_01b4: ldloc.3
IL_01b5: callvirt instance void [System]System.Diagnostics.Stopwatch::Stop()
IL_01ba: nop
IL_01bb: ldstr "is interface: {0:n}"
IL_01c0: ldloc.3
IL_01c1: callvirt instance valuetype [mscorlib]System.TimeSpan [System]System.Diagnostics.Stopwatch::get_Elapsed()
IL_01c6: stloc.s V_10
IL_01c8: ldloca.s V_10
IL_01ca: call instance float64 [mscorlib]System.TimeSpan::get_TotalMilliseconds()
IL_01cf: box [mscorlib]System.Double
IL_01d4: call string [mscorlib]System.String::Format(string,
object)
IL_01d9: call void [mscorlib]System.Console::WriteLine(string)
IL_01de: nop
IL_01df: ldloc.3
IL_01e0: callvirt instance void [System]System.Diagnostics.Stopwatch::Reset()
IL_01e5: nop
IL_01e6: ldloc.3
IL_01e7: callvirt instance void [System]System.Diagnostics.Stopwatch::Start()
IL_01ec: nop
IL_01ed: ldc.i4.0
IL_01ee: stloc.s V_19
IL_01f0: br.s IL_0202
IL_01f2: ldloc.0
IL_01f3: isinst [System]System.Diagnostics.ICollectData
IL_01f8: ldnull
IL_01f9: cgt.un
IL_01fb: stloc.2
IL_01fc: ldloc.s V_19
IL_01fe: ldc.i4.1
IL_01ff: add
IL_0200: stloc.s V_19
IL_0202: ldloc.s V_19
IL_0204: ldloc.s times
IL_0206: clt
IL_0208: stloc.s V_20
IL_020a: ldloc.s V_20
IL_020c: brtrue.s IL_01f2
IL_020e: ldloc.3
IL_020f: callvirt instance void [System]System.Diagnostics.Stopwatch::Stop()
IL_0214: nop
IL_0215: ldstr "is interface (no match): {0:n}"
IL_021a: ldloc.3
IL_021b: callvirt instance valuetype [mscorlib]System.TimeSpan [System]System.Diagnostics.Stopwatch::get_Elapsed()
IL_0220: stloc.s V_10
IL_0222: ldloca.s V_10
IL_0224: call instance float64 [mscorlib]System.TimeSpan::get_TotalMilliseconds()
IL_0229: box [mscorlib]System.Double
IL_022e: call string [mscorlib]System.String::Format(string,
object)
IL_0233: call void [mscorlib]System.Console::WriteLine(string)
IL_0238: nop
IL_0239: ldloc.3
IL_023a: callvirt instance void [System]System.Diagnostics.Stopwatch::Reset()
IL_023f: nop
IL_0240: ldloc.3
IL_0241: callvirt instance void [System]System.Diagnostics.Stopwatch::Start()
IL_0246: nop
IL_0247: ldc.i4.0
IL_0248: stloc.s V_21
IL_024a: br.s IL_025a
IL_024c: ldloc.0
IL_024d: isinst Foo
IL_0252: stloc.s node
IL_0254: ldloc.s V_21
IL_0256: ldc.i4.1
IL_0257: add
IL_0258: stloc.s V_21
IL_025a: ldloc.s V_21
IL_025c: ldloc.s times
IL_025e: clt
IL_0260: stloc.s V_22
IL_0262: ldloc.s V_22
IL_0264: brtrue.s IL_024c
IL_0266: ldloc.3
IL_0267: callvirt instance void [System]System.Diagnostics.Stopwatch::Stop()
IL_026c: nop
IL_026d: ldstr "as Class: {0:n}"
IL_0272: ldloc.3
IL_0273: callvirt instance valuetype [mscorlib]System.TimeSpan [System]System.Diagnostics.Stopwatch::get_Elapsed()
IL_0278: stloc.s V_10
IL_027a: ldloca.s V_10
IL_027c: call instance float64 [mscorlib]System.TimeSpan::get_TotalMilliseconds()
IL_0281: box [mscorlib]System.Double
IL_0286: call string [mscorlib]System.String::Format(string,
object)
IL_028b: call void [mscorlib]System.Console::WriteLine(string)
IL_0290: nop
IL_0291: ldloc.3
IL_0292: callvirt instance void [System]System.Diagnostics.Stopwatch::Reset()
IL_0297: nop
IL_0298: ldloc.3
IL_0299: callvirt instance void [System]System.Diagnostics.Stopwatch::Start()
IL_029e: nop
IL_029f: ldc.i4.0
IL_02a0: stloc.s V_23
IL_02a2: br.s IL_02b2
IL_02a4: ldloc.0
IL_02a5: isinst [System]System.Diagnostics.ICollectData
IL_02aa: stloc.s o
IL_02ac: ldloc.s V_23
IL_02ae: ldc.i4.1
IL_02af: add
IL_02b0: stloc.s V_23
IL_02b2: ldloc.s V_23
IL_02b4: ldloc.s times
IL_02b6: clt
IL_02b8: stloc.s V_24
IL_02ba: ldloc.s V_24
IL_02bc: brtrue.s IL_02a4
IL_02be: ldloc.3
IL_02bf: callvirt instance void [System]System.Diagnostics.Stopwatch::Stop()
IL_02c4: nop
IL_02c5: ldstr "as interface (no match): {0:n}"
IL_02ca: ldloc.3
IL_02cb: callvirt instance valuetype [mscorlib]System.TimeSpan [System]System.Diagnostics.Stopwatch::get_Elapsed()
IL_02d0: stloc.s V_10
IL_02d2: ldloca.s V_10
IL_02d4: call instance float64 [mscorlib]System.TimeSpan::get_TotalMilliseconds()
IL_02d9: box [mscorlib]System.Double
IL_02de: call string [mscorlib]System.String::Format(string,
object)
IL_02e3: call void [mscorlib]System.Console::WriteLine(string)
IL_02e8: nop
IL_02e9: ldloc.3
IL_02ea: callvirt instance void [System]System.Diagnostics.Stopwatch::Reset()
IL_02ef: nop
IL_02f0: ldloc.3
IL_02f1: callvirt instance void [System]System.Diagnostics.Stopwatch::Start()
IL_02f6: nop
IL_02f7: ldc.i4.0
IL_02f8: stloc.s V_25
IL_02fa: br.s IL_0318
IL_02fc: ldtoken Foo
IL_0301: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_0306: ldloc.0
IL_0307: callvirt instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()
IL_030c: callvirt instance bool [mscorlib]System.Type::IsAssignableFrom(class [mscorlib]System.Type)
IL_0311: stloc.2
IL_0312: ldloc.s V_25
IL_0314: ldc.i4.1
IL_0315: add
IL_0316: stloc.s V_25
IL_0318: ldloc.s V_25
IL_031a: ldloc.s times
IL_031c: clt
IL_031e: stloc.s V_26
IL_0320: ldloc.s V_26
IL_0322: brtrue.s IL_02fc
IL_0324: ldloc.3
IL_0325: callvirt instance void [System]System.Diagnostics.Stopwatch::Stop()
IL_032a: nop
IL_032b: ldstr "IsAssignableFrom: {0:n}"
IL_0330: ldloc.3
IL_0331: callvirt instance valuetype [mscorlib]System.TimeSpan [System]System.Diagnostics.Stopwatch::get_Elapsed()
IL_0336: stloc.s V_10
IL_0338: ldloca.s V_10
IL_033a: call instance float64 [mscorlib]System.TimeSpan::get_TotalMilliseconds()
IL_033f: box [mscorlib]System.Double
IL_0344: call string [mscorlib]System.String::Format(string,
object)
IL_0349: call void [mscorlib]System.Console::WriteLine(string)
IL_034e: nop
IL_034f: ldloc.3
IL_0350: callvirt instance void [System]System.Diagnostics.Stopwatch::Reset()
IL_0355: nop
IL_0356: ret
} // end of method Program::Main
@giggio
Copy link
Author

giggio commented Jan 26, 2016

Results on a Surface Pro 4 (i5):

is Class: 39.59
is Class (no match): 48.91
is Struct: 59.04
is Struct (no match): 56.03
is interface: 54.98
is interface (no match): 60.32
as Class: 49.14
as interface (no match): 71.54
IsAssignableFrom: 141.57

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment