February 2004 - Posts

I just re-learned a valuable lesson.  I was preparing for an upcoming class that I’m teaching on .NET for my team, and I was reviewing the .NET Garbage collector.  I thought that I’d throw together a few quick apps using WeakReferences to show when objects are garbage collected, but I wasn’t getting the behavior I was expecting.  Unless an object was explicitly set to null, the objects were not being collected.  I was amazed, as this really isn’t how GC is documented, and both of my Heroes, Software Legend Jeffrey Richter and Father of COM (is Love) Don Box clearly state in their books that objects are eligible for GC after their last reference.

Well, I threw together the following code in the Main() method of a C# console app:

 

Console.WriteLine("Starting GC Example App...");

object gcTestObjectWithNull = new object();

object gcTestObject = new object();

WeakReference wr = new WeakReference(gcTestObject);

WeakReference wrWithNull = new WeakReference(gcTestObjectWithNull);

Console.WriteLine( "wr.IsAlive= " + wr.IsAlive );

Console.WriteLine( "wrWithNull.IsAlive= " + wrWithNull.IsAlive );

gcTestObjectWithNull = null;

GC.Collect();

Console.WriteLine("\nWe've just garbage collected, and \n");

Console.WriteLine( "wr.IsAlive= " + wr.IsAlive );

Console.WriteLine( "wrWithNull.IsAlive= " + wrWithNull.IsAlive );

 

My (unexpected) output was consistently:

 

Starting GC Example App...

wr.IsAlive= True

wrWithNull.IsAlive= True

 

We've just garbage collected, and

 

wr.IsAlive= True

wrWithNull.IsAlive= False

 

Well, this would certainly contradict the GC documentation, wouldn’t it?  Note that the object that is getting collected is set to null, while the object that sticks around is not.

 

As I’m writing up my blog findings, ready to jump on the Paul Wilson “null is necessary” bandwagon, it suddenly strikes me – I’ve been doing all this testing in DEBUG mode.  A quick build of the same project in RELEASE results in:

 

 

Starting GC Example App...

wr.IsAlive= True

wrWithNull.IsAlive= True

 

We've just garbage collected, and

 

wr.IsAlive= False

wrWithNull.IsAlive= False

 

Ahh, now there’s the predictable behavior that I’ve been looking for!  What a difference a compiler switch makes!  I'll step back off Paul's null bandwagon for the moment ;-)

 

--

 

[Editorial Note: I'm not arguing with Paul's case that null may be necessary in some circumstances, but I'd claim that it is the exception rather than the rule.]

As I've posted before, MSBuild support is noticeably absent in the next version of Visual C++.  With all of Microsoft's hype over MSBuild, this is a glaring omission.  As a new blogger, and member of the Visual C++ IDE's project/build system team, perhaps Josh can help explain this?

I've read quite a few articles and books that proclaim the benefits of multi-threading, and many people admire the beauty of a nicely threaded program.  I agree fully - a well-implemented threading server certainly can reap great performance benefits.  SQL Server is a wonderful example of this.  So much thought was put into threading in SQL Server that they implemented their own thread scheduler, pre-empting the OS threading model through some quite clever trickery.

However, sometimes people can go over the top with threading.  Really.

I've recently taken over an installation project at my new job.  It's a bit involved, as it installs several databases, sets registry, config data, and a bunch of other one-time gunk that installs normally do.  It was originally implemented in Installshield 5, with custom calls into C++ dlls, as was common in the days of installshield 5.  My task involves helping to drag this project into the 21st century, adapting it to windows installer using Installshield 9.

All's fine and dandy on the Installshield side.  The bigger problem I am having is that in the custom C++ code, there is some convoluted threading going on. 

Yes, threading.  In an installation project.  One might ask why.  I know that I have, several times, while cursing the assorted bugs that come along with this. (It's actually worse than simple threading - they implemented application windows to listen to a message pump so that child threads could send messages to the window.  Ugh!)


Threading is a good thing to implement if there is a performance issue, I agree.  But this is hardly the case in an installation.  The 5 or 10 seconds that one might save is hardly critical, and certainly not worth the synchronicity issues that are introduced.

So, for all you super-smart gurus out there who thing that cutting edge needs to be everywhere:  Think before you act.  Threaded installs may sound great, but they aren't.  Trust me.

More Posts