Question about .Net memory

This is a generic .Net question - I never understood this.

I have a winform with one button on it.
The form has NO global variables.
When I start the application, it takes 22 Mb, but the I click the button. This starts a real heavy string routine.
All data is local in this routine; strings, lists and integers, so when the routine ends, all varables are out of scope and should be garbage collected. I should expect a memory usage of 22Mb again.
But reality is somewhere between 300 and 700Mb.
Running a forced GC.Collect won’t free the memory.
Edit: The result is written to disk, not stored anywhere.
How is this possible?

Even if you pass the highest level (3 iirc) to collect?

Any non-memory objects there that might need to be Disposed (or created with using)?

Both: No.
But could it be heap fragmentation that causes this?

Could be, but seems unlikely. Also note though that maybe the process just holds on to memory it already allocated “because it can”, w/o that meaning the memory is not actually available (by your app to reuse, or to be freed fully when other recesses need it and there’s shortage. Having “free” memory is not really a goal, on modern OSs, optimal usage of all available memory is.

Only proper profiling will show you real memory problems — not going by what TaskMan shows.

It is what visual Studio says.
And it bothers me because of 2 reasons:

  1. Terminal server - biggest bottleneck is memory.
  2. I am old skool. - in 1981 I started with only 2KB, and now a simple form is eating Gigabytes …

After setting all reference variables to nil before the end of the function, the GC.Collect(3) helps (till 47Mb)

There is also a thing called “String interning” in .NET.

Depending on how exactly you did implement string manipulations it could result in increased memory consumption after the method completes.

In case you do heavy string manipulations you should consider using a System.Text.StringBuilder to construct a resulting sting.

1 Like

This seems wrong. If there are no globals/fields involved, setting variables to nil at the end of the method or not should have zero effect on GC.

good call, yes.

String constants are always interned, and interned strings are never released.It is faster, but cost a lot of memory. I use a string builder (with preallocated memory - speed and peak memory usage is no problem).

But I see the problem. I do the GC Collect at the end of the routine, where the variables are not yet out of scope. If I create an extra calling function - that make the variables go out of scope, GC.Collect(3) is enough to get the memory back (at least to 47 Mb, started at 22 Mb, so there is still 25Mb gone) - but is stays on 47 after 10 times running.

1 Like