0

From time to time, our web application will cause this error:

System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.

The application is C# ASP.NET 4.5 Web Forms application, running on Windows 2008 R2 server with 6G memory. We have increased memory several times, but it still happens. So I am wondering if its application's problem? What could be the reason?

edit

I have this stack, don't know if it helps at all:

System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.

Generated: Wed, 29 Jul 2015 08:49:24 GMT

System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.
   at ASP.popups_downloadtrendpdf_aspx.__BuildControlTree(popups_downloadtrendpdf_aspx __ctrl)
   at ASP.popups_downloadtrendpdf_aspx.FrameworkInitialize()
   at System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
   at System.Web.UI.Page.ProcessRequest()
   at System.Web.UI.Page.ProcessRequestWithNoAssert(HttpContext context)
   at System.Web.UI.Page.ProcessRequest(HttpContext context)
   at ASP.popups_downloadtrendpdf_aspx.ProcessRequest(HttpContext context)
   at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

edit

So this is the code that generates PDF, its based on XSL-FO string. Does this caused problem?

PDFGenerator.PDFGenerator svc = new PDFGenerator.PDFGenerator();
byte[] myfile = svc.ProcessFO(foString);
if (myfile != null)
{
    System.Web.HttpResponse response = System.Web.HttpContext.Current.Response;
    response.Clear();
    response.AddHeader("Content-Type", "application/pdf");
    response.AddHeader("Content-Disposition", "attachment; filename=" + filename + "; size=" + myfile.Length.ToString());
    response.Flush();
    response.BinaryWrite(myfile);
    response.Flush();                    
 }

edit

code for ProcessFO():

    [WebMethod]
    public byte[] ProcessFO(string requestFO)
    {
        byte[] result = null;
        FODocument doc = new FODocument();
        try
        {
            byte[] byteArray = System.Text.Encoding.UTF8.GetBytes(requestFO);
            using (MemoryStream stream = new MemoryStream(byteArray))
            {
                using (MemoryStream pdfStream = new MemoryStream())
                {
                    doc.generate(stream, pdfStream);
                    result = pdfStream.ToArray();
                }
            }
        }
        catch (System.Exception exc)
        {
            logger.Debug("Trouble in ProcessFO: " + exc.Message);
            logger.Debug(exc.StackTrace);
        }
        return result;
    }
Hiraeth
  • 203
  • 2
  • 11
  • There are a number of reasons for running out of memory and they are often not because of total memory. Can you please post the code that causes the issue? Without it we really can't give a good answer. – Enigmativity Jul 30 '15 at 02:34
  • It could be due to a problem with the code, but could also be related to something else going on the server; the server shares memory with a lot of components, and something else could be a hog. – Brian Mains Jul 30 '15 at 02:39
  • It sounds like a pretty normal memory leak ( where object keep accumulating in memory). Do some memory profiling on a test server. search for terms like .net memory profiling memory leak how to – monkeyhouse Jul 30 '15 at 02:40
  • Could we get a complete stack trace? Perhaps it's some code handling file uploads and someone uploads a +inf bytes large file? Have you checked your performance monitors to see the size of your different gc generations? – sisve Jul 30 '15 at 02:52

2 Answers2

2

This looks like you have a memory leak. Now I won't get into the virtual memory vs physical memory, but the solution here is not to increase the memory. You have to fix the part of your code that "leaks".

In .net, there could be a lot of possibilities (event handlers not released (well maybe more in desktop apps), disposal of unmanaged memory, etc.), so without the code, this answer can't get much into details.

You should try some memory profilers (start a trial of dotMemory or redgate's memory profiler). Or, look for WinDbg with the sos library.

0

Looking at the stack trace I see "downloadtrendpdf". Is the app buffering PDF files in memory for upload/download operations? A lot WebForms controls are notorious for doing that. That will make you run out of memory quickly.

Dmitry S.
  • 8,373
  • 2
  • 39
  • 49
  • That is the problem. The large byte array can take a lot of memory. Try to see if there are any methods on the `svc` object that return a `Stream` instead of the `byte[]`. – Dmitry S. Jul 31 '15 at 21:06
  • I have two questions, does current approach cause memory leak? also, why stream will solve the problem that byte[] cause? `svc.ProcessFO` is a method that we create ourselves, we can change that if needed. I posted the code in the edit. Do you think it will solve the problem by returning a stream? – Hiraeth Jul 31 '15 at 21:39
  • The file is being sent to the the `HttpContext.Current.Response.OutputStream` stream. Instead of loading the whole file into memory a stream would allow you to push small buffers of 4 KB or so at a time into the output stream. Make sure to use a binary stream writer and not the `MemoryStream` abstraction which is based on an array. – Dmitry S. Jul 31 '15 at 22:21
  • Here is an example. The `fs` variable is a `FileStream` for the file. http://stackoverflow.com/questions/5828315/write-pdf-stream-to-response-stream In the 4.5 .NET version streams also have a `CopyTo` method which is a loop that uses a 4K B buffer. So the code would be `fs.CopyTo(Response.OutputStream)`. – Dmitry S. Jul 31 '15 at 22:27