2

I have an application that creates trees of nodes, then tosses them and makes new trees.

The application allocates about 20 MB upon startup. But I tried loading a large file of nodes many times, and the allocated memory went above 700 MB. I thought I would see memory being freed by the garbage collector on occasion.

The machine I'm on has 12 GB of RAM, so maybe it's just that such a "small" amount of memory being allocated doesn't matter to the GC.

I've found a lot of good info on how the GC works, and that it's best not to tell it what to do. But I wanted to verify that it's actually doing anything, and that I'm not somehow doing something wrong in the code that prevents my objects from being cleaned up.

Almo
  • 15,538
  • 13
  • 67
  • 95
  • 5
    Short answer: When it needs to. – Brian Rasmussen Feb 29 '12 at 23:45
  • ^^^ Yep. Implementation defined my friend. You should design your application such that it does not matter. If you need deterministic memory management then you are using the wrong language. – Ed S. Feb 29 '12 at 23:46
  • 2
    @BrianRasmussen That's the optimistic point of view. I'd rather say whenever it deigns to do so. – CodesInChaos Feb 29 '12 at 23:49
  • Woa, lots of good info. Will go over all this tomorrow at work, and upvote some answers and pick one. Thanks. – Almo Mar 01 '12 at 03:52
  • 2
    You apparently believe the lie that RAM has something to do with memory management. I assure you it does not. Think of memory as *disk space*. *RAM is just a special kind of chip that makes your disks faster*. The garbage collector does not care how much RAM you have; it cares how much *virtual space* you have. How the *virtual space* is mapped to *physical RAM* is not hugely relevant to the garbage collector; that's more the operating system's problem. If you care about memory usage **learn how modern memory management systems work**. – Eric Lippert Mar 01 '12 at 06:52
  • Update: Found the issue. The List in question was being held by a dialog that was not being Disposed. The combination of dotTrace and learning that IDisposable objects need to be disposed by the user is what I needed. – Almo Mar 01 '12 at 19:55

7 Answers7

7

The GC generally runs when either of the scenarios below occur:

  • You call GC.Collect (which you shouldn't)
  • Gen0's budget is exhausted

There are some other scenarios as well, but I'll skip those for now.

You didn't tell us how you measured the memory usage, but if you're looking at the memory usage of process itself (e.g. through task manager), then you may not see the numbers you expect. Remember that the .NET runtime essentially has its own memory manager that handles memory usage on behalf of you managed application. The runtime tries to be smart about it so it doesn't allocate and free memory to the OS all the time (those are expensive operations). This question may be relevant as well.

If you're concerned about memory leaks have a look at some of the answers here.

Community
  • 1
  • 1
Brian Rasmussen
  • 114,645
  • 34
  • 221
  • 317
  • I did not know about the GC not freeing to the OS. That makes sense, and answers my question. – Almo Mar 01 '12 at 14:28
2

enter image description here

This comic is the best way to explain this topic :)

Almo
  • 15,538
  • 13
  • 67
  • 95
Dave Bish
  • 19,263
  • 7
  • 46
  • 63
  • That's a good illustration, though I was more worried about knowing if it had ever run or if I was leaking, than knowing exactly when it runs and using that information in the application somehow. – Almo Mar 01 '12 at 14:27
2

When does the .Net 3.5 garbage collector run?
I thought I would see memory being freed by the garbage collector on occasion.

Since the GC is non-deterministic, you won't be able to necessarily determine when it is going to issue a collection. Short answer: It will run when needed. Trying to analyze your code and predict or assume it should be running at a certain time usually ends up down a rabbit hole.

Bryan Crosby
  • 6,486
  • 3
  • 36
  • 55
2

You may have the managed equivalent of a memory leak. Are you maintaining stale references to these objects (i.e., do you have a List<T> or some other object which tracks these nodes)?

Are the subscribing to an event of an object that is not going out of scope? A reference to the subscribee of an event is maintained, so if you don't detach it will keep your objects alive.

You may also be forgetting to Dispose of objects that implement IDisposable. Can't say without seeing your code.

The exact behavior of the GC is implementation defined. You should design your application such that it does not matter. If you need deterministic memory management then you are using the wrong language. Use a tool (RedGate's ANTS profiler will do) to see if you are leaking references somewhere.

Ed S.
  • 122,712
  • 22
  • 185
  • 265
2

Answer to: do I leak objects or GC have not need to run yet?

Use memory profiler to see what objects are allocated. As basic step - force garbage collection (GC.Collect) and check out if allocated memory (GC.GetTotalMemory) seems to be reasonable.

Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
2

If you want to make sure that you're not leaving any unwanted object behind you can use dotTrace memory profiler. It allows you to take two snapshots of objects in memory (taken some time apart) and compare them. You will can clearly see if any old nodes are still hanging around and what is keeping a reference to them and stops them from being collected.

Jakub Konecki
  • 45,581
  • 7
  • 87
  • 126
1

You can monitor the garbage collector activity in .NET 4.0 and beyond with GC.RegisterForFullGCNotification as described in this link: http://www.abhisheksur.com/2010/08/garbage-collection-notifications-in-net.html

Joe H
  • 841
  • 7
  • 20