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是个好主意,但为什么不只是通过流输出出来,而不是试图抓住避免问题它全部在内存中?