加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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

发布时间:2020-12-15 08:14:46 所属栏目:百科 来源:网络整理
导读:我有一个简单的场景,我试图在一个库存对象列表上测试表达式编译树的性能.下面是代码 表达式编译树的性能比静态lambda调用慢5倍.我不确定这是否是表达式编译树可以预期的标准性能.非常感谢任何见解. LambdaExpression();ListStock stocks = new ListStock();f
我有一个简单的场景,我试图在一个库存对象列表上测试表达式编译树的性能.下面是代码

表达式编译树的性能比静态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之间执行.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读