Evaluation: Finding Out of Memory Exception Cause

Use this forum for questions on how to use .NET Memory Profiler and how to analyse memory usage.
Post Reply
Buck221B
Posts: 2
Joined: Mon Sep 02, 2013 7:11 pm

Evaluation: Finding Out of Memory Exception Cause

Post by Buck221B » Mon Sep 02, 2013 8:01 pm

Any ideas on what is causing an eventual out of memory exception? The .NET Memory Profiler session is at https://www.dropbox.com/sh/4pa36pfhcykieme/1hp7wUrPkV. This is a WPF application that uses unsafe for performance reasons, as well as third party libraries and drivers. Hopefully it is obvious, but I do not see it. Thanks!

The steps to generate the snapshots were:
1. Start the profile and the session using the standalone application.
2. Take several consequently images which display on the screen.
3. Record the snapshot (snapshot 1)
4. Take over 1 minute of consecutive images which display on the screen.
5. Record the next snapshot (snapshot 3)
Note: If I had left the acquisition looping at step 4 (instead of stopping) it would have ended at the out of memory exception.

Thanks,

Buck

Andreas Suurkuusk
Posts: 1029
Joined: Wed Mar 02, 2005 7:53 pm

Re: Evaluation: Finding Out of Memory Exception Cause

Post by Andreas Suurkuusk » Tue Sep 03, 2013 8:00 pm

The snapshots in the session file do not indicate a memory leak. The overview shows that you do not have any excessive memory usage, and the managed memory usage has only increased with about 2KB between the snapshots, and the unmanaged memory usage has decreased by 65MB. But then I looked at the native memory view. You have used about 1.2 GB of memory, and you have 700 MB of (potentially) shared memory that has not been identified by the profiler. This memory is most likely caused by memory mapped files, as the profiler does not track the actual memory "allocated" using MapViewOfFile, only the number of views mapped.

In your session file, you have 330 "Mapped memory" instances and most of them are created by the BitmapMapper.Setup method (using MemoryMappedFile.CreateViewAccessor). The MemoryMappedViewAccessor is never disposed (it is marked as an undisposed instance by the profiler). However, the mapped view should be released by the finalizer anyway, so I'm not sure why your application seems to be leaking memory mapped views. I will investigate this a bit further and see if I can come up with an explanation. The best way to investigate this further would be for us to profile your application ourselves. If there's any possibility for you to provide us with the application that exhibits this problem, please contact us at support@scitech.se.
Best regards,

Andreas Suurkuusk
SciTech Software AB

Andreas Suurkuusk
Posts: 1029
Joined: Wed Mar 02, 2005 7:53 pm

Re: Evaluation: Finding Out of Memory Exception Cause

Post by Andreas Suurkuusk » Wed Sep 04, 2013 7:07 pm

Thanks for the code snippet you sent by e-mail.

The problem with your code is that you only create a single instance of BitmapMapper and then you call the Setup method many times (289 times in the session you sent). The setup method creates a memory mapped view that gets released in the Dispose method, but the Dispose method is never called since the BitmapMapper instance is reused.

Normally this would not be a big problem, since the memory mapped view handles will be released in their finalizers. However, you also call SafeMemoryMappedViewHandle.AcquirePointer and do not call ReleasePointer until the Dispose method is called (which it's not). AcquirePointer is a dangerous method (it does itself call DangerousAddRef) and should be used with care. The AcquirePointer method is a very fast method, so you should call AcquirePointer/ReleasePointer each time you need to use the pointer and not store it in a class field. From the MSDN documentation:
When AcquirePointer returns, you should perform bounds checking by verifying that the pointer parameter is null. If it is not null, you must call the SafeBuffer.ReleasePointer method in a constrained execution region (CER).

Code: Select all

byte* pointer = null;
RuntimeHelpers.PrepareConstrainedRegions();
try {
    MySafeBuffer.AcquirePointer(ref pointer);
    // Use pointer here, with your own bounds checking.
    }
finally {
    if (pointer != null)
        MySafeBuffer.ReleasePointer();
    }
The constrained execution region might be an overkill, but you should definitely release the pointer in a finally clause.

I hope this helps.
Best regards,

Andreas Suurkuusk
SciTech Software AB

Buck221B
Posts: 2
Joined: Mon Sep 02, 2013 7:11 pm

Re: Evaluation: Finding Out of Memory Exception Cause

Post by Buck221B » Fri Sep 06, 2013 4:06 am

Hello Andreas,

Perfect and thanks! That cleaned it right up.

Best and thanks again,

Buck

Post Reply

Who is online

Users browsing this forum: Bing [Bot] and 12 guests