2011-10-23 40 views
1

我想对ArrayList(System.Collections - C#)在开始时插入项目的速度进行性能测试。性能测试ArrayList in C#

我已经打开一个文件用于读取数据线,建立一个秒表又创造了一个ArrayList添加项目(如下):

Stopwatch watchTime = new Stopwatch(); 
Double totalTime = 0; 
using (StreamReader readText = new StreamReader("data.txt")) 
{ 
    String line; 
    Int32 counter = 0; 
    while ((line = readText.ReadLine()) != null) 
    { 
    } 
} 

我使用计数器保持跟踪有多少物品进入ArrayList。

在while循环,我有以下几点:

watchTime.Start(); 
theList.Insert(0, line); 
watchTime.Stop(); 
Double time = watchTime.Elapsed.TotalMilliseconds; 
totalTime = totalTime + time; 
Console.WriteLine(time); 
watchTime.Reset(); 
++counter; 

这是如何快速插入项目检查到ArrayList中发生之初的正确方式?

我做了另一个程序,做了完全相同的事情 - 但是使用一个字典。令我惊讶的是,这个ArrayList插入项目所花费的时间要比Dictionary所需的时间长得多。这是为什么发生?

+0

您可以启动一个性能分析器,例如[ANTS Profiler](http://www.red-gate.com/products/dotnet-development/ants-performance-profiler/)并查看性能正在发生的变化成。 –

+0

为什么要测量'ArrayList'。从.NET 2.0开始已经被弃用了。 –

+0

@亨克抱歉,您能向我解释为什么会出现这种情况吗?秒表仅包围插入 - 而不是其他任何东西。 – BigBug

回答

4

嗯,我建议:

  • 不要使用文件以获取输入。为什么要将IO引入系统?
  • 除了反复停止和启动秒表,只需将很多行插入ArrayList而无需执行其他任何操作。时间一个大循环。

至于为什么Dictionary<,>便宜 - 你没有表现出任何代码,但基本上你插入的代码将不得不在每次插入ArrayList的全部内容复制。 ArrayList维护一个数组来保存列表的内容。通常数组大于列表 - 当你在结尾添加一个元素时,如果只能将新值赋给数组的右边位。如果将它插入到其他地方,它必须复制数组的元素以为新元素“腾出空间”。

你会发现它在结尾添加的速度要快很多。 Dictionary<,>使用完全不同的数据结构;它必须在某些方面调整大小,但总的来说,它们的特点会有很大不同。

(我会建议你使用List<T>,而不是ArrayList入手,如果你愿意,你可以在开始反复插入一个集合,考虑LinkedList<T> - 或者可能是队列或堆栈,这取决于你想要什么稍后再做。)

+0

谢谢,读这实际上是非常有用的解释为什么我看到ArrayList需要这么多时间只是在开始插入一些东西。我真的想要性能测试一个ArrayList与一个字典只是为了了解它是如何工作的,以及为什么在插入不同的地方时可能比另一个更慢......感谢您的回应 - 非常有帮助。 – BigBug

+0

@BlueButtons:值得了解的是,在列表排序时,字典不是 - 您并不真正插入字典中的“地点”,只需将键映射到值。 –

+0

@ Jon这是否意味着您使用的字符串类型(即int或字符串)是否也会影响插入的速率?我猜它会的。 – BigBug

1

太复杂了。在最后添加的列表中读取“正常”文件,然后将第一个列表添加到第二个列表中。否则,你正试图对太多的小动作进行基准测试,并且你会遇到精确性问题。

一些代码

ArrayList tempList = new ArrayList(); 

using (StreamReader readText = new StreamReader("data.txt")) 
{ 
    String line; 
    Int32 counter = 0; 
    while ((line = readText.ReadLine()) != null) 
    { 
     tempList.Add(line); 
    } 
} 

ArrayList theList = new ArrayList(); 

Stopwatch watchTime = Stopwatch.StartNew(); 

foreach (string line in tempList) 
{ 
    theList.Insert(0, line); 
} 

watchTime.Stop(); 

我要补充的是与Stopwatch可以StartStop然后Start再次,它会继续保持时间。要重置它,还有另一种方法,Restart

至于其他可能建议:

  • 使用List<string>而不是ArrayList(速度是一样的,但List<string>是类型安全的)
  • 在一般情况下,如果你只有在头部插入元素将它们插入到尾部(快得多)并“反转”索引(因此索引0是索引Count - 1,1是Count - 2等等)。 “中间”或“顶部”插入列表不是“制造”的。他们是为了“添加最后”而制作的。
+1

为什么麻烦阅读,如果唯一的目标是基准'ArrayList.Insert'?只需多次插入相同的字符串参考。 –

+0

好的,谢谢。我会试试看看我得到了什么样的结果。感谢您的回应,非常感谢。 – BigBug

+0

@JonSkeet他读文件知道有多少字符串:-)我认为他必须读一个文件,而不是他想看看有多少O(n)慢是ArrayList只是为了它。 – xanatos