5

在我们的 ASP.Net 4.0 网站中,我们每天都遇到 OutOfMemoryExceptions。我们怀疑问题之一是 LOH 碎片,因此我们一直在研究可以更有效地分配内存的代码更改。

例如,我们正在生成一个想要返回给浏览器的大字符串 (2mb)。分页数据不是一种选择。

是否更有效:

  1. 在 StringBuilder 中构建字符串,然后调用Response.Write(bigString)
  2. 通过重复调用来逐个编写字符串Response.Write(smallString)

如果我遵循选项 1,那么我将在 LOH 上占用一个大字符串,然后将其复制到 Response 对象的内部缓冲区。所以这看起来我现在至少暂时在 LOH 上有两个大街区。

如果我遵循选项 2,那么我将处理大量收集垃圾的小字符串,并且只有 LOH 上的一个大块用于响应对象的缓冲区。

所以在我看来选项2更好。

我是否正确理解这一点?

该服务器有 4gb 的 RAM,运行的是 Windows 2003 32 位。这是服务器上运行的唯一站点。所以每个进程都有 4gb 的地址空间,但只有 2gb 可用。当虚拟字节达到约 1.8Gb 时,我们开始收到 OOM 错误,然后我们回收解决问题的站点约 24 小时。私有字节在 500-800mb 之间变化。我认为问题不在于我们的物理内存不足。

4

2 回答 2

1

在不知道实现的情况下,我的回答可能没有我希望的那么有用。不过,我会冒险一试。

如果是我,我会利用两种策略:

  1. 利用硬盘空间并写入存储在服务器缓存目录中的文本文件(假设只有一个 Web 服务器)
  2. 使用老式的 Server.Execute("~/filename.txt"); 将文本文件内容吐出到您的页面上。
于 2014-06-10T03:48:11.740 回答
0

答案可能取决于您如何构建“2Mb 大字符串”。例如,使用 StringBuilder 类连接内容至关重要,例如

System.Text.StringBuilder sb = new System.Text.StringBuilder(256*1024);
sb.AppendText("some text");
sb.AppendText(myObject.name);
sb.AppendText("more text");
Response.Write(sb.ToString());

并且不要像这样使用字符串连接:

myString += "some text";
myString += myObject.name;
myString += "more text";

如果您使用后一种方法,我预计您可能会消耗 GB 内存以创建 2Mb 字符串并不断与垃圾收集器争斗。

当然,写入 Response 对象可能会胜过这两种技术,但 YMMV。

于 2014-06-12T22:23:10.263 回答