考虑以下对集合的简单操作:
static List<int> x = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var result = x.Where(i => i % 2 == 0).Where(i => i > 5);
Run Code Online (Sandbox Code Playgroud)
现在让我们使用表达式.以下代码大致相当:
static void UsingLambda() {
Func<IEnumerable<int>, IEnumerable<int>> lambda = l => l.Where(i => i % 2 == 0).Where(i => i > 5);
var t0 = DateTime.Now.Ticks;
for (int j = 1; j < MAX; j++)
var sss = lambda(x).ToList();
var tn = DateTime.Now.Ticks;
Console.WriteLine("Using lambda: {0}", tn …Run Code Online (Sandbox Code Playgroud) 为什么Func<>从Expression<Func<>>via .Compile()创建的文件比直接使用Func<>声明要慢得多?
我刚刚使用Func<IInterface, object>声明直接更改为Expression<Func<IInterface, object>>在我正在处理的应用程序中创建的一个,我注意到性能下降了.
我刚做了一点测试,Func<>从一个Expression创建的"几乎"是Func<>直接声明的时间的两倍.
在我的机器上,Direct Func<>大约需要7.5秒,Expression<Func<>>大约需要12.6秒.
这是我使用的测试代码(运行Net 4.0)
// Direct
Func<int, Foo> test1 = x => new Foo(x * 2);
int counter1 = 0;
Stopwatch s1 = new Stopwatch();
s1.Start();
for (int i = 0; i < 300000000; i++)
{
counter1 += test1(i).Value;
}
s1.Stop();
var result1 = s1.Elapsed;
// Expression . Compile()
Expression<Func<int, Foo>> expression = x => new Foo(x …Run Code Online (Sandbox Code Playgroud) 我正在开发一个允许用户输入任意表达式的库.然后,我的库将这些表达式作为更大表达式的一部分编译到委托中.现在,由于仍然未知的原因,Compile有时/经常编译表达式导致代码远远低于它不是编译表达式时的代码.之前我问了一个关于这个的问题,一个解决方法是不使用Compile,但是在新的动态程序集中CompileToMethod创建static一个新类型的方法.这工作,代码很快.
但是用户可以输入任意表达式,结果是如果用户调用非公共函数或访问表达式中的非公共字段,则System.MethodAccessException在调用委托时抛出(在非公共方法的情况下) .
我可以在这里做的是创建一个新的ExpressionVisitor,检查表达式是否访问非公共的东西,并Compile在这些情况下使用较慢的,但我宁愿让动态程序集以某种方式获得访问非公共成员的权限.或者找出我能做些什么Compile来减慢速度(有时候).
重现此问题的完整代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;
namespace DynamicAssembly
{
public class Program
{
private static int GetValue()
{
return 1;
}
public static int GetValuePublic()
{
return 1;
}
public static int Foo;
static void Main(string[] args)
{
Expression<Func<int>> expression = () => 10 + GetValue();
Foo = expression.Compile()(); …Run Code Online (Sandbox Code Playgroud) 我写了一个复制公共属性的简单对象复制器.我无法弄清楚为什么Dynamic方法比c#版本慢得多.
持续时间
C#方法:4,963毫秒
动态方法:19,924毫秒
请注意 - 当我在启动秒表之前运行动态方法时 - 持续时间不包括编译阶段.我在调试和发布模式下,在x86和x64模式下运行,从VS和命令行运行,结果大致相同(动态方法慢400%).
const int NBRECORDS = 100 * 1000 * 1000;
public class Person
{
private int mSomeNumber;
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime DateOfBirth { get; set; }
public int SomeNumber
{
get { return mSomeNumber; }
set { mSomeNumber = value; }
}
}
public static Action<T1, T2> CreateCopier<T1, T2>()
{
var meth = new DynamicMethod("copy", null, new Type[] { typeof(T1), …Run Code Online (Sandbox Code Playgroud) 我正在研究动态实例化类的自动化.
我决定写一个表达式树,它会生成一个Func,可以为我实例化我的类.但是,我注意到我的性能降低了3倍Func,而不是简单地使用new.
根据我对表达树和调用函数的了解,性能差异应该几乎不存在(可能是20-30%,但远不及慢3倍)
首先,这是我正在构建的表达式
public Expression<Func<A1, T>> BuildLambda<T, A1>(string param1Name)
{
var createdType = typeof(T);
var param = Expression.Parameter(typeof(A1), param1Name);
var ctor = Expression.New(createdType);
var prop = createdType.GetProperty(param1Name);
var displayValueAssignment = Expression.Bind(prop, param);
var memberInit = Expression.MemberInit(ctor, displayValueAssignment);
return
Expression.Lambda<Func<A1, T>>(memberInit, param);
}
Run Code Online (Sandbox Code Playgroud)
然后我继续编译它(我只做一次)
var c1 = mapper.BuildLambda<Class1, int>("Id").Compile();
Run Code Online (Sandbox Code Playgroud)
然后我像这样调用我的Func
var result = c1.Invoke(5);
Run Code Online (Sandbox Code Playgroud)
当我把这最后一部分放在一个循环中并将它与类似的东西进行比较时
var result = new Class1() { Id = 5 };
Run Code Online (Sandbox Code Playgroud)
我做了几个测试,比较两者的性能,这就是我最终得到的结果:
100,000 Iterations - new: 0ms. | Func 2ms. …Run Code Online (Sandbox Code Playgroud) 我有一个简单的场景,我试图在一个库存对象列表上测试表达式编译树的性能.下面是代码
表达式编译树的性能比静态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 = …Run Code Online (Sandbox Code Playgroud)