5

We've been running into daily OutOfMemoryExceptions in our ASP.Net 4.0 website. We suspect one of the problems is LOH fragmentation so we've been looking into code changes that would allocate memory more efficiently.

For example, we're generating a large string (2mb) that we want to return to the browser. Paging the data is not an option.

Is it more efficient to:

  1. build the string in a StringBuilder and then make a single call to Response.Write(bigString) or
  2. write the string piecemeal by repeated calls to Response.Write(smallString)

If I follow option 1 then I've got the one big string taking space on the LOH that then is copied to the Response object's internal buffer. So this seems like I've now got 2 big blocks on the LOH at least temporarily.

If I follow option 2 then I'm dealing with lots of small strings that get garbage collected and only the one large block on the LOH for the Response object's buffer.

So it seems to me option 2 is better.

Am I understanding this correctly?

The server has 4gb of Ram and is running Windows 2003 32bit. This is the only site running on the server. So each process has a 4gb address space but only 2gb is usable. We start getting OOM errors when virtual bytes hits about 1.8Gb and then we recycle the site which resolves the problem for about 24 hours. Private bytes varies between 500-800mb. I don't think the problem is that we are running out of physical memory.

  • If it's memory that concerns you, I'd probably try lots of `Response.Write` with frequent `Response.Flush` calls. That might keep the memory footprint to a minimum. – DavidG Jun 03 '14 at 22:32
  • 5
    Don't guess - use a memory profiler tool. For example, RedGate ANTS Memory Profiler lets you profile ASP.NET apps. You can take "snapshots" and compare the memory use between the two. It will show undisposed IDisposable instances, with a stack walk to the code that instantiates the objects hogging memory. – Neil Moss Jun 03 '14 at 22:58
  • How much memeory has the server got, is this running as 32 or 64 bit, how many strings are concurrently buildt – 3dd Jun 10 '14 at 04:35

2 Answers2

1

Without knowing the implementation, my answer may be a little less helpful than what I would hope. I'll venture a go, though.

If it were me, I would leverage two tactics:

  1. Take advantage of hard disk space and write to a text file stored in a cache directory on the server (assuming only one web server)
  2. Use an old-school Server.Execute("~/filename.txt"); to spit out the text file contents onto your page.
0

The answer could depend on how you are building your "large 2Mb string". For example, it is paramount that you use the StringBuilder class to concatenate content e.g.

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());

and DO NOT use string concatenation like this:

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

If you are using the latter approach, I would expect you could be running into consuming GB of memory in order to create a 2Mb string and constantly battling with the garbage collector.

Of course, writing to the Response object will probably trump both techniques, but YMMV.

Chris Walsh
  • 3,166
  • 1
  • 34
  • 54