服务器由于内存中的大型StringBuilder实例而停止

时间:2010-08-02 21:57:59

标签: vb.net performance stringbuilder

所以,我有这个代码从数据库中获取大量数据,并对该数据执行一系列计算。然而,这不是造成停顿的原因。当我拿走所有准备好的“最终”数据时,停止进入,并将其写入文本文件。

文本文件中的每一行都是根据已对其执行计算的数据创建的。每行“对应”来自数据库的记录。用户必须一次在大约30-40,000条记录上执行此文件导出通常。现在,即使我使用的是StringBuilder,由于纯粹的大量记录,这仍然会停止。

我目前在代码中做的是创建一个StringBuilder,将所有数据(在计算之后)附加到它,将其转换为String,将其添加到要从Function返回的List(Of String),然后清除StringBuilder,并对下一行执行相同的操作,并执行此操作,直到创建并附加,转换每个行,然后将其插入List。

然后,另一个类接收此List(Of String)并获取每个String并最终将其附加到文件中。

有没有人知道如何改进此代码并使其不会每次都停止服务器?之前没有找到它的原因是因为当我在本地测试时,我一次只测试1-50条记录。

提前致谢!

编辑:

r = Class.ExportFile(ID)
data = Encoding.ASCII.GetBytes(r.ResponseString)

Return File(data, "text/plain", r.DefaultFileName)

-Scott

4 个答案:

答案 0 :(得分:3)

返回IEnumerable而不是大字符串或字符串列表,并一次写一行到该文件。这样你可以懒惰地评估数据,所以你不需要保持庞大的字符串。 e.g。

IEnumerable<string> Process() {
   var rows = QueryTheDatabase();
   foreach(var row in rows) {
      yield return ProcessARecord(row);//process and build a string of
                                         //one row
    }
 }

调用者只是在返回的IEnumerable上执行操作,并将每行写入文件。

答案 1 :(得分:2)

对我来说,你最好直接将大部分数据写入文件中 - 一定要一次写一行到StringBuilder,然后将结果字符串写入你的文件中最终出口到。这将降低内存使用率,如果您使用StreamWriter,则会缓冲写入并且性能不会受到明显影响。

答案 2 :(得分:0)

你可能会遇到内存碎片问题。在32位世界中使用 REALLY 大型动态数据结构会导致这种情况。就个人而言,我只用300mb的琴弦击中了它,但我通常会避免陷入这种情况,所以这并不是说太多。

正如其他人所说,打破它,这样你就没有这么大的字符串了。

答案 3 :(得分:0)

使用IEnumerable / iterator块而不是List。转换非常简单:将函数的返回类型从List<string>更改为IEnumerable<string>,然后将当前调用列表.Add()方法的位置更改为使用yield return的行代替。然后还要更改您的其他课程以接受IEnumerable<string>而不是List<string>。您可能还需要对其他方法进行类似的转换,以便以这种方式处理数据库中的整个链。

这样做是为了让你一次只在内存中保存一条记录。每条记录都将转换为字符串,并由您的输出方法即时处理。