views:

106

answers:

4

My .net application does some heavy string loading/manipulation and unfortunately the memory consumption keeps rising and rising and when looking at it with a profiler I see alot of unreleased string instances. Now at one point of time or another I do need all objects t hat do have these string fields, but once done, I could get rid of e.g. the half of it and I Dispose() and set the instances to null, but the Garbage Collector does not to pick that up.. they remain in memory (even after half an hour after disposing etc).

Now how do I get properly rid of unneeded strings/object instances in order to release them?

They are nowhere referenced anymore (afaik) but e.g. aspose's memory profiler says their distance to the gc's root is '3'?

Update: The original strings are coming from an interop instance. Is it possible that those are causing the leaks?

As in.. assigning

myClass.StringProperty = interopInstance.Description.Text;

.. does my .StringProperty still have a reference to that interop one and therefore 'leaking'/keep the interopInstance uncollected & not properly released/unmarshaled?

A: 

Question is: How do you store your strings?

Steav
And how often make new string instances?
Rafal Ziolkowski
My data structure basically just is a class with lot's of (automatic) properties, most of them being plain strings, 4 are List<string> with about 80-90 entries per instance. They are filled once and read often. However, one particular string property contains strings up to several megabytes.
Jörg B.
+3  A: 
Steven
But do not call GC.Collect() too often it is pretty bad for performance.
Rafal Ziolkowski
@Rafal: Yes, of course. I didn't mean I should use that in his production code. Use it to test whether the memory is collectable.
Steven
Oh I do get SystemOutOfMemoryExceptions.. with one example run I have about 1200 instances of my class, which has, among other -small- string properties one 'big' one.. meaning each instance of my class usually has several 100kbyte, sometimes several megaybtes of string 'data' in it. (which I unfortunately need).
Jörg B.
When you're getting OOM, you've got a different problem. Perhaps you're holding on too long to those big objects -or- you're simply using more memory than the OS can give you.
Steven
What do you mean by.. 'hold on too long'? I know when I don't need these large objects anymore, but how do I get properly rid of them? Does the 'string' part have anything to do with it? I could store them differently aswell, I only need the actual string representation 2 times during runtime)
Jörg B.
You get rid of them by not referencing (directly or indirectly) them anymore. Strings are just normal CLR objects, so there is nothing special about them. What do you mean by "I only need the actual string representation 2 times during runtime"? Perhaps it is time to show us some code (you can edit your question for this).
Steven
@Jörg: I updated my anwser to say something about interop.
Steven
+1  A: 

Just taking a punt on this but are you concatenating a lot of strings? If so are you using the '+' operator to do so? A string is immutable, meaning that you could be creating a new string object in memory every time you work on it.

If you are concatenating strings you should consider using a StringBuilder object (if you are not doing so already) or even the String.Concat() method. This could be the problem, especially if you are concatenating strings in a loop at any point.

Peter Kelly
A: 

I've been working on a system for transmitting data between many terminals. These terminals generate Text Data (in XML) that is then Compressed and transmitted to other terminals. Originally we experienced the exact same issue you are with the application using more and more and more Ram and eventually running out of memory.. The speed at which it ran out was exponentially faster the more terminals that were connected to it.

Performance of this system was not the most important feature, but longterm uptime was.

After trawling through with profilers to find where our memory was disappearing we found that our strings ended up in LOH if there was anything substantial in them.

I know it's controversial and many people say don't force GC.Collect but i've also found other sites eg Rico Mariani that say if you have specific needs and you are sure that your objects end up in LOH then go ahead and do it, just remember that GC.Collect will impact performance.

The good news was that once we added this to the string processing area of the program we stay on about the same ram usage for the entire life of the application, and some of the systems that we've got this running have uptimes >60days.

Paul Farry