<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Steven Pratschner's .Net CF WebLog : GC</title><link>http://blogs.msdn.com/stevenpr/archive/tags/GC/default.aspx</link><description>Tags: GC</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Using the .NetCF Remote Performance Monitor to find memory leaks: A real world example</title><link>http://blogs.msdn.com/stevenpr/archive/2007/03/23/using-the-netcf-remote-performance-monitor-to-find-memory-leaks-a-real-world-example.aspx</link><pubDate>Fri, 23 Mar 2007 20:32:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1938492</guid><dc:creator>stevenpr</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/stevenpr/comments/1938492.aspx</comments><wfw:commentRss>http://blogs.msdn.com/stevenpr/commentrss.aspx?PostID=1938492</wfw:commentRss><description>&lt;P&gt;A few weeks ago I posted an entry describing &lt;A class="" href="http://blogs.msdn.com/stevenpr/archive/2007/03/08/finding-managed-memory-leaks-using-the-net-cf-remote-performance-monitor.aspx" mce_href="http://blogs.msdn.com/stevenpr/archive/2007/03/08/finding-managed-memory-leaks-using-the-net-cf-remote-performance-monitor.aspx"&gt;how to use the .Net Compact Framework Remote Performance Monitor to find managed memory leaks&lt;/A&gt;.&amp;nbsp; The other day I ran across a post from &lt;A class="" href="http://blogs.msdn.com/controlpanel/blogs/www.satter.org" mce_href="http://blogs.msdn.com/controlpanel/blogs/www.satter.org"&gt;Rabi&amp;nbsp;Satter&lt;/A&gt;&amp;nbsp;describing how he used to tool to solve a critical leak for one of his customers.&amp;nbsp; His&amp;nbsp;real world experience&amp;nbsp;provides a much more complete memory leak example than my original post did.&amp;nbsp; Check it out: &lt;SPAN style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 'Tahoma','sans-serif'; mso-ansi-language: EN-US; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;. &lt;A href="http://www.satter.org/2007/03/thank_god_for_c.html"&gt;http://www.satter.org/2007/03/thank_god_for_c.html&lt;/A&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 'Tahoma','sans-serif'; mso-ansi-language: EN-US; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;Thanks,&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 'Tahoma','sans-serif'; mso-ansi-language: EN-US; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;Steven&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 'Tahoma','sans-serif'; mso-ansi-language: EN-US; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;SPAN lang=EN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Rockwell','serif'; mso-ansi-language: EN"&gt;This posting is provided "AS IS" with no warranties, and confers no rights.&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1938492" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/stevenpr/archive/tags/GC/default.aspx">GC</category><category domain="http://blogs.msdn.com/stevenpr/archive/tags/Diagnostics/default.aspx">Diagnostics</category></item><item><title>Using the .Net Compact Framework Remote Performance Monitor to Optimize your application's memory usage</title><link>http://blogs.msdn.com/stevenpr/archive/2007/01/02/using-the-net-compact-framework-remote-performance-monitor-to-optimize-your-application-s-memory-usage.aspx</link><pubDate>Wed, 03 Jan 2007 02:51:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1401044</guid><dc:creator>stevenpr</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/stevenpr/comments/1401044.aspx</comments><wfw:commentRss>http://blogs.msdn.com/stevenpr/commentrss.aspx?PostID=1401044</wfw:commentRss><description>&lt;P&gt;The &lt;A class="" href="http://dotnet.sys-con.com/read/issue/827.htm" target=_blank mce_href="http://dotnet.sys-con.com/read/issue/827.htm"&gt;November issue of .Net Developers Journal&lt;/A&gt;&amp;nbsp;includes a &lt;A class="" href="http://dotnet.sys-con.com/read/315037.htm" mce_href="http://dotnet.sys-con.com/read/315037.htm"&gt;new article on using the Remote Performance Montior&lt;/A&gt;.&amp;nbsp; In the article I describe how to interpret the various memory-related counters to optimize how your Compact Framework application uses memory on the device.&lt;/P&gt;
&lt;P&gt;Thanks,&lt;/P&gt;
&lt;P&gt;Steven&lt;/P&gt;
&lt;P&gt;&lt;SPAN lang=EN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Rockwell','serif'; mso-ansi-language: EN"&gt;This posting is provided "AS IS" with no warranties, and confers no rights.&lt;/SPAN&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1401044" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/stevenpr/archive/tags/GC/default.aspx">GC</category><category domain="http://blogs.msdn.com/stevenpr/archive/tags/Diagnostics/default.aspx">Diagnostics</category></item><item><title>.Net Compact Framework GC article in .Net Developers Journal</title><link>http://blogs.msdn.com/stevenpr/archive/2006/02/08/528138.aspx</link><pubDate>Thu, 09 Feb 2006 04:23:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:528138</guid><dc:creator>stevenpr</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/stevenpr/comments/528138.aspx</comments><wfw:commentRss>http://blogs.msdn.com/stevenpr/commentrss.aspx?PostID=528138</wfw:commentRss><description>&lt;p&gt;&lt;font face=Verdana size=2&gt;I recently wrote an article for .&lt;a href="http://dotnet.sys-con.com/"&gt;Net Developers Journal&lt;/a&gt; on how operations like boxing and string manipulations can affect the performance of the Compact Framework's garbage collector. Credit for the ideas and samples in the article go to &lt;a HREF="/romanbat/"&gt;Roman Batoukov&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Check out the &lt;a href="http://dotnet.sys-con.com/general/currentcover.htm"&gt;February issue&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;For more Compact Framework performance information, see the &lt;a HREF="/netcfteam/archive/2005/05/04/414820.aspx"&gt;FAQ&lt;/a&gt; on our &lt;a HREF="/netcfteam/"&gt;team blog&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Thanks,&lt;br /&gt;Steven&lt;/font&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=528138" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/stevenpr/archive/tags/GC/default.aspx">GC</category></item><item><title>The Design of the .Net Compact Framework CLR, Part III: GC Heap Management</title><link>http://blogs.msdn.com/stevenpr/archive/2005/12/14/503818.aspx</link><pubDate>Thu, 15 Dec 2005 02:31:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:503818</guid><dc:creator>stevenpr</dc:creator><slash:comments>5</slash:comments><comments>http://blogs.msdn.com/stevenpr/comments/503818.aspx</comments><wfw:commentRss>http://blogs.msdn.com/stevenpr/commentrss.aspx?PostID=503818</wfw:commentRss><description>&lt;P&gt;&lt;FONT face=Verdana size=2&gt;Here's Part III of the series on the design of the .Net Compact Framework CLR.&amp;nbsp; Previous posts in this series provided an overview of how the CLR manages memory and described the basic design tenants of the JIT compilers:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;&lt;a href="http://blogs.msdn.com/stevenpr/archive/2005/12/12/502908.aspx"&gt;Part I, Overview and Background&lt;/A&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;&lt;a href="http://blogs.msdn.com/stevenpr/archive/2005/12/12/502978.aspx"&gt;Part II, Jit Compiler Design Considerations&lt;/A&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;This post focuses on the design of the garbage collector from the perspective of how the GC heap is managed.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;---------&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;Garbage collection is typically the topic that first comes to mind when discussing how memory is managed on the .Net platform. Not surprisingly, the Compact Framework’s garbage collector differs in many respects from its desktop counterpart due to the constraints in which it must run. Like most other subsystems within the Compact Framework CLR, the garbage collector has been designed to free all the memory it can when the amount of memory available on the device is low.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;At a high level, the GC performs two basic functions: it allocates memory to hold instances of reference types and it collects the instances that are no longer needed.&lt;/FONT&gt;&lt;/P&gt;
&lt;H2&gt;&lt;FONT face="Times New Roman"&gt;Allocating Reference Types&lt;/FONT&gt;&lt;/H2&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;As described in &lt;a href="http://blogs.msdn.com/stevenpr/archive/2005/12/12/502908.aspx"&gt;Part 1&lt;/A&gt;, the GC heap lives in the per-application 32 MB virtual address space. As with the JIT heap, the GC heap starts small and grows incrementally as more space is needed. However, there are two important differences in the way the GC heap grows when compared to the JIT heap: the GC heap grows in fixed increments, and it does not grow unbounded.&lt;BR&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;The growth increment for the GC heap is generally 64K. When a new 64K “segment” is created, allocations occur from that segment until no more room is available, at which point another segment is created. The Compact Framework GC allocates new segments using the standard Win32 API &lt;/FONT&gt;&lt;FONT face="Lucida Console" size=2&gt;VirtualAlloc&lt;/FONT&gt;&lt;FONT face=Verdana size=2&gt;. Allocations within a segment are very fast. Performance tests on version 2 of the .Net Compact Framework show that the allocator can create up to 7.5 million instances of a small reference type per second. The allocator is so fast because the algorithm it uses is simple. A pointer is maintained to the “next available location” in the GC heap. To allocate space for a new instance, the allocator simply moves the pointer by the number of bytes needed to hold the object as shown in Figure 4:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;IMG height=188 src="http://static.flickr.com/20/73548464_970f38bce4_o.jpg" width=448&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;&lt;B&gt;Figure 4&lt;/B&gt;&lt;BR&gt;&lt;I&gt;Allocating a new reference type is simply a matter of adjusting the “next object” pointer.&lt;/I&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;While the default growth increment for the GC heap is 64K, the allocator will grow the heap in larger increments to accommodate objects greater than 64K. For example, if a program attempts to create an object that is 70k, the allocator will create a new segment of that size to store the larger object.&lt;BR&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;The GC heap grows in increments as described until it reaches 1 MB, at which point a collection begins (more on this later). The GC heap may continue to grow after that, but a collection occurs whenever 1MB of objects has been allocated since the last collection occurred.&lt;/FONT&gt;&lt;/P&gt;
&lt;H2&gt;Collecting Reference Types&lt;/H2&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;Now that we’ve seen how the GC heap grows, let’s take a look at how it shrinks. Again, the ability to reduce the size of the GC heap under memory pressure is key to helping applications run well on memory constrained devices. In this section, we’ll look at what causes a collection to occur and when memory is freed and returned to the operating system.&lt;BR&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;There are several triggers that can cause a garbage collection to occur. As described, one of those triggers is the allocation of 1MB of managed objects. Other triggers include resource failures such as the inability to allocate more memory, create more window handles and so on. See &lt;a href="http://blogs.msdn.com/stevenpr/archive/2004/07/26/197254.aspx"&gt;An Overview of the .Net Compact Framework Garbage Collector&lt;/A&gt; for more details on what triggers a collection.&lt;BR&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;FONT face=Verdana size=2&gt;Memory is not freed and returned to the operating system every time a GC occurs.&amp;nbsp; To understand when memory is freed from the operating system’s perspective, let’s take a closer look at what happens when the collector runs.&lt;/FONT&gt;&lt;/P&gt;
&lt;H3&gt;Unreferenced Objects&lt;/H3&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;During every collection, the GC looks through the heap to find objects that are no longer referenced. The memory for these unneeded objects is freed in the sense that more space is now available in the GC heap. After freeing the unreferenced types, it’s possible that some number of 64K segments may be completely empty. If a segment is completely empty, and the GC still has 1MB of allocated segments, the empty 64K segments will be returned to the operating system by calling &lt;/FONT&gt;&lt;FONT face="Lucida Console" size=2&gt;VirtualFree&lt;/FONT&gt;&lt;FONT face=Verdana size=2&gt;. With the exception of a “full” GC (described below), the collector always keeps a 1MB cache of 64K segments, even if some of them are empty. By caching segments in this way, performance is improved by reducing the number of calls to &lt;/FONT&gt;&lt;FONT face="Lucida Console" size=2&gt;VirtualAlloc&lt;/FONT&gt;&lt;FONT face=Verdana size=2&gt; and &lt;/FONT&gt;&lt;FONT face="Lucida Console" size=2&gt;VirtualFree&lt;/FONT&gt;&lt;FONT face=Verdana size=2&gt;.&lt;/FONT&gt;&lt;/P&gt;
&lt;H3&gt;&lt;FONT face="Times New Roman"&gt;Compacting the GC Heap&lt;/FONT&gt;&lt;/H3&gt;
&lt;P class=MsoNormal&gt;&lt;FONT face=Verdana size=2&gt;The GC may optionally compact the heap during a collection.&amp;nbsp; When the heap reaches a state where it is sufficiently fragmented, the collector “compacts” the heap by moving all live objects close to each other.&amp;nbsp; The primary goal in compacting the heap is to make larger blocks of memory available in which to allocate more objects.&amp;nbsp; Figure 5 represents the contents of a GC heap before and after compaction.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;IMG height=375 src="http://static.flickr.com/20/73548465_5ff931caa1_o.jpg" width=718&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;FONT face=Verdana size=2&gt;&lt;B&gt;Figure 5&lt;/B&gt;&lt;BR&gt;&lt;I&gt;The contents of a sample GC heap before and after compaction&lt;/I&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=NormalContinuation&gt;&lt;FONT face=Verdana size=2&gt;As with the “simple” object collection, the GC will return empty 64K segments to the operating system as long as the 1MB segment cache is full.&lt;/FONT&gt;&lt;/P&gt;
&lt;H3&gt;A "Full" GC&lt;/H3&gt;
&lt;P class=MsoNormal&gt;&lt;FONT face=Verdana size=2&gt;Under the normal course of events, the GC works as described above: periodic collections are made after every 1MB of allocations, the heap is compacted if it gets too fragmented, and empty segments are returned to the operating system as long as the collector’s 1 MB cache is full.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;There three scenarios, however, in which more drastic steps are taken to make more memory available. These scenarios align exactly with the times at which the JIT reduces the size of it’s heap as described in &lt;a href="http://blogs.msdn.com/stevenpr/archive/2005/12/12/502978.aspx"&gt;Part II&lt;/A&gt;: when a failure to allocate memory or other resource occurs, when an application is moved to the background, or when an application receives the &lt;/FONT&gt;&lt;FONT face="Lucida Console" size=2&gt;WM_HIBERNATE&lt;/FONT&gt;&lt;FONT face=Verdana size=2&gt; message from the operating system. At these times, the GC will hot hold onto its 1MB segment cache. It will collect all unreferenced objects, compact the heap, and free any memory it can.&lt;/FONT&gt;&lt;/P&gt;
&lt;H3&gt;Pulling it All Together&lt;/H3&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;Now that we’ve seen how the GC allocates and frees memory, let’s look at the size of the GC heap over the lifetime of an application.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;IMG height=673 src="http://static.flickr.com/34/73548466_cb15c52ed7_o.jpg" width=800&gt;&lt;/P&gt;
&lt;P class=FigNum&gt;&lt;B&gt;&lt;FONT face=Verdana size=2&gt;Figure 6&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=FigNum&gt;&lt;I&gt;&lt;FONT face=Verdana size=2&gt;The size of the GC heap over the lifetime of an application.&lt;/FONT&gt;&lt;/I&gt;&lt;/P&gt;
&lt;P class=MsoCaption&gt;&lt;FONT face=Verdana size=2&gt;The graph in Figure 6 tracks two pieces of data. The yellow line shows the cumulative number of bytes the garbage collector has been asked to allocate over the lifetime of the application. This number will continue to grow without bounds as long as the application continues to allocate new objects.&lt;BR&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoCaption&gt;&lt;FONT face=Verdana size=2&gt;The blue line in Figure 6 shows the size of the GC heap over time. There are several points worth noting. First, when the application starts and continues to run, we see the size of the GC heap growing in a consistent stair-step fashion. Each “step” in the graph corresponds to a newly created 64K GC segment. Second, we can see that the blue line levels off after some time. As you’d expect from the earlier description of the allocation and collection algorithms, the point at which the size of the heap flattens out is at 1MB. Next, you can see a dramatic drop in the size of the heap. In this case, the drop occurs when I moved the application I was monitoring into the background. After the application switches to the foreground, we start to see the heap growing in 64K chunks again.&lt;BR&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoCaption&gt;&lt;FONT face=Verdana size=2&gt;This series of posts has now covered the basics of how the .Net Compact Framework managed memory, and the design decisions made while building the JIT compilers and the garbage collector. In my next post, I’ll look at how the need to run efficiently on memory constrained devices has affected the design of the CLR’s class loader.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Rockwell size=2&gt;This posting is provided "AS IS" with no warranties, and confers no rights.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoCaption&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;BR&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=503818" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/stevenpr/archive/tags/GC/default.aspx">GC</category></item><item><title>An Overview of the .Net Compact Framework Garbage Collector</title><link>http://blogs.msdn.com/stevenpr/archive/2004/07/26/an-overview-of-the-net-compact-framework-garbage-collector.aspx</link><pubDate>Mon, 26 Jul 2004 21:18:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:197254</guid><dc:creator>stevenpr</dc:creator><slash:comments>24</slash:comments><comments>http://blogs.msdn.com/stevenpr/comments/197254.aspx</comments><wfw:commentRss>http://blogs.msdn.com/stevenpr/commentrss.aspx?PostID=197254</wfw:commentRss><description>&lt;p class="Figure" style="margin: 6pt 0in"&gt;&lt;font face="Verdana" size="2"&gt;Developers frequently ask for more information about how the garbage collector works in the Compact Framework.&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;In this blog entry, I&amp;#x2019;ll address the questions we are most often asked about the collector.&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;I&amp;#x2019;ll start by describing the overall model for collections in the Compact Framework.&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;I&amp;#x2019;ll then point out a few of the key differences between how collections are done in the Compact Framework and the full .Net Framework.&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;If you have questions I don&amp;#x2019;t answer, feel free to send me mail or comment on this entry and I&amp;#x2019;ll work to get them addressed in the future.&lt;/font&gt;&lt;/p&gt;  &lt;h1 style="margin: 0.25in 0in 6pt"&gt;&lt;font face="Verdana" size="3"&gt;Collection Model&lt;/font&gt;&lt;/h1&gt;  &lt;p class="Figure" style="margin: 6pt 0in"&gt;&lt;font face="Verdana"&gt;&lt;font size="2"&gt;Let&amp;#x2019;s start by looking at the collection model used by the Compact Framework.&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;In this section, I&amp;#x2019;ll describe the conditions that cause a collection to occur and the specific steps taken each time the collector runs.&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p class="Figure" style="margin: 6pt 0in"&gt;&lt;font face="Verdana" size="2"&gt;A collection is initiated when either:&lt;/font&gt;&lt;/p&gt;  &lt;p class="Figure" style="margin: 6pt 0in 6pt 0.5in; text-indent: -0.25in; mso-list: l0 level1 lfo1; tab-stops: list .5in"&gt;&lt;span style="font-family: symbol; mso-fareast-font-family: symbol; mso-bidi-font-family: symbol"&gt;&lt;span style="mso-list: ignore"&gt;&lt;font size="2"&gt;&amp;#xB7;&lt;/font&gt;&lt;span style="font: 7pt &amp;#x27;Times New Roman&amp;#x27;"&gt;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;font face="Verdana" size="2"&gt;1MB of objects have been allocated,&lt;/font&gt;&lt;/p&gt;  &lt;p class="Figure" style="margin: 6pt 0in 6pt 0.5in; text-indent: -0.25in; mso-list: l0 level1 lfo1; tab-stops: list .5in"&gt;&lt;span style="font-family: symbol; mso-fareast-font-family: symbol; mso-bidi-font-family: symbol"&gt;&lt;span style="mso-list: ignore"&gt;&lt;font size="2"&gt;&amp;#xB7;&lt;/font&gt;&lt;span style="font: 7pt &amp;#x27;Times New Roman&amp;#x27;"&gt;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;font face="Verdana" size="2"&gt;An application is moved to the background,&lt;/font&gt;&lt;/p&gt;  &lt;p class="Figure" style="margin: 6pt 0in 6pt 0.5in; text-indent: -0.25in; mso-list: l0 level1 lfo1; tab-stops: list .5in"&gt;&lt;span style="font-family: symbol; mso-fareast-font-family: symbol; mso-bidi-font-family: symbol"&gt;&lt;span style="mso-list: ignore"&gt;&lt;font size="2"&gt;&amp;#xB7;&lt;/font&gt;&lt;span style="font: 7pt &amp;#x27;Times New Roman&amp;#x27;"&gt;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;font face="Verdana" size="2"&gt;A failure to allocate memory occurs&lt;/font&gt;&lt;/p&gt;  &lt;p class="Figure" style="margin: 6pt 0in 6pt 0.5in; text-indent: -0.25in; mso-list: l0 level1 lfo1; tab-stops: list .5in"&gt;&lt;span style="font-family: symbol; mso-fareast-font-family: symbol; mso-bidi-font-family: symbol"&gt;&lt;span style="mso-list: ignore"&gt;&lt;font size="2"&gt;&amp;#xB7;&lt;/font&gt;&lt;span style="font: 7pt &amp;#x27;Times New Roman&amp;#x27;"&gt;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;font size="2"&gt;&lt;font face="Verdana"&gt;An application calls &lt;/font&gt;&lt;span class="CodeChar"&gt;&lt;font face="Lucida Console" color="#000080"&gt;GC.Collect&lt;/font&gt;&lt;/span&gt;&lt;font face="Verdana"&gt; (more on this later). &lt;/font&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p class="Figure" style="margin: 6pt 0in"&gt;   &lt;p&gt;&lt;font face="Verdana" size="2"&gt;&amp;#xA0;&lt;/font&gt;&lt;/p&gt; &lt;/p&gt;  &lt;p class="Figure" style="margin: 6pt 0in"&gt;&lt;font face="Verdana" size="2"&gt;When doing a collection, the Compact CLR performs the following steps:&lt;/font&gt;&lt;/p&gt;  &lt;p class="Figure" style="margin: 6pt 0in 6pt 0.25in"&gt;&lt;font size="2"&gt;&lt;font face="Verdana"&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;1. Brings all threads to a &amp;#x201C;safe point&amp;#x201D;.&lt;/b&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;Before a collection can occur, the CLR must ensure that all threads are in a &amp;#x201C;known&amp;#x201D; state with respect to the GC heap.&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;That is, no threads are in a state in which they can alter the GC heap in any way once a collection begins.&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;To do this, the CLR brings all threads to a state where they are not executing any managed code, nor are they running in the unmanaged portion of the CLR.&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;Once they reach a safe point, threads are not allowed to proceed until the collection has finished (except for the thread that actually does the collection, that is).&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p class="Figure" style="margin: 6pt 0in 6pt 0.25in"&gt;&lt;font size="2"&gt;&lt;font face="Verdana"&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;2. Marks all objects that descend from live roots&lt;/b&gt;. Once all threads have reached a safe point, the objects in the GC heap are examined.&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;Those that descend from live roots, such as local variables in the current scope, statics and so on are marked. Note that there is not a special thread that exists solely to do garbage collections.&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;The thread that was running when the GC was triggered is the thread that does the collection.&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p class="Figure" style="margin: 6pt 0in 6pt 0.25in"&gt;&lt;font size="2"&gt;&lt;font face="Verdana"&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;3. Frees all unmarked objects and populates the finalization queue&lt;/b&gt;. The memory for all unmarked objects that don&amp;#x2019;t have finalizers is freed.&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;Those unmarked objects that do have finalizers are placed on a list known as the finalization queue. &lt;/font&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p class="Figure" style="margin: 6pt 0in 6pt 0.25in"&gt;&lt;font size="2"&gt;&lt;font face="Verdana"&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;4. Occasionally, compacts the GC heap.&lt;/b&gt; If the CLR determines that the GC heap is sufficiently fragmented, the heap is compacted.&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;The heuristic used to determine when a compaction should occur is currently based on the percentage of fragmentation in the heap, but different heuristics may be used in future releases. &lt;/font&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p class="Figure" style="margin: 6pt 0in 6pt 0.25in"&gt;&lt;font size="2"&gt;&lt;font face="Verdana"&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;5. &amp;#x201C;Pitches&amp;#x201D; Jitted code in some scenarios.&lt;/b&gt; The Compact Framework CLR maintains jitted code in an in-memory cache.&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;Instead of recompiling a method each time it is called, the native code for that method is simply retrieved from the cache.&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;When a failure to allocate memory occurs, or when an application is moved to the background, the contents of the code cache are freed, or &amp;#x201C;pitched&amp;#x201D;, to make more memory available to the system.&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p class="Figure" style="margin: 6pt 0in 6pt 0.25in"&gt;&lt;font size="2"&gt;&lt;font face="Verdana"&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;6. Runs the finalizers for all objects on the finalization queue&lt;/b&gt;. After the unused objects are freed and the optional compacting and code pitching occurs, the collection is considered done and all threads are allowed to resume.&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;In the background, the CLR uses a dedicated thread to run the finalizers for all objects on the finalization queue.&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;Those objects are then freed the next time a collection occurs. &lt;/font&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p class="Figure" style="margin: 6pt 0in"&gt;   &lt;p&gt;&lt;font face="Verdana" size="2"&gt;&amp;#xA0;&lt;/font&gt;&lt;/p&gt; &lt;/p&gt;  &lt;h1 style="margin: 0.25in 0in 6pt"&gt;&lt;font face="Verdana" size="3"&gt;How is the NetCF collector different from the collector in the Full .Net Framework?&lt;/font&gt;&lt;/h1&gt;  &lt;p class="MsoNormal" style="margin: 6pt 0in"&gt;&lt;font face="Verdana" size="2"&gt;The Compact Framework targets significantly different scenarios than the full .Net Framework does.&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;While the Compact Framework is tuned specifically for use on devices with limited resources, the full .Net Framework supports scenarios ranging from client side UI applications to server side applications such as SQL Server and ASP.Net that may run on machines with multiple processors.&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;As such, it&amp;#x2019;s natural to find significant differences between the Compact Framework&amp;#x2019;s garbage collector and the garbage collector provided by the full .Net Framework.&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;The primary differences between the two collectors are:&lt;/font&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin: 6pt 0in 6pt 0.25in"&gt;&lt;font size="2"&gt;&lt;font face="Verdana"&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;Different basic collection model&lt;/b&gt;. As we&amp;#x2019;ve seen, the .Net CF has a standard mark and sweep collection model augmented with occasional compaction and code pitching.&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;While the high level goal (to reclaim memory allocated to objects that are no longer used) is the same, the basic collection model on the full .Net Framework is substantially different.&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;In particular, the full .Net Framework uses a &amp;#x201C;generational&amp;#x201D; model whereby objects that survive collections are promoted to higher generations that are collected less frequently.&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;In this way, the collector on the full .Net Framework tunes itself such that less time is spent analyzing objects that aren&amp;#x2019;t likely to be collected anyway.&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;There are other differences as well.&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;For example, the full .Net Framework handles unusually large objects differently than normal objects and the events that cause a GC to occur are different.&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;Chapter 19 in Jeff Richter&amp;#x2019;s&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;&amp;#x201C;Applied .Net Framework Programming&amp;#x201D; book provides a thorough, yet easily readable description of how garbage collection works on the full .Net Framework.&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin: 6pt 0in 6pt 0.25in"&gt;&lt;font size="2"&gt;&lt;font face="Verdana"&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;Fewer GC &amp;#x201C;configurations&lt;/b&gt;&amp;#x201D;. Because the full .Net Framework supports such a wide variety of application scenarios, its garbage collector is able to run in different &amp;#x201C;modes&amp;#x201D; specifically tuned by scenario.&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;In particular, the collection strategy used by the full .Net Framework is different depending on whether you are running an interactive application on a work station vs. a server application with high throughput requirements on a multi processor machine.&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;You&amp;#x2019;ve probably heard these referred to as &amp;#x201C;workstation&amp;#x201D; vs. &amp;#x201C;server&amp;#x201D; garbage collection.&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;Also, the workstation flavor of garbage collection has a concurrent mode in which the collector uses threads differently in an attempt to keep the application&amp;#x2019;s user interface as responsive as possible.&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;The Compact Framework supports none of these different GC modes.&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;Because the range of application scenarios is smaller, and the collector itself must be smaller, a single collection model is used regardless of the type of device your application is running on. &lt;/font&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin: 6pt 0in 6pt 0.25in"&gt;&lt;font size="2"&gt;&lt;font face="Verdana"&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;Code pitching&lt;/b&gt;. As described, the Compact Framework&amp;#x2019;s collector frees code it has previously jitted in order to free memory in certain scenarios.&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;The collector on the full .Net Framework has no such &amp;#x201C;code pitching&amp;#x201D; capability &amp;#x2013; the amount of jitted code kept in memory is free to grow without bounds.&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;  &lt;h1 style="margin: 0.25in 0in 6pt"&gt;&lt;font face="Verdana" size="3"&gt;Other Frequently Asked Questions&lt;/font&gt;&lt;/h1&gt;  &lt;p class="MsoNormal" style="margin: 6pt 0in"&gt;&lt;font face="Verdana" size="2"&gt;I&amp;#x2019;ve tried to answer many of the commonly asked GC questions in this blog.&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;We&amp;#x2019;ve covered questions like &amp;#x201C;what causes a GC?&amp;#x201D;, &amp;#x201C;what happens during a GC?&amp;#x201D;, and &amp;#x201C;How is the .Net CF collector different from the one in the full .Net Framework&amp;#x201D;?&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;In this section, I&amp;#x2019;ve added answers to a few more common questions.&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;If you still have questions unanswered, feel free to send them my way and I&amp;#x2019;ll research them and post the results.&lt;/font&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin: 6pt 0in 6pt 0.25in"&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;&lt;font face="Verdana"&gt;&lt;font size="2"&gt;What are the ramifications of calling GC.Collect()?         &lt;p&gt;&lt;/p&gt;       &lt;/font&gt;&lt;/font&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin: 6pt 0in 6pt 0.25in"&gt;&lt;font face="Verdana" size="2"&gt;You&amp;#x2019;ve probably heard the old wisdom &amp;#x201C;Yes, there is an API you can use to force a garbage collection, but don&amp;#x2019;t ever call it &amp;#x2013; the garbage collector can do a better job on its own&amp;#x201D;.&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;Here&amp;#x2019;s the thinking behind that statement:&lt;/font&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin: 6pt 0in 6pt 0.25in"&gt;&lt;font size="2"&gt;&lt;font face="Verdana"&gt;Garbage collection is a relatively expensive operation.&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;As we&amp;#x2019;ve seen, a collection involves &amp;#x201C;suspending&amp;#x201D; threads, traversing object graphs, moving blocks of memory around and so on.&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;Each time you force a collection, you&amp;#x2019;re forcing the Compact CLR to, at a minimum, get all threads to a state in which a collection can start, and scan the object graph looking for unused objects.&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;Clearly, calling &lt;/font&gt;&lt;span class="CodeChar"&gt;&lt;font face="Lucida Console" color="#000080"&gt;GC.Collect()&lt;/font&gt;&lt;/span&gt;&lt;font face="Verdana"&gt; repeatedly will have a seriously negative performance impact.&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0;&amp;#xA0; &lt;/span&gt;The Compact Framework&amp;#x2019;s collector will kick in automatically after 1MB of objects have been created.&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;As such, collections do happen occasionally - they don&amp;#x2019;t only happen when memory is exhausted.&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;Furthermore, when a call to &lt;/font&gt;&lt;span class="CodeChar"&gt;&lt;font face="Lucida Console" color="#000080"&gt;GC.Collect()&lt;/font&gt;&lt;/span&gt;&lt;font face="Verdana"&gt; returns, you can&amp;#x2019;t be guaranteed that all object finalizers have finished running.&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;As a result, you cannot force a collection in hopes of deterministically finalizing a particular object (use the Dispose pattern to deterministically free resources associated with an object).&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0;&amp;#xA0; &lt;/span&gt;That said, it is possible that you may have a scenario in which you&amp;#x2019;ll benefit by initiating collections yourself.&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;If you believe you have such a scenario, feel free to try it, but be aware of the implications and measure performance carefully to make sure you&amp;#x2019;re not doing more harm than good.&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin: 6pt 0in 6pt 0.25in"&gt;&lt;b style="mso-bidi-font-weight: normal"&gt;&lt;font face="Verdana"&gt;&lt;font size="2"&gt;Can I prevent a GC from occurring?         &lt;p&gt;&lt;/p&gt;       &lt;/font&gt;&lt;/font&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin: 6pt 0in 6pt 0.25in"&gt;&lt;font size="2"&gt;&lt;font face="Verdana"&gt;There are no APIs you can use to prevent a GC from occurring.&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;As we&amp;#x2019;ve seen, the time spent in garbage collection is a function of the number of objects that have been allocated.&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;As such, really the only way to &amp;#x201C;prevent&amp;#x201D; a collection is to keep the number of objects you allocate to a minimum.&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;When you consider this, however, be sure to remember that there are subtle scenarios in which allocations may be happening on your behalf that you may not be aware of.&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;The best example of this is boxing.&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;Boxing a value type necessarily creates a reference type in the GC heap, so even though you aren&amp;#x2019;t explicitly calling &lt;/font&gt;&lt;span class="CodeChar"&gt;&lt;font face="Lucida Console" color="#000080"&gt;new(),&lt;/font&gt;&lt;/span&gt;&lt;font face="Verdana"&gt; you&amp;#x2019;re still allocating objects.&lt;span style="mso-spacerun: yes"&gt;&amp;#xA0; &lt;/span&gt;It might be tempting to think that a call to &lt;/font&gt;&lt;span class="CodeChar"&gt;&lt;font face="Lucida Console" color="#000080"&gt;GC.Collect()&lt;/font&gt;&lt;/span&gt;&lt;font face="Verdana"&gt; can be used to &amp;#x201C;time&amp;#x201D; collections, but as described above, such calls are likely to negatively impact performance instead of helping consistently.&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin: 6pt 0in 6pt 0.25in"&gt;&lt;font face="Verdana" size="2"&gt;&lt;/font&gt;&amp;#xA0;&lt;/p&gt;  &lt;p class="MsoNormal" style="margin: 6pt 0in 6pt 0.25in"&gt;&lt;font face="Arial" size="1"&gt;This posting is provided &amp;quot;AS IS&amp;quot; with no warranties, and confers no rights.     &lt;br /&gt;Some of the information contained within this post may be in relation to beta software.&amp;#xA0; Any and all details are subject to change.&lt;/font&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=197254" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/stevenpr/archive/tags/GC/default.aspx">GC</category></item></channel></rss>