大数据集合处理性能基准测试

在处理数十亿条记录时,选择最佳的数据结构是一个挑战。本文将探讨在非实时操作系统环境下,如何通过性能基准测试来确定最佳的数据结构。在阅读本文之前,请考虑以下要点:操作系统不是实时操作系统,因此将展示的是平均结果;二分查找(Binary Search)需要排序,而排序的时间复杂度在本研究中被忽略,可以使用任何方便的排序算法,并将其复杂度加到结果之上。

什么是好的解决方案?

好的解决方案是在最小化时间成本的同时,提供最大的速度和容量。显然,由于工作操作系统不是实时操作系统,区分出了确定性的问题。但是,如果能想出一个更确定性的解决方案,那就再好不过了。

机器规格

执行所有单元测试的机器具有以下硬件和软件配置:

  • CPU: Intel (R) Core (TM) i7-6650U @ 2.2GHz (4 CPUs), ~2.2GHz
  • RAM: 8 GB
  • 操作系统: Windows 10 Pro
  • 开发环境: Visual Studio 2017

本文将对C#.NET语言中处理大数据集合的性能进行基准测试,从容量、速度和时间成本的角度来探讨。选择的集合类型包括数组(Array)、列表(List)和字典(Dictionary)。

托管代码是由微软创造的一个术语,指的是在CLR(如.NET或Mono)的管理下执行的代码。有关托管代码和非托管代码的更多信息,请访问以下链接:

  • MSDN上的托管/非托管代码互操作性概述
  • WiKi上的托管代码

由于CLR的干扰,托管代码的执行可能不那么确定性,因此提供一个提供粗略估计的基准测试可能非常有用。然而,在考虑这个基准测试的结果之前,最好回答以下两个问题:

  • 大数据集合的最大大小是多少?
  • 数据类型是什么?将处理什么样的数据?整数、文本等。

正如将从结果中看到的,每个集合的性能高度依赖于集合的大小和正在使用的算法,例如搜索。

测试方法

请注意,所有测试都是在非实时操作系统中进行的。这意味着结果不是确定性的。为了克服这种非确定性结果,执行了100次所有测试,所以将看到的是100次迭代的平均时间。

考虑的操作是创建和搜索,因为这两个操作是最昂贵且最重要的。

搜索操作

以下方法展示了搜索测试的模式,如所见,考虑的总是最坏的情况,这意味着正在寻找的项目几乎在集合的末尾。搜索算法被包围在包含时钟的Monitor对象中,该对象在进入搜索主体之前开始,并在集合中找到项目后立即停止:

[TestMethod] [TestCategory("Owner [C# Array]")] public void FindByForInArry() { try { string find = mocklbl + (capacity - 1); Monitor.Reset(); for (int j = 0; j < iteration; j++) { string found = ""; Monitor.Start(); for (int i = 0; i < capacity; i++) { if (array[i] == find) { found = array[i]; break; } } Monitor.Stop(); Assert.AreEqual(find, found); } Monitor.LogAvgElapsed("FindByForInArray"); } catch (Exception ex) { Monitor.WriteLog(ex.Message); throw ex; } }

搜索时间复杂度

从上面的图表中,可以列出一些有趣的事实:

  • 二分查找(第二列)总是需要0毫秒来找到项目。
  • 在1000000(100万)记录和10000000(1000万)记录之间的时间变化在所有搜索算法中呈指数级变化(比较绿线和黄线)。
  • 字典数据结构无法处理10000000(1000万)记录(这就是为什么绿线没有超过FindByFindInArray)。
  • 通过枚举进行查找是最差的搜索算法(见第三列)。
  • 在列表和数组上搜索算法的顺序从最好到最差是:二分查找、Find、For循环和枚举对象。
  • 超过100000(10万)记录后,数据结构和搜索算法之间没有显著差异。
  • 如果不需要键值对,则使用带有二分查找的列表是最好的选择。

创建时间复杂度

[TestMethod] [TestCategory("Owner [C# Array]")] public void FetchMockData(long capacity = 1000) { try { capacity = Monitor.BySize; for (int j = 0; j < 100; j++) { Monitor.Reset(); Monitor.Start(); array = new string[capacity]; for (int i = 0; i < capacity; i++) { array[i] = mocklbl + i; } Monitor.Stop(); } Monitor.WriteLog($"The creation of array took:{Monitor.AvgElapsedInMiliseconds}"); } catch (Exception ex) { Monitor.WriteLog(ex.Message); throw ex; } }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485