It should probably go without saying, but to make it explicit: any code using the dynamic keyword, or the Dynamic Language Runtime (DLR) is not going to be highly optimized. Performance tuning is often about stripping away abstractions, but using the DLR is adding one huge abstraction layer. It has its place, certainly, but a fast system is not one of them.
When you use dynamic, what looks like straightforward code is anything but.
Take a simple, admittedly contrived example:
static void Main(string[] args) { int a = 13; int b = 14; int c = a + b; Console.WriteLine(c); }
The IL for this is equally straightforward:
.method private hidebysig static void Main ( string[] args ) cil managed { // Method begins at RVA 0x2050 // Code size 17 (0x11) .maxstack 2 .entrypoint .locals init ( [0] int32 a, [1] int32 b, [2] int32 c ) IL_0000: ldc.i4.s 13 IL_0002: stloc.0 IL_0003: ldc.i4.s 14 IL_0005: stloc.1 IL_0006: ldloc.0 IL_0007: ldloc.1 IL_0008: add IL_0009: stloc.2 IL_000a: ldloc.2 IL_000b: call void [mscorlib]System.Console::WriteLine(int32) IL_0010: ret } // end of method Program::Main
Now let’s just make those ints dynamic:
static void Main(string[] args) { dynamic a = 13; dynamic b = 14; dynamic c = a + b; Console.WriteLine(c); }
For the sake of space, I am actually going to not show the IL here, but this is what it looks like when you convert it back to C#:
private static void Main(string[] args) { object a = 13; object b = 14; if (Program.<Main>o__SiteContainer0.<>p__Site1 == null) { Program.<Main>o__SiteContainer0.<>p__Site1 = CallSite<Func<CallSite, object, object, object>>. Create(Binder.BinaryOperation(CSharpBinderFlags.None, ExpressionType.Add, typeof(Program), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) })); } object c = Program.<Main>o__SiteContainer0. <>p__Site1.Target(Program.<Main>o__SiteContainer0.<>p__Site1, a, b); if (Program.<Main>o__SiteContainer0.<>p__Site2 == null) { Program.<Main>o__SiteContainer0.<>p__Site2 = CallSite<Action<CallSite, Type, object>>. Create(Binder.InvokeMember(CSharpBinderFlags.ResultDiscarded, "WriteLine", null, typeof(Program), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create( CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.IsStaticType, null), CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) })); } Program.<Main>o__SiteContainer0.<>p__Site2.Target( Program.<Main>o__SiteContainer0.<>p__Site2, typeof(Console), c); }
Even the call to WriteLine isn’t straightforward. From simple, straightforward code, it has gone to a mishmash of memory allocations, delegates, dynamic method invocation, and these objects called CallSites.
I do not mean to dump too much on the DLR. It is a perfectly fine framework for rapid development and scripting. It opens up great possibilities for interfacing between dynamic languages and .NET. If you are interested in what it offers, read a good overview at http://www.writinghighperf.net/go/24.
For all your application development needs, visit www.verbat.com for a fiscally conscious proposal that meets your needs ( So I can keep this blog going as well!!!!)
Alternatively click through the link if you found this article interesting. (This will help the companies Search engine rankings)
Leave a Reply