Home > .Net, C# > Getting OutOfMemory exception in .Net process, possible solutions.

Getting OutOfMemory exception in .Net process, possible solutions.

Getting OutOfMemoryexception in .Net process, possible solutions.

I want to share with you very interesting and complicated problem that we managed to overcome. I will describe all our resolution procedure step by step. Hope it will help others as it helped us, in any case I have learned a lot.

 

We have encountered a serious problem such as OutOfMemoryException

In my application – WinForm application i have managed code and un-managed (C/C++) 3’rd party code that perform many un-managed memory allocations at beginning of the process load and during runtime.

As we started to suffer from memory problems, we decided to enlarge address space that our process can use from 2 GB to 3 GB. This operation was done by using /LARGEADDRESSAWARE flag for our process and OS configured with /3GB. Unfortunately enlarge address space to our application seems to be good solution, but it didn’t help in our case.

So we started debugging and deeply investigate our Outofmemory problems. As usual main tool that we have used was WinDbg. Interesting things were discovered by using WinDbg and using following command “!address –summary” which shows us that we have not reached 3GB memory limit. Although that we have free memory, the memory wasn’t continuous so the CLR or native code failed to allocate memory. The problem appear to be defragmentation problem.

Additionally we have used nice tool that  help us to indicate our problem  – VMMap can  be downloaded here. Step by step debugging helped us to detect where and who was making this “problematic” memory allocations. Part of the allocations was made when the Application was really need those instances – for example we have WPF controls and some 3’rd party WinForm controls such Janus and Syncfusion, when all relevant modules were loaded in to process memory and it could take around 100MB. We didn’t expect such behavior, so we moved all those initializations to occur in the beginning of the process load (application initialization stage). It was trade of Application Initialization time and memory defrag. Additional problem was pinning with Native code memory allocations.

Problem wasn’t solved in special scenarios OutOfMemoryException still occurred (thanks for our changes all application worked better).

We continued to think, search for good final solution. Read about .Net garbage collector heuristics. Finally the smartest guy in our team had an idea! His idea was to stress .Net GC.

He called it GC Stress – its mean very original approach, we have allocated fictive continuous memory in order to ensure Commit memory.

See following code example:

 

            List<byte[]> memlist = new List<byte[]>();
            for (int i = 0; i < 55 * 1024; i++ )
            {
                byte[] byteArr = new byte[1024];
                memlist.Add(byteArr);
            }
            memlist.Clear();
            memlist = null;

 

From our experience and benchmark we have decided on 250 MB of allocations, of course it’s depend on concrete application.

Such behavior gives us ability to allocate dummy continuous memory before Native code makes its allocation (pinning). When CLR needs this memory back Garbage Collector simply frees the memory and we have free continuous memory available for our process use.

 

Of course this solution is only temporal, till we will refactor the problematic legacy code. The best choice is move to Windows 7 64bit.

 

Categories: .Net, C# Tags: , , , , ,
  1. No comments yet.
  1. No trackbacks yet.