[翻译]“LINQ to Objects”提供程序是否内置性能优化?
2010-03-03 00:37
471 查看
原文来自Alexandra Rusina在CSharpFAQ的:Does the “LINQ to Objects” provider have built-in performance optimization?
让我们从基础开始,可能会重复一些你已经知道的信息。在LINQ性能优化中最重要的一点,当然是延迟执行。那便意味着当你声明一个变量并分配给它一个查询字符串,其查询字符串并没有立即执行。
// 查询没有执行。
var query = from item in storage select item;
变量query现在存储着命令,查询执行被延迟直到你从变量query请求获取数据。这通常发生在如下几种情况:foreach循环,或当你调用一个聚集函数像Min,Max和Average,或当你使用ToList或ToArray方法缓存该查询结果。
// foreach循环。
foreach (var item in query)
Console.WriteLine(item);
// Count函数。
int total = query.Count();
// ToArray方法。
var cachedQuery = query.ToArray();
现在让我们来看看幕后究竟发生了什么。在查询执行的时候是否有什么编译器级的优化发生?答案是yes。然而,这里有个陷阱。从现在起我们将只讨论使用“LINQ to Objects”提供程序对IEnumerable和IEnumerable<T>集合的查询。对于其他LINQ提供程序,包括LINQ to SQL和LINQ to XML,可能应用的是不同的优化规则。
注意:人们常常认为,由于延迟执行,执行第一次查询需要花费更长时间。然而,在LINQ to Objects中,第一次执行和之后的每一次并没有差别。其他LINQ提供程序的规则可能不同(比如,这里可能有些会进行缓存),但你需要参考特定的提供程序的详细文档。
LINQ to Objects查询在下面这些情况下会做优化:
一些方法调用会被优化,如果数据源实现了一个必要的接口。下面表格列出了这些优化。
如果连续的一个或多个Select操作后面跟着连续的一个或多个Where操作,查询只会创建一个IEnumerable或IEnumerable<T>对象而不会创建中间对象。
考虑下面的查询:
var query = from item in storage
where item.Category = "Food"
where item.Price < 100
select item;
在这里,查询只会创建一个IEnumerable对象。
如果你查询一个数组或List,接口IEnumerable或IEnumerable<T>不会在foreach循环中使用枚举器。相反,在使用前会创建一个数组或List的简单for循环,元素被直接访问。
此外,where操作符实现了简单的if语句,所以不会有中间的枚举器产生。
再次说明,其他LINQ提供程序可能拥有它们自己的性能优化规则。但上面的规则应该能给你一些怎么使用LINQ to Objects的意见。
让我们从基础开始,可能会重复一些你已经知道的信息。在LINQ性能优化中最重要的一点,当然是延迟执行。那便意味着当你声明一个变量并分配给它一个查询字符串,其查询字符串并没有立即执行。
// 查询没有执行。
var query = from item in storage select item;
变量query现在存储着命令,查询执行被延迟直到你从变量query请求获取数据。这通常发生在如下几种情况:foreach循环,或当你调用一个聚集函数像Min,Max和Average,或当你使用ToList或ToArray方法缓存该查询结果。
// foreach循环。
foreach (var item in query)
Console.WriteLine(item);
// Count函数。
int total = query.Count();
// ToArray方法。
var cachedQuery = query.ToArray();
现在让我们来看看幕后究竟发生了什么。在查询执行的时候是否有什么编译器级的优化发生?答案是yes。然而,这里有个陷阱。从现在起我们将只讨论使用“LINQ to Objects”提供程序对IEnumerable和IEnumerable<T>集合的查询。对于其他LINQ提供程序,包括LINQ to SQL和LINQ to XML,可能应用的是不同的优化规则。
注意:人们常常认为,由于延迟执行,执行第一次查询需要花费更长时间。然而,在LINQ to Objects中,第一次执行和之后的每一次并没有差别。其他LINQ提供程序的规则可能不同(比如,这里可能有些会进行缓存),但你需要参考特定的提供程序的详细文档。
LINQ to Objects查询在下面这些情况下会做优化:
一些方法调用会被优化,如果数据源实现了一个必要的接口。下面表格列出了这些优化。
LINQ方法 | 优化 |
Cast | 如果数据源已经对给定的类型T实现接口IEnumerable<T>,则会直接返回数据序列而不需要转换。 |
Contains | 如果数据源实现了接口ICollection或ICollection<T>,其接口的相应的方法会被使用。 |
Count | |
ElementAt | 如果数据源实现了接口IList或IList<T>,接口的Count方法和索引器会被使用。 |
ElementAtOrDefault | |
First | |
FirstOrDefault | |
Last | |
LastOrDefault | |
Single | |
SingleOrDefault |
考虑下面的查询:
var query = from item in storage
where item.Category = "Food"
where item.Price < 100
select item;
在这里,查询只会创建一个IEnumerable对象。
如果你查询一个数组或List,接口IEnumerable或IEnumerable<T>不会在foreach循环中使用枚举器。相反,在使用前会创建一个数组或List的简单for循环,元素被直接访问。
此外,where操作符实现了简单的if语句,所以不会有中间的枚举器产生。
再次说明,其他LINQ提供程序可能拥有它们自己的性能优化规则。但上面的规则应该能给你一些怎么使用LINQ to Objects的意见。
相关文章推荐
- linq to sql 系列之 linq to sql性能优化技巧
- linq to sql 系列之 linq to sql性能优化技巧
- Linq-to-SQL性能优化提升实践
- LINQ to Sql系列四 性能优化总结
- linq to sql 系列之 linq to sql性能优化技巧
- 也记一次性能优化:LINQ to SQL中Contains方法的优化
- linq to sql 系列之 linq to sql性能优化技巧
- java程序中比较常见的四种判断是否为空的性能优化比较
- WPF DataGrid 和LINQ to SQL示例程序之一 (提供源代码下载)
- NHibernate初学者指南(15):使用LINQ to NHibernate提供程序查询数据
- 【翻译】Pro LINQ Language Integrated Query in C# 2008 -- 第三章 (LINQ TO Objects) 第三节
- LINQ to Objects / LINQ to SQL / LINQ to XML 示例程序下载
- linq to sql 系列之 linq to sql性能优化技巧
- 【翻译】Pro LINQ Language Integrated Query in C# 2008 -- 第三章 (LINQ TO Objects) 第二节
- 【翻译】Pro LINQ Language Integrated Query in C# 2008 -- 第三章 (LINQ TO Objects) 第一节
- ASP.NET程序性能优化(一)
- LINQ to SQL 性能 10 Tips
- lua程序性能优化(字符串连接与格式化)
- 查询表达式和LINQ to Objects
- 优化程序性能