Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

System.OutOfMemoryException because of Large Dictionary

I keep a large cache in a dictionary with value IEnumerable<KeyValuePair<DateTime, Double>>. I remove items from the dictionary periodically and add items to the dictionary periodically. Every now and again I get a System.OutOfMemoryException. I wanted to know why doesn't the garbage collector come to my rescue?

like image 469
Anish Patel Avatar asked Mar 17 '11 07:03

Anish Patel


People also ask

How do you fix system OutOfMemoryException out of memory?

You can do either of the following to address the error: Replace the call to the StringBuilder. StringBuilder(Int32, Int32) constructor with a call any other StringBuilder constructor overload. The maximum capacity of your StringBuilder object will be set to its default value, which is Int32.

What is System OutOfMemoryException?

OutOfMemoryException Class (System) The exception that is thrown when there is not enough memory to continue the execution of a program.


3 Answers

Remember that a Heap can get fragmented as @Gabe mentioned. Even though you might have free memory it might not have a chunk large enough to allocate the dictionary to when it performs it's resize.

Perhaps you could use the caching block from the patterns and practices library MSDN Library Link that will assist you in implementing a good cache. Maybe you could choose an algorithm that doesn't dynamically allocate memory, with a fixed number of entries?

Also note that if there isn't any memory that you can use then it's a problem with the size of your cache, not the garbage collector.

like image 197
Spence Avatar answered Nov 04 '22 02:11

Spence


It's quite possible that the GC is coming to your rescue for a lot of the time, but that you're just going beyond its capabilities sometimes.

Just to be absolutely clear, is this a Dictionary<DateTime, Double> or a Dictionary<SomeKeyType, IEnumerable<KeyValuePair<DateTime, Double>>>? If it's the latter, then perhaps you're holding onto references somewhere else?

How large is your cache getting? Do you have monitoring to keep track of it? What makes you think it's the dictionary which is causing the problem? If you have control over how much you cache, have you tried reducing the size?

like image 44
Jon Skeet Avatar answered Nov 04 '22 04:11

Jon Skeet


Since you're asking why the GC doesn't rescue you I'll give an answer to that.

Using a programming language/environment with a garbage collector makes live easier for you but won't make memory management a thing of the past.

If you assign big chunk of memory going over about 2 gig in a 32bit xp machine you're just reached one of the first .Net memory boundaries. Keeping 2 gig in memory is always a bad idea.

On a memory constrained machine running a huge database or the like you'll quickly hit the boundaries of available memory. Since the GC is not OS aware it might nog notice a low memory situation in time (creating huge objects like bitmaps can trigger this situation). Manually calling GC.Collect once you're set a huge object to nothing help a lot here.

Keeping a big dictionary in memory is a very simple description. Can you tell us whats in the collection and how big those items are theoretically.

If you mean big like 2,147,483,647 items you could have hit the Integer size limit.

To sum up:

  • Don't keep unneeded items in memory or swap them out to disk.
  • Do call GC.Collect once you've freed 'big' items (but not in a loop of deleting items, after the loop please)
like image 2
CodingBarfield Avatar answered Nov 04 '22 03:11

CodingBarfield