SortedSet <t>包含vs Linq查询</t>

时间:2010-08-05 17:03:23

标签: .net linq-to-objects

我有一个非常简单的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机制?

3 个答案:

答案 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的集合上一样长。