2008-09-29 68 views
6

我們有幾個操作,我們正在做大量的大字符串連接,並且最近遇到了內存不足異常。不幸的是,調試代碼不是一種選擇,因爲這發生在客戶現場。因此,在查看代碼大修之前,我想問一下:StringBuilder對於大型字符串的RAM消耗特性是什麼?什麼是StringBuilder的RAM消耗?

尤其是它們與標準字符串類型進行比較。字符串的大小超過了10 MB,我們似乎遇到了大約20 MB的問題。

備註:這不是關於速度,而是RAM。

回答

6

這是一個很好的研究String Concatenation vs Memory Allocation

如果你可以避免連接,那就做吧!

這是沒有道理的,如果你不 有來連接,但希望你 源代碼好看,使用 第一種方法。如果它是單個字符串,它將被優化爲 。

不要使用+ =連接。幕後發生了太多的變化 ,這些都不是我的代碼中最明顯的 。 I 建議使用String.Concat() 明確地使用任何過載(2 字符串,3個字符串,字符串數組)。 這將清楚地顯示你的代碼 沒有任何意外,而 允許自己保持對 的效率檢查。

嘗試估計一個StringBuilder的目標大小。

更準確,你可以估算 需要的尺寸,更低臨時 字符串的StringBuilder將不得不 創建,以增加其內部 緩衝區。

當性能出現問題時,不要使用任何Format()方法。

開銷太大參與 解析格式,當你可以 構建陣列出件時 所有正在使用的是{X}取代。 格式()有助於提高可讀性,但 當您使用 時,需要執行的操作之一是將應用程序的所有可能的性能提高到 。

10

每次StringBuilder用完空間時,它會重新分配一個新的緩衝區兩倍於原始緩衝區的大小,複製舊的字符,並讓舊的緩衝區得到GC'd。有可能你使用的足夠多(稱之爲x),使得2x大於你允許分配的內存。您可能需要爲您的字符串確定一個最大長度,並將其傳遞給StringBuilder的構造函數,以便預先分配,並且不受雙倍重新分配的支配。

-2

我不知道字符串生成器的確切內存模式,但常用的字符串不是一個選項。

當您使用公共字符串時,每個連接都會創建另一對字符串對象,並且內存消耗會飛漲,從而導致垃圾收集器被頻繁調用。

string a = "a"; 

//creates object with a 

a += "b" 

/creates object with b, creates object with ab, assings object with ab to "a" pointer 
+0

我建議你在依賴這個之前檢查字符串類的實現。 至少在Java中,它比現在更聰明。我沒有檢查.net的實現,但我不明白爲什麼他們不會進行相同的優化。 – 2008-09-29 16:55:32

1

Strigbuilder是一個完美的解決由連接字符串引起的內存問題的解決方案。

爲了回答您的具體問題,Stringbuilder與常規字符串相比具有恆定的開銷,其中字符串的長度等於當前分配的Stringbuilder緩衝區的長度。緩衝區可能是結果字符串大小的兩倍,但是在連接到Stringbuilder之前不會再有內存分配,直到緩衝區被填充,所以它確實是一個很好的解決方案。

與字符串相比,這是優秀的。

string output = "Test"; 
output += ", printed on " + datePrinted.ToString(); 
output += ", verified by " + verificationName; 
output += ", number lines: " + numberLines.ToString(); 

此代碼具有存儲爲代碼,則在所述的方法創建,一個來自可變2文字四根弦,但它使用六個獨立的中間弦,其越來越長。如果這種模式繼續下去,它會以指數速率增加內存使用量,直到GC開始清理它。

+0

對於低估這一點的人,請解釋。 – torial 2008-09-29 20:58:22

3

您可能感興趣的繩索數據結構。本文:Ropes: Theory and practice解釋了它們的優點。也許有一個.NET的實現。

[更新,回覆評論] 使用較少的內存嗎?在文章中搜索內存,你會發現一些提示。
基本上,是的,儘管結構開銷,因爲它只是在需要時增加內存。當使用舊的緩衝區時,StringBuilder必須分配一個更大的緩衝區(它可能已經浪費了空的內存)並丟棄舊的緩衝區(這將被垃圾收集,但仍然可以使用大量的內存)。

我還沒有找到.NET的實現,但至少有一個C++實現(在SGI的STL中:http://www.sgi.com/tech/stl/Rope.html)。也許你可以利用這個實現。請注意我參考的頁面有關於內存性能的工作。

請注意,繩索不是解決所有問題的方法:它們的用處很大程度上取決於您如何構建大型字符串以及如何使用它們。文章指出了優點和缺點。

+0

有關它如何執行RAM方式而不是速度方面的任何數據? – torial 2008-09-29 20:59:29

相關問題