c# – 编译表达式树的性能

前端之家收集整理的这篇文章主要介绍了c# – 编译表达式树的性能前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个简单的场景,我试图在一个库存对象列表上测试表达式编译树的性能.下面是代码

表达式编译树的性能比静态lambda调用慢5倍.我不确定这是否是表达式编译树可以预期的标准性能.非常感谢任何见解.

LambdaExpression();
List<Stock> stocks = new List<Stock>();
for (int ctr = 0; ctr <= 5000000; ctr++)
{
    Stock stk1 = new Stock() { Price = ctr,Symbol = "A",CloseDate = DateTime.Now,FaceValue = ctr } ;
    stocks.Add(stk1);
}
CompileTimeLamda(a);
DynamicLambda(a);


public static void LambdaExpression()
{
    ParameterExpression CS1 = Expression.Parameter(typeof(Stock),"d");

    var line1 = Expression.Equal(Expression.Property(CS1,typeof(Stock).GetProperty("Symbol")),Expression.Constant("MSFT",typeof(string)));
    var line2 = Expression.GreaterThan(Expression.Property(Expression.Property(CS1,typeof(Stock).GetProperty("CloseDate")),typeof(DateTime).GetProperty("Millisecond")),Expression.Constant(0,typeof(int)));
    var line3 = Expression.GreaterThan(Expression.Property(CS1,typeof(Stock).GetProperty("Price")),Expression.Constant((double)0,typeof(double)));
    var line4 = Expression.And(line1,line2);
    var line5 = Expression.OrElse(line4,line3);

    func = Expression.Lambda<Func<Stock,bool>>(line5,new ParameterExpression[] {  CS1 } ).Compile();
}


public static void DynamicLambda(List<Stock> stks)
{
    Stopwatch watch = new Stopwatch();
    watch.Start();
    foreach (var d in stks)
    {
        func(d);
    }
    watch.Stop();
    Console.WriteLine("Dynamic Lambda :" + watch.ElapsedMilliseconds);
}

public static void CompileTimeLamda(List<Stock> stks)
{
    Stopwatch watch = new Stopwatch();
    watch.Start();
    foreach (var d in stks)
    {
        if (d.Symbol == "MSFT" && d.CloseDate.Millisecond > 0 ||
                                  (d.Price) > 0) ;
    }
    watch.Stop();
    Console.WriteLine("Compile Time Lamda " +watch.ElapsedMilliseconds);
}

解决方法

不同之处在于编译器有更多的信息,如果你在编译时编译它而不是在运行时就花费更多的精力优化代码…而且,使用lambda,你有一个更“灵活”的程序(你可以在运行时选择lambda).这需要付出代价
一个额外的函数调用,并失去了许多潜在的优化.

为了进行更“公平”的比较,您可以使用以下内容比较静态lambda与动态lambda:

Func<Stock,bool> compileTime = (Stock d) => (d.Symbol == "MSFT" && d.CloseDate.Millisecond > 0) || d.Price > 0;

而不是硬编码的代码..

在那里你也会发现一个区别,但是稍微小一点……差别是出于同样的原因(更多优化)……你可以通过手工优化你的lambda来减少差异(尽管这并不总是可能的),因为编译器可以创建无法使用lambda手动创建的有效CLI代码.

但是,例如,如果您从以下位置更改动态lambda:

var line5 = Expression.OrElse(line4,line3);

至:

var line5 = Expression.OrElse(line3,line4);

您将看到lambda如何在原始编译代码的1x和2x之间执行.

猜你在找的C#相关文章