C# 数组或 List(T) 以获得最佳性能

Posted

技术标签:

【中文标题】C# 数组或 List(T) 以获得最佳性能【英文标题】:C# array or List(T) for max performance 【发布时间】:2018-12-19 13:13:11 【问题描述】:

任何人都可以建议在这种情况下选择什么: 我有 100-500 个(它们是动态的,意味着在每个请求中它们的数量总是不同的)元素,其中包含元素名称、类型、id。目前我使用多维数组

public static Object[,] Item_data = new Object[500, 3];

然后我将数据设置为数组:

int found_items = 0;
        foreach (Object m in queryCollection)
        
            Item_data[found_items, 0] = m[0];

            Item_data[found_items, 1] = m[1];

            Item_data[found_items, 2] = m[0];
            found_plans++;
        

我还有 8 个其他相同的结构数组填充不同的数据,它花费大约 0.8-1.5 秒,问题是我需要按 id、名称和类型对这些数组 ASC、DESC 进行排序,如果我手动使用另一个循环对数据进行排序需要时间,所以我注意到 List(T) 它具有排序功能,但根据这些主题,它的速度要慢得多:

Performance of Arrays vs. Lists

https://jacksondunstan.com/articles/3058

https://softwareengineering.stackexchange.com/questions/221892/should-i-use-a-list-or-an-array

在这种情况下是否值得使用 List(T)?或者任何人都可以推荐其他东西吗?

【问题讨论】:

你对它进行了基准测试吗?相关阅读:ericlippert.com/2012/12/17/performance-rant 解决方案是否适合您在很大程度上取决于您的数据和周围环境。因此,在您的 特殊 情况下,依赖处理 general 性能方面的其他主题并不一定是有意义的。至少第三个链接向您表明,这实际上取决于您的用例使用哪种数据结构。除此之外,考虑这一点通常并不重要,因为实际性能瓶颈通常在其他地方。 对于初学者来说,使用Object 处理可能具有原始类型(如int)的数据会导致访问效率非常低。多维数组造成访问不便。首先从语言中显而易见的内容开始(即具有属性的类,您使用内置的.OrderBy 进行排序)。只有当这还不够快时,您才应该开始考虑花哨的东西,例如,使用在线排序算法或 B 树对数据进行排序,而不是之后。另外,永远不要忘记数据库是一回事,很多聪明人都对它们进行了优化。 @JeroenMostert 我使用对象数组,因为它的存储类型如 RegistryKind、Windows 安全等,所以对象是最好的解决方案。而且我无法访问排序数据库,因为它非常有限,所以我对软件而不是数据库部分进行排序。 你的超快数组使用什么排序代码? 【参考方案1】:

如果您需要快速访问该结构,您是否尝试过使用 Dictionary<> ? 您可以使用System.Linq对其进行排序

https://msdn.microsoft.com/en-us/library/xfhwa508%28v=vs.110%29.aspx

【讨论】:

在插入新值、删除特定索引 id 处的值以及使用类型 string、int、double 等方面,它的速度是否相同? 它们在添加新项目时具有相同的复杂性。但是 Dictionary 在删除或查找项目时具有更好的性能(因为它们正在使用密钥)。如果您有唯一的 ID,则可以将它们用作密钥。然后查找或删除特定项目会更快。 Dictionary 和 List 在速度上有什么区别?,看来字典准备要简单得多。 我没有实际的基准,但 List 主要是 O(n) 而 Dictionary 主要是 O(1) 复杂度(我们谈论的是秒与毫秒)。 好的,我想我得到了我需要的一切。谢谢。主题标记为答案。我可以给rep+,但声望太低了。【参考方案2】:

List<T> 内部实现了T[],只是它的灵活性和内部在容量结束时不断扩展。因为对于所有重要的操作,它在内部做数组操作,只是为动态扩展提供了方便。

根据你的问题:

我有 100-500 个(它们是动态的,意味着在每次请求时它们的数量总是不同的)

现在理想情况下,new List<T>(100 / 200) 是一个更好和最优化的选择,因为它会动态扩展以包含更多数据,但请注意没有多维列表的概念,如多维数组。尽管您可以使用类似于List<List<T>> 的东西来获得类似于锯齿状数组T[][] 的东西,但是使用List<T> 无法替代T[,]。多维数组适用于定义了上下界的矩阵形式的数据。

这和内存优化有关,涉及到各种操作,List<T>暴露了Array操作(就地排序),List<T>T[]也暴露了IEnumerable<T>的Linq扩展API,这些都不是由于额外的内存分配,它们与就地排序一样高效,并且它们是在通用接口而不是特定数据结构上完成的。

现在关于各种用例:

如果都是枚举/数据顺序处理,那么T[]List<T>都是高效的,实际上它们提供了一个二分查找选项,使得查找排序后的数据为O(LogN),比@987654336好很多@,实际上你可以考虑SortedList<TK,TV>,它默认是排序的,但只是它内部的IDictionary,类似的是SortedDictionary<TK,TV>,对于非常快速的元素搜索没有IDictionary<TK,TV>的替代品,它是@987654341 @。

以上所有观点都只是理论 找到合适的内存和性能组合的最佳方法是使用各种数据结构测试您的用例,您将能够找到适合所有用例的最小的妥协

【讨论】:

微软表明 list 可以创建对象,这样我可以将多维数组扔到 thrash bin 并使用 List msdn.microsoft.com/en-us/library/6sh2ey19(v=vs.110).aspx 正如我所提到的,您需要有一个非多维数组用例才能使 List<T> 工作,更重要的是尝试针对流行数据结构的各种用例,例如 Dictionary<TK,TV>跨度>

以上是关于C# 数组或 List(T) 以获得最佳性能的主要内容,如果未能解决你的问题,请参考以下文章

Ram 或 DB 表中的表,以获得最佳性能

如何将 Argb32 加载到特征矩阵中以获得最佳性能?

以在 Oracle 和 SQL Server 中获得最佳性能为目标的数据建模

在 Postgres 中,如何匹配多个“标签”以获得最佳性能?

Spring Batch 异步处理器配置以获得最佳性能

我应该为我的库和应用程序使用哪些编译器标志以获得最佳性能 NDK (CMake)