Dynamic Language Performanceor How I Learned to Love MetaprogrammingW. Kevin Hazzard, C# MVPNoVA Code CampOctober 2009
AgendaMetaObjects and MetaProgrammingDynamic Language Runtime ArchitectureThe dynamic keyword in C# 4The CallSite<T> ClassThe CSharpRuntimeBinderDynamicMetaObjectsAdaptive Inline CachingDemonstrationsFluent XML ParsingPerformance of Python to C# Integration
Metaobject VisualizationMetaobjectcontrolcreateinvokeBacking ObjectsUsers and programs interact with metaobjects, not directly with their backing objects.
DLR Architecture
The dynamic Keyword[Dynamic] objectDX = someFunction();dynamic DX = someFunction();DX( ‘A’ );DX.Foo( 1 );DX.Bar = ‘X’;int V = DX.Baz;DX[0] = 100;string S = DX[0];// invoke the object// invoke the Foo member// set the Bar member// convert the Baz member to integer// set index 0 to 100// convert index 0 to stringIs dynamic a new type? NoThe dynamic type is totally static This type is a signal to the compiler to perform late binding
Let's Stop and Reflectclass Program{  dynamic Jabberwocky( dynamicarg ) {return arg.foo();  }}[return: Dynamic] object Jabberwocky( [Dynamic] objectarg ) {if (<Jabberwocky>o__SiteContainer2.<>p__Site3 == null) {    <Jabberwocky>o__SiteContainer2.<>p__Site3 = CallSite<Func<CallSite, object, object>>.Create(newCSharpInvokeMemberBinder( CSharpCallFlags.None,           "foo", typeof( Program ), null, newCSharpArgumentInfo[] { newCSharpArgumentInfo(CSharpArgumentInfoFlags.None, null ) } ) );  }return <Jabberwocky>o__SiteContainer2.<>p__Site3.Target(    <Jabberwocky>o__SiteContainer2.<>p__Site3, arg );}
The CallSite<T> ClassIn the System.Runtime.CompilerServices namespaceCreated and managed in a static container class for each venueKey members:Create – creates and assign a binderTarget – a delegate that invokes the binderBinder – connects an appropriate metaobject to the underlying call implementation
The CSharpRuntimeBinderWhat might these describe?Semantic CheckerSymbol TableExpression Tree CreatorExpression FactoryContext InfoControllerDispatcher
What is a metaobject?An object that:May contain info on the:CreatesControlsInvokesDescribesImplementsInterfaces ofType ofMethods ofFields ofProperties ofAttributes of… another object
The DynamicMetaObject ClassBinds up “The Twelve" DLR methods
All expression tree-orientedBindCreateInstanceBindBinaryOperationBindUnaryOperationBindConvertBindDeleteMemberBindDeleteIndexBindInvokeBindInvokeMemberBindGetMemberBindSetMemberBindGetIndexBindSetIndex
IDynamicMetaObjectProviderpublic interface IDynamicMetaObjectProvider{    DynamicMetaObject GetMetaObject(        Expression parameter );}Pattern for implementing a custom metaobjectThe returned DynamicMetaObject must implement all twelve binding methods (and more)Lots of Expression Tree knowledge is requiredNot a trivial exercise
DynamicObject to the rescue!public class DynamicObject : IDynamicMetaObjectProvider {  protected DynamicObject();public virtual DynamicMetaObjectGetMetaObject(...);public virtual boolTryBinaryOperation(...);public virtual boolTryConvert(...);public virtual boolTryCreateInstance(...);public virtual boolTryDeleteIndex(...);public virtual boolTryDeleteMember(...);public virtual boolTryGetIndex(...);public virtual boolTryGetMember(...);public virtual boolTryInvoke(...);public virtual boolTryInvokeMember(...);public virtual boolTrySetIndex(...);public virtual boolTrySetMember(...);public virtual boolTryUnaryOperation(...);}
Example – Fluent XML ParsingWouldn't it be nice if we could read and write XML like a set of nested objects without deep knowledge of the XML DOM or LINQ to XML?<books pubdate="2009-06-15">  <book price="45.99" title="Surgery for Dummies">    <id isbn10="4389880339"/>    <authors>      <author>        <name>          <first>Mortimer</first>          <last>Snerdly</last>        </name>        <email address="mort@surgery.com"/>      </author>    </authors>  </book></books>WriteLine( books.book[0].authors.author[0].name.first);
Fluent XML pARSING in C#Demonstration
Adaptive Inline CachingEach CallSite uses 3 levels of cachingLevel 0 – a dynamically generated delegate for some of the call patterns encountered at the siteLevel 1 – a read-only set of rules for all of the call patterns that the site has seen so farLevel 2 – a read-only set of rules that spans multiple call sites
What about level 2 cache misses?A level 2 cache miss causes:The creation of a new ruleThe insertion of the new rule into the level 2 cache (on the ActionBinder)The insertion of the new rule into the level 1 cache (on the CallSite rule set)Possible insertion into the level 0 cache (on the CallSite dynamic delegate)
Performance ofPython to C# IntegrationDemonstration

