6

Would appreciate any kind of help here.

A brief description about scenario -

There is a COM+ running on server (written in C#). The task of this COM is to take a file name, page number of a multi-paged tiff file and the resolution to convert it to a gif file image. This COM is called from a web application using a proxy. The web site gets the converted image and displays in the requested resolution. For printing - it makes 2 request - 1st for display resolution, 2nd in full resolution (which gets printed using window.print()).

Problem -

After sometime server goes out of memory and images are not getting displayed on web site. Server needs to be restarted periodically.

Error

EventType clr20r3, P1 imageCOM.exe, P2 1.0.0.0, P3 4fd65854, P4 prod.web.imaging, P5 1.0.0.0, P6 4fd65853, P7 1a, P8 21, P9 system.outofmemoryexception, P10 NIL.

Here is the error(s) on the web server (these continuously appear every minute) ….

System.Net.WebException: Unable to connect to the remote server ---> System.Net.Sockets.SocketException: No connection could be made because the target machine actively refused it
   at System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot, SocketAddress socketAddress)
   at System.Net.Sockets.Socket.InternalConnect(EndPoint remoteEP)
   at System.Net.ServicePoint.ConnectSocketInternal(Boolean connectFailure, Socket s4, Socket s6, Socket& socket, IPAddress& address, ConnectSocketState state, IAsyncResult asyncResult, Int32 timeout, Exception& exception)
   --- End of inner exception stack trace ---

I do not have access to production server, but error sent by sysadmin states OutOfMemory.

Thus, assuming memory leak and focusing on it - my findings so far with limited experience of handling this kind of situation -

  • Perfmon - I see that Process/Private Bytes are increasing and so is .Net CLR memory/# of bytes in Heap. Thus, I assume it's Managed memory leak. I am not sure though.
  • CPU Usage - started with 8% and went up to 80% only at beginning. It dropped back and stayed between 3% - 12%, except couple of times when it went back to 75%-85%. Not sure what is going on here.
  • I started to debug server COM to have a look at heap, gcroot etc.

    1. There are 2 objects for count is increasing in the heap with every request made. 1 object is that hold the image data. 2nd object is the event handler to remove the Object 1 (image) from cache when it expires after a certain time.
    2. Looking at the method call - both objects lead to the same method.
    3. Code Implementation wise - Requested images are getting cached (up to a certain number) - I can understand it is for better performance. Probably, this is why reference to objects are increasing in heap as mentioned in bullet 1.

I know I gave very vague description, but I need some kind of lead to detect the real issue on server.

EDIT: Image object has been disposed like

Bitmap retVal;

      using (MemoryStream buffer = new MemoryStream(doc.FileData, 0, doc.DocumentSize, false, false))
      {
        using (Bitmap original = new Bitmap(buffer))
        {
        //select the page to convert and
        //perform scaling - full resolution or the requested resolution.  
        }
      }

      using (MemoryStream buffer = new MemoryStream())
      {
        retVal.Save(buffer, ImageFormat.Gif);
        retVal.Dispose();
        return buffer.GetBuffer();
      }
peacefulmember
  • 293
  • 2
  • 5
  • 14

2 Answers2

2

Make sure you are disposing the Image objects (such as Bitmap) after you're done using them. I'm guessing you're opening the tiff image as a bitmap and rescaling it and then saving it again as a gif. If you don't dispose the Bitmap it will leak memory (usually several MB each time depending on the size of the image).

Paccc
  • 1,211
  • 13
  • 15
  • 3
    Along that line: make sure *everything* that implements `IDisposable` is being disposed of properly. The easiest way to remember is by incorporating the `using` statement: `using (System.Drawing.Bitmap b = new System.Drawing.Bitmap(...)) { /* Do stuff */ }`; (which disposes it for your without forcing you to call `.Dispose()`). – Cᴏʀʏ Aug 23 '12 at 16:07
  • @Cory - Image object has been disposed by incorporating the using statement. – peacefulmember Aug 23 '12 at 17:12
  • I have edited my original message to show how image has been disposed. Please point out if it is not done correctly. Another point to make is that scaling of image is done using unsafe code of C++. I see it has LockBits at the begining and UnlockBits at the end, so assuming there also object is disposed properly. Any thoughts! – peacefulmember Aug 23 '12 at 17:50
1

I think your 1st point might be the reason for the issue. You might try reducing the cache expiry time and check how much time it is taking to get outofmemory error again, you might have to make changes in your algorithm to avoid this situation. Your 2nd should not be the reason for the error.

Avichal Badaya
  • 3,423
  • 1
  • 21
  • 23
  • How do I check that object 1 is released? Are you referring to looking in to heap and gcroot? Like I stated my knowledge is limited here. – peacefulmember Aug 23 '12 at 18:00
  • your answer lead me to the right direction. All issues have not resolved yet, but I am able to detect one of the big memory leak. thanks. – peacefulmember Aug 29 '12 at 15:32