If broken it is, fix it you should

Using the powers of the debugger to solve the problems of the world - and a bag of chips    by Tess Ferrandez, ASP.NET Escalation Engineer (Microsoft)

.NET Garbage Collection PopQuiz

.NET Garbage Collection PopQuiz

Rate This
  • Comments 25

Time for a little pop-quiz/potential interview questions to get some action going in the comments section... 

Feel free to answer any or all of the below questions, I'll follow up with a post later if all of them are not answered...

 

1. How many GC threads do we have in a .NET process running the Server version of the GC on a dual-core machine?

2. What GC mode is used in the web development server (cassini) on a quad proc machine? Why?  (you can choose from server, workstation or concurrent-workstation)

3. How many finalizer threads do we have in a .NET process running the Server version of the GC on a quad proc machine?

4. When is an object garbage collected?

5. What causes an object to move from Generation 0 to Generation 1 or to Generation 2?

6. If you look at the GC sizes for Generation 0, 1 and 2 in perfmon, why is most of the memory in the process in Gen 2?

7. How many heaps will you have at startup on a 4 proc machine running the server GC?  How many would you have if the same machine was running the workstation GC?  Will the memory used for these show up in private bytes or virtual bytes in perfmon or both?

8. (Leading question:))  Is the fact that you have mscorwks.dll loaded in the process in 2.0 an indication of that you are running the workstation version of the GC?

9. Can you manually switch GC modes for a process?  If so, how and under what circumstances?

10. Name at least 2 ways to make objects survive GC collections unneccessarily.

11. Can a .NET application have a *real* memory leak?  In the C++ sense where we allocate a chunk of memory and throw away the handle/pointer to it?

12. Why is it important to close database connections and dispose of objects? Doesn't the GC take care of that for me?  

 

and if you don't think these questions are enough... feel free to post some of your own questions on the same theme...

Have fun,