Dynamic Language Performance

  • 1.
    Dynamic Language PerformanceorHow I Learned to Love MetaprogrammingW. Kevin Hazzard, C# MVPNoVA Code CampOctober 2009
  • 2.
    AgendaMetaObjects and MetaProgrammingDynamicLanguage Runtime ArchitectureThe dynamic keyword in C# 4The CallSite<T> ClassThe CSharpRuntimeBinderDynamicMetaObjectsAdaptive Inline CachingDemonstrationsFluent XML ParsingPerformance of Python to C# Integration
  • 3.
    Metaobject VisualizationMetaobjectcontrolcreateinvokeBacking ObjectsUsersand programs interact with metaobjects, not directly with their backing objects.
  • 4.
  • 5.
    The dynamic Keyword[Dynamic]objectDX = someFunction();dynamic DX = someFunction();DX( ‘A’ );DX.Foo( 1 );DX.Bar = ‘X’;int V = DX.Baz;DX[0] = 100;string S = DX[0];// invoke the object// invoke the Foo member// set the Bar member// convert the Baz member to integer// set index 0 to 100// convert index 0 to stringIs dynamic a new type? NoThe dynamic type is totally static This type is a signal to the compiler to perform late binding
  • 6.
    Let's Stop andReflectclass Program{ dynamic Jabberwocky( dynamicarg ) {return arg.foo(); }}[return: Dynamic] object Jabberwocky( [Dynamic] objectarg ) {if (<Jabberwocky>o__SiteContainer2.<>p__Site3 == null) { <Jabberwocky>o__SiteContainer2.<>p__Site3 = CallSite<Func<CallSite, object, object>>.Create(newCSharpInvokeMemberBinder( CSharpCallFlags.None, "foo", typeof( Program ), null, newCSharpArgumentInfo[] { newCSharpArgumentInfo(CSharpArgumentInfoFlags.None, null ) } ) ); }return <Jabberwocky>o__SiteContainer2.<>p__Site3.Target( <Jabberwocky>o__SiteContainer2.<>p__Site3, arg );}
  • 7.
    The CallSite<T> ClassInthe System.Runtime.CompilerServices namespaceCreated and managed in a static container class for each venueKey members:Create – creates and assign a binderTarget – a delegate that invokes the binderBinder – connects an appropriate metaobject to the underlying call implementation
  • 8.
    The CSharpRuntimeBinderWhat mightthese describe?Semantic CheckerSymbol TableExpression Tree CreatorExpression FactoryContext InfoControllerDispatcher
  • 9.
    What is ametaobject?An object that:May contain info on the:CreatesControlsInvokesDescribesImplementsInterfaces ofType ofMethods ofFields ofProperties ofAttributes of… another object
  • 10.
    The DynamicMetaObject ClassBindsup “The Twelve" DLR methods
  • 11.
  • 12.
    IDynamicMetaObjectProviderpublic interface IDynamicMetaObjectProvider{ DynamicMetaObject GetMetaObject( Expression parameter );}Pattern for implementing a custom metaobjectThe returned DynamicMetaObject must implement all twelve binding methods (and more)Lots of Expression Tree knowledge is requiredNot a trivial exercise
  • 13.
    DynamicObject to therescue!public class DynamicObject : IDynamicMetaObjectProvider { protected DynamicObject();public virtual DynamicMetaObjectGetMetaObject(...);public virtual boolTryBinaryOperation(...);public virtual boolTryConvert(...);public virtual boolTryCreateInstance(...);public virtual boolTryDeleteIndex(...);public virtual boolTryDeleteMember(...);public virtual boolTryGetIndex(...);public virtual boolTryGetMember(...);public virtual boolTryInvoke(...);public virtual boolTryInvokeMember(...);public virtual boolTrySetIndex(...);public virtual boolTrySetMember(...);public virtual boolTryUnaryOperation(...);}
  • 14.
    Example – FluentXML ParsingWouldn't it be nice if we could read and write XML like a set of nested objects without deep knowledge of the XML DOM or LINQ to XML?<books pubdate="2009-06-15"> <book price="45.99" title="Surgery for Dummies"> <id isbn10="4389880339"/> <authors> <author> <name> <first>Mortimer</first> <last>Snerdly</last> </name> <email address="mort@surgery.com"/> </author> </authors> </book></books>WriteLine( books.book[0].authors.author[0].name.first);
  • 15.
    Fluent XML pARSINGin C#Demonstration
  • 16.
    Adaptive Inline CachingEachCallSite uses 3 levels of cachingLevel 0 – a dynamically generated delegate for some of the call patterns encountered at the siteLevel 1 – a read-only set of rules for all of the call patterns that the site has seen so farLevel 2 – a read-only set of rules that spans multiple call sites
  • 17.
    What about level2 cache misses?A level 2 cache miss causes:The creation of a new ruleThe insertion of the new rule into the level 2 cache (on the ActionBinder)The insertion of the new rule into the level 1 cache (on the CallSite rule set)Possible insertion into the level 0 cache (on the CallSite dynamic delegate)
  • 18.
    Performance ofPython toC# IntegrationDemonstration