我有一个非常简单的SortedSet和一个CompareTo方法,它根据两个类字段进行排序。随着它的使用,这个集合可以变得非常大(百万+对象),并随着时间的推移而增长和增长。我一直在使用一个简单的Contains方法来确定集合中是否已存在新值...
作为一项学术练习,我正在使用Linq(我相当新的)做一些基准测试,以达到同样的效果,并且我确信我对Linq有一些了解,因为我不能远远接近它性能,我想知道是否有一些Linq大师可以给我一个关于如何加快它的指针。
所以......对象有一个看起来像这样的CompareTo:
public int CompareTo(EntityHistoryChange other)
{
int recordIdComp = Recordid.CompareTo(other.Recordid);
int tableIdComp = Tablename.CompareTo(other.Tablename);
if (recordIdComp == 0 && tableIdComp == 0)
return 0;
else if (recordIdComp != 0)
return recordIdComp;
else
return tableIdComp;
}
简单列表上的相应Linq查询:
var handledChange = from thisChange in handledChanges
where thisChange.Recordid == recordId
&& thisChange.Tablename == tableName
select thisChange;
我想结果不应该让我感到惊讶......
Linq Lookup on 18772 rows: 46 ms
SortSet Lookup on 18772 rows: 3 ms
所以问题是 - 什么是等效的LINQ机制?
答案 0 :(得分:2)
Linq永远不会像这样快,因为Linq看到的对象不是SortedSet,而是IEnumerable<T>
,除了“给我一个对象列表”之外没有语义。你根本没有利用Set'ness。
SortedSet<T>
排序的关键是什么?这不是通过SortedSet.Contains查找,那么你可以查看表名吗?
答案 1 :(得分:0)
许多LINQ运算符检查IEnumerable<T>
以外的接口并使用它们。
E.g。 Count
将检查ICollection<T>
并使用其Count属性,而不是遍历整个集合。查看这些(在基准之外)的唯一方法是查看IL(或使用Refector),当然实现可能会随着新的.NET版本(包括SP)而改变。例如。在.NET中,r.5 Count
没有检查ICollection
,但它确实在4中。
答案 2 :(得分:0)
LINQ不是要替换给定作业使用正确的数据结构。它只是使处理这些数据结构更容易。如果要将数据存储在SQL数据库中,则仍需要在数据库上使用智能索引来提高性能。同样,对于LINQ to Objects,您需要在适当的情况下利用SortedSet<T>
等数据结构。
所以问题的答案是:模拟Contains方法的LINQ查询是:
var exists = handledChanges.Any(c => c.Recordid = recordId && c.Tablename == tableName);
但是如果你正在使用LINQ to Objects,那么在数据结构上使用Contains方法永远不会达到与快速查找相同的性能。如果您正在使用LINQ to SQL或LINQ to Entities,这将提供优化的SQL查询,该查询可以非常快速地运行。
顺便说一句,如果你的目标是在内存中集合上获得更快的查找,你可能需要考虑使用带有自定义IEqualityComparer的HashSet。它的Contains方法在数百万个对象的集合上应该与在10的集合上一样长。