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.
advertisement
- Getting to grips with Microsoft's IT Health Environment Scanner
- Virtualise your servers
- The changing face of travel gadgets
- Build your own distributed file system
- The bulletproof Dell that costs an arm and a leg
- Microsoft Office 2010 Technical Preview: Q&A
- Lawnmowers, the TyTN II and one odd insurance request
- There'll never be a bulletproof OS
- How far can we trust apps?
- Five nice touches in Outlook 2010
- Why Britain's watchdogs have fewer teeth than goldfish
- Tabbed documents: how to make Office 2010 great
- Outlook 2010 People Pane – does it spell death to Xobni
- Microsoft Outlook 2010 screenshots
- Co-Authoring in Word 2010 and SharePoint Foundation 2010
- Microsoft Outlook 2010 screenshots: Backstage view
- Flash 10.1: Developing for Desktop and Device
- Microsoft Office 2010 screenshots: Recover unsaved items
- Microsoft Word 2010 screenshots: Text Effects
- Microsoft Word 2010: inserting screenshots
- Q&A: Why Conficker was a victim of its own success
- App developers losing faith in Android
- Biz Stone: Murdoch's Google veto will "fail fast"
- Google adds automatic captions to YouTube
- China ramps up cyber spying
- Mozilla maintains dependence on Google
- Windows 7 flying off the shelves
- Google Chrome OS: full details unveiled
- AOL slashes 2,500 jobs
- YouTube begins streaming full-length shows
advertisement
Printed from www.pcpro.co.uk


