我在SO {
上使用的micro ORM上阅读了这篇文章作者展示了这个堆栈跟踪:
System.Reflection.Emit.DynamicMethod.CreateDelegate
System.Data.Linq.SqlClient.ObjectReaderCompiler.Compile
System.Data.Linq.SqlClient.SqlProvider.GetReaderFactory
System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.Compile
System.Data.Linq.CommonDataServices+DeferredSourceFactory`1.ExecuteKeyQuery
System.Data.Linq.CommonDataServices+DeferredSourceFactory`1.Execute
System.Linq.Enumerable.SingleOrDefault
System.Data.Linq.EntityRef`1.get_Entity
然后说:
在上面的描述中你可以看到'EntityRef'正在烘焙一个方法,这不是问题,除非它每秒发生100次。
有人可以通过“烘焙方法”解释堆栈跟踪与他的意思有关吗?为什么会出现性能问题?
答案 0 :(得分:10)
当您执行以下操作时:
int[] items = whatever;
IEnumerable<int> query = from item in items where item % 2 == 0 select item;
然后编译器将其转换为:
static bool Predicate(int item) { return item % 2 == 0; }
...
IEnumerable<int> query = Enumerable.Where<int>(items, new Func<int, bool> (Predicate));
即,编译器为该方法生成IL。在运行时构建查询对象时,Where返回的对象保留在谓词的委托上,并在必要时执行谓词。
但是如果你愿意,可以在运行时为代理构建 IL。你所做的是将谓词的主体保存为表达式树。在运行时,表达式树可以动态地将自身编译为全新的IL;基本上我们启动了一个非常简化的编译器,它知道如何为表达式树生成IL。这样,您可以在运行时更改谓词的详细信息,并重新编译谓词,而无需重新编译整个程序。
该评论的作者使用“烘焙”作为“动态轻量级代码生成”的俚语。
答案 1 :(得分:1)
它指的是在运行时动态创建方法,例如使用表达式树。将表达式树编译为方法并返回已编译方法的委托可称为“烘焙”该方法。
答案 2 :(得分:0)
这是一种奇特的方式,说他们使用Reflection.Emit发出动态代码。一个众所周知的缓慢过程。