Performance of compiled-to-delegate Expression

前端 未结 5 666
無奈伤痛
無奈伤痛 2020-12-02 10:07

I\'m generating an expression tree that maps properties from a source object to a destination object, that is then compiled to a Func

5条回答
  •  温柔的废话
    2020-12-02 10:45

    You are may compile Expression Tree manually via Reflection.Emit. It will generally provide faster compilation time (in my case below ~30 times faster), and will allow you to tune emitted result performance. And it not so hard to do, especially if your Expressions are limited known subset.

    The idea is to use ExpressionVisitor to traverse the expression and emit the IL for corresponding expression type. It's also "quite" simple to write your own Visitor to handle the known subset of expressions, and fallback to normal Expression.Compile for not yet supported expression types.

    In my case I am generating the delegate:

    Func createA = state =>
        new A(
            new B(), 
            (string)state[11], 
            new ID[2] { new D1(), new D2() }) { 
            Prop = new P(new B()), Bop = new B() 
        };
    

    The test creates the corresponding expression tree and compares its Expression.Compile vs visiting and emitting the IL and then creating delegate from DynamicMethod.

    The results:

    Compile Expression 3000 times: 814
    Invoke Compiled Expression 5000000 times: 724
    Emit from Expression 3000 times: 36
    Run Emitted Expression 5000000 times: 722

    36 vs 814 when compiling manually.

    Here the full code.

提交回复
热议问题