3

當RowCollection是50000+,因此我需要使內存更有效。該函數只需構造RowCollection中存儲的行索引的逗號分隔字符串即可。任何人都可以在下面找到任何明顯的內存飢餓操作?VB.net需要內存高效功能

N.B RowCollection只包含存儲爲整數的行索引列表。

Private Function GetCommaSeparatedString(ByRef RowIndexes As ArrayList) As String 
     Dim RowString As String = String.Empty 

     'Build a string of the row indexes 
     'Add one onto each index value so our indexes begin at 1 
     For Each Row In RowIndexes 
      RowString += CInt(Row.ToString) + 1 & "," 
     Next 

     'Remove the last comma 
     If RowString.Length > 0 Then 
      RowString = RowString.Substring(0, RowString.Length - 1) 
     End If 

     Return RowString 
    End Function 

在此先感謝。

+1

正確的拼寫是「分離」的。 – 2010-08-31 16:07:32

+0

在附註中,爲什麼'ArrayList'?這看起來像'List '的工作。 – 2010-08-31 19:26:39

回答

4

我不確定你爲什麼會出現內存錯誤,除非你的行的字符串表示是非常大的,因爲你永遠不會有超過一個或兩個非垃圾回收的字符串。

但是,你的方法可怕的低效率,因爲它花費了很多時間複製半建的字符串的內容。構建大型字符串時,StringBuilder更合適,因爲它可以在不重新創建內容的情況下進行修改。然而,在這種情況下,即使是一個StringBuilder也是一個壞主意,因爲你正在加入字符串,並且已經有了一個方法來實現它:String.Join。只需使用LINQ查詢做附加一個對指數的東西,你會得到一個班輪:

Private Function GetCommaSeparatedString(ByVal RowIndexes As ArrayList) As String 
    Return String.Join(",", From index In RowIndexes Select CInt(index) + 1) 
End Function 

我也建議不要通過引用傳遞,除非你真的需要它。你沒有修改RowIndexes,所以按值傳遞它。我也不確定你爲什麼ToString() - 索引,然後立即解析它。他們不是已經是整數嗎?只需使用CInt。

+1

我完全同意你的觀點,儘管如果可能的話,我可能會使用這種方法重新設計代碼。 – 2010-08-31 19:10:07

+0

@PhilipRieck'流出來'是什麼意思? – 2010-08-31 20:29:52

+0

@Strilanc或者創建一個IEnumerable 方法來獲取行,或者通過附加逗號等的textreader讀取它 - 也就是說,不要嘗試一次從內存中處理整個文件。 – 2010-09-01 02:03:59

1

這是因爲在每次迭代中,在幕後創建2個字符串,並且它們越來越接近末端。

「1,2,3,4,5,.... 499500」 「1,2,3,4,5,... 499,500,」

在只有端500次迭代,您將創建近2千個字符長的2個字符串,只是在下一次迭代中丟棄它們(但運行時可能會使它們保留)。

在上一次迭代中,假設您的行索引甚至是連續的,則您的字符串(從1到50000)的長度將爲100,000個字符。這意味着你已經分配了〜10,000,000,000個字符或(我相信2個字節/字符)20千兆字節的字符串。

您可以在字符串(RowString)上使用StringBuilder而不是+=開始。
防爆

Dim RowString As StringBuilder = new StringBuilder(100000) 

For Each Row In RowIndexes 
    RowString.Append(CInt(Row.ToString) + 1).Append(",") 
Next 

'...' 

Return RowString.ToString 

您可以嘗試下一個爲好,但你就應該剖析兩種,並挑選最適合你的。

Private Function GetCommaSeperatedString(ByRef RowIndexes As ArrayList) As String 
    Dim indexArray as String[] = RowIndexes 
           .Select(Function(r)=> (CInt(r.ToString) + 1)ToString) 
           .ToArray 
    return String.Join(',', indexArray) 
End Function 



*注:這些都是我曾經寫過VB的第一線,所以我可能已經取得了基本的錯誤(尤其是在LINQ /λ的東西),但問題是那裏。

3

更新:雖然這是使用StringBuilder,看看更好的方法通過StrilancSteven Sudit

那麼直的變化,你仍然可以運行的內存(內存有限,畢竟) ,但你應該使用一個StringBuilder,而不是連接字符串。每一次,你正在創建一個新的字符串對象,而不是改變它(如string是不可改變的)

Private Function GetCommaSeparatedString(ByRef RowIndexes As ArrayList) As String 
    Dim RowString As New StringBuilder() 

    'Build a string of the row indexes 
    'Add one onto each index value so our indexes begin at 1 
    For Each Row In RowIndexes 
     RowString.AppendFormat("{0},", CInt(Row.ToString) + 1) 
    Next 

    'Remove the last comma 
    If RowString.Length > 0 Then 
     RowString.Append(RowString.Substring(0, RowString.Length - 1)) 
    End If 

    Return RowString 
End Function 
+0

@Steven Sudit有沒有答案我會去 - 流它,或創建並丟棄每一行,因爲你需要它。我不能立即想到一個有效的設計,它應該要求整個內容作爲一個字符串。 – 2010-08-31 19:05:05

2

StringBuilder是個好主意,但爲什麼不只是通過流輸出出來,而不是試圖抓住避免問題它全部在內存中?