Tess





  • 1/ 4 gc threads, one per processor.

    2/ I think that it would be workstation, since it is basically a winforms application.

    3/ Either one or four, although I am leaning toward one.

    4/ Um, during garbage collection? Not sure I understand the question.

    5/ A GC that runs but find that it is still rooted somewhere will promite it to the next generation.

    6/ Gen 2 also include the large objects, no?

    7/ No idea

    8/ Yes.

    9/ Define GC modes, you mean workstation vs server? If so, I believe that the answer is no. If it is possible, probably via obscure COM API.

    10/ Static Event Handlers, Cache[Guid.NewGuid()] = new object()

    11/ Yes, usually via calling unmanaged API.

    12/ It does, in the finalizer thread, which takes a _long_ time to process things. Basically this shove stuff like connection pooling out of the window, not to mention that basically resources are held for much longer.

  • 1) 2 threads

    2) Workstation,

    3) 4

    4) Out of scope

    5) Allocation triggers GC and it causes live objects to promote from 0 to 1 or 1 to 2

    6) Long lived and big objects(8 kb) promoted to generation  2

    7) server GC -> 4 heaps and workstation GC -> 1 heap and initially it will be private bytes

    8) Yes

    9) For individual process answer is no, but we can set GC mode for machine, it is usually done for Winform application on multicore machines 

    10) A) Implement destructor and write resurrect pattern for that object. b) Declare object globally so unless and until appdomin is not unloaded it will survive.

    11) Yes

    12) GC is able to release manage memory only and database connection you can visualize as tunnel from manage world to OS, so if IDisposable is implemented and you don’t call Close() than at some time if GC happen (at least 2) than it might close that connection.

  • I make mistake in my previous ans, I get confused between Server mode and concurrent-workstation mode

    1->1 Thread

    3 ->1

    7-> In both cases 1 heap only

  • 1 - I somehow gathered that the server GC interupts the current thread, that would mean zero. Not sure though.

    2 - Agree with Rahien.

    3 - cbrumme wrote about it, but I forgot it. One?

    4 - When there is no reference to it and any finalizing is done.

    5 - Agree with Rahien.

    6 - It has all objects of any serious life time. 0 and 1 have a fixed (small) size and pass their stuff to 2.

    7 - How would the number of procs or the GC type affect the number of heaps? One, or maybe one per app domain. (The allocated address range should show up in virtual bytes, the actually memory in private bytes. But don't take my word for that.)

    8 - yes

    9 - Only through hosting APIs before any managed code gets executed.

    10 - Keep references in static structures, do not unregister for finalization (that would prevent collection only once), fixing it for interop ...

    11 - If it could, i'd definately like to hear about it! (I don't think unmanaged stuff counts)

    12 - The GC generally doesn't care about anything but memory, so running out of connections won't trigger it. Also, there are situations where you need resources freed immediately, e.g. if you need to access the resource again using another managed wrapper. Files and DB records could remain locked without disposing.

  • Currently interviewing for a .Net PFE position w/ you guys, so I should know all of these, so here goes:

    1. Two, one per CPU

    2. Don't know, but if I had to guess I'd say Concurrent GC...that's the one I'd want used if I had a choice.

    3. ?

    4. You never know for sure, but it's marked for GC when it's reference count equals zero.

    5. When it "survives" a GC, i.e. it still has references to it when the GC is invoked.

    6. These are the objects with the most references to them, as well as the "large object heap."

    7. Guessing... 4. 1. Private bytes.

    8. No. mscorsvr was folded into mscorwks for the 2.0 release.

    9. I have no idea. I'm assuming you can via config sections, but the process will need to be restarted.

    10. Pin them via managed C++? That's the only one I know of.

    11. Yes (kinda), objects can be orphaned but they won't hang around forever.

    12. In the case of a database connection, that is an unmanaged resource and thus needs to be cleaned up in Dispose (finalizers). Only objects containing references to unmanaged resources should have dispose called on them.

  • 1/ It's dual core, so only 2

    3/ 1

    10/ Give it an unnecessary finalizer

  • 1. How many GC threads do we have in a .NET process running the Server version of the GC on a dual-core machine?

    --- How many dual core processors are in the machine?  Are the cores hyperthreaded?  My understanding is that there will be one GC thread per logical CPU on the server version of the GC, so if it's a single dual core processor without hyperthreading, I'd expect 2.  With hyperthreading, I'd expect 4.

    2. What GC mode is used in the web development server (cassini) on a quad proc machine? Why?  (you can choose from server, workstation or concurrent-workstation)

    --- I don't know, but I'd guess either server or concurrent workstation.  If it's a webdev server with multiple processors, we're expecting multiple users with notable load.  We want to take advantage of all that CPU power.

    3. How many finalizers do we have in a .NET process running the Server version of the GC on a quad proc machine?

    --- I believe there's still only one finalizer thread.  Is there one thread per application or AppDomain?  Or are applications defined by their AppDomain?

    4. When is an object garbage collected?

    --- When a garbage collection takes place and the object has no remaining references.  (Perhaps surprisingly, this may result in an object being GC'd before it looks like it's gone out-of-scope.)

    5. What causes an object to move from Generation 0 to Generation 1 or to Generation 2?

    --- I believe an object is promoted through the generations when it survives a garbage collection at its current generation.  (A gen1 object won't be promoted to gen2 on a gen0 collection).

    6. If you look at the GC sizes for Generation 0, 1 and 2 in perfmon, why is most of the memory in the process in Gen 2?

    --- I'm not really certain.  I know that Gen2 collections don't happen very often and gen2 should hold all information that lives as long as the process.  Perhaps System.String objects end up in Gen2 because of the flyweight pattern that they use in the CLR?

    7. How many heaps will you have at startup on a 4 proc machine running the server GC?  How many would you have if the same machine was running the workstation GC?  Will the memory used for these show up in private bytes or virtual bytes in perfmon or both?

    --- I don't know.  I suppose I'm not as well-versed as I ought to be in the differences between the GC flavors.

    8. (Leading question:))  Is the fact that you have mscorwks.dll loaded in the process in 2.0 an indication of that you are running the workstation version of the GC?

    --- I don't think so.  I recall reading somewhere that all flavors were merged into the one file for 2.0.  

    9. Can you manually switch GC modes for a process?  If so, how and under what circumstances?

    --- I don't know.  If you can, I'd be interested in knowing the reasoning behind the feature.  I can't think of a use-case off the top of my head.

    10. Name at least 2 ways to make objects survive GC collections unneccessarily.

    --- (A) Implement a useless finalizer.  (B) Keep references hanging around when you'll never use them again and the CLR has no way of determining that they'll never be used again.  Perhaps by forgetting to unpin some memory?

    11. Can a .NET application have a *real* memory leak?  In the C++ sense where we allocate a chunk of memory and throw away the handle/pointer to it?

    Yes, .net applications can make calls against unmanaged, leaky code.

    12. Why is it important to close database connections and dispose of objects? Doesn't the GC take care of that for me?  

    It's important to dispose the objects because it prevents the unnecessary promotion of the entire disposable object graph to a higher generation for finalization.

  • 1 - what was I thinking, even with all threads frozen, this would still mean that GC needs dedicated threads, one per processor would be the logical answer. 4, then.

  • Bottom line, none of this should really matter to the developer. Just be sure to close and dispose of all your objects and let .Net worry about the clean up. In the instance where memory management becomes an issue, the cause is usually a call to an unmanaged API that you have no control over any way (Thanks Crystal Reports). If you are really concerned about memory management, use the USING (){} statement and call the GC after major events in the code. Oh, did I mention be sure to close and dispose of your objects?

  • Great questions but to point 11 I wonder if you could do something like this

    unsafe

    {

    }

    and do as much memory leaking as you like!

  • Interesting questions, and I'd love to get the answer for several of them!

    4. When the object gets unreferenced and the GC runs. To make things clear: an unreferenced object in the heap will not get garbage-collected until the GC runs.

    5. Objects that are still referenced when the GC runs move from gen 0 to gen 1. And so forth.

    6. Obviously, these are long-run objects since they weren't GC'ed for quite a long period. Obviouly too, there will lay the open forms of my application and shared objects, which usually are the biggest. In other words, objets that have short lives usually also are small.

    11. Supposedly no, that's what the GC is there for.

    12. The GC will eventually call Dispose on IDisposable objects. Knowing that there may be quite some time until an object gets GC'ed (see 4), and that many resources are limited, you call Dispose yourself as soon as you're over with an object. It doesn't get GC'd when you call Dispose, but it releases its resources.

  • So how much faster is it really and is it? WCF performance in comparison. [Via: clemensv@microsoft.com...

  • Awesome answers from all,  I'm really excited to see that so many people answered so fast:)  I'm going to give it a few days to see what more comes in and send my answers out over the weekend, until then, have a great easter weekend

  • mark: you can use pointers with unsafe, but GC could still clean them up (or move them), so you'd have to pin them first. once pinned, they aren't going to be collected. however, as long as you use the "fixed" statement, you can be pretty sure that the pin will be released. so i'd still think the answer to be "no".

    btw, i have to correct my answert to 1 again: without hyperthreading, dual core means two logical processors, not four. I guess that was supposed to be the easy part ;-)

  • 1. Two one for each core

    2. I am purely guessing workstation with concurrent GC off.

    3. One.

    4. When the GC feels it is time.

    5. After having survived a GC 0 and 1 collection if it’s not on the LOH.

    6. Probably because the applications has reached a “balanced state” where the long lived data lives in GEN 2 and the short lived data which probably is less only exists in GEN 0.

    7. I am clueless here but I guess 4 heaps with server and 1 with workstation.

    8. I guess yes.

    9. While the process is running? Otherwise I believe it is in the config file.

    10. Implement an empty finalizer or have a strong reference to the object from an object with a finalizer.

    11. You could always block the finalizer thread so my answer has to be yes.

    12. It is not important! At least until you have convinced you boss that some cool new hardware will solve your resource problems ;-)

Page 1 of 2 (25 items) 12
Leave a Comment
  • Please add 7 and 8 and type the answer here:
  • Post