[stringtemplate-interest] StringTemplate Compiler for .NET

Sam Harwell sharwell at pixelminegames.com
Wed Mar 18 17:25:38 PDT 2009


So here we go/you've inspired me. :) For syntax highlighting, view in
HTML.

 

I'm starting with the if condition evaluation in ConditionalExpr. The
delegate returned can call either the interpreted version or a dynamic
method to evaluate the expression. The delegates are created on-demand
inside ConditionalExpr.Write, and called instead of directly creating
instances of ActionEvaluator like before.

 

public static bool EnableDynamicMethods = true;

static int _evaluatorNumber = 1;

static System.Func<StringTemplate, IStringTemplateWriter, bool>
GetEvaluator( ASTExpr chunk, ITree condition )

{

    if ( EnableDynamicMethods )

    {

        try

        {

            Type[] parameterTypes = { typeof( StringTemplate ), typeof(
IStringTemplateWriter ) };

            DynamicMethod method = new DynamicMethod(
"ConditionEvaluator" + _evaluatorNumber++, typeof( bool ),
parameterTypes );

 

            var gen = method.GetILGenerator();

            ActionEvaluator evalCompiled = new ActionEvaluator( null,
chunk, null, condition );

            evalCompiled.ifConditionCompiled( gen );

            gen.Emit( OpCodes.Ret );

 

            var dynamicEvaluator = (System.Func<StringTemplate,
IStringTemplateWriter, bool>)method.CreateDelegate( typeof(
System.Func<StringTemplate, IStringTemplateWriter, bool> ) );

            return dynamicEvaluator;

        }

        catch

        {

            // fall back to interpreted version

        }

    }

 

    return new System.Func<StringTemplate, IStringTemplateWriter, bool>(
( self, @out ) =>

    {

        ActionEvaluator eval = new ActionEvaluator( self, chunk, @out,
condition );

        return eval.ifCondition();

    } );

}

 

Inside ActionEvaluator.g3, I'm working my way up, and it throws
System.NotImplementedException if it doesn't know how to emit IL for the
[sub]expression. The exception results in automatic fallback to the
interpreted code that we know works.

 

public

ifConditionCompiled[System.Reflection.Emit.ILGenerator gen]

        :       ifAtomCompiled[$gen]

        |       ^(NOT ifAtomCompiled[$gen])

                {EmitNot($gen);}

        ;

 

ifAtomCompiled[System.Reflection.Emit.ILGenerator gen]

        :       exprCompiled[$gen] {EmitTest($gen);}

        ;

 

exprCompiled[System.Reflection.Emit.ILGenerator gen]

        :       ^(PLUS exprCompiled[$gen] exprCompiled[$gen])

                {throw new System.NotImplementedException();}

        |       templateApplication

                {throw new System.NotImplementedException();}

        |       attribute

                {throw new System.NotImplementedException();}

        |       templateInclude

                {throw new System.NotImplementedException();}

        |       function

                {throw new System.NotImplementedException();}

        |       list

                {throw new System.NotImplementedException();}

        |       ^(VALUE exprCompiled[$gen])

                {throw new System.NotImplementedException();}

        ;

 

Helper methods do the actual emit:

 

static void EmitNot( ILGenerator gen )

{

    gen.Emit( OpCodes.Not );

}

static void EmitTest( ILGenerator gen )

{

    var label = gen.DefineLabel();

    var label2 = gen.DefineLabel();

    gen.Emit( OpCodes.Brtrue_S, label );

    gen.Emit( OpCodes.Ldc_I4_0 );

    gen.Emit( OpCodes.Br_S, label2 );

    gen.MarkLabel( label );

    gen.Emit( OpCodes.Ldc_I4_1 );

    gen.MarkLabel( label2 );

}

 

Sam

 

-----Original Message-----
From: stringtemplate-interest-bounces at antlr.org
[mailto:stringtemplate-interest-bounces at antlr.org] On Behalf Of Volkan
Ceylan
Sent: Tuesday, March 17, 2009 3:52 AM
To: stringtemplate-interest at antlr.org
Subject: [stringtemplate-interest] StringTemplate Compiler for .NET

 

> I'm extremely interested to see how the compiled code performs
compared

> to my C# port of StringTemplate.

 

 Hi, is your C# port open source? Would like to see what optimizations

you did. I'm currently working on public 3.1beta at stringtemplate.org

 

> That aside, I think the idea of compiling templates to an assembly is
great.

 

Actually, i'm not thinking about compiling to an assembly, but to

dynamic methods. AFAIK, due to some problems with .NET, when you load

an assembly, there is no way to unload it, unless you use a separate

application domain to load assemblies, and unload the domain

completely.

 

Dynamic methods can be garbage collected when you have no delegates or

references to them. That's why i prefer dynamic methods versus

assemblies. The only problem with dynamic methods i see is that they

are harder to debug :(

 

>I used a sampling method to profile the library. The test was a batch
conversion

> of the 8 grammars that are used in the C# port of the ANTLR >Tool.
54.33% (inclusive)

> of the samples were in Antlr3.StringTemplate.dll. Only 6.59%
(inclusive) was spent

> in >ASTExpr.rawGetObjectProperty, which is responsible for all
measurable uses of .NET reflection.

> 35.31% (inclusive) of the time was spent in >ActionEvaluator.action,

> (note: this call encapsulates all calls to
ASTExpr.rawGetObjectProperty).

 

ActionEvaluator.action is walking a tree and consists of some costly

CASE statements. When a template is compiled, there will not be any of

them in the generated IL. Currently i'm having about 10x speed for

simple templates.

 

 

> By implementing a System.Type -> System.Reflection.MemberInfo map in
ASTExpr and

> caching the property accessors, I was able to reduce the time spent in

> ASTExpr.rawGetObjectProperty to 2.36% (inclusive).

 

This is a nice idea, would like to see implementation. There may be

even a further improvement by compiling property accessors as dynamic

methods such as (type, property) -> dynamic get delegate (though i'm

not %100 sure about that, need to see source code of new DLR)

 

> PS: I've thought about doing something similar to the CLI compilation
with

> ANTLR grammars, but profiling the generated code has shown that it's
not the bottleneck right now.

 

I don't know much about ANTLR and its grammars, other than a general

overview of what it is used for :(

_______________________________________________

stringtemplate-interest mailing list

stringtemplate-interest at antlr.org

http://www.antlr.org/mailman/listinfo/stringtemplate-interest

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.antlr.org/pipermail/stringtemplate-interest/attachments/20090318/94ee6415/attachment-0001.html 


More information about the stringtemplate-interest mailing list