NDepend搜索更快的收集机会

时间:2016-07-22 17:33:30

标签: c# .net performance ndepend cqlinq

我有一个巨大的遗留代码库,我想优化它,让它更快。 出于这个原因,我考虑寻找机会,用HashSets和Dictionaries替换列表和数组。

在.NET Framework Usage / System.collection

下有以下NDepend查询
// <Name>Caution with List.Contains()</Name>
let containsMethods = ThirdParty.Methods.WithFullNameIn(
   "System.Collections.Generic.List<T>.Contains(T)",
   "System.Collections.Generic.IList<T>.Contains(T)",
   "System.Collections.ArrayList.Contains(Object)")

from m in Application.Methods.UsingAny(containsMethods) 
select m

这个查询还不够。它将使用以下代码列出一个函数:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ListOptimisation
{
    class Program
    {
        static void Main(string[] args)
        {
            int aLength = 10000;
            List<int> aNumbers2Search = Enumerable.Range(0, aLength).ToList();

            List<int> aTestList = Enumerable.Range(0, aLength).ToList();
            int[] aTestArray = Enumerable.Range(0, aLength).ToArray();

            HashSet<int> aTestHash = new HashSet<int>(Enumerable.Range(0, aLength));
            Dictionary<int, int> aTestDictionary = new Dictionary<int, int>();
            for(int i = 0; i < aLength; ++i)
            {
                aTestDictionary.Add(i, i);
            }

            Search(aTestList, aNumbers2Search);
            SearchIList(aTestList, aNumbers2Search);
            SearchIEnumerable(aTestList, aNumbers2Search);
            Search(aTestArray, aNumbers2Search);
            SearchIList(aTestArray, aNumbers2Search);
            SearchIEnumerable(aTestArray, aNumbers2Search);
            Search(aTestHash, aNumbers2Search);
            SearchIEnumerable(aTestHash, aNumbers2Search);
            Search(aTestDictionary, aNumbers2Search);
        }

        private static void Search(List<int> testList_in, List<int> numbers2Search_in)
        {
            numbers2Search_in.ForEach(x => testList_in.Contains(x));
        }

        private static void Search(HashSet<int> testHash_in, List<int> numbers2Search_in)
        {
            numbers2Search_in.ForEach(x => testHash_in.Contains(x));
        }

        private static void Search(Dictionary<int, int> testDictionary_in, List<int> numbers2Search_in)
        {
            numbers2Search_in.ForEach(x => testDictionary_in.ContainsKey(x));
        }

        private static void Search(int[] testArray_in, List<int> numbers2Search_in)
        {
            numbers2Search_in.ForEach(x => testArray_in.Contains(x));
        }

        private static void SearchIList(IList<int> testIList_in, List<int> numbers2Search_in)
        {
            numbers2Search_in.ForEach(x => testIList_in.Contains(x));
        }

        private static void SearchIEnumerable(IEnumerable<int> testIEnumerable_in, List<int> numbers2Search_in)
        {
            numbers2Search_in.ForEach(x => testIEnumerable_in.Contains(x));
        }
    }
}

更好的查询是这个:

// <Name>Caution with List style contains</Name>
let containsMethods = ThirdParty.Methods.WithSimpleName("Contains").Except(ThirdParty.Methods.WithFullNameIn("System.Collections.Generic.HashSet<T>.Contains(T)"))

from m in Application.Methods.UsingAny(containsMethods) 
select m

//<Description>
// Alternative to Caution with List.Contains()
//</Description>

这将列出4个函数(List,IList,int [],IEnumerable)。 我是关于CQLinq的新手。 我的问题是:

  • 是否有人可以编写更好的查询来检测可能的错误.NET容器使用情况(不仅仅是包含,还包括其他可能的操作)?
  • 您如何或是否会检测到错误的容器使用情况?

最后一条评论,一些我们的业务逻辑处理大量数据,因此具有正确的容器,数据结构和算法计数。

2 个答案:

答案 0 :(得分:1)

这不是优化性能问题的好方法。除非您处理大量列表,否则此优化对您的系统会产生轻微影响。

使用performance profiling software可以获得更好的结果。如果您希望通过搜索某些代码模式来提高性能,请尝试搜索嵌套循环和昂贵的代码,例如文件和数据库相关的方法。

答案 1 :(得分:1)

确实尝试使用List<T>.Contains()调用替换Hashset<T>.Contains()次调用不是微优化,并且可以显着提高性能。实际上,根据我的经验,重构依赖于O(1)散列集搜索的算法是提高性能的最佳方法之一。

您编写的CQLinq查询是识别某些潜在慢点的第一步。但是,要开始重构,您必须 1)审核代码以在运行时评估集合大小,并且2)在实际情况下使用performance profiling tool来评估这些潜在的慢点是否有对性能的影响,以及查找与查询不匹配的其他慢点。