繁体   English   中英

VB.net内存高效功能需要

[英]VB.net Memory efficient function needed

当RowCollection为50000+时,我从以下函数中获取内存不足,因此我需要使其更高效。 该函数只需构造一个逗号分隔的行存储在RowCollection中的行索引字符串。 以下任何人都可以发现任何明显的记忆饥饿操作吗?

NB 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

提前致谢。

我不确定你为什么会出现内存错误,除非你的行的字符串表示非常大,因为你从来没有超过一个或两个非垃圾收集字符串。

然而,你的方法效率极其低下的,因为它花费如此多的时间复制建了一半的字符串的内容。 构建大型字符串时,StringBuilder更合适,因为每次都可以修改它而无需重新创建内容。

但是,在这种情况下,即使是StringBuilder也是一个坏主意,因为你正在加入字符串,并且已经有一种方法可以做到这一点:String.Join。 只需使用LINQ查询来执行add-one-to-index-stuff就可以得到一个单行:

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。

更新 :虽然这是使用stringbuilder的直接更改,但请查看StrilancSteven Sudit的更好方法

好吧,你可能仍然会耗尽内存(毕竟内存有限的),但你应该使用StringBuilder,而不是连接字符串。 每次,您创建一个新的字符串对象而不是更改它(因为字符串是不可变的)

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

StringBuilder是一个好主意,但为什么不通过流输出输出而不是试图将其全部保存在内存中来避免问题呢?

这是因为在每次迭代中,你在幕后创建了2个字符串,并且它们越来越接近结尾。

“1,2,3,4,5,...... 499,500”“1,2,3,4,5,...... 499,500,”

在仅500次迭代结束时,您将创建2个字符串,长度接近2000个字符,只是为了在下一次迭代中将它们丢弃(但运行时可能会保留它们)。

在最后一次迭代中,假设您的行索引是连续的,那么您的字符串(从1到50000)将是100,000个字符长。 这意味着您已经分配了~100,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 / lambda中),但重点在于。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM