Wednesday, January 05, 2011

WP7: When does GC Consider a Local Variable as Garbage

Consider the following code that I received

static void Foo()
{
   TestClass t = new TestClass();
   List<object>l = new List<object>();
   l.Add(t); // Last use of l and t
   WeakReference w = new WeakReference(t);
   GC.Collect();
   GC.WaitForPendingFinalizers();
   Console.WriteLine("Is Alive {0}", w.IsAlive);
}

If this code is is run on the desktop it prints Is Alive False. Very similar to the observation made by a developer in http://stackoverflow.com/questions/3161119/does-the-net-garbage-collector-perform-predictive-analysis-of-code. This happens because beyond the last usage of l and t, the desktop GC considers l and t to be garbage and collects it.

Even though this seems trivial, it isn’t. During JITing of this method the JITer performs code analysis and ensures that runtime tables are updated to reflect whether at a particular time a given local variable is alive or not (it is not used beyond that point). This needs a bunch of data structures to be maintained (lifetime tables) and also dynamic analysis of code.

In case of Windows Phone 7 (or other platforms using NETCF) for the same code you’d get Is Alive True. Which means the NETCF GC considers the object to be alive even beyond it’s last usage in the function.

Due to the limited resources available on devices, NETCF does not do these dynamic analysis. So we trade off some runtime performance to ensure faster JITing (and hence application faster startup). All local variables of all functions in the call stacks of the all managed threads in execution during garbage collection is considered live (hence also object roots) and not collect. In NETCF the moment the function Foo returns and the stack is unwound the local objects on it including t and l becomes garbage.

Read more: I know the answer (it's 42)