views:

182

answers:

8

I ran some code last Friday before leaving work, and I'm here on Monday, and it stopped with an OutOfMemoryException. This entire process I estimate required making tens of billions of calculations, so it wasn't some small task.

I don't even know how to begin fixing this.
Any pointers?

+1  A: 

Aaah... this is one of the exceptions which you really dont want to get in your application. We did get this exception too in our project and we used .net memory profiler to check the memory usages and leakages. To some extent we could reduce the frequency of getting outofmemory exception. Given below is the link for profiler -

http://memprofiler.com/

Sachin Shanbhag
I've found the SciTech profiler to be easier to use than ANTS. Worth a try.
spender
@spender - Thanks for this. We can try out on this new profiler too. Can you provide a link to this SciTech profiler?
Sachin Shanbhag
It's the one linked to: http://memprofiler.com
spender
@spender - Its the same which we have used too. check the link in my answer ;)
Sachin Shanbhag
@Sachin: Crossed wires!. I was simply agreeing that your recommendation (and link) are good. I am 100% aware that the "SciTech profiler" and the profiler pointed to by the link in your answer are one and the same. ;)
spender
@spender - haha.. ok I thought they were different. thanks. Yeah we used this and it was really easy to use as you said...
Sachin Shanbhag
+5  A: 

Well, given the contet you provided, or the lack thereof, I can only provide some general ideas here: First of all, the obvious answer would be to take a look at the information contained in the exception itself, which should give you an idea of where in your code allocation failed.

Second, you employ memory profiling to get a better idea of what is going on in your application - I'm a user of dotTrace, but there might be free alternatives available.

Apart from this general adivce, you might want to include some more information in your question. What type of objects are you allocating, when are you allocating, are you using native resources etc.

Jim Brissom
I throughly recommend dotTrace.
Preet Sangha
+3  A: 

This post from Eric Lippert may help: “Out Of Memory” Does Not Refer to Physical Memory

asawyer
+1  A: 

You need to identify what caused it, where it came from, and then you can look into rewriting that section so it uses less memory, maybe by breaking it into pieces and then freeing some resources.

Try introducing a log somewhere (doing step 1, doing step2) with timestamps to help identify where it's failing, then you can ask a more specific question about reducing the memory dependency if it isn't obvious.

Beth
+3  A: 

There are several things you can try.

First, do a rough pass with the Performance Monitor, built into Windows. Add a counter for Process -> Private bytes used, and adjust the scaling accordingly so you can get a quick glance at memory usage. Instead of waiting overnight, you'll be able to identify a leak a little sooner. Another counter you can try is found in .NET Memory, but since my performance monitor isn't currently letting me add the .NET counters (ARGH!), I can't tell you exactly what the sub-selection is.

Are you allocated memory via unmanaged code in your calculation function? If so, are you Disposing of the memory properly? Any code you write that allocates memory this way should implement IDisposable, and you should also call Dispose() on these classes to make sure they get cleaned up.

Are you calling your function recursively? You could be allocating tons of memory each time through your function, and while you might not blow the stack, you'll be using up the heap.

Is there any memory you can get rid of sooner? Even if you aren't using unmanaged code, you can still flag your managed code so that the garbage collector deletes it sooner and then it won't end up in the Gen2 heap. Implement IDisposable, and then call Dispose() on classes that you don't need to hang around anymore.

Are you using threads? You could be allocating memory in your thread, and if you don't properly handle errors by calling EndInvoke, you'll orphan memory in this way.

If all else fails, try a memory profiler like ANTS5 from RedGate. It found another bug in my code, where I was registering an event handler, but not unregistering it. As a result, my code hung onto all of the bits and pieces related to this event, which unfortunately was also hanging onto bits of memory. :)

Hope this helps. I've gone through all of this recently and these are the most helpful tips I can come up with right now.

Dave
ANTS is pretty good.
Steven Sudit
+2  A: 

I gather you are storing the results of your calculations in a container like a list or an array. Try writing your results to file rather than storing them in memory.

Kogitsune
It's in a static array so each instance of the class it is in can add to it. There are approximately 12m instances of this class in my program. If this static array is the reason why this error is showing up, how can I better manage the memory being used by this array?
Soo
+2  A: 

The simplest, most straightforward solution would be this:

  1. Use procdump (included in Sysinternals Suite) to take a full memory dump of your process when it reaches some unreasonable working set size.
  2. Load the dump into WinDbg and also load the SOS debugging extension.
  3. Use the following command: !dumpheap -stat in order to see which type of objects takes up the most of memory.
  4. Dump the list of objects (of the leaking type) using !dumpheap -type <MY_TYPE>
  5. Choose a couple of instances, and issue the command: !gcroot <OBJ_ADDRESS>. The output should tell you which object still holds a reference to it, and why does that object isn't released.

In case you suspect the source of leak is from some native code, you could verify this by issuing the following command: !eeheap -gc. The output will tell you how much memory does the managed heap takes. If you're process's private working set size is substantially larger than the managed heap's size, then you've probably got a native leak on your hands (or, perhaps from some reason you've spawned a lot of threads, so you're running out of space due to the thread's stacks [you could check how many threads are spawned in your process by issuing this command: ~*, or: !threads to show only the managed ones]).

Liran
+1 For including the SOS commands.
Conrad Frix
+2  A: 

If you are allocating very large arrays repeatedly, you may be running into Large Object Heap Fragmentation. If this is the case, you may need to consider whether you can reuse work arrays to prevent the re-allocations and subsequent fragmentation. I definitely recommend running a memory profiler, however, as it's more likely that you have something lingering in memory past what you assumed was its expiration date.

Dan Bryant
I'm using a static array so each instance of the class it is in can add to it. There are approximately 12m instances of this class in my program. If this static array is the reason why this error is showing up, how can I better manage the memory being used by this array?
Soo
The array is static, as in a static member of the class? If that's the case, I wouldn't expect that to cause LOH fragmentation, as it's only a single array.
Dan Bryant