I have a class B from which I produce a huge number of instances to speed up some searching in an optimization problem. The number gets so large that I frequently produce OutOfMemory-Exceptions. As workaround, I reduce the number of instances every x seconds, but I would like to do something more sensible. For that I would like to know:
What is a good way to manage the number of instances "alive" (created and not yet garbage collected)
More technical: How can I estimate the RAM I have to use (say) about half of it for my instances?
First of all, I would try to reduce the memory footprint of every single object as much as possible. Since you create huge numbers of objects, it is likely that many of them share similar properties, which renders them a perfect candidate for the flyweight pattern. A classical example according to the Wikipedia article is word processing:
A classic example usage of the flyweight pattern is the data structures for graphical representation of characters in a word processor. It might be desirable to have, for each character in a document, a glyph object containing its font outline, font metrics, and other formatting data, but this would amount to hundreds or thousands of bytes for each character. Instead, for every character there might be a reference to a flyweight glyph object shared by every instance of the same character in the document; only the position of each character (in the document and/or the page) would need to be stored internally.
As a second step, I would estimate the size of a single object. I emphasize estimating in this context because getting the actual size is not that easy in C#. This estimate can then be used to the set a maximum number N
of objects you can safely instantiate without encountering an OutOfMemoryException
.
You can make use of this information by tracking how many objects are (approximately) alive by updating an object counter every time an object is created or destructed, e.g.
class Foo {
private static NumberOfInstances = 0;
public Foo() {
NumberOfInstances++;
}
~Foo() {
NumberOfInstances--;
}
}
If thread-safety is an issue, this implementation would of course have to be refined a little.
Edit: As mike z pointed out in his comment, implementing this via a finalizer may cause severe performance problems in this context. Consequently, it would probably be better to implement IDisposable
and perform the decrement in the Dispose
operation. However, this has the disadvantage that it is possible to forget disposing the object. However, I doubt that this will be a serious issue in your case.
I don't know the answer to the second question, but the answer to the first question could be:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With