比较集合方法中的性能

时间:2014-03-18 21:04:15

标签: c# .net linq collections

我有一个方法Comparer,我比较了两个集合的对象的一些属性。

public IEnumerable<Product> Comparer(IEnumerable<Product> collection, IEnumerable<Product> target,  string comparissonKey)
{
    var count = 0;
    var stopWatch = new Stopwatch();                

    var result = new ConcurrentBag<Product>();

    var parallelOptions = new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount * 2 };

    Parallel.ForEach(collection, parallelOptions, obj =>
    {
        count++;
        if (count == 60000)
        {
            stopwatch.Stop();
            //breakpoint
            var aux = stopwatch.Elapsed;
        }
        var comparableObj = obj;
        comparableObj.IsDifferent = false;
        bool hasTargetObject = false;
        comparableObj.Exist = true;

        Product objTarget = null;
        foreach (Product p in target)
        {
            if (obj.Key == p.Key)
            {
                objTarget = p;
                break;
            }
        }

        if (objTarget != null)
        {
           //Do stuff
        }

        if (hasTargetObject) return;

        if (comparableObj.IsDifferent)
        {
            //Do Stuff
        }
    });

    return result.ToList();
}

如果我像这样执行这个方法,我会在aux变量中断几乎50秒到断点。 如果我评论第二个foreach(在Parallel.Foreach内)它会在不到1秒的时间内中断。

我需要使用Key在目标集合中找到相应的对象,所以我做了第二个foreach。我使用LINQ where子句但没有得到更好的结果。有什么建议可以改善这种方法的表现吗?

2 个答案:

答案 0 :(得分:1)

您可以使用字典来提高效果:

    public IEnumerable<Product> Comparer(IEnumerable<Product> collection, IEnumerable<Product> target, string comparissonKey)
    {
        var count = 0;
        var stopWatch = new Stopwatch();

        var result = new ConcurrentBag<Product>();
        var parallelOptions = new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount * 2 };

        // create a dictionary for fast lookup
        var targetDictionary = target.ToDictionary(p => p.Key);

        Parallel.ForEach(collection, parallelOptions, obj =>
        {
            count++;
            if (count == 60000)
            {
                stopwatch.Stop();
                //breakpoint
                var aux = stopwatch.Elapsed;
            }
            var comparableObj = obj;
            comparableObj.IsDifferent = false;
            bool hasTargetObject = false;
            comparableObj.Exist = true;

            Product objTarget = null;

            // lookup using dictionary
            if (targetDictionary.TryGetValue(obj.Key, out objTarget))
            {
                //Do stuff
            }

            if (hasTargetObject) return;

            if (comparableObj.IsDifferent)
            {
                //Do Stuff
            }
        });

        return result.ToList();
    }

答案 1 :(得分:1)

如果Key确实是一个关键词 然后使用HashSet,因为它有IntersetWith并且正在快速吸烟 http://msdn.microsoft.com/en-us/library/bb359438.aspx

在您的类产品上,您需要覆盖GetHashCode和Equals
使用GetHashCode的密钥

Override GetHashCode on overriding Equals