Why collect garbage?
Posted on 23 May 2006 at 11:27
Thomas Lee demonstrates how the .NET framework is responsible for reclaiming your system's vital resources
Just about everything that happens in a Windows application uses some of the host PC's memory resources. This is quite obvious in the case of a database application or a spreadsheet storing its data in memory, but it's equally true of most other resources too. Whenever a graphics application draws a rectangle on the screen, it must first obtain a buffer in video memory to hold the pixels; whenever a file is sent over the network, the copy process first obtains a buffer in memory to hold data being sent to the network adapter; even writing data to disk will usually allocate some memory buffers to hold the data being written. Whenever the .NET Framework creates an instance of a class, this too consumes a variety of memory resources. In all these cases, the application begins by requesting some resource from the operating system, performs some processing on that resource (for example, displays the rectangle or sends the data buffer to the network port) and then, when completed, releases the resource back to the OS for reuse.
Under Win32, the applications programmer is responsible for explicitly acquiring all resources, using them correctly (for example, never trying to use a resource that's already been released) and for releasing them when no longer needed. For a complex application, managing all this resource allocation is a major problem, and failing to release some resource after use will create a memory or handle "leak" that's a frequent cause of application crashes. Handles and memory are both finite resources, and once they're all tied up the application or service may stop working. Sometimes, just stopping and restarting that process or service will solve the problem (temporarily), but other times you'll need a reboot - something most server administrators try to avoid.
To detect such leaks in memory and handles, start out by simply monitoring the Total Commit Charge value you see at the bottom left of Task Manager's Performance tab. If you click on the Processes tab and use the View/Select Columns menu, you can also monitor individual processes' memory and GDI Object usage. For a more fine-grained analysis, use the Performance Monitor to detect leaks in memory and handles.
Fortunately, all of this is rarely necessary with .NET applications, because Microsoft built proper memory management into the .NET Framework, and in particular automatic garbage collection. Garbage collection frees the programmer from having to worry about memory allocation and deallocation (although not quite completely, as we'll see later). This not only improves programmers' productivity no end, since writing the memory management for a complex application is hard work, but also creates far more reliable applications and services.
Memory management in .NET
To understand garbage collection, you first have to understand how .NET allocates memory. Whenever an application needs a block of dynamic memory for whatever reason, .NET allocates blocks from what's known as the "managed heap" - a large area of memory owned and managed by the .NET Framework, which it shares among all the .NET applications running on the computer. From here, .NET keeps track of the usage of each of these memory blocks and reclaims them when they're no longer in use - the act of garbage collection itself.
The screenshot below shows you the managed heap, with three objects allocated called A, B and C. In addition, .NET maintains a pointer to the first free chunk of memory in the managed heap, which is shown as Next Object (before). When an application asks for a block of memory to store the Next Object, .NET will advance this pointer by the size of the newly allocated block and pass the block's starting address back to the requesting application. This makes memory allocation very simple, and therefore very fast. By comparison, memory allocation in a traditional C program is painfully slow, requiring the Memory Manager to walk the length of a linked list of memory blocks until it finds one big enough to satisfy the request. This block then gets divided into two parts: one to satisfy the memory request and the remainder being put back onto the linked list as a smaller chunk. This process is more complicated and much slower than allocation under .NET.
From around the web
advertisement
- Why you have to be left in the dark on OS patches
- Is Microsoft mismanaging Windows on ARM?
- Dealing with spam surrogates
- Why 3G broadband can be better and cheaper than ADSL
- Is Twitter bad for business?
- Publishing your email address isn't a security disaster
- Why you'll need a fax machine to develop iOS apps
- Learning to adapt to the mobile web
- Why you shouldn't use WPS on your Wi-Fi network
- Disabled users suffer when software breaks the rules
- Laptop bag reviews: nine tested
- Sony VAIO T Series Ultrabook review: first look
- Revealed: the military standards and robots HP uses to test its laptops
- Windows 8: multi-monitors and double standards?
- Why is TalkTalk's year-old porn filter suddenly big news?
- Why are laptop screens so far behind mobiles?
- HP EliteBook Folio review: first look
- The shoebox-sized all-in-one printer
- Forget the Ultrabook: here comes the HP Sleekbook
- HP Spectre XT review: first look
- Autonomy's Lynch joins 27,000 on way out of HP
- ICO: no fines for breaking cookie rules
- HP set to slash up to 30,000 jobs
- Government sites to miss cookie deadline
- Microsoft tweaks multi-monitor support in Windows 8
- Apple patches Leopard, despite ending support last year
- Defra opens rural broadband funding applications
- BT's broadband sales surpass calls revenue
- Apple patches multiple security issues
- FBI warns travellers to beware attacks via hotel Wi-Fi
advertisement

