2011-10-23 41 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