To Dispose or not To Dispose

Once upon a time there were functional programming languages where you did what you needed to do explicitly within the function:

C (slightly fictional)

// create resource
HWND hwnd = CreateHWnd( ... );

// use resource
DoSomethingWithMyWindow(hwnd, "something");
.
.
.

// delete resource
DeleteHWnd(hwnd);

Then object oriented languages came along and the above pattern kind of continued, though someone came up with a pattern – Resource Acquisition Is Initialization. In short, we manage the resource within the lifetime of an object, so when that object drops out of existence, the clean-up happens.

C++ equivalent of the above

class MyWnd 
{
    private:
    HWND wnd;

    public:
    MyWnd()
    {
        wnd = ::CreateHWnd( ... );
    }

    ~MyWnd()
    {
        ::DeleteHWnd(wnd);
    }

    void DoSomething()
    {
        ::DoSomething(wnd, "something");
    }
}


// calling code
MyWnd window();
window.DoSomething();

This is great. The class encapsulates the resource handling (and the API calls around it) and when the object drops off the stack, the destructor is called automatically, which guarantees resource handling, even if there are exceptions. But…

In C++ you don’t always create objects locally. So, you still ended up with explicit creates and destroys:

MyWnd* pWnd = new MyWnd();
.
.
pWnd->DoSomething();
.
.
delete pWnd;

And if there were exceptions, or odd flows of control, you might “forget” to tidy up this resource. Such a shame. So C++ people came up with smart pointers – objects that managed the pointer to the object and remembered to delete it when everyone had finished with it.

SmartPtr<MyWnd> pWnd(new MyWnd());

pWnd->DoSomething();

// and when the local pWnd object is destroyed, it deletes the MyWnd inside of it.

These were enhanced to do things like reference counting so you could share the object around. However, there was always a risk of memory leaks, and it meant that ALL resources were cleaned up on the same thread as the key code being executed. Sometimes you’d prefer to clean up your resources in idle time, rather than as you go.

So garbage collection is the answer?

With garbage collection, you have an automated routine which finds spare resources and clears them. It does it “when it wants to”. This is great. No longer will:

MyThing thing = new MyThing();

Need to come with a phalanx of code that remembers to delete “thing” wherever it becomes obsoletes. Memory leaks are kind of a thing of the past…

…but some resources need to be explicitly returned at the exact moment you’re finished with them. Some resources are not internal to the program you are writing. System resources like handles, windows32 objects, files, network connections, they all need releasing at the right time.

Welcome back the destruction pattern

In .NET there is a workaround for this problem – IDisposable.

The basic usage of IDisposable is that you either call it explicitly:

// we won't be using this resource anymore
myResource.Dispose();

or, you take the resource and use it through the using keyword

// this resource is only needed for the duration of this call
using(MyResource r = new MyResource())
{
  r.DoSomething();
}

This is the functional equivalent of

// this resource is only needed for the duration of this call
MyResource r= new MyResource();
try
{
  r.DoSomething();
}
finally
{
  r.Dispose();
}

The finally statement giving us a guarantee that the resource will be cleared.

And now to the major point. Disposing is almost entirely used for dropping resources. There’s not a huge benefit in using Disposing for pure .NET objects, things which ultimately boil down to bits of CLR managed memory. The benefit comes when the .NET object manages some OS resource like a network connection or file handle.

If you want to push it, you might use the Dispose pattern if HUGE CLR memory is managed by an object and you want to release it immediately. Especially if you suspect that other things are keeping a reference open to this object. Allowing the object to be garbage collected is still the preference.

Test it!
I have done some tests. I wrote a console application like this:

    class Program
    {
        static void Main(string[] args)
        {
            while (true)
            {
                var memoryObject = new MemoryObject();
                memoryObject.DoSomething();
            }
        }
    }

I ran this and monitored the memory. “MemoryObject” was a class I wrote that used a StringBuilder to make a new string and then kept references to the builder and the string. The string was about 1k in size.

Running this infinite loop might cause the memory to balloon, but the application quickly stabilised at about 7.5Mb.

I then implemented the IDisposable pattern on “MemoryObject”, but I didn’t modify the calling code. To implement IDisposable, you have to handle the “Dispose” method and use it to clear any internal resources, and you also implement a finalizer.

With finalizer as part of the program, but not being used, the memory footprint INCREASED to about double. This will be because the garbage collector probably reserves objects that need finalizing for a separate thread or somesuch – it treats them more carefully. So, the Dispose pattern on this pure CLR object-based class made memory management worse.

Implementing the using pattern on my calling code:

            while (true)
            {
                using (var memoryObject = new MemoryObject())
                {
                    memoryObject.DoSomething();
                }
            }

Well, then things went back to normal… perhaps a little worse than normal, but not measurably bad.

Summary
When you are managing system resources, you need to release them in time. IDisposable is the technique for this in .NET. However, if you use it to explicitly release CLR objects then you are trying to do the job of the garbage collector and might actually be hampering the GC’s effectiveness.

In place of explictly Disposing objects, try dropping your reference to them and let the GC do its job. If lots of bits of the system might have references, try dealing with that, as a reference to a Disposed object is actually a bad thing! Nobody wants a Zombie!

Final gotcha
It might seem like a good idea to go through setting object references to null if the objects are not needed any more. This is true if the parent object is going to “live on”, but is not true if the parent object will not be needed any more.

See this post on null and Dispose() for more.

About these ads

Software developer, stand-up comedian, musician, writer, jolly big cheer-monkey, skeptical thinker, Doctor Who fan, lover of fine sounds.

Posted in .NET

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 698 other followers

%d bloggers like this: